mirror of
git://sourceware.org/git/libabigail.git
synced 2025-01-22 01:03:02 +00:00
aad0e11f50
When comparing the two libc binaries from "https://the.owo.foundation/Ac1Ksw8.tgz", abidiff crashes. It appears to be due to an assert that is hit because the overload of default_reporter::report for fn_parm_diff momentarily removes the redundant-ness from the categorization of the diff node of the type of a function parameter. The problem is that the sole child diff node of that type diff node is itself redundant. So the function parameter type diff node should really be redundant too. Oops, there is a logic violation there, hence the assert violation. I commented out the line that removes the redundant-ness. After all, if function parameter types shouldn't be redundant, that should have been taken care of by the redundancy_marking_visitor code in abg-comparison.cc as well as its associated category propagation code. But then consider what happens with a reproducer of the libc binaries above: $ cat test-PR29387-v0.c typedef int Integer; void f0(Integer i, char c) { i + c; } void f1(Integer i, unsigned char c) { i + c; } $ $ cat test-PR29387-v1.c typedef long int Integer; void f0(Integer i, char c) { i + c; } void f1(Integer i, unsigned char c) { i + c; } $ gcc -g test-PR29387-v0.c $ gcc -g test-PR29387-v1.c $ $ abidiff test-PR29387-v0.o test-PR29387-v1.o Functions changes summary: 0 Removed, 2 Changed, 0 Added functions Variables changes summary: 0 Removed, 0 Changed, 0 Added variable 2 functions with some indirect sub-type change: [C] 'function void f0(Integer, char)' at PR29387-test-v1.c:4:1 has some indirect sub-type changes: parameter 1 of type 'typedef Integer' changed: underlying type 'int' changed: type name changed from 'int' to 'long int' type size changed from 32 to 64 (in bits) [C] 'function void f1(Integer, unsigned char)' at PR29387-test-v1.c:10:1 has some indirect sub-type changes: $ $ So, the problem is this peace of report: [C] 'function void f1(Integer, unsigned char)' at PR29387-test-v1.c:10:1 has some indirect sub-type changes: You see that the report is empty; the reporter could not say what changed. What changed is the typedef "Integer" that changed from "int" to "long int". The redundancy_marking_visitor pass marked the change of the underlying type of the Integer typedef as being redundant. This is because that typedef change has already been reported on the f0 function interface. The problem is that by design, the 'int' to 'long int' change should not have been marked as being redundant by the redundancy_marking_visitor pass. This is because, we want to see all the "basic type changes" on function parameters types. They are deemed "local changes" of the function types, and we want to see all local changes to functions because it is almost 100% sure these are non-compatible changes. The root cause of the problem is that the function has_basic_type_change_only in abg-comparison.cc fails to detect that the parameter change carries a typedef-to-basic-type change, so the function parameter is wrongly marked as being redundant even though it ultimately carries a basic type change. This patch thus teaches has_basic_type_change_only to look through parameter changes to better detect basic type changes. * include/abg-comparison.h (peel_fn_parm_diff) (peel_typedef_qualified_type_or_parameter_diff): Declare ... * src/abg-comparison.cc (peel_fn_parm_diff) (peel_typedef_qualified_type_or_parameter_diff): ... new functions. (has_basic_type_change_only): Look through function parameters, typedefs and qualified types. * src/abg-default-reporter.cc (default_reporter::report): Remove the temporary removal of the redundant categorisation. Redundant-ness should have been handled by the redundancy_marking_visitor pass. * tests/data/test-diff-filter/test-PR29387-report.txt: Reference test output. * tests/data/test-diff-filter/test-PR29387-v{0,1}.c: Source of the input tests. * tests/data/test-diff-filter/test-PR29387-v{0,1}.o: Input test binaries. * tests/data/Makefile.am: Add the new test material above to the source distribution. * tests/test-diff-filter.cc (in_out_specs): Add the test binaries above to the test harness. Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2879 lines
67 KiB
C++
2879 lines
67 KiB
C++
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
// -*- Mode: C++ -*-
|
|
//
|
|
// Copyright (C) 2013-2022 Red Hat, Inc.
|
|
//
|
|
// Author: Dodji Seketeli
|
|
|
|
#ifndef __ABG_COMPARISON_H__
|
|
#define __ABG_COMPARISON_H__
|
|
|
|
/// @file
|
|
|
|
#include <memory>
|
|
#include <ostream>
|
|
#include <unordered_map>
|
|
#include <unordered_set>
|
|
#include "abg-corpus.h"
|
|
#include "abg-diff-utils.h"
|
|
#include "abg-reporter.h"
|
|
|
|
namespace abigail
|
|
{
|
|
|
|
/// @brief utilities to compare abi artifacts
|
|
///
|
|
/// The main entry points of the namespace are the compute_diff()
|
|
/// overloads used to compute the difference between two abi artifacts.
|
|
namespace comparison
|
|
{
|
|
|
|
namespace filtering
|
|
{
|
|
struct filter_base;
|
|
typedef shared_ptr<filter_base> filter_base_sptr;
|
|
typedef std::vector<filter_base_sptr> filters;
|
|
}
|
|
|
|
// Inject types we need into this namespace.
|
|
using std::ostream;
|
|
using std::vector;
|
|
using std::unordered_map;
|
|
using std::unordered_set;
|
|
using std::pair;
|
|
|
|
using diff_utils::insertion;
|
|
using diff_utils::deletion;
|
|
using diff_utils::edit_script;
|
|
|
|
class diff;
|
|
|
|
/// Convenience typedef for a shared_ptr for the @ref diff class
|
|
typedef shared_ptr<diff> diff_sptr;
|
|
|
|
/// Convenience typedef for a weak_ptr for the @ref diff class
|
|
typedef weak_ptr<diff> diff_wptr;
|
|
|
|
/// Hasher for @ref diff_sptr.
|
|
struct diff_sptr_hasher
|
|
{
|
|
/// The actual hashing functor.
|
|
size_t
|
|
operator()(const diff_sptr& t) const
|
|
{return reinterpret_cast<size_t>(t.get());}
|
|
}; // end struct diff_sptr_hasher
|
|
|
|
/// Convenience typedef for a vector of @ref diff_sptr.
|
|
typedef vector<diff_sptr> diff_sptrs_type;
|
|
|
|
/// Convenience typedef for a vector of @ref diff*.
|
|
typedef vector<diff*> diff_ptrs_type;
|
|
|
|
/// Convenience typedef for an unoredered set of @ref diff_sptr
|
|
typedef unordered_set<diff_sptr, diff_sptr_hasher> unordered_diff_sptr_set;
|
|
|
|
class decl_diff_base;
|
|
|
|
/// Convenience typedef for a shared_ptr of @ref decl_diff_base.
|
|
typedef shared_ptr<decl_diff_base> decl_diff_base_sptr;
|
|
|
|
/// Convenience typedef for a vector of @ref decl_diff_base_sptr.
|
|
typedef vector<decl_diff_base_sptr> decl_diff_base_sptrs_type;
|
|
|
|
class type_diff_base;
|
|
/// Convenience pointer for a shared pointer to a type_diff_base
|
|
typedef shared_ptr<type_diff_base> type_diff_base_sptr;
|
|
|
|
/// Convenience typedef for a vector of @ref type_diff_base_sptr
|
|
typedef vector<type_diff_base_sptr> type_diff_base_sptrs_type;
|
|
|
|
class function_decl_diff;
|
|
|
|
/// Convenience typedef for a shared pointer to a @ref function_decl type.
|
|
typedef shared_ptr<function_decl_diff> function_decl_diff_sptr;
|
|
|
|
/// Convenience typedef for a vector of @ref function_decl_diff_sptr
|
|
typedef vector<function_decl_diff_sptr> function_decl_diff_sptrs_type;
|
|
|
|
class fn_parm_diff;
|
|
|
|
/// Convenience typedef for a shared pointer to a @ref fn_parm_diff
|
|
/// type.
|
|
typedef shared_ptr<fn_parm_diff> fn_parm_diff_sptr;
|
|
|
|
class var_diff;
|
|
|
|
/// Convenience typedef for a shared pointer to a @ref var_diff type.
|
|
typedef shared_ptr<var_diff> var_diff_sptr;
|
|
|
|
/// Convenience typedef for a vector of @ref var_diff_sptr.
|
|
typedef vector<var_diff_sptr> var_diff_sptrs_type;
|
|
|
|
class base_diff;
|
|
|
|
/// Convenience typedef for a shared pointer to a @ref base_diff type.
|
|
typedef shared_ptr<base_diff> base_diff_sptr;
|
|
|
|
/// Convenience typedef for a vector of @ref base_diff_sptr.
|
|
typedef vector<base_diff_sptr> base_diff_sptrs_type;
|
|
|
|
class class_diff;
|
|
|
|
/// Convenience typedef for a shared pointer on a @ref class_diff type.
|
|
typedef shared_ptr<class_diff> class_diff_sptr;
|
|
|
|
/// Convenience typedef for a map of pointer values. The Key is a
|
|
/// pointer value and the value is potentially another pointer value
|
|
/// associated to the first one.
|
|
typedef unordered_map<size_t, size_t> pointer_map;
|
|
|
|
/// Convenience typedef for a map which key is a string and which
|
|
/// value is a @ref decl_base_sptr.
|
|
typedef unordered_map<string, decl_base_sptr> string_decl_base_sptr_map;
|
|
|
|
/// Convenience typedef for a map which key is a string and which
|
|
/// value is a @ref type_base_sptr.
|
|
typedef unordered_map<string, type_base_sptr> string_type_base_sptr_map;
|
|
|
|
/// Convenience typedef for a map which key is an unsigned integer and
|
|
/// which value is a @ref decl_base_sptr
|
|
typedef unordered_map<unsigned, decl_base_sptr> unsigned_decl_base_sptr_map;
|
|
|
|
/// Convenience typedef for a map of string and class_decl::basse_spec_sptr.
|
|
typedef unordered_map<string, class_decl::base_spec_sptr> string_base_sptr_map;
|
|
|
|
/// Convenience typedef for a map of string and @ref base_diff_sptr.
|
|
typedef unordered_map<string, base_diff_sptr> string_base_diff_sptr_map;
|
|
|
|
/// Convenience typedef for a map which value is a changed function
|
|
/// parameter and which key is the name of the function parameter.
|
|
typedef unordered_map<string, fn_parm_diff_sptr> string_fn_parm_diff_sptr_map;
|
|
|
|
/// Convenience typedef for a map which key is an integer and which
|
|
/// value is a changed parameter.
|
|
typedef unordered_map<unsigned, fn_parm_diff_sptr>
|
|
unsigned_fn_parm_diff_sptr_map;
|
|
|
|
/// Convenience typedef for a map which key is an integer and which
|
|
/// value is a parameter.
|
|
typedef unordered_map<unsigned,
|
|
function_decl::parameter_sptr> unsigned_parm_map;
|
|
|
|
/// Convenience typedef for a map which value is a
|
|
/// type_diff_base_sptr. The key of the map is the qualified name of
|
|
/// the changed type.
|
|
typedef unordered_map<string,
|
|
type_diff_base_sptr> string_type_diff_base_sptr_map;
|
|
|
|
/// Convenience typedef for a map which value is a
|
|
/// decl_diff_base_sptr. The key of the map is the qualified name of
|
|
/// the changed type.
|
|
typedef unordered_map<string,
|
|
decl_diff_base_sptr> string_decl_diff_base_sptr_map;
|
|
|
|
/// Convenience typedef for a map which value is a diff_sptr. The key
|
|
/// of the map is the qualified name of the changed type.
|
|
typedef unordered_map<string, diff_sptr> string_diff_sptr_map;
|
|
|
|
/// Convenience typedef for a map which value is a diff*. The key of
|
|
/// the map is the qualified name of the changed type.
|
|
typedef unordered_map<string, diff*> string_diff_ptr_map;
|
|
|
|
/// Convenience typedef for a map whose key is a string and whose
|
|
/// value is a changed variable of type @ref var_diff_sptr.
|
|
typedef unordered_map<string,
|
|
var_diff_sptr> string_var_diff_sptr_map;
|
|
|
|
|
|
/// Convenience typedef for a map whose key is an unsigned int and
|
|
/// whose value is a changed variable of type @ref var_diff_sptr.
|
|
typedef unordered_map<unsigned, var_diff_sptr> unsigned_var_diff_sptr_map;
|
|
|
|
/// Convenience typedef for a map which value is a function
|
|
/// parameter. The key is the name of the function parm.
|
|
typedef unordered_map<string, function_decl::parameter_sptr> string_parm_map;
|
|
|
|
/// Convenience typedef for a map which value is an enumerator. The
|
|
/// key is the name of the enumerator.
|
|
typedef unordered_map<string, enum_type_decl::enumerator> string_enumerator_map;
|
|
|
|
/// Convenience typedef for a changed enumerator. The first element
|
|
/// of the pair is the old enumerator and the second one is the new enumerator.
|
|
typedef std::pair<enum_type_decl::enumerator,
|
|
enum_type_decl::enumerator> changed_enumerator;
|
|
|
|
/// Convenience typedef for a vector of changed enumerators.
|
|
typedef vector<changed_enumerator> changed_enumerators_type;
|
|
|
|
/// Convenience typedef for a map which value is a changed enumerator.
|
|
/// The key is the name of the changed enumerator.
|
|
typedef unordered_map<string, changed_enumerator> string_changed_enumerator_map;
|
|
|
|
/// Convenience typedef for a map which key is a string and which
|
|
/// value is a pointer to @ref decl_base.
|
|
typedef unordered_map<string, function_decl*> string_function_ptr_map;
|
|
|
|
/// Convenience typedef for a map which key is a string and which
|
|
/// value is a @ref function_decl_diff_sptr.
|
|
typedef unordered_map<string,
|
|
function_decl_diff_sptr>
|
|
string_function_decl_diff_sptr_map;
|
|
|
|
/// Convenience typedef for a pair of class_decl::member_function_sptr
|
|
/// representing a changed member function. The first element of the
|
|
/// pair is the initial member function and the second element is the
|
|
/// changed one.
|
|
typedef pair<method_decl_sptr,
|
|
method_decl_sptr> changed_member_function_sptr;
|
|
|
|
/// Convenience typedef for a hash map of strings and changed member functions.
|
|
typedef unordered_map<string,
|
|
changed_member_function_sptr>
|
|
string_changed_member_function_sptr_map;
|
|
|
|
/// Convenience typedef for a hash map of strings and member functions.
|
|
typedef unordered_map<string, method_decl_sptr> string_member_function_sptr_map;
|
|
|
|
/// Convenience typedef for a map which key is a string and which
|
|
/// value is a point to @ref var_decl.
|
|
typedef unordered_map<string, var_decl*> string_var_ptr_map;
|
|
|
|
/// Convenience typedef for a pair of pointer to @ref var_decl
|
|
/// representing a @ref var_decl change. The first member of the pair
|
|
/// represents the initial variable and the second member represents
|
|
/// the changed variable.
|
|
typedef std::pair<var_decl*, var_decl*> changed_var_ptr;
|
|
|
|
/// Convenience typedef for a pair of @ref var_decl_sptr representing
|
|
/// a @ref var_decl change. The first member of the pair represents
|
|
/// the initial variable and the second member represents the changed
|
|
/// variable.
|
|
typedef std::pair<var_decl_sptr, var_decl_sptr> changed_var_sptr;
|
|
|
|
/// Convenience typedef for a vector of @changed_var_sptr.gg381
|
|
typedef vector<changed_var_sptr> changed_var_sptrs_type;
|
|
|
|
/// Convenience typedef for a map whose key is a string and whose
|
|
/// value is an @ref elf_symbol_sptr.
|
|
typedef unordered_map<string, elf_symbol_sptr> string_elf_symbol_map;
|
|
|
|
/// Convenience typedef for a map which key is a string and which
|
|
/// value is a @ref var_diff_sptr.
|
|
typedef unordered_map<string, var_diff_sptr> string_var_diff_ptr_map;
|
|
|
|
class diff_context;
|
|
|
|
/// Convenience typedef for a shared pointer of @ref diff_context.
|
|
typedef shared_ptr<diff_context> diff_context_sptr;
|
|
|
|
/// Convenience typedef for a weak pointer of @ref diff_context.
|
|
typedef weak_ptr<diff_context> diff_context_wptr;
|
|
|
|
class diff_node_visitor;
|
|
|
|
class diff_traversable_base;
|
|
|
|
/// Convenience typedef for shared_ptr on diff_traversable_base.
|
|
typedef shared_ptr<diff_traversable_base> diff_traversable_base_sptr;
|
|
|
|
/// An enum for the different ways to visit a diff tree node.
|
|
///
|
|
/// This is used by the node traversing code, to know when to avoid
|
|
/// visiting children nodes, for instance.
|
|
enum visiting_kind
|
|
{
|
|
/// The default enumerator value of this enum. It doesn't have any
|
|
/// particular meaning yet.
|
|
DEFAULT_VISITING_KIND = 0,
|
|
|
|
/// This says that the traversing code should avoid visiting the
|
|
/// children nodes of the current node being visited.
|
|
SKIP_CHILDREN_VISITING_KIND = 1,
|
|
|
|
/// This says that the traversing code should not mark visited nodes
|
|
/// as having been traversed. This is useful, for instance, for
|
|
/// visitors which have debugging purposes.
|
|
DO_NOT_MARK_VISITED_NODES_AS_VISITED = 1 << 1
|
|
};
|
|
|
|
visiting_kind
|
|
operator|(visiting_kind l, visiting_kind r);
|
|
|
|
visiting_kind
|
|
operator&(visiting_kind l, visiting_kind r);
|
|
|
|
visiting_kind
|
|
operator~(visiting_kind l);
|
|
|
|
/// The base class for the diff classes that are to be traversed.
|
|
class diff_traversable_base : public traversable_base
|
|
{
|
|
public:
|
|
virtual bool
|
|
traverse(diff_node_visitor& v);
|
|
}; // end struct diff_traversable_base
|
|
|
|
/// An enum for the different categories that a diff tree node falls
|
|
/// into, regarding the kind of changes it represents.
|
|
///
|
|
/// Note that if you add an enumerator to this enum, you need to
|
|
/// update a few spots accordingly:
|
|
///
|
|
/// * update the ACCESS_CHANGE_CATEGORY enumerator (which is the
|
|
/// last enumerator of this enum by OR-ing its initializer with
|
|
/// the new enumerator.
|
|
///
|
|
/// * update the categorize_harmless_diff_node or
|
|
/// categorize_harmful_diff_node function depending on if the new
|
|
/// enumerator classifies diff nodes as harmless or harmful.
|
|
///
|
|
/// * update the get_default_harmless_categories_bitmap or
|
|
/// get_default_harmful_categories_bitmap function as well, just
|
|
/// like above.
|
|
///
|
|
/// * update the "operator<<(ostream& o, diff_category c)" streaming
|
|
/// operator so that it can stream the new enumerator to a textual
|
|
/// output stream.
|
|
enum diff_category
|
|
{
|
|
/// This means the diff node does not carry any (meaningful) change,
|
|
/// or that it carries changes that have not yet been categorized.
|
|
NO_CHANGE_CATEGORY = 0,
|
|
|
|
/// This means the diff node (or at least one of its descendant
|
|
/// nodes) carries access related changes, e.g, a private member
|
|
/// that becomes public.
|
|
ACCESS_CHANGE_CATEGORY = 1,
|
|
|
|
/// This means the diff node (or at least one of its descendant
|
|
/// nodes) carries a change involving two compatible types. For
|
|
/// instance a type and its typedefs.
|
|
COMPATIBLE_TYPE_CHANGE_CATEGORY = 1 << 1,
|
|
|
|
/// This means that a diff node in the sub-tree carries a harmless
|
|
/// declaration name change. This is set only for name changes for
|
|
/// data members and typedefs.
|
|
HARMLESS_DECL_NAME_CHANGE_CATEGORY = 1 << 2,
|
|
|
|
/// This means that a diff node in the sub-tree carries an addition
|
|
/// or removal of a non-virtual member function.
|
|
NON_VIRT_MEM_FUN_CHANGE_CATEGORY = 1 << 3,
|
|
|
|
/// This means that a diff node in the sub-tree carries an addition
|
|
/// or removal of a static data member.
|
|
STATIC_DATA_MEMBER_CHANGE_CATEGORY = 1 << 4,
|
|
|
|
/// This means that a diff node in the sub-tree carries an addition
|
|
/// of enumerator to an enum type.
|
|
HARMLESS_ENUM_CHANGE_CATEGORY = 1 << 5,
|
|
|
|
/// This means that a diff node in the sub-tree carries an a symbol
|
|
/// alias change that is harmless.
|
|
HARMLESS_SYMBOL_ALIAS_CHANGE_CATEGORY = 1 << 6,
|
|
|
|
/// This means that a diff node in the sub-tree carries a harmless
|
|
/// union change.
|
|
HARMLESS_UNION_CHANGE_CATEGORY = 1 << 7,
|
|
|
|
/// This means that a diff node in the sub-tree carries a harmless
|
|
/// data member change. An example of harmless data member change
|
|
/// is an anonymous data member that replaces a given data member
|
|
/// without locally changing the layout.
|
|
HARMLESS_DATA_MEMBER_CHANGE_CATEGORY = 1 << 8,
|
|
|
|
/// This means that a diff node was marked as suppressed by a
|
|
/// user-provided suppression specification.
|
|
SUPPRESSED_CATEGORY = 1 << 9,
|
|
|
|
/// This means that a diff node was warked as being for a private
|
|
/// type. That is, the diff node is meant to be suppressed by a
|
|
/// suppression specification that was auto-generated to filter out
|
|
/// changes to private types.
|
|
PRIVATE_TYPE_CATEGORY = 1 << 10,
|
|
|
|
/// This means the diff node (or at least one of its descendant
|
|
/// nodes) carries a change that modifies the size of a type or an
|
|
/// offset of a type member. Removal or changes of enumerators in a
|
|
/// enum fall in this category too.
|
|
SIZE_OR_OFFSET_CHANGE_CATEGORY = 1 << 11,
|
|
|
|
/// This means that a diff node in the sub-tree carries an
|
|
/// incompatible change to a vtable.
|
|
VIRTUAL_MEMBER_CHANGE_CATEGORY = 1 << 12,
|
|
|
|
/// A diff node in this category is redundant. That means it's
|
|
/// present as a child of a other nodes in the diff tree.
|
|
REDUNDANT_CATEGORY = 1 << 13,
|
|
|
|
/// This means that a diff node in the sub-tree carries a type that
|
|
/// was declaration-only and that is now defined, or vice versa.
|
|
TYPE_DECL_ONLY_DEF_CHANGE_CATEGORY = 1 << 14,
|
|
|
|
/// A diff node in this category is a function parameter type which
|
|
/// top cv-qualifiers change.
|
|
FN_PARM_TYPE_TOP_CV_CHANGE_CATEGORY = 1 << 15,
|
|
|
|
/// A diff node in this category has a function parameter type with a
|
|
/// cv-qualifiers change.
|
|
FN_PARM_TYPE_CV_CHANGE_CATEGORY = 1 << 16,
|
|
|
|
/// A diff node in this category is a function return type with a
|
|
/// cv-qualifier change.
|
|
FN_RETURN_TYPE_CV_CHANGE_CATEGORY = 1 << 17,
|
|
|
|
/// A diff node in this category is a function (or function type)
|
|
/// with at least one parameter added or removed.
|
|
FN_PARM_ADD_REMOVE_CHANGE_CATEGORY = 1 << 18,
|
|
|
|
/// A diff node in this category is for a variable which type holds
|
|
/// a cv-qualifier change.
|
|
VAR_TYPE_CV_CHANGE_CATEGORY = 1 << 19,
|
|
|
|
/// A diff node in this category carries a change from void pointer
|
|
/// to non-void pointer.
|
|
VOID_PTR_TO_PTR_CHANGE_CATEGORY = 1 << 20,
|
|
|
|
/// A diff node in this category carries a change in the size of the
|
|
/// array type of a global variable, but the ELF size of the
|
|
/// variable didn't change.
|
|
BENIGN_INFINITE_ARRAY_CHANGE_CATEGORY = 1 << 21,
|
|
|
|
/// A special enumerator that is the logical 'or' all the
|
|
/// enumerators above.
|
|
///
|
|
/// This one must stay the last enumerator. Please update it each
|
|
/// time you add a new enumerator above.
|
|
EVERYTHING_CATEGORY =
|
|
ACCESS_CHANGE_CATEGORY
|
|
| COMPATIBLE_TYPE_CHANGE_CATEGORY
|
|
| HARMLESS_DECL_NAME_CHANGE_CATEGORY
|
|
| NON_VIRT_MEM_FUN_CHANGE_CATEGORY
|
|
| STATIC_DATA_MEMBER_CHANGE_CATEGORY
|
|
| HARMLESS_ENUM_CHANGE_CATEGORY
|
|
| HARMLESS_SYMBOL_ALIAS_CHANGE_CATEGORY
|
|
| HARMLESS_UNION_CHANGE_CATEGORY
|
|
| HARMLESS_DATA_MEMBER_CHANGE_CATEGORY
|
|
| SUPPRESSED_CATEGORY
|
|
| PRIVATE_TYPE_CATEGORY
|
|
| SIZE_OR_OFFSET_CHANGE_CATEGORY
|
|
| VIRTUAL_MEMBER_CHANGE_CATEGORY
|
|
| REDUNDANT_CATEGORY
|
|
| TYPE_DECL_ONLY_DEF_CHANGE_CATEGORY
|
|
| FN_PARM_TYPE_TOP_CV_CHANGE_CATEGORY
|
|
| FN_PARM_TYPE_CV_CHANGE_CATEGORY
|
|
| FN_RETURN_TYPE_CV_CHANGE_CATEGORY
|
|
| FN_PARM_ADD_REMOVE_CHANGE_CATEGORY
|
|
| VAR_TYPE_CV_CHANGE_CATEGORY
|
|
| VOID_PTR_TO_PTR_CHANGE_CATEGORY
|
|
| BENIGN_INFINITE_ARRAY_CHANGE_CATEGORY
|
|
}; // enum diff_category
|
|
|
|
diff_category
|
|
operator|(diff_category c1, diff_category c2);
|
|
|
|
diff_category&
|
|
operator|=(diff_category& c1, diff_category c2);
|
|
|
|
diff_category&
|
|
operator&=(diff_category& c1, diff_category c2);
|
|
|
|
diff_category
|
|
operator^(diff_category c1, diff_category c2);
|
|
|
|
diff_category
|
|
operator&(diff_category c1, diff_category c2);
|
|
|
|
diff_category
|
|
operator~(diff_category c);
|
|
|
|
diff_category
|
|
get_default_harmless_categories_bitmap();
|
|
|
|
diff_category
|
|
get_default_harmful_categories_bitmap();
|
|
|
|
ostream&
|
|
operator<<(ostream& o, diff_category);
|
|
|
|
class corpus_diff;
|
|
|
|
/// This type contains maps. Each map associates a type name to a
|
|
/// diff of that type. Not all kinds of diffs are present; only those
|
|
/// that carry leaf changes are, for now.
|
|
class diff_maps
|
|
{
|
|
struct priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
public:
|
|
|
|
diff_maps();
|
|
|
|
~diff_maps();
|
|
|
|
const string_diff_ptr_map&
|
|
get_type_decl_diff_map() const;
|
|
|
|
string_diff_ptr_map&
|
|
get_type_decl_diff_map();
|
|
|
|
const string_diff_ptr_map&
|
|
get_enum_diff_map() const;
|
|
|
|
string_diff_ptr_map&
|
|
get_enum_diff_map();
|
|
|
|
const string_diff_ptr_map&
|
|
get_class_diff_map() const;
|
|
|
|
string_diff_ptr_map&
|
|
get_class_diff_map();
|
|
|
|
const string_diff_ptr_map&
|
|
get_union_diff_map() const;
|
|
|
|
string_diff_ptr_map&
|
|
get_union_diff_map();
|
|
|
|
const string_diff_ptr_map&
|
|
get_typedef_diff_map() const;
|
|
|
|
string_diff_ptr_map&
|
|
get_typedef_diff_map();
|
|
|
|
const string_diff_ptr_map&
|
|
get_array_diff_map() const;
|
|
|
|
string_diff_ptr_map&
|
|
get_array_diff_map();
|
|
|
|
const string_diff_ptr_map&
|
|
get_reference_diff_map() const;
|
|
|
|
string_diff_ptr_map&
|
|
get_reference_diff_map();
|
|
|
|
const string_diff_ptr_map&
|
|
get_fn_parm_diff_map() const;
|
|
|
|
string_diff_ptr_map&
|
|
get_fn_parm_diff_map();
|
|
|
|
const string_diff_ptr_map&
|
|
get_function_type_diff_map() const;
|
|
|
|
string_diff_ptr_map&
|
|
get_function_type_diff_map();
|
|
|
|
const string_diff_ptr_map&
|
|
get_function_decl_diff_map() const;
|
|
|
|
string_diff_ptr_map&
|
|
get_function_decl_diff_map();
|
|
|
|
const string_diff_ptr_map&
|
|
get_var_decl_diff_map() const;
|
|
|
|
string_diff_ptr_map&
|
|
get_var_decl_diff_map();
|
|
|
|
const string_diff_ptr_map&
|
|
get_distinct_diff_map() const;
|
|
|
|
string_diff_ptr_map&
|
|
get_distinct_diff_map();
|
|
|
|
bool
|
|
insert_diff_node(const diff *d,
|
|
const type_or_decl_base_sptr& impacted_iface);
|
|
|
|
artifact_sptr_set_type*
|
|
lookup_impacted_interfaces(const diff *d) const;
|
|
}; // end class diff_maps
|
|
|
|
/// A convenience typedef for a shared pointer to @ref corpus_diff.
|
|
typedef shared_ptr<corpus_diff> corpus_diff_sptr;
|
|
|
|
/// The context of the diff. This type holds various bits of
|
|
/// information that is going to be used throughout the diffing of two
|
|
/// entities and the reporting that follows.
|
|
class diff_context
|
|
{
|
|
struct priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
diff_sptr
|
|
has_diff_for(const type_or_decl_base_sptr first,
|
|
const type_or_decl_base_sptr second) const;
|
|
|
|
diff_sptr
|
|
has_diff_for_types(const type_base_sptr first,
|
|
const type_base_sptr second) const;
|
|
|
|
const diff*
|
|
has_diff_for(const diff* d) const;
|
|
|
|
diff_sptr
|
|
has_diff_for(const diff_sptr d) const;
|
|
|
|
void
|
|
add_diff(const type_or_decl_base_sptr first,
|
|
const type_or_decl_base_sptr second,
|
|
const diff_sptr d);
|
|
|
|
void
|
|
add_diff(const diff_sptr d);
|
|
|
|
void
|
|
add_diff(const diff* d);
|
|
|
|
void
|
|
set_canonical_diff_for(const type_or_decl_base_sptr first,
|
|
const type_or_decl_base_sptr second,
|
|
const diff_sptr);
|
|
|
|
diff_sptr
|
|
set_or_get_canonical_diff_for(const type_or_decl_base_sptr first,
|
|
const type_or_decl_base_sptr second,
|
|
const diff_sptr canonical_diff);
|
|
|
|
public:
|
|
diff_context();
|
|
|
|
~diff_context();
|
|
|
|
void
|
|
set_corpus_diff(const corpus_diff_sptr&);
|
|
|
|
const corpus_diff_sptr&
|
|
get_corpus_diff() const;
|
|
|
|
corpus_sptr
|
|
get_first_corpus() const;
|
|
|
|
corpus_sptr
|
|
get_second_corpus() const;
|
|
|
|
reporter_base_sptr
|
|
get_reporter() const;
|
|
|
|
void
|
|
set_reporter(reporter_base_sptr&);
|
|
|
|
diff_sptr
|
|
get_canonical_diff_for(const type_or_decl_base_sptr first,
|
|
const type_or_decl_base_sptr second) const;
|
|
|
|
diff_sptr
|
|
get_canonical_diff_for(const diff_sptr d) const;
|
|
|
|
void
|
|
initialize_canonical_diff(const diff_sptr diff);
|
|
|
|
void
|
|
keep_diff_alive(diff_sptr&);
|
|
|
|
diff*
|
|
diff_has_been_visited(const diff*) const;
|
|
|
|
diff_sptr
|
|
diff_has_been_visited(const diff_sptr) const;
|
|
|
|
void
|
|
mark_diff_as_visited(const diff*);
|
|
|
|
void
|
|
forget_visited_diffs();
|
|
|
|
void
|
|
mark_last_diff_visited_per_class_of_equivalence(const diff*);
|
|
|
|
void
|
|
clear_last_diffs_visited_per_class_of_equivalence();
|
|
|
|
const diff*
|
|
get_last_visited_diff_of_class_of_equivalence(const diff*);
|
|
|
|
void
|
|
forbid_visiting_a_node_twice(bool f);
|
|
|
|
bool
|
|
visiting_a_node_twice_is_forbidden() const;
|
|
|
|
void
|
|
forbid_visiting_a_node_twice_per_interface(bool);
|
|
|
|
bool
|
|
visiting_a_node_twice_is_forbidden_per_interface() const;
|
|
|
|
diff_category
|
|
get_allowed_category() const;
|
|
|
|
void
|
|
set_allowed_category(diff_category c);
|
|
|
|
void
|
|
switch_categories_on(diff_category c);
|
|
|
|
void
|
|
switch_categories_off(diff_category c);
|
|
|
|
const filtering::filters&
|
|
diff_filters() const;
|
|
|
|
void
|
|
add_diff_filter(filtering::filter_base_sptr);
|
|
|
|
void
|
|
maybe_apply_filters(diff_sptr diff);
|
|
|
|
void
|
|
maybe_apply_filters(corpus_diff_sptr diff);
|
|
|
|
suppr::suppressions_type&
|
|
suppressions() const;
|
|
|
|
void
|
|
add_suppression(const suppr::suppression_sptr suppr);
|
|
|
|
void
|
|
add_suppressions(const suppr::suppressions_type& supprs);
|
|
|
|
void
|
|
show_leaf_changes_only(bool f);
|
|
|
|
bool
|
|
show_leaf_changes_only() const;
|
|
|
|
bool
|
|
show_hex_values() const;
|
|
|
|
void
|
|
show_hex_values(bool f);
|
|
|
|
bool
|
|
show_offsets_sizes_in_bits() const;
|
|
|
|
void
|
|
show_offsets_sizes_in_bits(bool f);
|
|
|
|
void
|
|
show_relative_offset_changes(bool f);
|
|
|
|
bool
|
|
show_relative_offset_changes(void);
|
|
|
|
void
|
|
show_stats_only(bool f);
|
|
|
|
bool
|
|
show_stats_only() const;
|
|
|
|
void
|
|
show_soname_change(bool f);
|
|
|
|
bool
|
|
show_soname_change() const;
|
|
|
|
void
|
|
show_architecture_change(bool f);
|
|
|
|
bool
|
|
show_architecture_change() const;
|
|
|
|
void
|
|
show_deleted_fns(bool f);
|
|
|
|
bool
|
|
show_deleted_fns() const;
|
|
|
|
void
|
|
show_changed_fns(bool f);
|
|
|
|
bool
|
|
show_changed_fns() const;
|
|
|
|
void
|
|
show_added_fns(bool f);
|
|
|
|
bool
|
|
show_added_fns() const;
|
|
|
|
void
|
|
show_deleted_vars(bool f);
|
|
|
|
bool
|
|
show_deleted_vars() const;
|
|
|
|
void
|
|
show_changed_vars(bool f);
|
|
|
|
bool
|
|
show_changed_vars() const;
|
|
|
|
void
|
|
show_added_vars(bool f);
|
|
|
|
bool
|
|
show_added_vars() const;
|
|
|
|
bool
|
|
show_linkage_names() const;
|
|
|
|
void
|
|
show_linkage_names(bool f);
|
|
|
|
bool
|
|
show_locs() const;
|
|
|
|
void
|
|
show_locs(bool f);
|
|
|
|
bool
|
|
show_redundant_changes() const;
|
|
|
|
void
|
|
show_redundant_changes(bool f);
|
|
|
|
bool
|
|
show_symbols_unreferenced_by_debug_info() const;
|
|
|
|
void
|
|
show_symbols_unreferenced_by_debug_info(bool f);
|
|
|
|
bool
|
|
show_added_symbols_unreferenced_by_debug_info() const;
|
|
|
|
void
|
|
show_added_symbols_unreferenced_by_debug_info(bool f);
|
|
|
|
void show_unreachable_types(bool f);
|
|
|
|
bool show_unreachable_types();
|
|
|
|
bool
|
|
show_impacted_interfaces() const;
|
|
|
|
void
|
|
show_impacted_interfaces(bool f);
|
|
|
|
void
|
|
default_output_stream(ostream*);
|
|
|
|
ostream*
|
|
default_output_stream();
|
|
|
|
void
|
|
error_output_stream(ostream*);
|
|
|
|
ostream*
|
|
error_output_stream() const;
|
|
|
|
bool
|
|
dump_diff_tree() const;
|
|
|
|
void
|
|
dump_diff_tree(bool f);
|
|
|
|
void
|
|
do_dump_diff_tree(const diff_sptr) const;
|
|
|
|
void
|
|
do_dump_diff_tree(const corpus_diff_sptr) const;
|
|
|
|
friend class_diff_sptr
|
|
compute_diff(const class_decl_sptr first,
|
|
const class_decl_sptr second,
|
|
diff_context_sptr ctxt);
|
|
};//end struct diff_context.
|
|
|
|
/// The abstraction of a change between two ABI artifacts, a.k.a an
|
|
/// artifact change.
|
|
///
|
|
/// In the grand scheme of things, a diff is strongly typed; for
|
|
/// instance, a change between two enums is represented by an
|
|
/// enum_diff type. A change between two function_type is represented
|
|
/// by a function_type_diff type and a change between two class_decl
|
|
/// is represented by a class_diff type. All of these types derive
|
|
/// from the @ref diff parent class.
|
|
///
|
|
/// An artifact change D can have one (or more) details named D'. A
|
|
/// detail is an artifact change that "belongs" to another one. Here,
|
|
/// D' belongs to D. Or said otherwise, D' is a child change of D.
|
|
/// Said otherwise, D and D' are related, and the relation is a
|
|
/// "child relation".
|
|
///
|
|
/// For instance, if we consider a change carried by a class_diff, the
|
|
/// detail change might be a change on one data member of the class.
|
|
/// In other word, the class_diff change might have a child diff node
|
|
/// that would be a var_diff node.
|
|
///
|
|
/// There are two ways to get the child var_diff node (for the data
|
|
/// member change detail) of the class_diff.
|
|
///
|
|
/// The first way is through the typed API, that is, through the
|
|
/// class_diff::sorted_changed_data_members() member function which
|
|
/// returns var_diff nodes.
|
|
///
|
|
/// The second way is through the generic API, that is, through the
|
|
/// diff::children_nodes() member function which returns generic diff
|
|
/// nodes. This second way enables us to walk the diff nodes graph in
|
|
/// a generic way, regardless of the types of the diff nodes.
|
|
///
|
|
/// Said otherwise, there are two views for a given diff node. There
|
|
/// is typed view, and there is the generic view. In the typed view,
|
|
/// the details are accessed through the typed API. In the generic
|
|
/// view, the details are gathered through the generic view.
|
|
///
|
|
///
|
|
/// Please read more about the @ref DiffNode "IR" of the comparison
|
|
/// engine to learn more about this.
|
|
///
|
|
/// This type encapsulates an edit script (a set of insertions and
|
|
/// deletions) for two constructs that are to be diff'ed. The two
|
|
/// constructs are called the "subjects" of the diff.
|
|
class diff : public diff_traversable_base
|
|
{
|
|
friend class diff_context;
|
|
|
|
// Forbidden
|
|
diff();
|
|
|
|
protected:
|
|
struct priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
diff(type_or_decl_base_sptr first_subject,
|
|
type_or_decl_base_sptr second_subject);
|
|
|
|
diff(type_or_decl_base_sptr first_subject,
|
|
type_or_decl_base_sptr second_subject,
|
|
diff_context_sptr ctxt);
|
|
|
|
void
|
|
begin_traversing();
|
|
|
|
void
|
|
end_traversing();
|
|
|
|
virtual void
|
|
finish_diff_type();
|
|
|
|
void
|
|
set_canonical_diff(diff *);
|
|
|
|
public:
|
|
type_or_decl_base_sptr
|
|
first_subject() const;
|
|
|
|
type_or_decl_base_sptr
|
|
second_subject() const;
|
|
|
|
const vector<diff*>&
|
|
children_nodes() const;
|
|
|
|
const diff*
|
|
parent_node() const;
|
|
|
|
diff* get_canonical_diff() const;
|
|
|
|
bool
|
|
is_traversing() const;
|
|
|
|
void
|
|
append_child_node(diff_sptr);
|
|
|
|
const diff_context_sptr
|
|
context() const;
|
|
|
|
void
|
|
context(diff_context_sptr c);
|
|
|
|
bool
|
|
currently_reporting() const;
|
|
|
|
void
|
|
currently_reporting(bool f) const;
|
|
|
|
bool
|
|
reported_once() const;
|
|
|
|
void
|
|
reported_once(bool f) const;
|
|
|
|
diff_category
|
|
get_category() const;
|
|
|
|
diff_category
|
|
get_local_category() const;
|
|
|
|
diff_category
|
|
get_class_of_equiv_category() const;
|
|
|
|
diff_category
|
|
add_to_category(diff_category c);
|
|
|
|
diff_category
|
|
add_to_local_category(diff_category c);
|
|
|
|
void
|
|
add_to_local_and_inherited_categories(diff_category c);
|
|
|
|
diff_category
|
|
remove_from_category(diff_category c);
|
|
|
|
diff_category
|
|
remove_from_local_category(diff_category c);
|
|
|
|
void
|
|
set_category(diff_category c);
|
|
|
|
void
|
|
set_local_category(diff_category c);
|
|
|
|
bool
|
|
is_filtered_out() const;
|
|
|
|
bool
|
|
is_filtered_out_wrt_non_inherited_categories() const;
|
|
|
|
bool
|
|
is_suppressed() const;
|
|
|
|
bool
|
|
is_suppressed(bool &is_private_type) const;
|
|
|
|
bool
|
|
to_be_reported() const;
|
|
|
|
bool
|
|
has_local_changes_to_be_reported() const;
|
|
|
|
virtual const string&
|
|
get_pretty_representation() const;
|
|
|
|
/// This constructs the relation between this diff node and its
|
|
/// detail diff nodes, in the generic view of the diff node.
|
|
///
|
|
/// Each specific typed diff node should implement how the typed
|
|
/// view "links" itself to its detail nodes in the generic sense.
|
|
virtual void
|
|
chain_into_hierarchy();
|
|
|
|
/// Pure interface to get the length of the changes encapsulated by
|
|
/// this diff. A length of zero means that the current instance of
|
|
/// @ref diff doesn't carry any change.
|
|
///
|
|
/// This is to be implemented by all descendants of this type.
|
|
virtual bool
|
|
has_changes() const = 0;
|
|
|
|
/// Pure interface to know if the current instance of @diff carries
|
|
/// a local change. A local change is a change that is on the @ref
|
|
/// diff object itself, as opposed to a change that is carried by
|
|
/// some of its children nodes.
|
|
///
|
|
/// This is to be implemented by all descendants of this type.
|
|
virtual enum change_kind
|
|
has_local_changes() const = 0;
|
|
|
|
/// Pure interface to report the diff in a serialized form that is
|
|
/// legible for the user.
|
|
///
|
|
/// Note that the serializd report has to leave one empty line at
|
|
/// the end of its content.
|
|
///
|
|
/// @param out the output stream to serialize the report to.
|
|
///
|
|
/// @param indent the indentation string to use.
|
|
virtual void
|
|
report(ostream& out, const string& indent = "") const = 0;
|
|
|
|
virtual bool
|
|
traverse(diff_node_visitor& v);
|
|
};// end class diff
|
|
|
|
diff_sptr
|
|
compute_diff(const decl_base_sptr,
|
|
const decl_base_sptr,
|
|
diff_context_sptr ctxt);
|
|
|
|
diff_sptr
|
|
compute_diff(const type_base_sptr,
|
|
const type_base_sptr,
|
|
diff_context_sptr ctxt);
|
|
|
|
/// The base class of diff between types.
|
|
class type_diff_base : public diff
|
|
{
|
|
struct priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
type_diff_base();
|
|
|
|
protected:
|
|
type_diff_base(type_base_sptr first_subject,
|
|
type_base_sptr second_subject,
|
|
diff_context_sptr ctxt);
|
|
|
|
public:
|
|
|
|
virtual enum change_kind
|
|
has_local_changes() const = 0;
|
|
|
|
virtual ~type_diff_base();
|
|
};// end class type_diff_base
|
|
|
|
/// The base class of diff between decls.
|
|
class decl_diff_base : public diff
|
|
{
|
|
struct priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
protected:
|
|
decl_diff_base(decl_base_sptr first_subject,
|
|
decl_base_sptr second_subject,
|
|
diff_context_sptr ctxt);
|
|
|
|
public:
|
|
|
|
virtual enum change_kind
|
|
has_local_changes() const = 0;
|
|
|
|
virtual ~decl_diff_base();
|
|
};// end class decl_diff_base
|
|
|
|
string
|
|
get_pretty_representation(diff*);
|
|
|
|
class distinct_diff;
|
|
|
|
/// Convenience typedef for a shared pointer to distinct_types_diff
|
|
typedef shared_ptr<distinct_diff> distinct_diff_sptr;
|
|
|
|
/// An abstraction of a diff between entities that are of a different
|
|
/// kind (disctinct).
|
|
class distinct_diff : public diff
|
|
{
|
|
struct priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
protected:
|
|
distinct_diff(type_or_decl_base_sptr first,
|
|
type_or_decl_base_sptr second,
|
|
diff_context_sptr ctxt = diff_context_sptr());
|
|
|
|
public:
|
|
|
|
const type_or_decl_base_sptr
|
|
first() const;
|
|
|
|
const type_or_decl_base_sptr
|
|
second() const;
|
|
|
|
const diff_sptr
|
|
compatible_child_diff() const;
|
|
|
|
virtual const string&
|
|
get_pretty_representation() const;
|
|
|
|
virtual bool
|
|
has_changes() const;
|
|
|
|
virtual enum change_kind
|
|
has_local_changes() const;
|
|
|
|
virtual void
|
|
report(ostream& out, const string& indent = "") const;
|
|
|
|
virtual void
|
|
chain_into_hierarchy();
|
|
|
|
static bool
|
|
entities_are_of_distinct_kinds(type_or_decl_base_sptr first,
|
|
type_or_decl_base_sptr second);
|
|
|
|
friend distinct_diff_sptr
|
|
compute_diff_for_distinct_kinds(const type_or_decl_base_sptr first,
|
|
const type_or_decl_base_sptr second,
|
|
diff_context_sptr ctxt);
|
|
};// end class distinct_types_diff
|
|
|
|
distinct_diff_sptr
|
|
compute_diff_for_distinct_kinds(const type_or_decl_base_sptr,
|
|
const type_or_decl_base_sptr,
|
|
diff_context_sptr ctxt);
|
|
|
|
/// Abstracts a diff between two instances of @ref var_decl
|
|
class var_diff : public decl_diff_base
|
|
{
|
|
struct priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
protected:
|
|
var_diff(var_decl_sptr first,
|
|
var_decl_sptr second,
|
|
diff_sptr type_diff,
|
|
diff_context_sptr ctxt = diff_context_sptr());
|
|
|
|
public:
|
|
var_decl_sptr
|
|
first_var() const;
|
|
|
|
var_decl_sptr
|
|
second_var() const;
|
|
|
|
diff_sptr
|
|
type_diff() const;
|
|
|
|
virtual void
|
|
chain_into_hierarchy();
|
|
|
|
virtual bool
|
|
has_changes() const;
|
|
|
|
virtual enum change_kind
|
|
has_local_changes() const;
|
|
|
|
virtual void
|
|
report(ostream& out, const string& indent = "") const;
|
|
|
|
virtual const string&
|
|
get_pretty_representation() const;
|
|
|
|
friend var_diff_sptr
|
|
compute_diff(const var_decl_sptr first,
|
|
const var_decl_sptr second,
|
|
diff_context_sptr ctxt);
|
|
};// end class var_diff
|
|
|
|
var_diff_sptr
|
|
compute_diff(const var_decl_sptr, const var_decl_sptr, diff_context_sptr);
|
|
|
|
class pointer_diff;
|
|
/// Convenience typedef for a shared pointer on a @ref
|
|
/// pointer_diff type.
|
|
typedef shared_ptr<pointer_diff> pointer_diff_sptr;
|
|
|
|
/// The abstraction of a diff between two pointers.
|
|
class pointer_diff : public type_diff_base
|
|
{
|
|
struct priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
protected:
|
|
pointer_diff(pointer_type_def_sptr first,
|
|
pointer_type_def_sptr second,
|
|
diff_sptr underlying_type_diff,
|
|
diff_context_sptr ctxt = diff_context_sptr());
|
|
|
|
public:
|
|
const pointer_type_def_sptr
|
|
first_pointer() const;
|
|
|
|
const pointer_type_def_sptr
|
|
second_pointer() const;
|
|
|
|
diff_sptr
|
|
underlying_type_diff() const;
|
|
|
|
void
|
|
underlying_type_diff(const diff_sptr);
|
|
|
|
virtual const string&
|
|
get_pretty_representation() const;
|
|
|
|
virtual bool
|
|
has_changes() const;
|
|
|
|
virtual enum change_kind
|
|
has_local_changes() const;
|
|
|
|
virtual void
|
|
report(ostream&, const string& indent = "") const;
|
|
|
|
virtual void
|
|
chain_into_hierarchy();
|
|
|
|
friend pointer_diff_sptr
|
|
compute_diff(pointer_type_def_sptr first,
|
|
pointer_type_def_sptr second,
|
|
diff_context_sptr ctxt);
|
|
};// end class pointer_diff
|
|
|
|
pointer_diff_sptr
|
|
compute_diff(pointer_type_def_sptr first,
|
|
pointer_type_def_sptr second,
|
|
diff_context_sptr ctxt);
|
|
|
|
class reference_diff;
|
|
|
|
/// Convenience typedef for a shared pointer on a @ref
|
|
/// reference_diff type.
|
|
typedef shared_ptr<reference_diff> reference_diff_sptr;
|
|
|
|
/// The abstraction of a diff between two references.
|
|
class reference_diff : public type_diff_base
|
|
{
|
|
struct priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
protected:
|
|
reference_diff(const reference_type_def_sptr first,
|
|
const reference_type_def_sptr second,
|
|
diff_sptr underlying,
|
|
diff_context_sptr ctxt = diff_context_sptr());
|
|
|
|
public:
|
|
reference_type_def_sptr
|
|
first_reference() const;
|
|
|
|
reference_type_def_sptr
|
|
second_reference() const;
|
|
|
|
const diff_sptr&
|
|
underlying_type_diff() const;
|
|
|
|
diff_sptr&
|
|
underlying_type_diff(diff_sptr);
|
|
|
|
virtual const string&
|
|
get_pretty_representation() const;
|
|
|
|
virtual bool
|
|
has_changes() const;
|
|
|
|
virtual enum change_kind
|
|
has_local_changes() const;
|
|
|
|
virtual void
|
|
report(ostream&, const string& indent = "") const;
|
|
|
|
virtual void
|
|
chain_into_hierarchy();
|
|
|
|
friend reference_diff_sptr
|
|
compute_diff(reference_type_def_sptr first,
|
|
reference_type_def_sptr second,
|
|
diff_context_sptr ctxt);
|
|
};// end class reference_diff
|
|
|
|
reference_diff_sptr
|
|
compute_diff(reference_type_def_sptr first,
|
|
reference_type_def_sptr second,
|
|
diff_context_sptr ctxt);
|
|
|
|
class array_diff;
|
|
|
|
/// Convenience typedef for a shared pointer on a @ref
|
|
/// array_diff type.
|
|
typedef shared_ptr<array_diff> array_diff_sptr;
|
|
|
|
/// The abstraction of a diff between two arrays.
|
|
class array_diff : public type_diff_base
|
|
{
|
|
struct priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
protected:
|
|
array_diff(const array_type_def_sptr first,
|
|
const array_type_def_sptr second,
|
|
diff_sptr element_type_diff,
|
|
diff_context_sptr ctxt = diff_context_sptr());
|
|
|
|
public:
|
|
const array_type_def_sptr
|
|
first_array() const;
|
|
|
|
const array_type_def_sptr
|
|
second_array() const;
|
|
|
|
const diff_sptr&
|
|
element_type_diff() const;
|
|
|
|
void
|
|
element_type_diff(diff_sptr);
|
|
|
|
virtual const string&
|
|
get_pretty_representation() const;
|
|
|
|
virtual bool
|
|
has_changes() const;
|
|
|
|
virtual enum change_kind
|
|
has_local_changes() const;
|
|
|
|
virtual void
|
|
report(ostream&, const string& indent = "") const;
|
|
|
|
virtual void
|
|
chain_into_hierarchy();
|
|
|
|
friend array_diff_sptr
|
|
compute_diff(array_type_def_sptr first,
|
|
array_type_def_sptr second,
|
|
diff_context_sptr ctxt);
|
|
};// end class array_diff
|
|
|
|
array_diff_sptr
|
|
compute_diff(array_type_def_sptr first,
|
|
array_type_def_sptr second,
|
|
diff_context_sptr ctxt);
|
|
|
|
class qualified_type_diff;
|
|
typedef class shared_ptr<qualified_type_diff> qualified_type_diff_sptr;
|
|
|
|
/// Abstraction of a diff between two qualified types.
|
|
class qualified_type_diff : public type_diff_base
|
|
{
|
|
struct priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
protected:
|
|
qualified_type_diff(qualified_type_def_sptr first,
|
|
qualified_type_def_sptr second,
|
|
diff_sptr underling,
|
|
diff_context_sptr ctxt = diff_context_sptr());
|
|
|
|
public:
|
|
const qualified_type_def_sptr
|
|
first_qualified_type() const;
|
|
|
|
const qualified_type_def_sptr
|
|
second_qualified_type() const;
|
|
|
|
diff_sptr
|
|
underlying_type_diff() const;
|
|
|
|
void
|
|
underlying_type_diff(const diff_sptr);
|
|
|
|
diff_sptr
|
|
leaf_underlying_type_diff() const;
|
|
|
|
virtual const string&
|
|
get_pretty_representation() const;
|
|
|
|
virtual bool
|
|
has_changes() const;
|
|
|
|
virtual enum change_kind
|
|
has_local_changes() const;
|
|
|
|
virtual void
|
|
report(ostream&, const string& indent = "") const;
|
|
|
|
virtual void
|
|
chain_into_hierarchy();
|
|
|
|
friend qualified_type_diff_sptr
|
|
compute_diff(const qualified_type_def_sptr first,
|
|
const qualified_type_def_sptr second,
|
|
diff_context_sptr ctxt);
|
|
};// end class qualified_type_diff.
|
|
|
|
qualified_type_diff_sptr
|
|
compute_diff(const qualified_type_def_sptr first,
|
|
const qualified_type_def_sptr second,
|
|
diff_context_sptr ctxt);
|
|
|
|
class enum_diff;
|
|
typedef shared_ptr<enum_diff> enum_diff_sptr;
|
|
|
|
/// Abstraction of a diff between two enums.
|
|
class enum_diff : public type_diff_base
|
|
{
|
|
struct priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
void
|
|
clear_lookup_tables();
|
|
|
|
bool
|
|
lookup_tables_empty() const;
|
|
|
|
void
|
|
ensure_lookup_tables_populated();
|
|
|
|
protected:
|
|
enum_diff(const enum_type_decl_sptr,
|
|
const enum_type_decl_sptr,
|
|
const diff_sptr,
|
|
diff_context_sptr ctxt = diff_context_sptr());
|
|
|
|
public:
|
|
const enum_type_decl_sptr
|
|
first_enum() const;
|
|
|
|
const enum_type_decl_sptr
|
|
second_enum() const;
|
|
|
|
diff_sptr
|
|
underlying_type_diff() const;
|
|
|
|
const string_enumerator_map&
|
|
deleted_enumerators() const;
|
|
|
|
const string_enumerator_map&
|
|
inserted_enumerators() const;
|
|
|
|
const string_changed_enumerator_map&
|
|
changed_enumerators() const;
|
|
|
|
virtual const string&
|
|
get_pretty_representation() const;
|
|
|
|
virtual bool
|
|
has_changes() const;
|
|
|
|
virtual enum change_kind
|
|
has_local_changes() const;
|
|
|
|
virtual void
|
|
report(ostream&, const string& indent = "") const;
|
|
|
|
virtual void
|
|
chain_into_hierarchy();
|
|
|
|
friend enum_diff_sptr
|
|
compute_diff(const enum_type_decl_sptr first,
|
|
const enum_type_decl_sptr second,
|
|
diff_context_sptr ctxt);
|
|
};//end class enum_diff;
|
|
|
|
enum_diff_sptr
|
|
compute_diff(const enum_type_decl_sptr,
|
|
const enum_type_decl_sptr,
|
|
diff_context_sptr);
|
|
|
|
/// This is the base class of @ref class_diff and @ref union_diff.
|
|
class class_or_union_diff : public type_diff_base
|
|
{
|
|
protected:
|
|
struct priv;
|
|
typedef std::unique_ptr<priv> priv_ptr;
|
|
priv_ptr priv_;
|
|
|
|
void
|
|
clear_lookup_tables(void);
|
|
|
|
bool
|
|
lookup_tables_empty(void) const;
|
|
|
|
void
|
|
ensure_lookup_tables_populated(void) const;
|
|
|
|
void
|
|
allocate_priv_data();
|
|
|
|
protected:
|
|
class_or_union_diff(class_or_union_sptr first_scope,
|
|
class_or_union_sptr second_scope,
|
|
diff_context_sptr ctxt = diff_context_sptr());
|
|
|
|
public:
|
|
|
|
const class_or_union_diff::priv_ptr&
|
|
get_priv() const;
|
|
|
|
//TODO: add change of the name of the type.
|
|
|
|
virtual ~class_or_union_diff();
|
|
|
|
class_or_union_sptr
|
|
first_class_or_union() const;
|
|
|
|
class_or_union_sptr
|
|
second_class_or_union() const;
|
|
|
|
const edit_script&
|
|
member_types_changes() const;
|
|
|
|
edit_script&
|
|
member_types_changes();
|
|
|
|
const edit_script&
|
|
data_members_changes() const;
|
|
|
|
edit_script&
|
|
data_members_changes();
|
|
|
|
const string_decl_base_sptr_map&
|
|
inserted_data_members() const;
|
|
|
|
const string_decl_base_sptr_map&
|
|
deleted_data_members() const;
|
|
|
|
const edit_script&
|
|
member_fns_changes() const;
|
|
|
|
edit_script&
|
|
member_fns_changes();
|
|
|
|
const function_decl_diff_sptrs_type&
|
|
changed_member_fns() const;
|
|
|
|
const string_member_function_sptr_map&
|
|
deleted_member_fns() const;
|
|
|
|
const string_member_function_sptr_map&
|
|
inserted_member_fns() const;
|
|
|
|
const var_diff_sptrs_type&
|
|
sorted_changed_data_members() const;
|
|
|
|
size_t
|
|
count_filtered_changed_data_members(bool local_only = false) const;
|
|
|
|
const var_diff_sptrs_type&
|
|
sorted_subtype_changed_data_members() const;
|
|
|
|
size_t
|
|
count_filtered_subtype_changed_data_members(bool local_only = false) const;
|
|
|
|
const string_decl_base_sptr_map&
|
|
data_members_replaced_by_adms() const;
|
|
|
|
const changed_var_sptrs_type&
|
|
ordered_data_members_replaced_by_adms() const;
|
|
|
|
const edit_script&
|
|
member_fn_tmpls_changes() const;
|
|
|
|
edit_script&
|
|
member_fn_tmpls_changes();
|
|
|
|
const edit_script&
|
|
member_class_tmpls_changes() const;
|
|
|
|
edit_script&
|
|
member_class_tmpls_changes();
|
|
|
|
virtual bool
|
|
has_changes() const;
|
|
|
|
virtual enum change_kind
|
|
has_local_changes() const;
|
|
|
|
virtual void
|
|
report(ostream&, const string& indent = "") const;
|
|
|
|
virtual void
|
|
chain_into_hierarchy();
|
|
|
|
friend class default_reporter;
|
|
}; // end class_or_union_diff;
|
|
|
|
/// This type abstracts changes for a class_decl.
|
|
class class_diff : public class_or_union_diff
|
|
{
|
|
struct priv;
|
|
typedef std::unique_ptr<priv> priv_ptr;
|
|
priv_ptr priv_;
|
|
|
|
const priv_ptr& get_priv()const;
|
|
|
|
void
|
|
clear_lookup_tables(void);
|
|
|
|
bool
|
|
lookup_tables_empty(void) const;
|
|
|
|
void
|
|
ensure_lookup_tables_populated(void) const;
|
|
|
|
void
|
|
allocate_priv_data();
|
|
|
|
protected:
|
|
class_diff(class_decl_sptr first_scope,
|
|
class_decl_sptr second_scope,
|
|
diff_context_sptr ctxt = diff_context_sptr());
|
|
|
|
public:
|
|
//TODO: add change of the name of the type.
|
|
|
|
virtual ~class_diff();
|
|
|
|
class_decl_sptr
|
|
first_class_decl() const;
|
|
|
|
class_decl_sptr
|
|
second_class_decl() const;
|
|
|
|
const edit_script&
|
|
base_changes() const;
|
|
|
|
edit_script&
|
|
base_changes();
|
|
|
|
const string_base_sptr_map&
|
|
deleted_bases() const;
|
|
|
|
const string_base_sptr_map&
|
|
inserted_bases() const;
|
|
|
|
const base_diff_sptrs_type&
|
|
changed_bases();
|
|
|
|
const vector<class_decl::base_spec_sptr>&
|
|
moved_bases() const;
|
|
|
|
virtual bool
|
|
has_changes() const;
|
|
|
|
virtual enum change_kind
|
|
has_local_changes() const;
|
|
|
|
virtual const string&
|
|
get_pretty_representation() const;
|
|
|
|
virtual void
|
|
report(ostream&, const string& indent = "") const;
|
|
|
|
virtual void
|
|
chain_into_hierarchy();
|
|
|
|
friend class_diff_sptr
|
|
compute_diff(const class_decl_sptr first,
|
|
const class_decl_sptr second,
|
|
diff_context_sptr ctxt);
|
|
|
|
friend class default_reporter;
|
|
};// end class_diff
|
|
|
|
class_diff_sptr
|
|
compute_diff(const class_decl_sptr first,
|
|
const class_decl_sptr second,
|
|
diff_context_sptr ctxt);
|
|
|
|
class union_diff;
|
|
typedef shared_ptr<union_diff> union_diff_sptr;
|
|
|
|
class union_diff : public class_or_union_diff
|
|
{
|
|
void
|
|
clear_lookup_tables(void);
|
|
|
|
bool
|
|
lookup_tables_empty(void) const;
|
|
|
|
void
|
|
ensure_lookup_tables_populated(void) const;
|
|
|
|
void
|
|
allocate_priv_data();
|
|
|
|
protected:
|
|
union_diff(union_decl_sptr first_union,
|
|
union_decl_sptr second_union,
|
|
diff_context_sptr ctxt = diff_context_sptr());
|
|
|
|
public:
|
|
|
|
virtual ~union_diff();
|
|
|
|
union_decl_sptr
|
|
first_union_decl() const;
|
|
|
|
union_decl_sptr
|
|
second_union_decl() const;
|
|
|
|
virtual const string&
|
|
get_pretty_representation() const;
|
|
|
|
virtual void
|
|
report(ostream&, const string& indent = "") const;
|
|
|
|
friend union_diff_sptr
|
|
compute_diff(const union_decl_sptr first,
|
|
const union_decl_sptr second,
|
|
diff_context_sptr ctxt);
|
|
}; // end class union_diff
|
|
|
|
union_diff_sptr
|
|
compute_diff(const union_decl_sptr first,
|
|
const union_decl_sptr second,
|
|
diff_context_sptr ctxt);
|
|
|
|
/// An abstraction of a diff between two instances of class_decl::base_spec.
|
|
class base_diff : public diff
|
|
{
|
|
struct priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
protected:
|
|
base_diff(class_decl::base_spec_sptr first,
|
|
class_decl::base_spec_sptr second,
|
|
class_diff_sptr underlying,
|
|
diff_context_sptr ctxt = diff_context_sptr());
|
|
|
|
public:
|
|
class_decl::base_spec_sptr
|
|
first_base() const;
|
|
|
|
class_decl::base_spec_sptr
|
|
second_base() const;
|
|
|
|
const class_diff_sptr
|
|
get_underlying_class_diff() const;
|
|
|
|
void
|
|
set_underlying_class_diff(class_diff_sptr d);
|
|
|
|
virtual const string&
|
|
get_pretty_representation() const;
|
|
|
|
virtual bool
|
|
has_changes() const;
|
|
|
|
virtual enum change_kind
|
|
has_local_changes() const;
|
|
|
|
virtual void
|
|
report(ostream&, const string& indent = "") const;
|
|
|
|
virtual void
|
|
chain_into_hierarchy();
|
|
|
|
friend base_diff_sptr
|
|
compute_diff(const class_decl::base_spec_sptr first,
|
|
const class_decl::base_spec_sptr second,
|
|
diff_context_sptr ctxt);
|
|
};// end class base_diff
|
|
|
|
base_diff_sptr
|
|
compute_diff(const class_decl::base_spec_sptr first,
|
|
const class_decl::base_spec_sptr second,
|
|
diff_context_sptr ctxt);
|
|
|
|
class scope_diff;
|
|
|
|
/// Convenience typedef for a shared pointer on a @ref scope_diff.
|
|
typedef shared_ptr<scope_diff> scope_diff_sptr;
|
|
|
|
/// An abstractions of the changes between two scopes.
|
|
class scope_diff : public diff
|
|
{
|
|
struct priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
bool
|
|
lookup_tables_empty() const;
|
|
|
|
void
|
|
clear_lookup_tables();
|
|
|
|
void
|
|
ensure_lookup_tables_populated();
|
|
|
|
protected:
|
|
scope_diff(scope_decl_sptr first_scope,
|
|
scope_decl_sptr second_scope,
|
|
diff_context_sptr ctxt = diff_context_sptr());
|
|
|
|
public:
|
|
|
|
friend scope_diff_sptr
|
|
compute_diff(const scope_decl_sptr first,
|
|
const scope_decl_sptr second,
|
|
scope_diff_sptr d,
|
|
diff_context_sptr ctxt);
|
|
|
|
friend scope_diff_sptr
|
|
compute_diff(const scope_decl_sptr first_scope,
|
|
const scope_decl_sptr second_scope,
|
|
diff_context_sptr ctxt);
|
|
|
|
const scope_decl_sptr
|
|
first_scope() const;
|
|
|
|
const scope_decl_sptr
|
|
second_scope() const;
|
|
|
|
const edit_script&
|
|
member_changes() const;
|
|
|
|
edit_script&
|
|
member_changes();
|
|
|
|
const decl_base_sptr
|
|
deleted_member_at(unsigned index) const;
|
|
|
|
const decl_base_sptr
|
|
deleted_member_at(vector<deletion>::const_iterator) const;
|
|
|
|
const decl_base_sptr
|
|
inserted_member_at(unsigned i);
|
|
|
|
const decl_base_sptr
|
|
inserted_member_at(vector<unsigned>::const_iterator i);
|
|
|
|
const diff_sptrs_type&
|
|
changed_types() const;
|
|
|
|
const diff_sptrs_type&
|
|
changed_decls() const;
|
|
|
|
const string_decl_base_sptr_map&
|
|
removed_types() const;
|
|
|
|
const string_decl_base_sptr_map&
|
|
removed_decls() const;
|
|
|
|
const string_decl_base_sptr_map&
|
|
added_types() const;
|
|
|
|
const string_decl_base_sptr_map&
|
|
added_decls() const;
|
|
|
|
virtual const string&
|
|
get_pretty_representation() const;
|
|
|
|
virtual bool
|
|
has_changes() const;
|
|
|
|
virtual enum change_kind
|
|
has_local_changes() const;
|
|
|
|
virtual void
|
|
report(ostream& out, const string& indent = "") const;
|
|
|
|
virtual void
|
|
chain_into_hierarchy();
|
|
|
|
friend class default_reporter;
|
|
friend class leaf_reporter;
|
|
};// end class scope_diff
|
|
|
|
scope_diff_sptr
|
|
compute_diff(const scope_decl_sptr first,
|
|
const scope_decl_sptr second,
|
|
scope_diff_sptr d,
|
|
diff_context_sptr ctxt);
|
|
|
|
scope_diff_sptr
|
|
compute_diff(const scope_decl_sptr first_scope,
|
|
const scope_decl_sptr second_scope,
|
|
diff_context_sptr ctxt);
|
|
|
|
/// Abstraction of a diff between two function parameters.
|
|
class fn_parm_diff : public decl_diff_base
|
|
{
|
|
struct priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
fn_parm_diff(const function_decl::parameter_sptr first,
|
|
const function_decl::parameter_sptr second,
|
|
diff_context_sptr ctxt);
|
|
|
|
public:
|
|
friend fn_parm_diff_sptr
|
|
compute_diff(const function_decl::parameter_sptr first,
|
|
const function_decl::parameter_sptr second,
|
|
diff_context_sptr ctxt);
|
|
|
|
const function_decl::parameter_sptr
|
|
first_parameter() const;
|
|
|
|
const function_decl::parameter_sptr
|
|
second_parameter() const;
|
|
|
|
diff_sptr
|
|
type_diff() const;
|
|
|
|
virtual const string&
|
|
get_pretty_representation() const;
|
|
|
|
virtual bool
|
|
has_changes() const;
|
|
|
|
virtual enum change_kind
|
|
has_local_changes() const;
|
|
|
|
virtual void
|
|
report(ostream&, const string& indent = "") const;
|
|
|
|
virtual void
|
|
chain_into_hierarchy();
|
|
}; // end class fn_parm_diff
|
|
|
|
fn_parm_diff_sptr
|
|
compute_diff(const function_decl::parameter_sptr first,
|
|
const function_decl::parameter_sptr second,
|
|
diff_context_sptr ctxt);
|
|
|
|
class function_type_diff;
|
|
|
|
/// A convenience typedef for a shared pointer to @ref
|
|
/// function_type_type_diff
|
|
typedef shared_ptr<function_type_diff> function_type_diff_sptr;
|
|
|
|
/// Abstraction of a diff between two function types.
|
|
class function_type_diff: public type_diff_base
|
|
{
|
|
struct priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
void
|
|
ensure_lookup_tables_populated();
|
|
|
|
const function_decl::parameter_sptr
|
|
deleted_parameter_at(int i) const;
|
|
|
|
const function_decl::parameter_sptr
|
|
inserted_parameter_at(int i) const;
|
|
|
|
protected:
|
|
function_type_diff(const function_type_sptr first,
|
|
const function_type_sptr second,
|
|
diff_context_sptr ctxt);
|
|
|
|
public:
|
|
friend function_type_diff_sptr
|
|
compute_diff(const function_type_sptr first,
|
|
const function_type_sptr second,
|
|
diff_context_sptr ctxt);
|
|
|
|
const function_type_sptr
|
|
first_function_type() const;
|
|
|
|
const function_type_sptr
|
|
second_function_type() const;
|
|
|
|
const diff_sptr
|
|
return_type_diff() const;
|
|
|
|
const string_fn_parm_diff_sptr_map&
|
|
subtype_changed_parms() const;
|
|
|
|
const string_parm_map&
|
|
removed_parms() const;
|
|
|
|
const string_parm_map&
|
|
added_parms() const;
|
|
|
|
const vector<function_decl::parameter_sptr>&
|
|
sorted_deleted_parms() const;
|
|
|
|
const vector<function_decl::parameter_sptr>&
|
|
sorted_added_parms() const;
|
|
|
|
virtual const string&
|
|
get_pretty_representation() const;
|
|
|
|
virtual bool
|
|
has_changes() const;
|
|
|
|
virtual enum change_kind
|
|
has_local_changes() const;
|
|
|
|
virtual void
|
|
report(ostream&, const string& indent = "") const;
|
|
|
|
virtual void
|
|
chain_into_hierarchy();
|
|
|
|
friend class default_reporter;
|
|
friend class leaf_reporter;
|
|
};// end class function_type_diff
|
|
|
|
function_type_diff_sptr
|
|
compute_diff(const function_type_sptr first,
|
|
const function_type_sptr second,
|
|
diff_context_sptr ctxt);
|
|
|
|
/// Abstraction of a diff between two function_decl.
|
|
class function_decl_diff : public decl_diff_base
|
|
{
|
|
struct priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
void
|
|
ensure_lookup_tables_populated();
|
|
|
|
|
|
protected:
|
|
function_decl_diff(const function_decl_sptr first,
|
|
const function_decl_sptr second,
|
|
diff_context_sptr ctxt);
|
|
|
|
public:
|
|
|
|
friend function_decl_diff_sptr
|
|
compute_diff(const function_decl_sptr first,
|
|
const function_decl_sptr second,
|
|
diff_context_sptr ctxt);
|
|
|
|
const function_decl_sptr
|
|
first_function_decl() const;
|
|
|
|
const function_decl_sptr
|
|
second_function_decl() const;
|
|
|
|
const function_type_diff_sptr
|
|
type_diff() const;
|
|
|
|
virtual const string&
|
|
get_pretty_representation() const;
|
|
|
|
virtual bool
|
|
has_changes() const;
|
|
|
|
virtual enum change_kind
|
|
has_local_changes() const;
|
|
|
|
virtual void
|
|
report(ostream&, const string& indent = "") const;
|
|
|
|
virtual void
|
|
chain_into_hierarchy();
|
|
}; // end class function_decl_diff
|
|
|
|
function_decl_diff_sptr
|
|
compute_diff(const function_decl_sptr first,
|
|
const function_decl_sptr second,
|
|
diff_context_sptr ctxt);
|
|
|
|
class type_decl_diff;
|
|
|
|
/// Convenience typedef for a shared pointer on a @ref type_decl_diff type.
|
|
typedef shared_ptr<type_decl_diff> type_decl_diff_sptr;
|
|
|
|
/// Abstraction of a diff between two basic type declarations.
|
|
class type_decl_diff : public type_diff_base
|
|
{
|
|
type_decl_diff();
|
|
|
|
protected:
|
|
type_decl_diff(const type_decl_sptr first,
|
|
const type_decl_sptr second,
|
|
diff_context_sptr ctxt = diff_context_sptr());
|
|
|
|
public:
|
|
friend type_decl_diff_sptr
|
|
compute_diff(const type_decl_sptr first,
|
|
const type_decl_sptr second,
|
|
diff_context_sptr ctxt);
|
|
|
|
const type_decl_sptr
|
|
first_type_decl() const;
|
|
|
|
const type_decl_sptr
|
|
second_type_decl() const;
|
|
|
|
virtual const string&
|
|
get_pretty_representation() const;
|
|
|
|
virtual bool
|
|
has_changes() const;
|
|
|
|
virtual enum change_kind
|
|
has_local_changes() const;
|
|
|
|
virtual void
|
|
report(ostream& out, const string& indent = "") const;
|
|
};// end type_decl_diff
|
|
|
|
type_decl_diff_sptr
|
|
compute_diff(const type_decl_sptr,
|
|
const type_decl_sptr,
|
|
diff_context_sptr);
|
|
|
|
class typedef_diff;
|
|
|
|
/// Convenience typedef for a shared pointer on a typedef_diff type.
|
|
typedef shared_ptr<typedef_diff> typedef_diff_sptr;
|
|
|
|
/// Abstraction of a diff between two typedef_decl.
|
|
class typedef_diff : public type_diff_base
|
|
{
|
|
struct priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
typedef_diff();
|
|
|
|
protected:
|
|
typedef_diff(const typedef_decl_sptr first,
|
|
const typedef_decl_sptr second,
|
|
const diff_sptr underlying_type_diff,
|
|
diff_context_sptr ctxt = diff_context_sptr());
|
|
|
|
public:
|
|
friend typedef_diff_sptr
|
|
compute_diff(const typedef_decl_sptr first,
|
|
const typedef_decl_sptr second,
|
|
diff_context_sptr ctxt);
|
|
|
|
const typedef_decl_sptr
|
|
first_typedef_decl() const;
|
|
|
|
const typedef_decl_sptr
|
|
second_typedef_decl() const;
|
|
|
|
const diff_sptr
|
|
underlying_type_diff() const;
|
|
|
|
void
|
|
underlying_type_diff(const diff_sptr);
|
|
|
|
virtual const string&
|
|
get_pretty_representation() const;
|
|
|
|
virtual bool
|
|
has_changes() const;
|
|
|
|
virtual enum change_kind
|
|
has_local_changes() const;
|
|
|
|
virtual void
|
|
report(ostream&, const string& indent = "") const;
|
|
|
|
virtual void
|
|
chain_into_hierarchy();
|
|
};// end class typedef_diff
|
|
|
|
typedef_diff_sptr
|
|
compute_diff(const typedef_decl_sptr,
|
|
const typedef_decl_sptr,
|
|
diff_context_sptr ctxt);
|
|
|
|
const diff*
|
|
get_typedef_diff_underlying_type_diff(const diff* diff);
|
|
|
|
class translation_unit_diff;
|
|
|
|
/// Convenience typedef for a shared pointer on a
|
|
/// @ref translation_unit_diff type.
|
|
typedef shared_ptr<translation_unit_diff> translation_unit_diff_sptr;
|
|
|
|
/// An abstraction of a diff between two translation units.
|
|
class translation_unit_diff : public scope_diff
|
|
{
|
|
struct priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
protected:
|
|
translation_unit_diff(translation_unit_sptr first,
|
|
translation_unit_sptr second,
|
|
diff_context_sptr ctxt = diff_context_sptr());
|
|
|
|
public:
|
|
|
|
const translation_unit_sptr
|
|
first_translation_unit() const;
|
|
|
|
const translation_unit_sptr
|
|
second_translation_unit() const;
|
|
|
|
friend translation_unit_diff_sptr
|
|
compute_diff(const translation_unit_sptr first,
|
|
const translation_unit_sptr second,
|
|
diff_context_sptr ctxt);
|
|
|
|
virtual bool
|
|
has_changes() const;
|
|
|
|
virtual enum change_kind
|
|
has_local_changes() const;
|
|
|
|
virtual void
|
|
report(ostream& out, const string& indent = "") const;
|
|
};//end class translation_unit_diff
|
|
|
|
translation_unit_diff_sptr
|
|
compute_diff(const translation_unit_sptr first,
|
|
const translation_unit_sptr second,
|
|
diff_context_sptr ctxt = diff_context_sptr());
|
|
|
|
/// An abstraction of a diff between between two abi corpus.
|
|
class corpus_diff
|
|
{
|
|
struct priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
protected:
|
|
corpus_diff(corpus_sptr first,
|
|
corpus_sptr second,
|
|
diff_context_sptr ctxt = diff_context_sptr());
|
|
|
|
void
|
|
finish_diff_type();
|
|
|
|
public:
|
|
|
|
class diff_stats;
|
|
|
|
virtual ~corpus_diff();
|
|
|
|
/// A convenience typedef for a shared pointer to @ref diff_stats
|
|
typedef shared_ptr<diff_stats> diff_stats_sptr;
|
|
|
|
corpus_sptr
|
|
first_corpus() const;
|
|
|
|
corpus_sptr
|
|
second_corpus() const;
|
|
|
|
const vector<diff*>&
|
|
children_nodes() const;
|
|
|
|
void
|
|
append_child_node(diff_sptr);
|
|
|
|
edit_script&
|
|
function_changes() const;
|
|
|
|
edit_script&
|
|
variable_changes() const;
|
|
|
|
bool
|
|
soname_changed() const;
|
|
|
|
bool
|
|
architecture_changed() const;
|
|
|
|
const string_function_ptr_map&
|
|
deleted_functions() const;
|
|
|
|
const string_function_ptr_map&
|
|
added_functions();
|
|
|
|
const string_function_decl_diff_sptr_map&
|
|
changed_functions();
|
|
|
|
const function_decl_diff_sptrs_type&
|
|
changed_functions_sorted();
|
|
|
|
const string_var_ptr_map&
|
|
deleted_variables() const;
|
|
|
|
const string_var_ptr_map&
|
|
added_variables() const;
|
|
|
|
const string_var_diff_sptr_map&
|
|
changed_variables();
|
|
|
|
const var_diff_sptrs_type&
|
|
changed_variables_sorted();
|
|
|
|
const string_elf_symbol_map&
|
|
deleted_unrefed_function_symbols() const;
|
|
|
|
const string_elf_symbol_map&
|
|
added_unrefed_function_symbols() const;
|
|
|
|
const string_elf_symbol_map&
|
|
deleted_unrefed_variable_symbols() const;
|
|
|
|
const string_elf_symbol_map&
|
|
added_unrefed_variable_symbols() const;
|
|
|
|
const string_type_base_sptr_map&
|
|
deleted_unreachable_types() const;
|
|
|
|
const vector<type_base_sptr>&
|
|
deleted_unreachable_types_sorted() const;
|
|
|
|
const string_type_base_sptr_map&
|
|
added_unreachable_types() const;
|
|
|
|
const vector<type_base_sptr>&
|
|
added_unreachable_types_sorted() const;
|
|
|
|
const string_diff_sptr_map&
|
|
changed_unreachable_types() const;
|
|
|
|
const vector<diff_sptr>&
|
|
changed_unreachable_types_sorted() const;
|
|
|
|
const diff_context_sptr
|
|
context() const;
|
|
|
|
const string&
|
|
get_pretty_representation() const;
|
|
|
|
bool
|
|
has_changes() const;
|
|
|
|
bool
|
|
has_incompatible_changes() const;
|
|
|
|
bool
|
|
has_net_subtype_changes() const;
|
|
|
|
bool
|
|
has_net_changes() const;
|
|
|
|
const diff_stats&
|
|
apply_filters_and_suppressions_before_reporting();
|
|
|
|
void
|
|
mark_leaf_diff_nodes();
|
|
|
|
diff_maps&
|
|
get_leaf_diffs();
|
|
|
|
const diff_maps&
|
|
get_leaf_diffs() const;
|
|
|
|
virtual void
|
|
report(ostream& out, const string& indent = "") const;
|
|
|
|
virtual bool
|
|
traverse(diff_node_visitor& v);
|
|
|
|
virtual void
|
|
chain_into_hierarchy();
|
|
|
|
friend corpus_diff_sptr
|
|
compute_diff(const corpus_sptr f,
|
|
const corpus_sptr s,
|
|
diff_context_sptr ctxt);
|
|
|
|
friend void
|
|
apply_suppressions(const corpus_diff* diff_tree);
|
|
|
|
friend void
|
|
maybe_report_unreachable_type_changes(const corpus_diff& d,
|
|
const corpus_diff::diff_stats &s,
|
|
const string& indent,
|
|
ostream& out);
|
|
|
|
friend class default_reporter;
|
|
friend class leaf_reporter;
|
|
}; // end class corpus_diff
|
|
|
|
corpus_diff_sptr
|
|
compute_diff(const corpus_sptr,
|
|
const corpus_sptr,
|
|
diff_context_sptr = diff_context_sptr());
|
|
|
|
corpus_diff_sptr
|
|
compute_diff(const corpus_group_sptr&,
|
|
const corpus_group_sptr&,
|
|
diff_context_sptr ctxt);
|
|
|
|
/// This is a document class that aims to capture statistics about the
|
|
/// changes carried by a @ref corpus_diff type.
|
|
///
|
|
/// Its values are populated by the member function
|
|
/// corpus_diff::apply_filters_and_suppressions_before_reporting()
|
|
class corpus_diff::diff_stats
|
|
{
|
|
struct priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
diff_stats();
|
|
|
|
public:
|
|
|
|
diff_stats(diff_context_sptr);
|
|
|
|
size_t num_func_removed() const;
|
|
void num_func_removed(size_t);
|
|
|
|
size_t num_removed_func_filtered_out() const;
|
|
void num_removed_func_filtered_out(size_t);
|
|
|
|
size_t net_num_func_removed() const;
|
|
|
|
size_t num_func_added() const;
|
|
void num_func_added(size_t);
|
|
|
|
size_t num_added_func_filtered_out() const;
|
|
void num_added_func_filtered_out(size_t);
|
|
|
|
size_t net_num_func_added() const;
|
|
|
|
size_t num_func_changed() const;
|
|
void num_func_changed(size_t);
|
|
|
|
size_t num_changed_func_filtered_out() const;
|
|
void num_changed_func_filtered_out(size_t);
|
|
|
|
size_t num_func_with_virtual_offset_changes() const;
|
|
void num_func_with_virtual_offset_changes(size_t);
|
|
|
|
size_t net_num_func_changed() const;
|
|
|
|
size_t num_vars_removed() const;
|
|
void num_vars_removed(size_t);
|
|
|
|
size_t num_removed_vars_filtered_out() const;
|
|
void num_removed_vars_filtered_out(size_t) const;
|
|
|
|
size_t net_num_vars_removed() const;
|
|
|
|
size_t num_vars_added() const;
|
|
void num_vars_added(size_t);
|
|
|
|
size_t num_added_vars_filtered_out() const;
|
|
void num_added_vars_filtered_out(size_t);
|
|
|
|
size_t net_num_vars_added() const;
|
|
|
|
size_t num_vars_changed() const;
|
|
void num_vars_changed(size_t);
|
|
|
|
size_t num_changed_vars_filtered_out() const;
|
|
void num_changed_vars_filtered_out(size_t);
|
|
|
|
size_t net_num_vars_changed() const;
|
|
|
|
size_t num_func_syms_removed() const;
|
|
void num_func_syms_removed(size_t);
|
|
|
|
size_t num_removed_func_syms_filtered_out() const;
|
|
void num_removed_func_syms_filtered_out(size_t);
|
|
|
|
size_t num_func_syms_added() const;
|
|
void num_func_syms_added(size_t);
|
|
|
|
size_t num_added_func_syms_filtered_out() const;
|
|
void num_added_func_syms_filtered_out(size_t);
|
|
|
|
size_t net_num_removed_func_syms() const;
|
|
size_t net_num_added_func_syms() const;
|
|
|
|
size_t num_var_syms_removed() const;
|
|
void num_var_syms_removed(size_t);
|
|
|
|
size_t num_removed_var_syms_filtered_out() const;
|
|
void num_removed_var_syms_filtered_out(size_t);
|
|
|
|
size_t num_var_syms_added() const;
|
|
void num_var_syms_added(size_t);
|
|
|
|
size_t num_added_var_syms_filtered_out() const;
|
|
void num_added_var_syms_filtered_out(size_t);
|
|
|
|
size_t net_num_removed_var_syms() const;
|
|
size_t net_num_added_var_syms() const;
|
|
|
|
size_t num_leaf_changes() const;
|
|
void num_leaf_changes(size_t);
|
|
|
|
size_t num_leaf_changes_filtered_out() const;
|
|
void num_leaf_changes_filtered_out(size_t);
|
|
|
|
size_t net_num_leaf_changes() const;
|
|
|
|
size_t num_leaf_type_changes() const;
|
|
void num_leaf_type_changes(size_t);
|
|
|
|
size_t num_leaf_type_changes_filtered_out() const;
|
|
void num_leaf_type_changes_filtered_out(size_t);
|
|
size_t net_num_leaf_type_changes() const;
|
|
|
|
size_t num_leaf_func_changes() const;
|
|
void num_leaf_func_changes(size_t);
|
|
|
|
size_t num_leaf_func_changes_filtered_out() const;
|
|
void num_leaf_func_changes_filtered_out(size_t);
|
|
size_t net_num_leaf_func_changes() const;
|
|
|
|
size_t num_leaf_var_changes() const;
|
|
void num_leaf_var_changes(size_t);
|
|
|
|
size_t num_leaf_var_changes_filtered_out() const;
|
|
void num_leaf_var_changes_filtered_out(size_t);
|
|
size_t net_num_leaf_var_changes() const;
|
|
|
|
size_t num_added_unreachable_types() const;
|
|
void num_added_unreachable_types(size_t);
|
|
|
|
size_t num_added_unreachable_types_filtered_out() const;
|
|
void num_added_unreachable_types_filtered_out(size_t);
|
|
size_t net_num_added_unreachable_types() const;
|
|
|
|
size_t num_removed_unreachable_types() const;
|
|
void num_removed_unreachable_types(size_t);
|
|
|
|
size_t num_removed_unreachable_types_filtered_out() const;
|
|
void num_removed_unreachable_types_filtered_out(size_t);
|
|
size_t net_num_removed_unreachable_types() const;
|
|
|
|
size_t num_changed_unreachable_types() const;
|
|
void num_changed_unreachable_types(size_t);
|
|
|
|
size_t num_changed_unreachable_types_filtered_out() const;
|
|
void num_changed_unreachable_types_filtered_out(size_t);
|
|
size_t net_num_changed_unreachable_types() const;
|
|
|
|
}; // end class corpus_diff::diff_stats
|
|
|
|
/// The base class for the node visitors. These are the types used to
|
|
/// visit each node traversed by the diff_traversable_base::traverse() method.
|
|
class diff_node_visitor : public node_visitor_base
|
|
{
|
|
protected:
|
|
struct priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
public:
|
|
|
|
diff_node_visitor();
|
|
|
|
virtual ~diff_node_visitor();
|
|
|
|
diff_node_visitor(visiting_kind k);
|
|
|
|
visiting_kind
|
|
get_visiting_kind() const;
|
|
|
|
void
|
|
set_visiting_kind(visiting_kind v);
|
|
|
|
void
|
|
or_visiting_kind(visiting_kind v);
|
|
|
|
void
|
|
set_current_topmost_iface_diff(diff*);
|
|
|
|
diff*
|
|
get_current_topmost_iface_diff() const;
|
|
|
|
virtual void
|
|
visit_begin(diff*);
|
|
|
|
virtual void
|
|
visit_begin(corpus_diff*);
|
|
|
|
virtual void
|
|
visit_end(diff*);
|
|
|
|
virtual void
|
|
visit_end(corpus_diff*);
|
|
|
|
virtual bool
|
|
visit(diff*, bool);
|
|
|
|
virtual bool
|
|
visit(distinct_diff*, bool);
|
|
|
|
virtual bool
|
|
visit(var_diff*, bool);
|
|
|
|
virtual bool
|
|
visit(pointer_diff*, bool);
|
|
|
|
virtual bool
|
|
visit(reference_diff*, bool);
|
|
|
|
virtual bool
|
|
visit(qualified_type_diff*, bool);
|
|
|
|
virtual bool
|
|
visit(enum_diff*, bool);
|
|
|
|
virtual bool
|
|
visit(class_diff*, bool);
|
|
|
|
virtual bool
|
|
visit(base_diff*, bool);
|
|
|
|
virtual bool
|
|
visit(scope_diff*, bool);
|
|
|
|
virtual bool
|
|
visit(function_decl_diff*, bool);
|
|
|
|
virtual bool
|
|
visit(type_decl_diff*, bool);
|
|
|
|
virtual bool
|
|
visit(typedef_diff*, bool);
|
|
|
|
virtual bool
|
|
visit(translation_unit_diff*, bool);
|
|
|
|
virtual bool
|
|
visit(corpus_diff*, bool);
|
|
}; // end struct diff_node_visitor
|
|
|
|
void
|
|
propagate_categories(diff* diff_tree);
|
|
|
|
void
|
|
propagate_categories(diff_sptr diff_tree);
|
|
|
|
void
|
|
propagate_categories(corpus_diff* diff_tree);
|
|
|
|
void
|
|
propagate_categories(corpus_diff_sptr diff_tree);
|
|
|
|
void
|
|
apply_suppressions(diff* diff_tree);
|
|
|
|
void
|
|
apply_suppressions(const corpus_diff* diff_tree);
|
|
|
|
void
|
|
apply_suppressions(diff_sptr diff_tree);
|
|
|
|
void
|
|
apply_suppressions(corpus_diff_sptr diff_tree);
|
|
|
|
void
|
|
print_diff_tree(diff* diff_tree, std::ostream&);
|
|
|
|
void
|
|
print_diff_tree(corpus_diff* diff_tree,
|
|
std::ostream&);
|
|
|
|
void
|
|
print_diff_tree(diff_sptr diff_tree,
|
|
std::ostream&);
|
|
|
|
void
|
|
print_diff_tree(corpus_diff_sptr diff_tree,
|
|
std::ostream&);
|
|
|
|
void
|
|
categorize_redundancy(diff* diff_tree);
|
|
|
|
void
|
|
categorize_redundancy(diff_sptr diff_tree);
|
|
|
|
void
|
|
categorize_redundancy(corpus_diff* diff_tree);
|
|
|
|
void
|
|
categorize_redundancy(corpus_diff_sptr diff_tree);
|
|
|
|
void
|
|
clear_redundancy_categorization(diff* diff_tree);
|
|
|
|
void
|
|
clear_redundancy_categorization(diff_sptr diff_tree);
|
|
|
|
void
|
|
clear_redundancy_categorization(corpus_diff* diff_tree);
|
|
|
|
void
|
|
clear_redundancy_categorization(corpus_diff_sptr diff_tree);
|
|
|
|
void
|
|
apply_filters(corpus_diff_sptr diff_tree);
|
|
|
|
bool
|
|
is_diff_of_variadic_parameter_type(const diff*);
|
|
|
|
bool
|
|
is_diff_of_variadic_parameter_type(const diff_sptr&);
|
|
|
|
bool
|
|
is_diff_of_variadic_parameter(const diff*);
|
|
|
|
bool
|
|
is_diff_of_variadic_parameter(const diff_sptr&);
|
|
|
|
const type_diff_base*
|
|
is_type_diff(const diff* diff);
|
|
|
|
const decl_diff_base*
|
|
is_decl_diff(const diff* diff);
|
|
|
|
const type_decl_diff*
|
|
is_diff_of_basic_type(const diff* diff);
|
|
|
|
const type_decl_diff*
|
|
is_diff_of_basic_type(const diff* diff, bool);
|
|
|
|
const class_or_union_diff*
|
|
is_diff_of_class_or_union_type(const diff *d);
|
|
|
|
bool
|
|
has_basic_type_change_only(const diff* diff);
|
|
|
|
const enum_diff*
|
|
is_enum_diff(const diff *diff);
|
|
|
|
const class_diff*
|
|
is_class_diff(const diff* diff);
|
|
|
|
const union_diff*
|
|
is_union_diff(const diff* diff);
|
|
|
|
const class_or_union_diff*
|
|
is_class_or_union_diff(const diff* d);
|
|
|
|
const class_or_union_diff*
|
|
is_anonymous_class_or_union_diff(const diff* d);
|
|
|
|
const array_diff*
|
|
is_array_diff(const diff* diff);
|
|
|
|
const function_type_diff*
|
|
is_function_type_diff(const diff* diff);
|
|
|
|
const function_type_diff*
|
|
is_function_type_diff_with_local_changes(const diff* diff);
|
|
|
|
const typedef_diff*
|
|
is_typedef_diff(const diff *diff);
|
|
|
|
const var_diff*
|
|
is_var_diff(const diff* diff);
|
|
|
|
const function_decl_diff*
|
|
is_function_decl_diff(const diff* diff);
|
|
|
|
const pointer_diff*
|
|
is_pointer_diff(const diff* diff);
|
|
|
|
const reference_diff*
|
|
is_reference_diff(const diff* diff);
|
|
|
|
const qualified_type_diff*
|
|
is_qualified_type_diff(const diff* diff);
|
|
|
|
const fn_parm_diff*
|
|
is_fn_parm_diff(const diff* diff);
|
|
|
|
const base_diff*
|
|
is_base_diff(const diff* diff);
|
|
|
|
const distinct_diff*
|
|
is_distinct_diff(const diff *diff);
|
|
|
|
bool
|
|
is_child_node_of_function_parm_diff(const diff* diff);
|
|
|
|
bool
|
|
is_child_node_of_base_diff(const diff* diff);
|
|
|
|
const corpus_diff*
|
|
is_corpus_diff(const diff* diff);
|
|
|
|
const diff*
|
|
peel_typedef_diff(const diff* dif);
|
|
|
|
const diff*
|
|
peel_pointer_diff(const diff* dif);
|
|
|
|
const diff*
|
|
peel_reference_diff(const diff* dif);
|
|
|
|
const diff*
|
|
peel_qualified_diff(const diff* dif);
|
|
|
|
const diff*
|
|
peel_fn_parm_diff(const diff* dif);
|
|
|
|
const diff*
|
|
peel_pointer_or_qualified_type_diff(const diff* dif);
|
|
|
|
const diff*
|
|
peel_typedef_or_qualified_type_diff(const diff* dif);
|
|
|
|
const diff*
|
|
peel_typedef_qualified_type_or_parameter_diff(const diff *dif);
|
|
}// end namespace comparison
|
|
|
|
}// end namespace abigail
|
|
|
|
#endif //__ABG_COMPARISON_H__
|