[applied] Bug 31642 - Categorize incompatible changes on functions and variables

Message ID 87o6xn48d1.fsf@redhat.com
State New
Headers
Series [applied] Bug 31642 - Categorize incompatible changes on functions and variables |

Commit Message

Dodji Seketeli March 27, 2025, 12:36 a.m. UTC
  Hello,

The function corpus_diff::has_incompatible_changes doesn't take into
account functions and variables with local and harmful changes.

Functions and variables with such changes should be accounted for as
having ABI incompatible changes.  As a result, abidiff and abipkgdiff
would automatically set the ABIDIFF_ABI_INCOMPATIBLE_CHANGE bit in the
bit-field returned in the exit code.

Note that a local change to a function/variable type is a change of
the type itself.  Changes of sub-types that are reachable through a
pointer/reference/array are not considered local to the type itself.
A harmful local change to a type changes either its size or its
layout.

Today, corpus_diff::has_incompatible_changes does not account for
functions and variables that have /local/ harmful changes to their
types.

This patch fixes that.

It augments the corpus_diff::diff_stats type with new properties
num_func_with_incompatible_changes and
num_var_with_incompatible_changes which are set in
corpus_diff::priv::apply_filters_and_compute_diff_stats when detecting
function and variable diff nodes that carry local harmful changes.

The patch introduces the function has_fn_return_or_parm_harmful_change
to detect when a function declaration has a direct (i.e, not through a
pointer type) harmful return or parameter type change as well as
has_fn_with_virtual_offset_change which detects when a function
declaration has a virtual offset change.  These two functions are used
together to detect functions that have local harmful changes.

The patch also introduces has_var_harmful_local_change to detect when
a variable has a local harmful change.

Note that the three newly functions above are used by the new function
has_incompatible_fn_or_var_change to detect if a diff node carries an
incompatible change to a function or a variable.

Note also that these functions are used in
corpus_diff::priv::apply_filters_and_compute_diff_stats to populate
the new corpus_diff::incompatible_changed_functions and
corpus_diff::incompatible_changed_variables properties containing
incompatible changed functions and variables of a given corpus.

The patch also alters the default and leaf reporter component to
report incompatible changes to functions and variables.

The patch thus adds new regression tests and adjust a lot of existing
ones.

	* include/abg-comp-filter.h (has_void_to_non_void_change)
	(has_fn_return_or_parm_harmful_change)
	(has_var_harmful_local_change, has_fn_with_virtual_offset_change)
	(has_incompatible_fn_or_var_change): Declared new functions.
	* include/abg-comparison.h (is_harmful_category): Declare new
	function.
	(corpus_diff::{changed_functions, changed_function_sorted}):
	Consitify declarations.
	(corpus_diff::{incompatible_changed_functions,
	incompatible_changed_variables}): Declare new member functions.
	(corpus_diff::diff_stats::{num_func_with_local_harmful_changes,
	num_func_with_incompatible_changes, void
	num_var_with_local_harmful_changes, void
	num_var_with_incompatible_changes,
	net_num_non_incompatible_var_changed}): Declare new accessors.
	* include/abg-ir.h (change_kind::LOCAL_TYPE_CHANGE_KIND): Fix the
	value of this enumerator.
	(change_kind::{LOCAL_NON_TYPE_CHANGE,SUBTYPE_CHANGE_KIND}_KIND):
	Adjust values of these enumerator as a consequence.
	* src/abg-comp-filter.cc
	(has_harmful_change, has_harmful_enum_change)
	(has_harmless_enum_change, is_void_to_non_void): Define new static
	functions.
	(is_1_dim_unknown_size_array_change): Factorize this function out
	of ...
	(is_var_1_dim_unknown_size_array_change): ... this.
	(has_fn_parm_type_cv_qual_change): Adjust to the use of
	type_diff_has_typedef_cv_qual_change_only.
	(has_added_or_removed_function_parameters): Fix indentation.
	(has_fn_return_or_parm_harmful_change)
	(has_fn_with_virtual_offset_change, has_var_harmful_local_change)
	(has_var_harmful_local_change, has_incompatible_fn_or_var_change)
	(has_void_to_non_void_change): Define new functions.
	(categorize_harmful_diff_node): Improve documentation.  Use the
	new has_harmful_change which is a factorization of this function.
	* src/abg-comparison-priv.h (is_less_than): Declare new function
	that takes a pair of decl_diff_base.  Remove the previous one that was
	taking a pair of function_decl_diff.
	(corpus_diff::priv::{incompatible_changed_fns_,
	incompatible_changed_vars_}): Define new member variables.
	(var_diff_sptr_comp::operator()): Adjust, make this use
	is_less_than.
	(corpus_diff::diff_stats::priv::{num_func_with_local_harmful_changes,
	num_func_with_incompatible_changes,
	num_var_with_local_harmful_changes,
	num_var_with_incompatible_changes}): Define new member variables.
	(corpus_diff::diff_stats::priv::priv): Initialize these new
	member variables.
	(sort_function_decl_diffs, sort_var_diffs): Declare new functions.
	* src/abg-comparison.cc (get_symbol): Define new static function.
	(is_less_than): Take decl_diff_base instead of function_decl_diff.
	Adjust to use the new get_symbol function.  Update comments.  Add
	a new overload.
	(sort_function_decl_diffs, sort_var_diffs, is_harmful_category):
	Define new functions.
	(corpus_diff::diff_stats::{num_func_with_local_harmful_changes,
	num_var_with_local_harmful_changes,
	num_func_with_incompatible_changes,
	num_var_with_incompatible_changes,
	net_num_non_incompatible_func_changed,
	net_num_non_incompatible_var_changed}): Define new member
	functions.
	(corpus_diff::{changed_functions, changed_functions_sorted}):
	Constify this member function.
	(corpus_diff::{incompatible_changed_functions,
	incompatible_changed_variables}): Likewise.
	(corpus_diff::priv::apply_filters_and_compute_diff_stats): Count
	function diff node carrying virtual member changes and return or
	parameter types harmful changes as functions with incompatible
	changes.  Likewise, count variable diff node carrying local
	harmful changes as variables with incompatible changes.
	(corpus_diff::has_incompatible_changes): Take into account
	functions with virtual offset changes or with local harmful
	changes, as well as variables with incompatible changes.
	(redundancy_marking_visitor::visit_end): If the diff node has
	local /harmful/ changes then it won't inherit redundancy from its
	children nodes.
	* src/abg-default-reporter.cc (emit_changed_fn_report)
	(emit_changed_var_report): Define new static functions.
	(default_reporter::report): In the overload for enum_diff, support
	emitting a report about changed enumerator name.  In the overload
	for corpus_diff, emit a new section for incompatible changes to
	functions and variables.  Use the new emit_changed_fn_report and
	emit_changed_var_report which have been factorized out of this
	function anyway.
	* src/abg-ir.cc (textually_equals): Add a change_kind* parameter
	to tell the kind of change there are between two ELF symbols if
	they are different.
	(var_equals_modulo_types): Adjust to use textually_equals for a
	more fined grained change_kind when it comes to ELF symbol
	changes.
	(decl_name_changed, integral_type_has_harmless_name_change):
	Define new functions.
	* src/abg-leaf-reporter.cc (emit_changed_var_report): Define new
	static function.
	(leaf_reporter::report): In the overload for corpus_diff, use the
	new emit_changed_var_report as it's was factorized from there.
	* src/abg-reporter-priv.cc (represent): In the overload for
	var_diff, adjust the call to filtering::has_harmless_name_change.
	(report_name_size_and_alignment_changes): Likewise.
	* tests/data/test-abidiff-exit/incompatible-changes/1/report0.txt:
	New test input.
	* tests/data/test-abidiff-exit/incompatible-changes/1/test-1-v{0,1}.{cc,o}:
	Likewise.
	* tests/data/test-abidiff-exit/test-changed-var-1-report-1.txt:
	Likewise.
	* tests/data/test-abidiff-exit/test-changed-var-1-v{0,1}.cc:
	Likewise.
	* tests/data/test-abidiff-exit/test-changed-var-1-v{0,1}.o:
	Likewise.
	* tests/data/test-abidiff-exit/test-enumerator-changes{2,3,4,5,6}-report-{1,2}.txt:
	Likewise.
	* tests/data/test-abidiff-exit/test-enumerator-changes{2,3,4,5,6}-v{0,1}.cc:
	Likewise.
	* tests/data/test-abidiff-exit/test-enumerator-changes{2,3,4,5,6}-v{0,1}.o:
	Likewise.
	* tests/data/Makefile.am: Add the new test material above to
	source distribution.
	* tests/data/test-abicompat/test7-fn-changed-report-0.1.txt:
	Adjust.
	* tests/data/test-abicompat/test7-fn-changed-report-0.txt:
	Likewise.
	* tests/data/test-abidiff-exit/PR30048-test-2-report-1.txt:
	Likewise.
	* tests/data/test-abidiff-exit/PR30048-test-report-0.txt:
	Likewise.
	* tests/data/test-abidiff-exit/PR31513/reported/PR31513-reported-report-1.txt:
	Likewise.
	* tests/data/test-abidiff-exit/ada-subrange/test1-ada-subrange/test1-ada-subrange-report-1.txt:
	Likewise.
	* tests/data/test-abidiff-exit/ada-subrange/test2-ada-subrange-redundant/test2-ada-subrange-redundant-report-1.txt:
	Likewise.
	* tests/data/test-abidiff-exit/btf/test0-report-1.txt: Likewise.
	* tests/data/test-abidiff-exit/btf/test0-report-2.txt: Likewise.
	* tests/data/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr1-output-1.txt:
	Likewise.
	* tests/data/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr2-output-1.txt:
	Likewise.
	* tests/data/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr3-output-1.txt:
	Likewise.
	* tests/data/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr4-output-1.txt:
	Likewise.
	* tests/data/test-abidiff-exit/test-crc-report.txt: Likewise.
	* tests/data/test-abidiff-exit/test-ld-2.28-210.so--ld-2.28-211.so.txt:
	Likewise.
	* tests/data/test-abidiff-exit/test-leaf-more-report.txt:
	Likewise.
	* tests/data/test-abidiff-exit/test-leaf-stats-report.txt:
	Likewise.
	* tests/data/test-abidiff-exit/test-net-change-report0.txt:
	Likewise.
	* tests/data/test-abidiff-exit/test-net-change-report2.txt:
	Likewise.
	* tests/data/test-abidiff-exit/test1-voffset-change-report0.txt:
	Likewise.
	* tests/data/test-abidiff/test-crc-report-0-1.txt: Likewise.
	* tests/data/test-abidiff/test-crc-report-1-0.txt: Likewise.
	* tests/data/test-abidiff/test-crc-report-1-2.txt: Likewise.
	* tests/data/test-abidiff/test-namespace-report.txt: Likewise.
	* tests/data/test-annotate/libtest23.so.abi: Likewise.
	* tests/data/test-annotate/libtest24-drop-fns-2.so.abi: Likewise.
	* tests/data/test-annotate/libtest24-drop-fns.so.abi: Likewise.
	* tests/data/test-annotate/test15-pr18892.so.abi: Likewise.
	* tests/data/test-annotate/test17-pr19027.so.abi: Likewise.
	* tests/data/test-annotate/test18-pr19037-libvtkRenderingLIC-6.1.so.abi:
	Likewise.
	* tests/data/test-annotate/test19-pr19023-libtcmalloc_and_profiler.so.abi:
	Likewise.
	* tests/data/test-annotate/test20-pr19025-libvtkParallelCore-6.1.so.abi:
	Likewise.
	* tests/data/test-annotate/test21-pr19092.so.abi: Likewise.
	* tests/data/test-diff-dwarf/test20-add-fn-parm-report-0.txt:
	Likewise.
	* tests/data/test-diff-dwarf/test24-added-fn-parms-report-0.txt:
	Likewise.
	* tests/data/test-diff-dwarf/test25-removed-fn-parms-report-0.txt:
	Likewise.
	* tests/data/test-diff-dwarf/test26-added-parms-before-variadic-report.txt:
	Likewise.
	* tests/data/test-diff-dwarf/test28-vtable-changes-report-0.txt:
	Likewise.
	* tests/data/test-diff-dwarf/test30-vtable-changes-report-0.txt:
	Likewise.
	* tests/data/test-diff-dwarf/test31-vtable-changes-report-0.txt:
	Likewise.
	* tests/data/test-diff-dwarf/test32-fnptr-changes-report-0.txt:
	Likewise.
	* tests/data/test-diff-dwarf/test33-fnref-changes-report-0.txt:
	Likewise.
	* tests/data/test-diff-dwarf/test35-pr19173-libfoo-long-clang-report-0.txt:
	Likewise.
	* tests/data/test-diff-dwarf/test35-pr19173-libfoo-long-gcc-report-0.txt:
	Likewise.
	* tests/data/test-diff-dwarf/test42-PR21296-clanggcc-report0.txt:
	Likewise.
	* tests/data/test-diff-dwarf/test46-rust-report-0.txt: Likewise.
	* tests/data/test-diff-dwarf/test9-report.txt: Likewise.
	* tests/data/test-diff-filter/libtest45-basic-type-change-report-0.txt:
	Likewise.
	* tests/data/test-diff-filter/test-PR27569-report-0.txt: Likewise.
	* tests/data/test-diff-filter/test-PR28013-fn-variadic.c.report.txt:
	Likewise.
	* tests/data/test-diff-filter/test15-0-report.txt: Likewise.
	* tests/data/test-diff-filter/test30-pr18904-rvalueref-report0.txt:
	Likewise.
	* tests/data/test-diff-filter/test30-pr18904-rvalueref-report1.txt:
	Likewise.
	* tests/data/test-diff-filter/test30-pr18904-rvalueref-report2.txt:
	Likewise.
	* tests/data/test-diff-filter/test35-pr18754-no-added-syms-report-0.txt:
	Likewise.
	* tests/data/test-diff-filter/test35-pr18754-no-added-syms-report-1.txt:
	Likewise.
	* tests/data/test-diff-filter/test41-report-0.txt: Likewise.
	* tests/data/test-diff-filter/test5-2-report.txt: Likewise.
	* tests/data/test-diff-filter/test6-report.txt: Likewise.
	* tests/data/test-diff-filter/test7-report.txt: Likewise.
	* tests/data/test-diff-pkg/libcdio-0.94-1.fc26.x86_64--libcdio-0.94-2.fc26.x86_64-report.1.txt:
	Likewise.
	* tests/data/test-diff-pkg/nss-3.23.0-1.0.fc23.x86_64-report-0.txt:
	Likewise.
	* tests/data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-0.txt:
	Likewise.
	* tests/data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-1.txt:
	Likewise.
	* tests/data/test-diff-suppr/PR31646/test-PR31646-result-1.txt:
	Likewise.
	* tests/data/test-diff-suppr/PR31646/test-PR31646-result-3.txt:
	Likewise.
	* tests/data/test-diff-suppr/test-has-data-member-inserted-between-1-report-2.txt:
	Likewise.
	* tests/data/test-diff-suppr/test-has-data-member-inserted-between-1-report-3.txt:
	Likewise.
	* tests/data/test-diff-suppr/test-has-data-member-inserted-between-1-report-4.txt:
	Likewise.
	* tests/data/test-diff-suppr/test-has-strict-flexible-array-data-member-conversion-report-1.txt:
	Likewise.
	* tests/data/test-diff-suppr/test-has-strict-flexible-array-data-member-conversion-report-2.txt:
	Likewise.
	* tests/data/test-diff-suppr/test10-changed-parm-c-report-0.txt:
	Likewise.
	* tests/data/test-diff-suppr/test30-report-0.txt: Likewise.
	* tests/data/test-read-dwarf/PR22015-libboost_iostreams.so.abi:
	Likewise.
	* tests/data/test-read-dwarf/PR22122-libftdc.so.abi: Likewise.
	* tests/data/test-read-dwarf/libtest23.so.abi: Likewise.
	* tests/data/test-read-dwarf/libtest24-drop-fns-2.so.abi:
	Likewise.
	* tests/data/test-read-dwarf/libtest24-drop-fns.so.abi: Likewise.
	* tests/data/test-read-dwarf/test-libandroid.so.abi: Likewise.
	* tests/data/test-read-dwarf/test10-pr18818-gcc.so.abi: Likewise.
	* tests/data/test-read-dwarf/test11-pr18828.so.abi: Likewise.
	* tests/data/test-read-dwarf/test12-pr18844.so.abi: Likewise.
	* tests/data/test-read-dwarf/test15-pr18892.so.abi: Likewise.
	* tests/data/test-read-dwarf/test16-pr18904.so.abi: Likewise.
	* tests/data/test-read-dwarf/test17-pr19027.so.abi: Likewise.
	* tests/data/test-read-dwarf/test18-pr19037-libvtkRenderingLIC-6.1.so.abi:
	Likewise.
	* tests/data/test-read-dwarf/test19-pr19023-libtcmalloc_and_profiler.so.abi:
	Likewise.
	* tests/data/test-read-dwarf/test20-pr19025-libvtkParallelCore-6.1.so.abi:
	Likewise.
	* tests/data/test-read-dwarf/test21-pr19092.so.abi: Likewise.
	* tests/data/test-read-dwarf/test22-pr19097-libstdc++.so.6.0.17.so.abi:
	Likewise.
	* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Likewise.
	* tests/test-abicompat.cc: Likewise.
	* tests/test-abidiff-exit.cc: Likewise.
	* tests/data/test-diff-suppr/test-has-strict-flexible-array-data-member-conversion-v{0,1}.o:
	Recompile these using gcc -g -c.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
libabigail@sourceware.org
---
 include/abg-comp-filter.h                     |  27 ++
 include/abg-comparison.h                      |  35 +-
 include/abg-ir.h                              |   6 +-
 src/abg-comp-filter.cc                        | 343 ++++++++++++++++--
 src/abg-comparison-priv.h                     |  34 +-
 src/abg-comparison.cc                         | 313 ++++++++++++++--
 src/abg-default-reporter.cc                   | 271 +++++++++-----
 src/abg-ir.cc                                 |  31 +-
 src/abg-leaf-reporter.cc                      |  83 +++--
 tests/data/Makefile.am                        |  36 ++
 .../test7-fn-changed-report-0.1.txt           |   8 +-
 .../test7-fn-changed-report-0.txt             |   8 +-
 .../PR30048-test-2-report-1.txt               |  40 +-
 .../PR30048-test-report-0.txt                 |  12 +-
 .../test1-ada-subrange-report-1.txt           |   6 +-
 .../test2-ada-subrange-redundant-report-1.txt |  20 +-
 .../test-abidiff-exit/btf/test0-report-1.txt  |   4 +-
 .../test-abidiff-exit/btf/test0-report-2.txt  |   4 +-
 .../incompatible-changes/1/report0.txt        |  14 +
 .../incompatible-changes/1/test-1-v0.cc       |  14 +
 .../incompatible-changes/1/test-1-v0.o        | Bin 0 -> 3152 bytes
 .../incompatible-changes/1/test-1-v1.cc       |  15 +
 .../incompatible-changes/1/test-1-v1.o        | Bin 0 -> 3248 bytes
 .../test-ptr-to-mbr1-output-1.txt             |   2 +-
 .../test-ptr-to-mbr2-output-1.txt             |   2 +-
 .../test-ptr-to-mbr3-output-1.txt             |   2 +-
 .../test-ptr-to-mbr4-output-1.txt             |   2 +-
 .../test-changed-var-1-report-1.txt           |  24 ++
 .../test-changed-var-1-v0.cc                  |  15 +
 .../test-abidiff-exit/test-changed-var-1-v0.o | Bin 0 -> 2712 bytes
 .../test-changed-var-1-v1.cc                  |  16 +
 .../test-abidiff-exit/test-changed-var-1-v1.o | Bin 0 -> 2872 bytes
 .../test-abidiff-exit/test-crc-report.txt     |   6 +-
 .../test-enumerator-changes2-report-1.txt     |   3 +
 .../test-enumerator-changes2-v0.cc            |  15 +
 .../test-enumerator-changes2-v0.o             | Bin 0 -> 3304 bytes
 .../test-enumerator-changes2-v1.cc            |  15 +
 .../test-enumerator-changes2-v1.o             | Bin 0 -> 3344 bytes
 .../test-enumerator-changes3-report-1.txt     |   3 +
 .../test-enumerator-changes3-report-2.txt     |  18 +
 .../test-enumerator-changes3-v0.cc            |  15 +
 .../test-enumerator-changes3-v0.o             | Bin 0 -> 3304 bytes
 .../test-enumerator-changes3-v1.cc            |  17 +
 .../test-enumerator-changes3-v1.o             | Bin 0 -> 3440 bytes
 .../test-enumerator-changes4-report-1.txt     |  13 +
 .../test-enumerator-changes4-v0.cc            |  17 +
 .../test-enumerator-changes4-v0.o             | Bin 0 -> 3440 bytes
 .../test-enumerator-changes4-v1.cc            |  18 +
 .../test-enumerator-changes4-v1.o             | Bin 0 -> 3488 bytes
 .../test-enumerator-changes5-report-1.txt     |  14 +
 .../test-enumerator-changes5-v0.cc            |  18 +
 .../test-enumerator-changes5-v0.o             | Bin 0 -> 3488 bytes
 .../test-enumerator-changes5-v1.cc            |  16 +
 .../test-enumerator-changes5-v1.o             | Bin 0 -> 3392 bytes
 .../test-enumerator-changes6-report-1.txt     |  11 +
 .../test-enumerator-changes6-v0.cc            |  18 +
 .../test-enumerator-changes6-v0.o             | Bin 0 -> 3488 bytes
 .../test-enumerator-changes6-v1.cc            |  17 +
 .../test-enumerator-changes6-v1.o             | Bin 0 -> 3440 bytes
 .../test-ld-2.28-210.so--ld-2.28-211.so.txt   |   2 +-
 .../test-leaf-more-report.txt                 |   2 +-
 .../test-leaf-stats-report.txt                |   2 +-
 .../test-net-change-report0.txt               |  24 +-
 .../test-net-change-report2.txt               |   2 +-
 .../test1-voffset-change-report0.txt          |  13 +-
 .../data/test-abidiff/test-crc-report-0-1.txt |   6 +-
 .../data/test-abidiff/test-crc-report-1-0.txt |   6 +-
 .../data/test-abidiff/test-crc-report-1-2.txt |   4 +-
 .../test-abidiff/test-namespace-report.txt    |   2 +-
 .../test20-add-fn-parm-report-0.txt           |   4 +-
 .../test24-added-fn-parms-report-0.txt        |   4 +-
 .../test25-removed-fn-parms-report-0.txt      |   4 +-
 ...t26-added-parms-before-variadic-report.txt |  10 +-
 .../test28-vtable-changes-report-0.txt        |  18 +-
 .../test30-vtable-changes-report-0.txt        |  22 +-
 .../test31-vtable-changes-report-0.txt        |   6 +-
 .../test32-fnptr-changes-report-0.txt         |  18 +-
 .../test33-fnref-changes-report-0.txt         |  18 +-
 ...t35-pr19173-libfoo-long-clang-report-0.txt |   2 +-
 ...est35-pr19173-libfoo-long-gcc-report-0.txt |   2 +-
 .../test-diff-dwarf/test46-rust-report-0.txt  |   4 +-
 tests/data/test-diff-dwarf/test9-report.txt   |  10 +-
 .../libtest45-basic-type-change-report-0.txt  |  12 +-
 .../test-PR27569-report-0.txt                 |   4 +-
 .../test-PR28013-fn-variadic.c.report.txt     |  12 +-
 .../data/test-diff-filter/test15-0-report.txt |   4 +
 .../test30-pr18904-rvalueref-report0.txt      |  18 +-
 .../test30-pr18904-rvalueref-report1.txt      |  18 +-
 .../test30-pr18904-rvalueref-report2.txt      |  18 +-
 .../test35-pr18754-no-added-syms-report-0.txt |   2 +-
 .../test35-pr18754-no-added-syms-report-1.txt |   2 +-
 .../data/test-diff-filter/test41-report-0.txt |  94 ++---
 .../data/test-diff-filter/test5-2-report.txt  |  21 +-
 tests/data/test-diff-filter/test6-report.txt  |   4 +-
 tests/data/test-diff-filter/test7-report.txt  |   4 +-
 .../nss-3.23.0-1.0.fc23.x86_64-report-0.txt   |   2 +-
 .../PR31646/test-PR31646-result-1.txt         |   4 +-
 .../PR31646/test-PR31646-result-3.txt         |   4 +-
 ...ata-member-inserted-between-1-report-2.txt |   2 +-
 ...ata-member-inserted-between-1-report-3.txt |   2 +-
 ...ata-member-inserted-between-1-report-4.txt |   2 +-
 ...-array-data-member-conversion-report-1.txt |   4 +-
 ...-array-data-member-conversion-report-2.txt |  26 +-
 ...flexible-array-data-member-conversion-v0.o | Bin 2440 -> 2856 bytes
 ...flexible-array-data-member-conversion-v1.o | Bin 2432 -> 2856 bytes
 .../test10-changed-parm-c-report-0.txt        |   4 +-
 .../data/test-diff-suppr/test30-report-0.txt  |  12 +-
 tests/test-abicompat.cc                       |   6 +-
 tests/test-abidiff-exit.cc                    | 170 ++++++++-
 109 files changed, 1786 insertions(+), 471 deletions(-)
 create mode 100644 tests/data/test-abidiff-exit/incompatible-changes/1/report0.txt
 create mode 100644 tests/data/test-abidiff-exit/incompatible-changes/1/test-1-v0.cc
 create mode 100644 tests/data/test-abidiff-exit/incompatible-changes/1/test-1-v0.o
 create mode 100644 tests/data/test-abidiff-exit/incompatible-changes/1/test-1-v1.cc
 create mode 100644 tests/data/test-abidiff-exit/incompatible-changes/1/test-1-v1.o
 create mode 100644 tests/data/test-abidiff-exit/test-changed-var-1-report-1.txt
 create mode 100644 tests/data/test-abidiff-exit/test-changed-var-1-v0.cc
 create mode 100644 tests/data/test-abidiff-exit/test-changed-var-1-v0.o
 create mode 100644 tests/data/test-abidiff-exit/test-changed-var-1-v1.cc
 create mode 100644 tests/data/test-abidiff-exit/test-changed-var-1-v1.o
 create mode 100644 tests/data/test-abidiff-exit/test-enumerator-changes2-report-1.txt
 create mode 100644 tests/data/test-abidiff-exit/test-enumerator-changes2-v0.cc
 create mode 100644 tests/data/test-abidiff-exit/test-enumerator-changes2-v0.o
 create mode 100644 tests/data/test-abidiff-exit/test-enumerator-changes2-v1.cc
 create mode 100644 tests/data/test-abidiff-exit/test-enumerator-changes2-v1.o
 create mode 100644 tests/data/test-abidiff-exit/test-enumerator-changes3-report-1.txt
 create mode 100644 tests/data/test-abidiff-exit/test-enumerator-changes3-report-2.txt
 create mode 100644 tests/data/test-abidiff-exit/test-enumerator-changes3-v0.cc
 create mode 100644 tests/data/test-abidiff-exit/test-enumerator-changes3-v0.o
 create mode 100644 tests/data/test-abidiff-exit/test-enumerator-changes3-v1.cc
 create mode 100644 tests/data/test-abidiff-exit/test-enumerator-changes3-v1.o
 create mode 100644 tests/data/test-abidiff-exit/test-enumerator-changes4-report-1.txt
 create mode 100644 tests/data/test-abidiff-exit/test-enumerator-changes4-v0.cc
 create mode 100644 tests/data/test-abidiff-exit/test-enumerator-changes4-v0.o
 create mode 100644 tests/data/test-abidiff-exit/test-enumerator-changes4-v1.cc
 create mode 100644 tests/data/test-abidiff-exit/test-enumerator-changes4-v1.o
 create mode 100644 tests/data/test-abidiff-exit/test-enumerator-changes5-report-1.txt
 create mode 100644 tests/data/test-abidiff-exit/test-enumerator-changes5-v0.cc
 create mode 100644 tests/data/test-abidiff-exit/test-enumerator-changes5-v0.o
 create mode 100644 tests/data/test-abidiff-exit/test-enumerator-changes5-v1.cc
 create mode 100644 tests/data/test-abidiff-exit/test-enumerator-changes5-v1.o
 create mode 100644 tests/data/test-abidiff-exit/test-enumerator-changes6-report-1.txt
 create mode 100644 tests/data/test-abidiff-exit/test-enumerator-changes6-v0.cc
 create mode 100644 tests/data/test-abidiff-exit/test-enumerator-changes6-v0.o
 create mode 100644 tests/data/test-abidiff-exit/test-enumerator-changes6-v1.cc
 create mode 100644 tests/data/test-abidiff-exit/test-enumerator-changes6-v1.o

new file mode 100644
index 00000000..58d6de1c
index a88d96fb..37cdaf3c 100644
new file mode 100644
index 00000000..1330f790
index 2dbfa555..e2fc8d20 100644
new file mode 100644
index 00000000..fe50baa4
new file mode 100644
index 00000000..9666a8fd
new file mode 100644
index 00000000..a6722144
new file mode 100644
index 00000000..1994119a
new file mode 100644
index 00000000..aea70235
new file mode 100644
index 00000000..1727d579
new file mode 100644
index 00000000..6974b95e
new file mode 100644
index 00000000..25b7f125
new file mode 100644
index 00000000..8925eb48
index 4e6af07b..5272fa11 100644
index da8d4137ad4639af460b144ceb464a021fb843ce..6a582fcafc4101cf2e53282495ca79a0846fa57c 100644
GIT binary patch
literal 2856
zcmc&$UvC>l5TEtM@wL~aO)WwH0J&Bm+NyVsO`5cY1WSRo5eP-8ctNV7JA3V1vG1b0
zi<PKIyjJQfAD|CB@CkrNJ_=ue2YBTHX7+Z{?Z&B)^1w*DGxM97ow?newZH%T%Lg?f
zfJwkQywVs2_-Xc)+*M*1F2VxjDAz%_1gW@pl~GT%L6*UcsJovb;2eNxG)RIOnuOc<
zLdo@+dXknfOQvsdG-v|XZ4f*27=(B3J(3*K6^RA$!F<zm7OyT|cpISB6prh8_q~t3
zd!A@wsyT4nO5JSU^)Mj<^CnP#A3Sf}bFlDPAvT*7)wl+m$Xsoj$CS&)I-g#yUBc||
z;Har8)JH4HoI0q~!G&AMg%E$w&k>`&!GXe}+NPRVtevlxQNe?eJb;H^eeG|wSN(Q7
zyb~_@ou$t5(rWvje`8zr{YO!$4Z)q8elRZgQ@J*jsmzles!`tCT|2nD609r-la3z@
zVU(pqe?KjfVT$3j!>!$HEL;7o|1@b0ld?5R;wVmrQ8H?6ZGY5WS?;t-S(HVqAC-|3
zgMKm?1jYW|UJhgmcB3LFN=#V>RB{rJWDw<fbQn-fFqY$3=0Pt@Co(UREDa{@u=oEZ
zK1I#&aAV`Xe*@3t=6^U4b%<}6=+I~2&wr-5I8!?gZ?V2-c8r6TY2;LWb<E^|(Y%J$
z0o7p!Qi%?nIffD70Cv(8a^Tz)l>D)UrjP@3$Iwp@Sunm!y%6MeiW7W{;oPHVQ8ssh
zD<GV{wvL17V#R=P8tYnr%fht^R}7qU5wvRH=59W*aH^4LTrqVMxHf{gW~zm2B>Xx}
zNL=S(rNV8^8UID=Z43WP>kt-)<1&homwCl^St{j02_f}0gmF<on9ETV_GP?3+)2_w
zhBhTfah%J^Yvw4A(xH4kWR#?mLofx41n(%lmyO2~pQ$j-N*Q9~;Y$<szU4|!#jj#C
z^&syjFV<zj;_8t$uxlt2W_MoK@G(U@{zEj<{WvN9=)UVkY@N=}UXxtAG$BnYb~M|*
zbT4Sl?vY0&{H_!Irt$O03F5m<zj#DzIP5hE|CuJF?<#gQ+rC?9u`zP)XwWCcAltY4
zr*ORfm%1sqPO6_?HM{;kV)mMpZd-#Zq!?uT?x1bj{{5=+Khm+3pZeX-zlRvDxrD={
z=Q@!zL6kW^^Jf~f<NweO0Xyn-SY`g=g!n7^Lbh}qGmc~agN|oA^G*9gYXirzAL+*5
s9fn~`$8YI?3uvMD&)z@U(`l(*>if&@G%sxDUpOJ2AA}z{P;)!}Um#i%o&W#<

delta 856
zcmZ`%O>7cD6rS1tWee@P0a|O*C8h~zSU{_gS}g_*A!#&?sXs9hfiAE@*$TV0CtEKj
zp0vJr@W!#%p1c|lCLX<*UcGr#uO4(}8G2~qB=5cNd-LVJH$MllJ>yMscTYses~Dgn
znnIIklVBm>3Z`Kqz|3(?*F^#ri-hw#2+I_V<X9;OP!vR`=OKyi+$APchZIGoLA`^p
zHb=n<PkFGgju#?^#z$r&Q*nei1M`ZeEooOYY>+l##4D6kjDkjb5gH+M|JP+m;neIs
zQi4Nk#AEy?5+)wgv58?A3d=Ftq1m-}Q2ExnS<2<iymiUS!UsHOndz39ZVtR!qm$n1
zyPn<f+<toC_1#_zb%`_m-oR<~><yEgh*nEv{6YUh=84<hbluD|x8E6T)f#rD>(py?
zr&V*hFv*=sp>nCTWG2_^e$Vqq4bvC>faRX&3RZS8#l|?4W}wY~#vxeaqi{nw4VG|9
zT_!W@==Wa%_J!M6g6~4SGJb{-*;9#)Ur#5Pu5td+h@vQq<NSNZXW+URzq)v0mr?ZK
zM1Ga=HjDIXC*YlU_O0|-->~a`tJ-yXHnIW?FQqE{kcObhCLG8nehOdYygohpPUs^m
z5(Zt#sE3SsP*L)D0bVF8`Vmu3A1l8qaj{AmCKqI=H-jIE&_ht=`9z22iDj939EMEw
z4PL49iS7TWwz-l1994<CR7HDmLym+P+z%zALnbM(f)OGjrw^Uyj(GSKx~BeQ^S-9@
F`~w^gflUAa
  

Patch

diff --git a/include/abg-comp-filter.h b/include/abg-comp-filter.h
index 4aed57b8..b2d053e8 100644
--- a/include/abg-comp-filter.h
+++ b/include/abg-comp-filter.h
@@ -113,12 +113,39 @@  has_lvalue_reference_ness_change(const diff *d);
 bool
 has_void_ptr_to_ptr_change(const diff* d);
 
+bool
+has_void_to_non_void_change(const diff* d);
+
+bool
+has_void_to_non_void_change(const diff_sptr& d);
+
 bool
 has_harmless_enum_to_int_change(const diff* d);
 
 bool
 has_benign_array_of_unknown_size_change(const diff* dif);
 
+diff_category
+has_fn_return_or_parm_harmful_change(const diff* d);
+
+diff_category
+has_var_harmful_local_change(const diff* d);
+
+diff_category
+has_var_harmful_local_change(const diff_sptr& d);
+
+bool
+has_fn_with_virtual_offset_change(const diff* d);
+
+bool
+has_fn_with_virtual_offset_change(const diff_sptr& d);
+
+bool
+has_incompatible_fn_or_var_change(const diff* d);
+
+bool
+has_incompatible_fn_or_var_change(const diff_sptr& d);
+
 struct filter_base;
 /// Convenience typedef for a shared pointer to filter_base
 typedef shared_ptr<filter_base> filter_base_sptr;
diff --git a/include/abg-comparison.h b/include/abg-comparison.h
index 66c90f3e..450f7412 100644
--- a/include/abg-comparison.h
+++ b/include/abg-comparison.h
@@ -506,6 +506,9 @@  get_default_harmless_categories_bitmap();
 diff_category
 get_default_harmful_categories_bitmap();
 
+bool
+is_harmful_category(diff_category);
+
 ostream&
 operator<<(ostream& o, diff_category);
 
@@ -2535,10 +2538,16 @@  public:
   added_functions();
 
   const string_function_decl_diff_sptr_map&
-  changed_functions();
+  changed_functions() const;
+
+  const function_decl_diff_sptrs_type&
+  changed_functions_sorted() const;
 
   const function_decl_diff_sptrs_type&
-  changed_functions_sorted();
+  incompatible_changed_functions() const;
+
+  function_decl_diff_sptrs_type&
+  incompatible_changed_functions();
 
   const string_var_ptr_map&
   deleted_variables() const;
@@ -2552,6 +2561,12 @@  public:
   const var_diff_sptrs_type&
   changed_variables_sorted();
 
+  const var_diff_sptrs_type&
+  incompatible_changed_variables() const;
+
+  var_diff_sptrs_type&
+  incompatible_changed_variables();
+
   const string_elf_symbol_map&
   deleted_unrefed_function_symbols() const;
 
@@ -2690,8 +2705,22 @@  public:
   size_t num_func_with_virtual_offset_changes() const;
   void num_func_with_virtual_offset_changes(size_t);
 
+  size_t num_func_with_local_harmful_changes() const;
+  void num_func_with_local_harmful_changes(size_t);
+
+  size_t num_func_with_incompatible_changes() const;
+  void num_func_with_incompatible_changes(size_t);
+
+  size_t num_var_with_local_harmful_changes() const;
+  void num_var_with_local_harmful_changes(size_t);
+
+  size_t num_var_with_incompatible_changes() const;
+  void num_var_with_incompatible_changes(size_t);
+
   size_t net_num_func_changed() const;
 
+  size_t net_num_non_incompatible_func_changed() const;
+
   size_t num_vars_removed() const;
   void num_vars_removed(size_t);
 
@@ -2716,6 +2745,8 @@  public:
 
   size_t net_num_vars_changed() const;
 
+  size_t net_num_non_incompatible_var_changed() const;
+
   size_t num_func_syms_removed() const;
   void num_func_syms_removed(size_t);
 
diff --git a/include/abg-ir.h b/include/abg-ir.h
index a19a1b80..d8ce0435 100644
--- a/include/abg-ir.h
+++ b/include/abg-ir.h
@@ -1362,12 +1362,12 @@  enum change_kind
   NO_CHANGE_KIND = 0,
 
   /// This means that a given IR artifact has a local type change.
-  LOCAL_TYPE_CHANGE_KIND = 1 << 0,
+  LOCAL_TYPE_CHANGE_KIND = 1 << 1,
 
   /// This means that a given IR artifact has a local non-type change.
   /// That is a change that is carried by the artifact itself, not by
   /// its type.
-  LOCAL_NON_TYPE_CHANGE_KIND = 1 << 1,
+  LOCAL_NON_TYPE_CHANGE_KIND = 1 << 2,
 
   /// Testing (anding) against this mask means that a given IR artifact has
   /// local differences, with respect to the other artifact it was compared
@@ -1378,7 +1378,7 @@  enum change_kind
   /// This means that a given IR artifact has changes in some of its
   /// sub-types, with respect to the other artifact it was compared
   /// against.
-  SUBTYPE_CHANGE_KIND = 1 << 2,
+  SUBTYPE_CHANGE_KIND = 1 << 3,
 };// end enum change_kind
 
 change_kind
diff --git a/src/abg-comp-filter.cc b/src/abg-comp-filter.cc
index 6735580d..d6609223 100644
--- a/src/abg-comp-filter.cc
+++ b/src/abg-comp-filter.cc
@@ -40,6 +40,9 @@  static bool
 type_diff_has_typedef_cv_qual_change_only(const type_base_sptr& f,
 					  const type_base_sptr& s);
 
+static diff_category
+has_harmful_change(const diff* d);
+
 static bool
 has_harmful_enum_change(const diff* diff);
 
@@ -1993,7 +1996,7 @@  static bool
 has_added_or_removed_function_parameters(const diff *dif)
 {
   const function_type_diff *fn_type_diff = is_function_type_diff(dif);
-    if (!fn_type_diff)
+  if (!fn_type_diff)
     if (const function_decl_diff* fn_decl_diff = is_function_decl_diff(dif))
       fn_type_diff = fn_decl_diff->type_diff().get();
 
@@ -2007,6 +2010,155 @@  has_added_or_removed_function_parameters(const diff *dif)
   return false;
 }
 
+/// Test if a diff node is a function diff node that carries either a
+/// return or a parameter type change that is deemed harmful.
+///
+/// @param d the diff node to consider.
+///
+/// @return the category of the change carried by @p or zero if
+/// doesn't carry any change.
+diff_category
+has_fn_return_or_parm_harmful_change(const diff* d)
+{
+  const function_decl_diff* fn_decl_diff = nullptr;
+  const function_type_diff* fn_type_diff = is_function_type_diff(d);
+
+  if (!fn_type_diff)
+    fn_decl_diff = is_function_decl_diff(d);
+
+  if (!fn_decl_diff && !fn_type_diff)
+    return NO_CHANGE_CATEGORY;
+
+  diff_category category = NO_CHANGE_CATEGORY;
+  if (fn_decl_diff)
+    category = fn_decl_diff->get_local_category();
+
+  if (is_harmful_category(category))
+    return category;
+
+  if (fn_decl_diff)
+    fn_type_diff = fn_decl_diff->type_diff().get();
+
+  if (!fn_type_diff)
+    return NO_CHANGE_CATEGORY;
+
+  diff_sptr return_type_diff = fn_type_diff->return_type_diff();
+  if (return_type_diff && !has_void_to_non_void_change(return_type_diff))
+    category = return_type_diff->get_local_category();
+
+  if (is_harmful_category(category))
+    return category;
+
+  for (const auto& entry : fn_type_diff->subtype_changed_parms())
+    {
+      category = entry.second->get_local_category();
+      if (is_harmful_category(category))
+	return category;
+    }
+
+  return NO_CHANGE_CATEGORY;
+}
+
+/// Test if a diff node carries a change to the offset of a virtual
+/// function.
+///
+/// @param d the diff node to consider.
+///
+/// @return true iff @p carries a change to the offset of a virtual
+/// function.
+bool
+has_fn_with_virtual_offset_change(const diff* d)
+{
+  const function_decl_diff* fn_diff = is_function_decl_diff(d);
+  if (!fn_diff)
+    return false;
+
+  if (fn_diff->get_local_category() & VIRTUAL_MEMBER_CHANGE_CATEGORY)
+    return true;
+
+  return false;
+}
+
+/// Test if a diff node carries a change to the offset of a virtual
+/// function.
+///
+/// @param d the diff node to consider.
+///
+/// @return true iff @p carries a change to the offset of a virtual
+/// function.
+bool
+has_fn_with_virtual_offset_change(const diff_sptr& d)
+{return has_fn_with_virtual_offset_change(d.get());}
+
+
+/// Test if a diff node carries a harmful local change to a variable.
+///
+/// @param d the diff node to consider.
+///
+/// @return the @ref diff_category of the harmful local change or zero
+/// if the diff node carries no harmful local change.
+diff_category
+has_var_harmful_local_change(const diff* d)
+{
+  const var_diff* vd = is_var_diff(d);
+  diff_category cat = NO_CHANGE_CATEGORY;
+
+  if (!vd || has_benign_array_of_unknown_size_change(d))
+    return cat;
+
+  cat = vd->get_local_category();
+  if (is_harmful_category(cat))
+    return cat;
+
+  diff_sptr type_diff = vd->type_diff();
+
+  cat = type_diff->get_local_category();
+  if (is_harmful_category(cat))
+    return cat;
+
+  return NO_CHANGE_CATEGORY;
+}
+
+/// Test if diff node carries a harmful local change to a variable.
+///
+/// @param d the diff node to consider.
+///
+/// @return the @ref diff_category of the harmful local change or zero
+/// if the diff node carries no harmful local change.
+diff_category
+has_var_harmful_local_change(const diff_sptr& d)
+{return has_var_harmful_local_change(d.get());}
+
+/// Test if a diff node carries an incompatible ABI change.
+///
+/// An incompatible ABI change is a potentially harmful ABI change
+/// (i.e, one that cannot be filtered out) that definitely makes the
+/// new ABI incompatible with the previous one.
+///
+/// @param d the diff node to consider.
+///
+/// @return true iff @p d carries an incompatible ABI change.
+bool
+has_incompatible_fn_or_var_change(const diff* d)
+{
+  return (has_fn_return_or_parm_harmful_change(d)
+	  || has_fn_with_virtual_offset_change(d)
+	  || has_var_harmful_local_change(d));
+}
+
+/// Test if a diff node carries an incompatible ABI change.
+///
+/// An incompatible ABI change is a potentially harmful ABI change
+/// (i.e, one that cannot be filtered out) that definitely makes the
+/// new ABI incompatible with the previous one.
+///
+/// @param d the diff node to consider.
+///
+/// @return true iff @p d carries an incompatible ABI change.
+bool
+has_incompatible_fn_or_var_change(const diff_sptr& d)
+{return has_incompatible_fn_or_var_change(d.get());}
+
 /// Test if a variable diff node carries a CV qualifier change on its type.
 ///
 /// @param dif the diff node to consider.  Note that if it's not of
@@ -2049,6 +2201,79 @@  is_void_ptr_to_ptr(const type_base* f, const type_base* s)
   return false;
 }
 
+/// Test if a pair of types represents a "void-to-non-void" change.
+///
+/// The test looks through potential typedefs.
+///
+/// @param f the first type to consider.
+///
+/// @param s the second type to consider.
+///
+/// @return true iff the pair of types represents a void-to-non-void
+/// type change.
+static bool
+is_void_to_non_void(const type_base* f, const type_base* s)
+{
+  f = peel_typedef_type(f);
+  s = peel_typedef_type(s);
+
+  if (!f || !s)
+    return false;
+
+  const environment& env = f->get_environment();
+  if (env.is_void_type(f) &&  !env.is_void_type(s))
+    return true;
+
+  return false;
+}
+
+/// Test if a pair of types represents a "void-to-non-void" change.
+///
+/// The test looks through potential typedefs.
+///
+/// @param f the first type to consider.
+///
+/// @param s the second type to consider.
+///
+/// @return true iff the pair of types represents a void-to-non-void
+/// type change.
+static bool
+is_void_to_non_void(const type_base_sptr& f, const type_base_sptr s)
+{return is_void_to_non_void(f.get(), s.get());}
+
+/// Test if a diff node carries a "void-to-non-void" type change
+///
+/// The test looks through potential typedefs.
+///
+/// @param f the first type to consider.
+///
+/// @param s the second type to consider.
+///
+/// @return true iff the pair of types represents a void-to-non-void
+/// type change.
+bool
+has_void_to_non_void_change(const diff* d)
+{
+  type_base_sptr f = is_type(d->first_subject());
+  type_base_sptr s = is_type(d->second_subject());
+
+  return is_void_to_non_void(f, s);
+}
+
+/// Test if a diff node carries a "void-to-non-void" type change
+///
+/// The test looks through potential typedefs.
+///
+/// @param f the first type to consider.
+///
+/// @param s the second type to consider.
+///
+/// @return true iff the pair of types represents a void-to-non-void
+/// type change.
+bool
+has_void_to_non_void_change(const diff_sptr& d)
+{return has_void_to_non_void_change(d.get());}
+
 /// Test if a diff node carries a void* to pointer type change.
 ///
 /// Note that this function looks through typedef and qualifier types
@@ -2135,9 +2360,75 @@  union_diff_has_harmless_changes(const diff *d)
   return false;
 }
 
+/// Test if a diff node carries a change that is categorized as
+/// "harmful".
+///
+/// A harmful change is a change that is not harmless.  OK, that
+/// smells bit like a tasteless tautology, but bear with me please.
+///
+/// A harmless change is a change that should be filtered out by
+/// default to avoid unnecessarily cluttering the change report.
+///
+/// A harmful change is thus a change that SHOULD NOT be filtered out
+/// by default because it CAN represent an incompatible ABI change.
+///
+/// An incompatbile ABI change is a harmful change that makes the new
+/// ABI incompatible with the previous one.
+///
+/// @return the category of the harmful changes carried by the diff
+/// node or zero if the change carries no harmful change.
+static diff_category
+has_harmful_change(const diff* d)
+{
+  diff_category category = NO_CHANGE_CATEGORY;
+  decl_base_sptr f = is_decl(d->first_subject()),
+    s = is_decl(d->second_subject());
+
+  // Detect size or offset changes as well as data member addition
+  // or removal.
+  //
+  // TODO: be more specific -- not all size changes are harmful.
+  if (!has_class_decl_only_def_change(d)
+      && !has_enum_decl_only_def_change(d)
+      && (type_size_changed(f, s)
+	  || type_has_offset_changes(f, s)
+	  || data_member_offset_changed(f, s)
+	  || non_static_data_member_type_size_changed(f, s)
+	  || non_static_data_member_added_or_removed(d)
+	  || base_classes_removed(d)
+	  || has_harmful_enum_change(d)
+	  || crc_changed(d)
+	  || namespace_changed(d)))
+    category |= SIZE_OR_OFFSET_CHANGE_CATEGORY;
+
+  if (has_virtual_mem_fn_change(d))
+    category |= VIRTUAL_MEMBER_CHANGE_CATEGORY;
+
+  if (has_lvalue_reference_ness_change(d))
+    category |= REFERENCE_LVALUENESS_CHANGE_CATEGORY;
+
+  if (has_added_or_removed_function_parameters(d))
+    category |= FN_PARM_ADD_REMOVE_CHANGE_CATEGORY;
+
+  if (is_non_compatible_distinct_change(d))
+    category |= NON_COMPATIBLE_DISTINCT_CHANGE_CATEGORY;
+
+  if (has_harmful_name_change(d))
+    category |= NON_COMPATIBLE_NAME_CHANGE_CATEGORY;
+
+  return category;
+}
+
 /// Detect if the changes carried by a given diff node are deemed
 /// harmless and do categorize the diff node accordingly.
 ///
+/// A harmless change is a change that ought to be filtered out by
+/// default from the change report.  Filtering out harmless changes is
+/// to avoid unnecessarily cluttering the change report.
+///
+/// A change is not harmless is a harmful node.  Note that harmful
+/// diff nodes are categorized by @ref categorize_harmful_diff_node.
+///
 /// @param d the diff node being visited.
 ///
 /// @param pre this is true iff the node is being visited *before* the
@@ -2225,6 +2516,21 @@  categorize_harmless_diff_node(diff *d, bool pre)
 /// Detect if the changes carried by a given diff node are deemed
 /// harmful and do categorize the diff node accordingly.
 ///
+/// A harmful change is a change that is not harmless.  OK, that
+/// smells bit like a tasteless tautology, but bear with me please.
+///
+/// A harmless change is a change that should be filtered out by
+/// default to avoid unnecessarily cluttering the change report.
+///
+/// A harmful change is thus a change that SHOULD NOT be filtered out
+/// by default because it CAN represent an incompatible ABI change.
+///
+/// An incompatbile ABI change is a harmful change that makes the new
+/// ABI incompatible with the previous one.
+///
+/// Note that harmless diff nodes are categorized by
+/// @ref categorize_harmless_diff_node.
+///
 /// @param d the diff node being visited.
 ///
 /// @param pre this is true iff the node is being visited *before* the
@@ -2241,40 +2547,7 @@  categorize_harmful_diff_node(diff *d, bool pre)
   if (pre)
     {
       diff_category category = NO_CHANGE_CATEGORY;
-      decl_base_sptr f = is_decl(d->first_subject()),
-	s = is_decl(d->second_subject());
-
-      // Detect size or offset changes as well as data member addition
-      // or removal.
-      //
-      // TODO: be more specific -- not all size changes are harmful.
-      if (!has_class_decl_only_def_change(d)
-	  && !has_enum_decl_only_def_change(d)
-	  && (type_size_changed(f, s)
-	      || type_has_offset_changes(f, s)
-	      || data_member_offset_changed(f, s)
-	      || non_static_data_member_type_size_changed(f, s)
-	      || non_static_data_member_added_or_removed(d)
-	      || base_classes_removed(d)
-	      || has_harmful_enum_change(d)
-	      || crc_changed(d)
-	      || namespace_changed(d)))
-	category |= SIZE_OR_OFFSET_CHANGE_CATEGORY;
-
-      if (has_virtual_mem_fn_change(d))
-	category |= VIRTUAL_MEMBER_CHANGE_CATEGORY;
-
-      if (has_lvalue_reference_ness_change(d))
-	category |= REFERENCE_LVALUENESS_CHANGE_CATEGORY;
-
-      if (has_added_or_removed_function_parameters(d))
-	category |= FN_PARM_ADD_REMOVE_CHANGE_CATEGORY;
-
-      if (is_non_compatible_distinct_change(d))
-	category |= NON_COMPATIBLE_DISTINCT_CHANGE_CATEGORY;
-
-      if (has_harmful_name_change(d))
-	category |= NON_COMPATIBLE_NAME_CHANGE_CATEGORY;
+      category = has_harmful_change(d);
 
       if (category)
 	{
diff --git a/src/abg-comparison-priv.h b/src/abg-comparison-priv.h
index f702c066..8a5773d5 100644
--- a/src/abg-comparison-priv.h
+++ b/src/abg-comparison-priv.h
@@ -714,6 +714,13 @@  struct base_diff_comp
   {return operator()(l.get(), r.get());}
 }; // end struct base_diff_comp
 
+bool
+is_less_than(const decl_diff_base& first, const decl_diff_base& second);
+
+bool
+is_less_than(const decl_diff_base_sptr& first,
+	     const decl_diff_base_sptr& second);
+
 /// A comparison functor to compare two instances of @ref var_diff
 /// that represent changed data members based on the offset of the
 /// initial data members, or if equal, based on their qualified name.
@@ -775,10 +782,7 @@  struct data_member_diff_comp
 
     return name1 < name2;
   }
-}; // end struct var_diff_comp
-
-bool
-is_less_than(const function_decl_diff& first, const function_decl_diff& second);
+}; // end struct data_member_diff_comp
 
 /// A comparison functor for instances of @ref function_decl_diff that
 /// represent changes between two virtual member functions.
@@ -1079,11 +1083,13 @@  struct corpus_diff::priv
   string_function_ptr_map		suppressed_added_fns_;
   string_function_decl_diff_sptr_map	changed_fns_map_;
   function_decl_diff_sptrs_type	changed_fns_;
+  function_decl_diff_sptrs_type	incompatible_changed_fns_;
   string_var_ptr_map			deleted_vars_;
   string_var_ptr_map			suppressed_deleted_vars_;
   string_var_ptr_map			added_vars_;
   string_var_ptr_map			suppressed_added_vars_;
   string_var_diff_sptr_map		changed_vars_map_;
+  var_diff_sptrs_type			incompatible_changed_vars_;
   var_diff_sptrs_type			sorted_changed_vars_;
   string_elf_symbol_map		added_unrefed_fn_syms_;
   string_elf_symbol_map		suppressed_added_unrefed_fn_syms_;
@@ -1302,11 +1308,9 @@  struct var_diff_sptr_comp
   ///
   /// @return true if @p f is less than @p s.
   bool
-  operator()(const var_diff_sptr f,
-	     const var_diff_sptr s)
+  operator()(const var_diff_sptr f, const var_diff_sptr s)
   {
-    return (f->first_var()->get_qualified_name()
-	    < s->first_var()->get_qualified_name());
+    return is_less_than(f, s);
   }
 }; // end struct var_diff_sptr_comp
 
@@ -1323,6 +1327,10 @@  struct corpus_diff::diff_stats::priv
   size_t		num_func_changed;
   size_t		num_changed_func_filtered_out;
   size_t		num_func_with_virt_offset_changes;
+  size_t		num_func_with_local_harmful_changes;
+  size_t		num_func_with_incompatible_changes;
+  size_t		num_var_with_local_harmful_changes;
+  size_t		num_var_with_incompatible_changes;
   size_t		num_vars_removed;
   size_t		num_removed_vars_filtered_out;
   size_t		num_vars_added;
@@ -1361,6 +1369,10 @@  struct corpus_diff::diff_stats::priv
       num_func_changed(),
       num_changed_func_filtered_out(),
       num_func_with_virt_offset_changes(),
+      num_func_with_local_harmful_changes(),
+      num_func_with_incompatible_changes(),
+      num_var_with_local_harmful_changes(),
+      num_var_with_incompatible_changes(),
       num_vars_removed(),
       num_removed_vars_filtered_out(),
       num_vars_added(),
@@ -1428,10 +1440,16 @@  sort_string_function_decl_diff_sptr_map
 (const string_function_decl_diff_sptr_map& map,
  function_decl_diff_sptrs_type& sorted);
 
+void
+sort_function_decl_diffs(function_decl_diff_sptrs_type& fn_diffs);
+
 void
 sort_string_var_diff_sptr_map(const string_var_diff_sptr_map& map,
 			      var_diff_sptrs_type& sorted);
 
+void
+sort_var_diffs(var_diff_sptrs_type& var_diffs);
+
 void
 sort_string_elf_symbol_map(const string_elf_symbol_map& map,
 			   vector<elf_symbol_sptr>& sorted);
diff --git a/src/abg-comparison.cc b/src/abg-comparison.cc
index d0eb4779..11e0a93f 100644
--- a/src/abg-comparison.cc
+++ b/src/abg-comparison.cc
@@ -168,18 +168,39 @@  sort_changed_data_members(changed_var_sptrs_type& to_sort)
   std::sort(to_sort.begin(), to_sort.end(), comp);
 }
 
-/// Compare two @ref function_decl_diff for the purpose of sorting.
+/// Get the ELF symbol associated to a decl.
 ///
-/// @param first the first @ref function_decl_diff to consider.
+/// Please note that ELF symbol are only associated to function or
+/// global variable decls.  So for any other kind of decl, this
+/// function returns nullptr.
+///
+/// @param d the decl to consider.
+///
+/// @return the ELF symbol associated to @p if any or nullptr.
+static elf_symbol_sptr
+get_symbol(const decl_base_sptr& d)
+{
+  if (function_decl_sptr fn = is_function_decl(d))
+    return fn->get_symbol();
+  else if (var_decl_sptr var = is_var_decl(d))
+    return var->get_symbol();
+
+  return elf_symbol_sptr();
+}
+
+/// Compare two decl diff nodes (@ref decl_diff_base) for the purpose
+/// of sorting.
+///
+/// @param first the first @ref decl_diff to consider.
 ///
 /// @param second the second @ref function_decl_diff to consider.
 ///
 /// @return true iff @p first compares less than @p second.
 bool
-is_less_than(const function_decl_diff& first, const function_decl_diff& second)
+is_less_than(const decl_diff_base& first, const decl_diff_base& second)
 {
-  function_decl_sptr f = first.first_function_decl(),
-    s = second.first_function_decl();
+  decl_base_sptr f = is_decl(first.first_subject()),
+    s = is_decl(second.first_subject());
 
   string fr = f->get_qualified_name(), sr = s->get_qualified_name();
 
@@ -195,20 +216,38 @@  is_less_than(const function_decl_diff& first, const function_decl_diff& second)
 	return fr < sr;
     }
 
-  if (f->get_symbol() && s->get_symbol())
+  if (get_symbol(f) && get_symbol(s))
     {
-      fr = f->get_symbol()->get_id_string();
-      sr = s->get_symbol()->get_id_string();
+      fr = get_symbol(f)->get_id_string();
+      sr = get_symbol(s)->get_id_string();
       if (fr != sr)
 	return fr < sr;
     }
-	
+
   fr = f->get_pretty_representation(true, true);
   sr = s->get_pretty_representation(true, true);
 
   return fr < sr;
 }
 
+/// Compare two decl diff nodes (@ref decl_diff_base) for the purpose
+/// of sorting.
+///
+/// @param first the first @ref decl_diff to consider.
+///
+/// @param second the second @ref function_decl_diff to consider.
+///
+/// @return true iff @p first compares less than @p second.
+bool
+is_less_than(const decl_diff_base_sptr& first,
+	     const decl_diff_base_sptr& second)
+{
+  if (!first || !second)
+    return false;
+
+  return is_less_than(*first, *second);
+}
+
 /// Sort an instance of @ref string_function_ptr_map map and stuff a
 /// resulting sorted vector of pointers to function_decl.
 ///
@@ -272,6 +311,19 @@  sort_string_function_decl_diff_sptr_map
   std::sort(sorted.begin(), sorted.end(), comp);
 }
 
+/// Sort a vector of @ref function_decl_diff_sptr.
+///
+/// The comparison functor used is function_decl_diff_comp.
+///
+/// @param fn_diffs in/out parameter.  The vector of @ref
+/// function_decl_diff_sptr to sort.
+void
+sort_function_decl_diffs(function_decl_diff_sptrs_type& fn_diffs)
+{
+  function_decl_diff_comp comp;
+  std::sort(fn_diffs.begin(), fn_diffs.end(), comp);
+}
+
 /// Sort of an instance of @ref string_var_diff_sptr_map map.
 ///
 /// @param map the input map to sort.
@@ -292,6 +344,19 @@  sort_string_var_diff_sptr_map(const string_var_diff_sptr_map& map,
   std::sort(sorted.begin(), sorted.end(), comp);
 }
 
+/// Sort a vector of @ref var_diff_sptr.
+///
+/// The comparison functor used is @ref var_diff_sptr_comp.
+///
+/// @param var_diffs in/out parameter the vector of @ref var_diff_sptr
+/// to sort.
+void
+sort_var_diffs(var_diff_sptrs_type& var_diffs)
+{
+  var_diff_sptr_comp comp;
+  std::sort(var_diffs.begin(), var_diffs.end(), comp);
+}
+
 /// Sort a map of string -> pointer to @ref elf_symbol.
 ///
 /// The result is a vector of @ref elf_symbol_sptr sorted by the
@@ -3188,6 +3253,32 @@  get_default_harmful_categories_bitmap()
 	  | abigail::comparison::FN_PARM_ADD_REMOVE_CHANGE_CATEGORY);
 }
 
+/// Test if an instance of @ref diff_category (a category bit-field)
+/// is harmful or not.
+///
+/// A harmful change is a change that is not harmless.  OK, that
+/// smells bit like a tasteless tautology, but bear with me please.
+///
+/// A harmless change is a change that should be filtered out by
+/// default to avoid unnecessarily cluttering the change report.
+///
+/// A harmful change is thus a change that SHOULD NOT be filtered out
+/// by default because it CAN represent an incompatible ABI change.
+///
+/// An incompatbile ABI change is a harmful change that makes the new
+/// ABI incompatible with the previous one.
+///
+/// @param c the instance of @ref diff_category to consider.  It is a
+/// bit-field of the categories of a given diff node.
+///
+/// @return true 
+bool
+is_harmful_category(diff_category c)
+{
+  diff_category dc = get_default_harmful_categories_bitmap();
+  return c & dc;
+}
+
 /// Serialize an instance of @ref diff_category to an output stream.
 ///
 /// @param o the output stream to serialize @p c to.
@@ -8860,6 +8951,74 @@  void
 corpus_diff::diff_stats::num_func_with_virtual_offset_changes(size_t n)
 {priv_->num_func_with_virt_offset_changes = n;}
 
+/// Getter for the number of functions with local harmful changes.
+///
+/// A local harmful change is a harmful change that is local to the
+/// function itself or is local to a return or parameter type.
+///
+/// @return the number of functions with local harmful changes.
+size_t
+corpus_diff::diff_stats::num_func_with_local_harmful_changes() const
+{return priv_->num_func_with_local_harmful_changes;}
+
+/// Setter for the number of functions with local harmful changes.
+///
+/// A local harmful change is a harmful change that is local to the
+/// function itself or is local to a return or parameter type.
+///
+/// @param n the number of functions with local harmful changes.
+void
+corpus_diff::diff_stats::num_func_with_local_harmful_changes(size_t n)
+{priv_->num_func_with_local_harmful_changes = n;}
+
+/// Getter for the number of variables with local harmful changes.
+///
+/// A local harmful change is a harmful change that is local to the
+/// variable itself or is local to its type.
+///
+/// @return the number of variables with local harmful changes.
+size_t
+corpus_diff::diff_stats::num_var_with_local_harmful_changes() const
+{return priv_->num_var_with_local_harmful_changes;}
+
+/// Setter for the number of variables with local harmful changes.
+///
+/// A local harmful change is a harmful change that is local to the
+/// variable itself or is local to its type.
+///
+/// @param n the number of variables with local harmful changes.
+void
+corpus_diff::diff_stats::num_var_with_local_harmful_changes(size_t n)
+{priv_->num_var_with_local_harmful_changes = n;}
+
+/// Getter for the number of functions with incompatible changes.
+///
+/// @return the number of functions with incompatible changes.
+size_t
+corpus_diff::diff_stats::num_func_with_incompatible_changes() const
+{return priv_->num_func_with_incompatible_changes;}
+
+/// Setter for the number of functions with incompatible changes.
+///
+/// @param n the number of functions with incompatible changes.
+void
+corpus_diff::diff_stats::num_func_with_incompatible_changes(size_t n)
+{priv_->num_func_with_incompatible_changes = n;}
+
+/// Getter for the number of variables with incompatible changes.
+///
+/// @return the number of variables with incompatible changes.
+size_t
+corpus_diff::diff_stats::num_var_with_incompatible_changes() const
+{return priv_->num_var_with_incompatible_changes;}
+
+/// Setter for the number of variables with incompatible changes.
+///
+/// @param n the number of variables with incompatible changes.
+void
+corpus_diff::diff_stats::num_var_with_incompatible_changes(size_t n)
+{priv_->num_var_with_incompatible_changes = n;}
+
 /// Getter for the number of functions that have a change in their
 /// sub-types, minus the number of these functions that got filtered
 /// out from the diff.
@@ -8871,6 +9030,15 @@  size_t
 corpus_diff::diff_stats::net_num_func_changed() const
 {return num_func_changed() - num_changed_func_filtered_out();}
 
+/// Getter of the net number of functions with changes that are not
+/// incompatible.
+///
+/// @return net number of functions with changes that are not
+/// incompatible.
+size_t
+corpus_diff::diff_stats::net_num_non_incompatible_func_changed() const
+{return net_num_func_changed() - num_func_with_incompatible_changes();}
+
 /// Getter for the number of variables removed.
 ///
 /// @return the number of variables removed.
@@ -9014,6 +9182,15 @@  size_t
 corpus_diff::diff_stats::net_num_vars_changed() const
 {return num_vars_changed() - num_changed_vars_filtered_out();}
 
+/// Getter of the net number of variables with changes that are not
+/// incompatible.
+///
+/// @return net number of variables with changes that are not
+/// incompatible.
+size_t
+corpus_diff::diff_stats::net_num_non_incompatible_var_changed() const
+{return net_num_vars_changed() - num_var_with_incompatible_changes();}
+
 /// Getter for the number of function symbols (not referenced by any
 /// debug info) that got removed.
 ///
@@ -10890,6 +11067,7 @@  corpus_diff::priv::apply_filters_and_compute_diff_stats(diff_stats& stat)
        i != changed_fns_.end();
        ++i)
     {
+      bool incompatible_change = false;
       if ((*i)->is_filtered_out())
 	{
 	  stat.num_changed_func_filtered_out
@@ -10899,16 +11077,36 @@  corpus_diff::priv::apply_filters_and_compute_diff_stats(diff_stats& stat)
 	    stat.num_leaf_func_changes_filtered_out
 	      (stat.num_leaf_func_changes_filtered_out() + 1);
 	}
-      else
+      else if (!(*i)->is_suppressed())
 	{
-	  if ((*i)->get_category() & VIRTUAL_MEMBER_CHANGE_CATEGORY)
-	    stat.num_func_with_virtual_offset_changes
-	      (stat.num_func_with_virtual_offset_changes() + 1);
+	  if (filtering::has_fn_with_virtual_offset_change(*i))
+	    {
+	      stat.num_func_with_virtual_offset_changes
+		(stat.num_func_with_virtual_offset_changes() + 1);
+	      incompatible_change = true;
+	    }
+
+	  // Are any of the local changes of the function_diff harmful?
+	  // If yes, then set stat.num_func_with_local_harmful_changes()
+	  // and stat.num_var_with_local_harmful_changes().
+	  if (filtering::has_fn_return_or_parm_harmful_change((*i).get()))
+	    {
+	      stat.num_func_with_local_harmful_changes
+		(stat.num_func_with_local_harmful_changes() + 1);
+	      incompatible_change = true;
+	    }
 	}
 
       if ((*i)->has_local_changes())
 	stat.num_leaf_func_changes
 	  (stat.num_leaf_func_changes() + 1);
+
+      if (incompatible_change)
+	{
+	  incompatible_changed_fns_.push_back(*i);
+	  stat.num_func_with_incompatible_changes
+	    (stat.num_func_with_incompatible_changes() + 1);
+	}
     }
 
   if (get_context()->do_log())
@@ -10937,6 +11135,18 @@  corpus_diff::priv::apply_filters_and_compute_diff_stats(diff_stats& stat)
 	    stat.num_leaf_var_changes_filtered_out
 	      (stat.num_leaf_var_changes_filtered_out() + 1);
 	}
+      else if (!(*i)->is_suppressed())
+	{
+	  if (filtering::has_var_harmful_local_change(*i))
+	    {
+	      incompatible_changed_vars_.push_back(*i);
+	      stat.num_var_with_local_harmful_changes
+		(stat.num_var_with_local_harmful_changes() + 1);
+	      stat.num_var_with_incompatible_changes
+		(stat.num_var_with_incompatible_changes() + 1);
+	    }
+	}
+
       if ((*i)->has_local_changes())
 	stat.num_leaf_var_changes
 	  (stat.num_leaf_var_changes() + 1);
@@ -11578,7 +11788,7 @@  corpus_diff::added_functions()
 /// usually made of the name and version of the underlying ELF symbol
 /// of the function for corpora that were built from ELF files.
 const string_function_decl_diff_sptr_map&
-corpus_diff::changed_functions()
+corpus_diff::changed_functions() const
 {return priv_->changed_fns_map_;}
 
 /// Getter for a sorted vector of functions which signature didn't
@@ -11587,9 +11797,27 @@  corpus_diff::changed_functions()
 /// @return a sorted vector of functions which signature didn't
 /// change, but which do have some indirect changes in their parms.
 const function_decl_diff_sptrs_type&
-corpus_diff::changed_functions_sorted()
+corpus_diff::changed_functions_sorted() const
 {return priv_->changed_fns_;}
 
+/// Getter of the set of diff nodes representing incompatibly changed
+/// functions
+///
+/// @return the set of diff nodes representing incompatibly changed
+/// functions
+const function_decl_diff_sptrs_type&
+corpus_diff::incompatible_changed_functions() const
+{return priv_->incompatible_changed_fns_;}
+
+/// Getter of the set of diff nodes representing incompatibly changed
+/// functions
+///
+/// @return the set of diff nodes representing incompatibly changed
+/// functions
+function_decl_diff_sptrs_type&
+corpus_diff::incompatible_changed_functions()
+{return priv_->incompatible_changed_fns_;}
+
 /// Getter for the variables that got deleted from the first subject
 /// of the diff.
 ///
@@ -11621,6 +11849,24 @@  const var_diff_sptrs_type&
 corpus_diff::changed_variables_sorted()
 {return priv_->sorted_changed_vars_;}
 
+/// Getter of the set of diff nodes representing incompatibly changed
+/// global variables.
+///
+/// @return the set of diff nodes representing incompatibly changed
+/// global variables.
+const var_diff_sptrs_type&
+corpus_diff::incompatible_changed_variables() const
+{return priv_->incompatible_changed_vars_;}
+
+/// Getter of the set of diff nodes representing incompatibly changed
+/// global variables.
+///
+/// @return the set of diff nodes representing incompatibly changed
+/// global variables.
+var_diff_sptrs_type&
+corpus_diff::incompatible_changed_variables()
+{return priv_->incompatible_changed_vars_;}
+
 /// Getter for function symbols not referenced by any debug info and
 /// that got deleted.
 ///
@@ -11804,18 +12050,21 @@  corpus_diff::has_incompatible_changes() const
     apply_filters_and_suppressions_before_reporting();
 
   bool has_incompatible_changes  =
-    (soname_changed() || architecture_changed()
-	  || stats.net_num_func_removed() != 0
-	  || (stats.num_func_with_virtual_offset_changes() != 0
-	      // If all reports about functions with sub-type changes
-	      // have been suppressed, then even those about functions
-	      // that are virtual don't matter anymore because the
-	      // user willingly requested to shut them down
-	      && stats.net_num_func_changed() != 0)
-	  || stats.net_num_vars_removed() != 0
-	  || stats.net_num_removed_func_syms() != 0
-	  || stats.net_num_removed_var_syms() != 0
-	  || stats.net_num_removed_unreachable_types() != 0);
+    (soname_changed()
+     || architecture_changed()
+     || stats.net_num_func_removed() != 0
+     || (stats.num_func_with_incompatible_changes()
+	 // If all reports about functions changes have been
+	 // suppressed, then even those about incompatible changes
+	 // don't matter anymore because the user willingly requested
+	 // to shut them down.
+	 && stats.net_num_func_changed() != 0)
+     || stats.net_num_vars_removed() != 0
+     || (stats.num_var_with_incompatible_changes()
+	 && stats.net_num_vars_changed() != 0)
+     || stats.net_num_removed_func_syms() != 0
+     || stats.net_num_removed_var_syms() != 0
+     || stats.net_num_removed_unreachable_types() != 0);
 
   // If stats.net_num_changed_unreachable_types() != 0 then walk the
   // corpus_diff::priv::changed_unreachable_types_, and see if there
@@ -13391,11 +13640,13 @@  struct redundancy_marking_visitor : public diff_node_visitor
       }
     else
       {
-	// Propagate the redundancy categorization of the children nodes
-	// to this node.  But if this node has local changes, then it
-	// doesn't inherit redundancy from its children nodes.
+	// Propagate the redundancy categorization of the children
+	// nodes to this node.  But if this node has local harmful
+	// changes then it doesn't inherit redundancy from its
+	// children nodes.
 	if (!(d->get_category() & REDUNDANT_CATEGORY)
-	    && (!d->has_local_changes_to_be_reported()
+	    && ((!d->has_local_changes_to_be_reported()
+		 || !is_harmful_category(d->get_local_category()))
 		// By default, pointer, reference, array and qualified
 		// types consider that a local changes to their
 		// underlying type is always a local change for
diff --git a/src/abg-default-reporter.cc b/src/abg-default-reporter.cc
index 7ff49c2c..fd7b7fcd 100644
--- a/src/abg-default-reporter.cc
+++ b/src/abg-default-reporter.cc
@@ -1889,6 +1889,143 @@  default_reporter::report(const translation_unit_diff& d,
   static_cast<const scope_diff&>(d).report(out, indent);
 }
 
+/// Emit a report about a changed function.
+///
+/// @param ctxt the diff context to use for the report.
+///
+/// @param fn_diff the function_diff node to emit the report for.
+///
+/// @param out the output stream to emit the report to.
+///
+/// @param indent the indentation string to use.
+///
+/// @param indirect_changed_subtypes if true, this means there are
+/// indirect sub-types changes.  Indirect means it's a pointed-to-type
+/// that changed.
+///
+/// @param emit_redundant_fn_changes if true, the function reports
+/// about changes carried by @fn_diff even if they are redundant.
+static void
+emit_changed_fn_report(const diff_context_sptr& ctxt,
+		       const function_decl_diff_sptr& fn_diff,
+		       ostream& out, const string indent,
+		       bool indirect_changed_subtypes = false,
+		       bool emit_redundant_fn_changes = true)
+{
+  bool saved_show_redundant_changes = ctxt->show_redundant_changes();
+  ctxt->show_redundant_changes(emit_redundant_fn_changes);
+
+  if (fn_diff->to_be_reported())
+    {
+      function_decl_sptr fn = fn_diff->first_function_decl();
+      out << indent << "  [C] '"
+	  << fn->get_pretty_representation() << "'";
+      report_loc_info(fn_diff->first_function_decl(), *ctxt, out);
+
+      out << " has some";
+      if (indirect_changed_subtypes)
+	out << " indirect";
+      out << " sub-type changes:\n";
+
+      if (// The symbol of the function has aliases and the
+	  // function is not a cdtor (yeah because c++ cdtors
+	  // usually have several aliases).
+	  (fn->get_symbol()->has_aliases()
+	   && !(is_member_function(fn)
+		&& get_member_function_is_ctor(fn))
+	   && !(is_member_function(fn)
+		&& get_member_function_is_dtor(fn)))
+	  || // We are in C and the name of the function is
+	  // different from the symbol name -- without
+	  // taking the possible symbol version into
+	  // account (this usually means the programmers
+	  // was playing tricks with symbol names and
+	  // versions).
+	  (is_c_language(get_translation_unit(fn)->get_language())
+	   && fn->get_name() != fn->get_symbol()->get_name()))
+	{
+	  // As the name of the symbol of the function doesn't
+	  // seem to be obvious here, make sure to tell the
+	  // user about the name of the (function) symbol she
+	  // is looking at here.
+	  int number_of_aliases =
+	    fn->get_symbol()->get_number_of_aliases();
+	  if (number_of_aliases == 0)
+	    {
+	      out << indent << "    "
+		  << "Please note that the exported symbol of "
+		"this function is "
+		  << fn->get_symbol()->get_id_string()
+		  << "\n";
+	    }
+	  else
+	    {
+	      out << indent << "    "
+		  << "Please note that the symbol of this function is "
+		  << fn->get_symbol()->get_id_string()
+		  << "\n     and it aliases symbol";
+	      if (number_of_aliases > 1)
+		out << "s";
+	      out << ": "
+		  << fn->get_symbol()->get_aliases_id_string(false)
+		  << "\n";
+	    }
+	}
+      fn_diff->report(out, indent + "    ");
+      // Extra spacing.
+      out << "\n";
+    }
+
+  ctxt->show_redundant_changes(saved_show_redundant_changes);
+}
+
+/// Emit a report about a changed variable.
+///
+/// @param ctxt the diff context to use for the report.
+///
+/// @param fn_diff the var_diff node to emit the report for.
+///
+/// @param out the output stream to emit the report to.
+///
+/// @param indent the indentation string to use.
+///
+/// @param indirect_changed_subtypes if true, this means there are
+/// indirect sub-types changes.  Indirect means it's a pointed-to-type
+/// that changed.
+///
+/// @param emit_redundant_var_changes if true, the function reports
+/// about changes carried by @fn_diff even if they are redundant.
+static void
+emit_changed_var_report(const diff_context_sptr& ctxt,
+			const var_diff_sptr& var_diff,
+			ostream& out, const string indent,
+			bool emit_redundant_var_changes = true)
+{
+  diff_sptr diff = var_diff;
+  if (!diff)
+    return;
+
+  bool saved_show_redundant_changes = ctxt->show_redundant_changes();
+  ctxt->show_redundant_changes(emit_redundant_var_changes);
+
+  if (diff->to_be_reported())
+    {
+      string n1 = diff->first_subject()->get_pretty_representation();
+      string n2 = diff->second_subject()->get_pretty_representation();
+
+      out << indent << "  [C] '" << n1 << "' was changed";
+      if (n1 != n2)
+	out << " to '" << n2 << "'";
+      report_loc_info(diff->second_subject(), *ctxt, out);
+      out << ":\n";
+      diff->report(out, indent + "    ");
+      // Extra spacing.
+      out << "\n";
+    }
+
+  ctxt->show_redundant_changes(saved_show_redundant_changes);
+}
+
 /// Report the changes carried by a @ref corpus_diff node in a
 /// serialized form.
 ///
@@ -1968,6 +2105,21 @@  default_reporter::report(const corpus_diff& d, ostream& out,
 	out << "\n";
     }
 
+  if (size_t num_changed = s.num_func_with_incompatible_changes())
+    {
+      if (num_changed == 1)
+	out << indent << "1 function with incompatible sub-type changes:\n\n";
+      else if (num_changed > 1)
+	out << indent << num_changed
+	    << " functions with incompatible sub-type changes:\n\n";
+
+      sort_function_decl_diffs(const_cast<corpus_diff&>(d).
+			       incompatible_changed_functions());
+      for (auto& fn_diff : d.incompatible_changed_functions())
+	if (fn_diff)
+	  emit_changed_fn_report(ctxt, fn_diff, out, indent);
+    }
+
   if (ctxt->show_added_fns())
     {
       if (s.net_num_func_added() == 1)
@@ -2016,8 +2168,8 @@  default_reporter::report(const corpus_diff& d, ostream& out,
     }
 
   if (ctxt->show_changed_fns())
+    if (size_t num_changed = s.net_num_non_incompatible_func_changed())
     {
-      size_t num_changed = s.num_func_changed() - s.num_changed_func_filtered_out();
       if (num_changed == 1)
 	out << indent << "1 function with some indirect sub-type change:\n\n";
       else if (num_changed > 1)
@@ -2027,71 +2179,11 @@  default_reporter::report(const corpus_diff& d, ostream& out,
       vector<function_decl_diff_sptr> sorted_changed_fns;
       sort_string_function_decl_diff_sptr_map(d.priv_->changed_fns_map_,
 					      sorted_changed_fns);
-      for (vector<function_decl_diff_sptr>::const_iterator i =
-	     sorted_changed_fns.begin();
-	   i != sorted_changed_fns.end();
-	   ++i)
-	{
-	  diff_sptr diff = *i;
-	  if (!diff)
-	    continue;
-
-	  if (diff->to_be_reported())
-	    {
-	      function_decl_sptr fn = (*i)->first_function_decl();
-	      out << indent << "  [C] '"
-		  << fn->get_pretty_representation() << "'";
-	      report_loc_info((*i)->first_function_decl(), *ctxt, out);
-	      out << " has some indirect sub-type changes:\n";
-	      if (// The symbol of the function has aliases and the
-		  // function is not a cdtor (yeah because c++ cdtors
-		  // usually have several aliases).
-		  (fn->get_symbol()->has_aliases()
-		   && !(is_member_function(fn)
-			&& get_member_function_is_ctor(fn))
-		   && !(is_member_function(fn)
-			&& get_member_function_is_dtor(fn)))
-		  || // We are in C and the name of the function is
-		     // different from the symbol name -- without
-		     // taking the possible symbol version into
-		     // account (this usually means the programmers
-		     // was playing tricks with symbol names and
-		     // versions).
-		  (is_c_language(get_translation_unit(fn)->get_language())
-		   && fn->get_name() != fn->get_symbol()->get_name()))
-		{
-		  // As the name of the symbol of the function doesn't
-		  // seem to be obvious here, make sure to tell the
-		  // user about the name of the (function) symbol she
-		  // is looking at here.
-		  int number_of_aliases =
-		    fn->get_symbol()->get_number_of_aliases();
-		  if (number_of_aliases == 0)
-		    {
-		      out << indent << "    "
-			  << "Please note that the exported symbol of "
-			"this function is "
-			  << fn->get_symbol()->get_id_string()
-			  << "\n";
-		    }
-		  else
-		    {
-		      out << indent << "    "
-			  << "Please note that the symbol of this function is "
-			  << fn->get_symbol()->get_id_string()
-			  << "\n     and it aliases symbol";
-		      if (number_of_aliases > 1)
-			out << "s";
-		      out << ": "
-			  << fn->get_symbol()->get_aliases_id_string(false)
-			  << "\n";
-		    }
-		}
-	      diff->report(out, indent + "    ");
-	      // Extra spacing.
-	      out << "\n";
-	    }
-	}
+      for (auto& fn_diff : sorted_changed_fns)
+	if (fn_diff && !filtering::has_incompatible_fn_or_var_change(fn_diff))
+	  emit_changed_fn_report(ctxt, fn_diff, out, indent,
+				 /*indirect_changed_subtypes=*/true,
+				 /*emit_redundant_fns=*/false);
       // Changed functions have extra spacing already. No new line here.
     }
 
@@ -2134,6 +2226,21 @@  default_reporter::report(const corpus_diff& d, ostream& out,
 	out << "\n";
     }
 
+  if (size_t num_changed = s.num_var_with_incompatible_changes())
+    {
+      if (num_changed == 1)
+	out << indent << "1 variable with incompatible sub-type changes:\n\n";
+      else if (num_changed  > 1)
+	out << indent << num_changed
+	    << " variables with incompatible sub-type changes:\n\n";
+
+      sort_var_diffs(const_cast<corpus_diff&>(d).
+		     incompatible_changed_variables());
+      for (auto& var_diff : d.incompatible_changed_variables())
+	if (var_diff)
+	  emit_changed_var_report(ctxt, var_diff, out, indent);
+    }
+
   if (ctxt->show_added_vars())
     {
       if (s.net_num_vars_added() == 1)
@@ -2171,9 +2278,8 @@  default_reporter::report(const corpus_diff& d, ostream& out,
     }
 
   if (ctxt->show_changed_vars())
+    if (size_t num_changed = s.net_num_non_incompatible_var_changed())
     {
-      size_t num_changed =
-	s.num_vars_changed() - s.num_changed_vars_filtered_out();
       if (num_changed == 1)
 	out << indent << "1 Changed variable:\n\n";
       else if (num_changed > 1)
@@ -2181,31 +2287,10 @@  default_reporter::report(const corpus_diff& d, ostream& out,
 	    << " Changed variables:\n\n";
       string n1, n2;
 
-      for (var_diff_sptrs_type::const_iterator i =
-	     d.priv_->sorted_changed_vars_.begin();
-	   i != d.priv_->sorted_changed_vars_.end();
-	   ++i)
-	{
-	  diff_sptr diff = *i;
-
-	  if (!diff)
-	    continue;
-
-	  if (!diff->to_be_reported())
-	    continue;
-
-	  n1 = diff->first_subject()->get_pretty_representation();
-	  n2 = diff->second_subject()->get_pretty_representation();
-
-	  out << indent << "  [C] '" << n1 << "' was changed";
-	  if (n1 != n2)
-	    out << " to '" << n2 << "'";
-	  report_loc_info(diff->second_subject(), *ctxt, out);
-	  out << ":\n";
-	  diff->report(out, indent + "    ");
-	  // Extra spacing.
-	  out << "\n";
-	}
+      for (auto& var_diff : d.priv_->sorted_changed_vars_)
+	if (var_diff
+	    && !filtering::has_incompatible_fn_or_var_change(var_diff))
+	  emit_changed_var_report(ctxt, var_diff, out, indent);
       // Changed variables have extra spacing already. No new line here.
     }
 
diff --git a/src/abg-ir.cc b/src/abg-ir.cc
index 85593169..59383b40 100644
--- a/src/abg-ir.cc
+++ b/src/abg-ir.cc
@@ -2087,10 +2087,20 @@  elf_symbol::create(const environment& e,
 /// are not taken into account.  Only the name, type, and version of
 /// the symbols are compared.
 ///
+/// @parm l the first ELF symbol to take into consideration in the
+/// comparison.
+///
+/// @param r the second ELF symbol to take into consideration in the
+/// comparison.
+///
+/// @param k a pointer to a bitfield that gives information about the
+/// kind of changes there are between @p l and @p r.  This one is set
+/// iff it's non-null and if the function returns false.
+///
 /// @return true iff the two symbols are textually equal.
 static bool
-textually_equals(const elf_symbol&l,
-		 const elf_symbol&r)
+textually_equals(const elf_symbol&l, const elf_symbol&r,
+		 change_kind* k = nullptr)
 {
   bool equals = (l.get_name() == r.get_name()
 		 && l.get_type() == r.get_type()
@@ -2101,12 +2111,21 @@  textually_equals(const elf_symbol&l,
 		 && l.get_crc() == r.get_crc()
 		 && l.get_namespace() == r.get_namespace());
 
+  if (!equals)
+    if (k)
+      *k |= LOCAL_NON_TYPE_CHANGE_KIND;
+
   if (equals && l.is_variable())
     // These are variable symbols.  Let's compare their symbol size.
     // The symbol size in this case is the size taken by the storage
     // of the variable.  If that size changes, then it's an ABI
     // change.
-    equals = l.get_size() == r.get_size();
+    if (l.get_size() != r.get_size())
+      {
+	equals = false;
+	if (k)
+	  *k| LOCAL_TYPE_CHANGE_KIND;
+      }
 
   return equals;
 }
@@ -21455,12 +21474,10 @@  var_equals_modulo_types(const var_decl& l, const var_decl& r, change_kind* k)
       else
 	ABG_RETURN_FALSE;
     }
-  else if (s0 && s0 != s1)
+  else if (s0 && !textually_equals(*s0, *s1, k))
     {
       result = false;
-      if (k)
-	*k |= LOCAL_NON_TYPE_CHANGE_KIND;
-      else
+      if (!k)
 	ABG_RETURN_FALSE;
     }
   bool symbols_are_equal = (s0 && s1 && result);
diff --git a/src/abg-leaf-reporter.cc b/src/abg-leaf-reporter.cc
index 9e24ef50..bac954fa 100644
--- a/src/abg-leaf-reporter.cc
+++ b/src/abg-leaf-reporter.cc
@@ -1035,6 +1035,39 @@  leaf_reporter::report(const translation_unit_diff& d,
   static_cast<const scope_diff&>(d).report(out, indent);
 }
 
+/// Emit a report about changes carried by a @ref var_diff node.
+///
+/// @param ctxt the diff context to use.
+///
+/// @param var_diff the @êef var_diff node to consider.
+///
+/// @param out the output stream to emit the report to.
+///
+/// @param indent the indentation string to use for the report.
+static void
+emit_changed_var_report(const diff_context_sptr& ctxt,
+			const var_diff_sptr& var_diff,
+			ostream& out, const string indent)
+{
+  diff_sptr diff = var_diff;
+  if (!diff
+      || !diff->to_be_reported()
+      || !diff->has_local_changes())
+    return;
+
+  string n1 = diff->first_subject()->get_pretty_representation();
+  string n2 = diff->second_subject()->get_pretty_representation();
+
+  out << indent << "  [C] '" << n1 << "' was changed";
+  if (n1 != n2)
+    out << " to '" << n2 << "'";
+  report_loc_info(diff->second_subject(), *ctxt, out);
+  out << ":\n";
+  diff->report(out, indent + "    ");
+  // Extra spacing.
+  out << "\n";
+}
+
 /// Report the changes carried by a @ref corpus_diff node.
 ///
 /// @param out the output stream to report to.
@@ -1307,33 +1340,35 @@  leaf_reporter::report(const corpus_diff& d,
 
   if (ctxt->show_changed_vars())
     {
-      size_t num_changed = s.net_num_leaf_var_changes();
-      if (num_changed == 1)
-	out << indent << "1 Changed variable:\n\n";
-      else if (num_changed > 1)
-	out << indent << num_changed
-	    << " Changed variables:\n\n";
-      string n1, n2;
-      for (diff_sptr diff : d.priv_->sorted_changed_vars_)
+      if (size_t num_changed = s.num_var_with_incompatible_changes())
 	{
-	  if (!diff)
-	    continue;
-
-	  if (!diff_to_be_reported(diff.get()))
-	    continue;
-
-	  n1 = diff->first_subject()->get_pretty_representation();
-	  n2 = diff->second_subject()->get_pretty_representation();
+	  if (num_changed == 1)
+	    out << indent << "1 variable with incompatible sub-type changes:\n\n";
+	  else if (num_changed  > 1)
+	    out << indent << num_changed
+		<< " variables with incompatible sub-type changes:\n\n";
+
+	  sort_var_diffs(const_cast<corpus_diff&>(d).
+			 incompatible_changed_variables());
+	  for (auto& var_diff : d.incompatible_changed_variables())
+	    if (var_diff)
+	      emit_changed_var_report(ctxt, var_diff, out, indent);
+	}
 
-	  out << indent << "  [C] '" << n1 << "' was changed";
-	  if (n1 != n2)
-	    out << " to '" << n2 << "'";
-	  report_loc_info(diff->second_subject(), *ctxt, out);
-	  out << ":\n";
-	  diff->report(out, indent + "    ");
-	  // Extra spacing.
-	  out << "\n";
+      if (size_t num_changed = (s.net_num_leaf_var_changes()
+				- s.num_var_with_incompatible_changes()))
+	{
+	  if (num_changed == 1)
+	    out << indent << "1 Changed variable:\n\n";
+	  else if (num_changed > 1)
+	    out << indent << num_changed
+		<< " Changed variables:\n\n";
+	  string n1, n2;
+	  for (var_diff_sptr diff : d.priv_->sorted_changed_vars_)
+	    if (diff && !filtering::has_incompatible_fn_or_var_change(diff))
+	      emit_changed_var_report(ctxt, diff, out, indent);
 	}
+
       // Changed variables have extra spacing already. No new line here.
     }
 
diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
index ebc5f0bc..7e63399c 100644
--- a/tests/data/Makefile.am
+++ b/tests/data/Makefile.am
@@ -358,6 +358,32 @@  test-abidiff-exit/test-enumerator-changes1-v0.c \
 test-abidiff-exit/test-enumerator-changes1-v0.o \
 test-abidiff-exit/test-enumerator-changes1-v1.c \
 test-abidiff-exit/test-enumerator-changes1-v1.o \
+test-abidiff-exit/test-enumerator-changes2-report-1.txt \
+test-abidiff-exit/test-enumerator-changes2-v0.cc \
+test-abidiff-exit/test-enumerator-changes2-v0.o \
+test-abidiff-exit/test-enumerator-changes2-v1.cc \
+test-abidiff-exit/test-enumerator-changes2-v1.o \
+test-abidiff-exit/test-enumerator-changes3-report-1.txt \
+test-abidiff-exit/test-enumerator-changes3-report-2.txt \
+test-abidiff-exit/test-enumerator-changes3-v0.cc \
+test-abidiff-exit/test-enumerator-changes3-v0.o \
+test-abidiff-exit/test-enumerator-changes3-v1.cc \
+test-abidiff-exit/test-enumerator-changes3-v1.o \
+test-abidiff-exit/test-enumerator-changes4-report-1.txt \
+test-abidiff-exit/test-enumerator-changes4-v0.cc \
+test-abidiff-exit/test-enumerator-changes4-v0.o \
+test-abidiff-exit/test-enumerator-changes4-v1.cc \
+test-abidiff-exit/test-enumerator-changes4-v1.o \
+test-abidiff-exit/test-enumerator-changes5-report-1.txt \
+test-abidiff-exit/test-enumerator-changes5-v0.cc \
+test-abidiff-exit/test-enumerator-changes5-v0.o \
+test-abidiff-exit/test-enumerator-changes5-v1.cc \
+test-abidiff-exit/test-enumerator-changes5-v1.o \
+test-abidiff-exit/test-enumerator-changes6-report-1.txt \
+test-abidiff-exit/test-enumerator-changes6-v0.cc \
+test-abidiff-exit/test-enumerator-changes6-v0.o \
+test-abidiff-exit/test-enumerator-changes6-v1.cc \
+test-abidiff-exit/test-enumerator-changes6-v1.o \
 test-abidiff-exit/test-anonymous-enums-change-report-v0.txt \
 test-abidiff-exit/test-anonymous-enums-change-report-v1.txt \
 test-abidiff-exit/test-anonymous-enums-change-v0.c \
@@ -455,6 +481,16 @@  test-abidiff-exit/non-del-anon-dm/reported/binaries-origin.txt \
 test-abidiff-exit/non-del-anon-dm/reported/librte_graph.so.24.0 \
 test-abidiff-exit/non-del-anon-dm/reported/librte_graph.so.24.1 \
 test-abidiff-exit/non-del-anon-dm/reported/report0.txt \
+test-abidiff-exit/incompatible-changes/1/report0.txt \
+test-abidiff-exit/incompatible-changes/1/test-1-v0.cc \
+test-abidiff-exit/incompatible-changes/1/test-1-v0.o \
+test-abidiff-exit/incompatible-changes/1/test-1-v1.cc \
+test-abidiff-exit/incompatible-changes/1/test-1-v1.o \
+test-abidiff-exit/test-changed-var-1-report-1.txt \
+test-abidiff-exit/test-changed-var-1-v0.cc \
+test-abidiff-exit/test-changed-var-1-v0.o \
+test-abidiff-exit/test-changed-var-1-v1.cc \
+test-abidiff-exit/test-changed-var-1-v1.o \
 \
 test-diff-dwarf/test0-v0.cc		\
 test-diff-dwarf/test0-v0.o			\
diff --git a/tests/data/test-abicompat/test7-fn-changed-report-0.1.txt b/tests/data/test-abicompat/test7-fn-changed-report-0.1.txt
index 39b69d8f..b1cd70d4 100644
--- a/tests/data/test-abicompat/test7-fn-changed-report-0.1.txt
+++ b/tests/data/test-abicompat/test7-fn-changed-report-0.1.txt
@@ -1,15 +1,17 @@ 
-ELF file 'test7-fn-changed-app.btf' might not be ABI compatible with 'libtest7-fn-changed-libapp-btf-v1.so' due to differences with 'libtest7-fn-changed-libapp-btf-v0.so' below:
+ELF file 'test7-fn-changed-app.btf' is not ABI compatible with 'libtest7-fn-changed-libapp-btf-v1.so' due to differences with 'libtest7-fn-changed-libapp-btf-v0.so' below:
 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:
+1 function with incompatible sub-type changes:
 
-  [C] 'function float add(float, float)' has some indirect sub-type changes:
+  [C] 'function float add(float, float)' has some sub-type changes:
     return type changed:
       type name changed from 'float' to 'int'
       type size hasn't changed
       mangled name changed from 'float' to int
 
+1 function with some indirect sub-type change:
+
   [C] 'function void print(const Student)' has some indirect sub-type changes:
     parameter 1 of type 'const Student' has sub-type changes:
       in unqualified underlying type 'struct Student':
diff --git a/tests/data/test-abicompat/test7-fn-changed-report-0.txt b/tests/data/test-abicompat/test7-fn-changed-report-0.txt
index 36952709..78bd4485 100644
--- a/tests/data/test-abicompat/test7-fn-changed-report-0.txt
+++ b/tests/data/test-abicompat/test7-fn-changed-report-0.txt
@@ -1,14 +1,16 @@ 
-ELF file 'test7-fn-changed-app' might not be ABI compatible with 'libtest7-fn-changed-libapp-v1.so' due to differences with 'libtest7-fn-changed-libapp-v0.so' below:
+ELF file 'test7-fn-changed-app' is not ABI compatible with 'libtest7-fn-changed-libapp-v1.so' due to differences with 'libtest7-fn-changed-libapp-v0.so' below:
 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:
+1 function with incompatible sub-type changes:
 
-  [C] 'function float add(float, float)' has some indirect sub-type changes:
+  [C] 'function float add(float, float)' has some sub-type changes:
     return type changed:
       type name changed from 'float' to 'int'
       type size hasn't changed
 
+1 function with some indirect sub-type change:
+
   [C] 'function void print(const Student)' has some indirect sub-type changes:
     parameter 1 of type 'const Student' has sub-type changes:
       in unqualified underlying type 'struct Student':
diff --git a/tests/data/test-abidiff-exit/PR30048-test-2-report-1.txt b/tests/data/test-abidiff-exit/PR30048-test-2-report-1.txt
index 7bbbc2e2..30f08545 100644
--- a/tests/data/test-abidiff-exit/PR30048-test-2-report-1.txt
+++ b/tests/data/test-abidiff-exit/PR30048-test-2-report-1.txt
@@ -1,23 +1,40 @@ 
 Functions changes summary: 0 Removed, 7 Changed, 0 Added functions
 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 
-7 functions with some indirect sub-type change:
+6 functions with incompatible sub-type changes:
 
-  [C] 'function int(*N(void))[7]' at PR30048-test-2-v0.cc:62:1 has some indirect sub-type changes:
+  [C] 'function int(*N(void))[7]' at PR30048-test-2-v0.cc:62:1 has some sub-type changes:
     return type changed:
       entity changed from 'int(*)[7]' to 'int'
       type size changed from 64 to 32 (in bits)
 
-  [C] 'function int* O(void)' at PR30048-test-2-v0.cc:64:1 has some indirect sub-type changes:
+  [C] 'function int* O(void)' at PR30048-test-2-v0.cc:64:1 has some sub-type changes:
     return type changed:
       entity changed from 'int*' to 'int'
       type size changed from 64 to 32 (in bits)
 
-  [C] 'function int (*P(void))(void)' at PR30048-test-2-v0.cc:67:1 has some indirect sub-type changes:
+  [C] 'function int (*P(void))(void)' at PR30048-test-2-v0.cc:67:1 has some sub-type changes:
     return type changed:
       entity changed from 'int (*)(void)' to 'int'
       type size changed from 64 to 32 (in bits)
 
+  [C] 'function volatile int(*n(void))[7]' at PR30048-test-2-v0.cc:72:1 has some sub-type changes:
+    return type changed:
+      entity changed from 'volatile int(*)[7]' to 'int'
+      type size changed from 64 to 32 (in bits)
+
+  [C] 'function volatile int* o(void)' at PR30048-test-2-v0.cc:74:1 has some sub-type changes:
+    return type changed:
+      entity changed from 'volatile int*' to 'int'
+      type size changed from 64 to 32 (in bits)
+
+  [C] 'function int (*p(void))(void)' at PR30048-test-2-v0.cc:77:1 has some sub-type changes:
+    return type changed:
+      entity changed from 'int (*)(void)' to 'int'
+      type size changed from 64 to 32 (in bits)
+
+1 function with some indirect sub-type change:
+
   [C] 'function amusement* fun(void)' at PR30048-test-2-v0.cc:57:1 has some indirect sub-type changes:
     return type changed:
       in pointed to type 'struct amusement' at PR30048-test-2-v1.cc:1:1:
@@ -119,18 +136,3 @@  Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
             type size changed from 64 to 32 (in bits)
           and offset changed from 6464 to 736 (in bits) (by -5728 bits)
 
-  [C] 'function volatile int(*n(void))[7]' at PR30048-test-2-v0.cc:72:1 has some indirect sub-type changes:
-    return type changed:
-      entity changed from 'volatile int(*)[7]' to 'int'
-      type size changed from 64 to 32 (in bits)
-
-  [C] 'function volatile int* o(void)' at PR30048-test-2-v0.cc:74:1 has some indirect sub-type changes:
-    return type changed:
-      entity changed from 'volatile int*' to 'int'
-      type size changed from 64 to 32 (in bits)
-
-  [C] 'function int (*p(void))(void)' at PR30048-test-2-v0.cc:77:1 has some indirect sub-type changes:
-    return type changed:
-      entity changed from 'int (*)(void)' to 'int'
-      type size changed from 64 to 32 (in bits)
-
diff --git a/tests/data/test-abidiff-exit/PR30048-test-report-0.txt b/tests/data/test-abidiff-exit/PR30048-test-report-0.txt
index 26c04c6d..ccaac841 100644
--- a/tests/data/test-abidiff-exit/PR30048-test-report-0.txt
+++ b/tests/data/test-abidiff-exit/PR30048-test-report-0.txt
@@ -1,7 +1,7 @@ 
 Functions changes summary: 0 Removed, 0 Changed, 0 Added function
 Variables changes summary: 0 Removed, 1 Changed, 0 Added variable
 
-1 Changed variable:
+1 variable with incompatible sub-type changes:
 
   [C] 'S s' was changed at PR30048-test-v1.c:6:1:
     size of symbol changed from 56 to 16
@@ -14,6 +14,12 @@  Variables changes summary: 0 Removed, 1 Changed, 0 Added variable
         'int (* f04)(int* restrict)', at offset 192 (in bits) at PR30048-test-v0.c:5:1
         'int (* f05)(const int* restrict)', at offset 256 (in bits) at PR30048-test-v0.c:6:1
       2 data member changes:
-        'int (* f06)(int* restrict const)' offset changed from 320 to 0 (in bits) (by -320 bits)
-        'int (* f07)(int* restrict const)' offset changed from 384 to 64 (in bits) (by -320 bits)
+        type of 'int (* f06)(int* restrict const)' changed:
+          in pointed to type 'function type int (int* restrict const)':
+        and offset changed from 320 to 0 (in bits) (by -320 bits)
+        type of 'int (* f07)(int* restrict const)' changed:
+          in pointed to type 'function type int (int* restrict const)':
+            parameter 1 of type 'int* restrict const' changed:
+              'int* restrict const' changed to 'int* const restrict'
+        and offset changed from 384 to 64 (in bits) (by -320 bits)
 
diff --git a/tests/data/test-abidiff-exit/ada-subrange/test1-ada-subrange/test1-ada-subrange-report-1.txt b/tests/data/test-abidiff-exit/ada-subrange/test1-ada-subrange/test1-ada-subrange-report-1.txt
index 1ca7d2f1..75571524 100644
--- a/tests/data/test-abidiff-exit/ada-subrange/test1-ada-subrange/test1-ada-subrange-report-1.txt
+++ b/tests/data/test-abidiff-exit/ada-subrange/test1-ada-subrange/test1-ada-subrange-report-1.txt
@@ -1,9 +1,9 @@ 
 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:
+1 function with incompatible sub-type changes:
 
-  [C] 'function test1__my_int[6] test1__first_function(void)' at test1.adb:6:1 has some indirect sub-type changes:
+  [C] 'function test1__my_int[6] test1__first_function(void)' at test1.adb:6:1 has some sub-type changes:
     return type changed:
       type name changed from 'test1__my_int[6]' to 'test1__my_int[7]'
       array type size changed from 96 to 112
@@ -11,6 +11,8 @@  Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
       array subrange changed: 
         upper bound of '<anonymous range>[6]' change from '5' to '6'
 
+1 function with some indirect sub-type change:
+
   [C] 'function test1__my_index test1__second_function(void)' at test1.adb:14:1 has some indirect sub-type changes:
     return type changed:
       upper bound of '<range test1__my_index>[6]' change from '5' to '6'
diff --git a/tests/data/test-abidiff-exit/ada-subrange/test2-ada-subrange-redundant/test2-ada-subrange-redundant-report-1.txt b/tests/data/test-abidiff-exit/ada-subrange/test2-ada-subrange-redundant/test2-ada-subrange-redundant-report-1.txt
index eaf3e83f..ab3a36e7 100644
--- a/tests/data/test-abidiff-exit/ada-subrange/test2-ada-subrange-redundant/test2-ada-subrange-redundant-report-1.txt
+++ b/tests/data/test-abidiff-exit/ada-subrange/test2-ada-subrange-redundant/test2-ada-subrange-redundant-report-1.txt
@@ -1,9 +1,9 @@ 
 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:
+2 functions with incompatible sub-type changes:
 
-  [C] 'function test__my_int[101] test__first_function(test__my_int[101]&)' at test.adb:6:1 has some indirect sub-type changes:
+  [C] 'function test__my_int[101] test__first_function(test__my_int[101]&)' at test.adb:6:1 has some sub-type changes:
     return type changed:
       type name changed from 'test__my_int[101]' to 'test__my_int[201]'
       array type size changed from 1616 to 3216
@@ -12,10 +12,24 @@  Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
         upper bound of '<anonymous range>[101]' change from '100' to '200'
         underlying type of range '<anonymous range>[101]' changed:
           type size changed from 8 to 16 (in bits)
+    parameter 1 of type 'test__my_int[101]&' changed:
+      in referenced type 'test__my_int[101]':
+        type name changed from 'test__my_int[101]' to 'test__my_int[201]'
+        array type size changed from 1616 to 3216
+        array type subrange 1 changed length from 101 to 201
+        array subrange changed: 
+          upper bound of '<anonymous range>[101]' change from '100' to '200'
+          underlying type of range '<anonymous range>[101]' changed:
+            type size changed from 8 to 16 (in bits)
 
-  [C] 'function test__my_index test__second_function(const test__my_index)' at test.adb:12:1 has some indirect sub-type changes:
+  [C] 'function test__my_index test__second_function(const test__my_index)' at test.adb:12:1 has some sub-type changes:
     return type changed:
       upper bound of '<range test__my_index>[101]' change from '100' to '200'
       underlying type of range '<range test__my_index>[101]' changed:
         type size changed from 8 to 16 (in bits)
+    parameter 1 of type 'const test__my_index' has sub-type changes:
+      in unqualified underlying type '<range test__my_index>[101]':
+        upper bound of '<range test__my_index>[101]' change from '100' to '200'
+        underlying type of range '<range test__my_index>[101]' changed:
+          type size changed from 8 to 16 (in bits)
 
diff --git a/tests/data/test-abidiff-exit/btf/test0-report-1.txt b/tests/data/test-abidiff-exit/btf/test0-report-1.txt
index 7533965a..e82da79a 100644
--- a/tests/data/test-abidiff-exit/btf/test0-report-1.txt
+++ b/tests/data/test-abidiff-exit/btf/test0-report-1.txt
@@ -1,9 +1,9 @@ 
 Functions changes summary: 0 Removed, 1 Changed, 0 Added function
 Variables changes summary: 0 Removed, 0 Changed (1 filtered out), 0 Added variable
 
-1 function with some indirect sub-type change:
+1 function with incompatible sub-type changes:
 
-  [C] 'function void fn0(const foo_type*)' has some indirect sub-type changes:
+  [C] 'function void fn0(const foo_type*)' has some sub-type changes:
     return type changed:
       type name changed from 'void' to 'int'
       type size changed from 0 to 32 (in bits)
diff --git a/tests/data/test-abidiff-exit/btf/test0-report-2.txt b/tests/data/test-abidiff-exit/btf/test0-report-2.txt
index 7bc1f6d0..99381d3d 100644
--- a/tests/data/test-abidiff-exit/btf/test0-report-2.txt
+++ b/tests/data/test-abidiff-exit/btf/test0-report-2.txt
@@ -1,9 +1,9 @@ 
 Functions changes summary: 0 Removed, 1 Changed, 0 Added function
 Variables changes summary: 0 Removed, 1 Changed, 0 Added variable
 
-1 function with some indirect sub-type change:
+1 function with incompatible sub-type changes:
 
-  [C] 'function void fn0(const foo_type*)' has some indirect sub-type changes:
+  [C] 'function void fn0(const foo_type*)' has some sub-type changes:
     return type changed:
       type name changed from 'void' to 'int'
       type size changed from 0 to 32 (in bits)
diff --git a/tests/data/test-abidiff-exit/incompatible-changes/1/report0.txt b/tests/data/test-abidiff-exit/incompatible-changes/1/report0.txt
new file mode 100644
index 00000000..fa3f5602
--- /dev/null
+++ b/tests/data/test-abidiff-exit/incompatible-changes/1/report0.txt
@@ -0,0 +1,14 @@ 
+Functions changes summary: 0 Removed, 1 Changed, 0 Added function
+Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+
+1 function with incompatible sub-type changes:
+
+  [C] 'function S0 fun0(void)' at test-1-v0.cc:8:1 has some sub-type changes:
+    return type changed:
+      type size changed from 64 to 96 (in bits)
+      1 data member insertion:
+        'int inserted', at offset 0 (in bits) at test-1-v1.cc:3:1
+      2 data member changes:
+        'int m0' offset changed from 0 to 32 (in bits) (by +32 bits)
+        'char m1' offset changed from 32 to 64 (in bits) (by +32 bits)
+
diff --git a/tests/data/test-abidiff-exit/incompatible-changes/1/test-1-v0.cc b/tests/data/test-abidiff-exit/incompatible-changes/1/test-1-v0.cc
new file mode 100644
index 00000000..386f469f
--- /dev/null
+++ b/tests/data/test-abidiff-exit/incompatible-changes/1/test-1-v0.cc
@@ -0,0 +1,14 @@ 
+// g++ -g -Wall -c *.cc
+
+struct S0
+{
+  int m0;
+  char m1;
+};
+
+S0
+fun0()
+{
+  S0 s = {};
+  return s;
+}
diff --git a/tests/data/test-abidiff-exit/incompatible-changes/1/test-1-v0.o b/tests/data/test-abidiff-exit/incompatible-changes/1/test-1-v0.o
new file mode 100644
index 0000000000000000000000000000000000000000..a6ba6eb19bb964352e5da0deea4d6ad8cff7f487
GIT binary patch
literal 3152
zcmcIm&2Jk;6o2FO#%{K8lej?JAZ3F<^n+d7!A;XtDMleQQJ@Mzm4FJ|wY|0%>~&>t
zqO=^SgoK2`p-3D!aOA?7BS#MK4{+pyRH?^utHc4`8^3YZlSM@!p5%G&{pNkm%$r$%
zvi`>FDIq|SfU9t*DHLEkb0}A&Sb>v}hZ`H8KiK$b{V_os2kVdD|M3fyOb}T@QZy{k
z5U1IgV!U01tPt6^5EI=Z7#WgKEI~T^4oYcAr_CUYz!VcSBL|U{HM#^asi5MU%mBpX
z1kI(sY-6Y?FtRHP;)-?I+RQIo2+xQYa(T;`pPQc%vzh5<0F1mavX-@Ck(J0}+ULQt
zu382z!(=gs$zAcvX(Kl@3v-)!@~@n_dm129rZm!jGoLzz*<YdxWOZ^cq(p<NbOf+)
z9k~fvIFDQi@kefo7%dckD9p<>r^I~f#4xP%GX)$Qsb|cIEpzfyQ*5PD=yL7)4SVgv
zh0-OvRB|u6MSHQhST0^FUAE8e_zio*i+IAhc+PgZ(QfFkw*1iV2X$1ve!acAzr5ru
zm7Tps+i5}dy>fFmEbak~P;YyEi2On1l$^byTdzZ*-Rt^=Mz8T<P-q2Fp%c`+TF~->
zPGNiJ<<e4lu|W2NLc@zZDLOdc2%1gD-$(l(toORNy(p-4d<VmaEq_ob{a<0nN*`0;
z+S=NReHORx+&|bkc?>7zi05>72gLrgm^+@y-p2!b7IFF!$%B72H~m>^ZEE68G#J8(
zBb{{`e*ZIR(n!3a*u>m!x{rY~Nn~J#Br=AV?8uY>u}2^_YrwIXb|@Nvmo0$|IG%t~
z{dmO^$bb_GDA`XP!70LQY=1_VZR~(Yjf~fANR!Cq)55xnOn7{CDjwnVQ}i?o3RnJT
z7^m|bT~n0L$Lv)N1l^3`l=lPHZ)y0uthY3LoAn-ZJ+E3L)oHQ~v1yid`{x)}>uRu0
zj~kJ~e;BGzVy^I?S--+uk8d+hdlTOua0hp~kyk?=^@qHzq{!coz@;|?+}dCOZr|^C
zZo{wbwyHtc?BSf0y;`mB?~P4+efg-2VVxlKl?$d&BEeOu<D=B|@eAaJy~ua*Rd5E8
zSO18E`0Z-5?{$4%$bV#W=udm3&Pj!<u%P-+;ba@91yl&rZ~RW&C?@OvFX9~a<G=N%
z^VefiI+g!EDKXM*sjui&s>E!h$j$nQ@fqY~r|u4YaEVs&r^h7xHyV)c4B2SZZR!5#
z7#ZJWusHG@3cBqU!b$Z%;`)_8)laXfUO(M0JtjhMz@XYk!iaR+Dq>0bZEmPr<b*`|
z>3z}j-$smLsyb1W^eZQ-D}cGmulUD^C;3<Sa{uxK|AW8re~KHj@C5&_*k3b)*Yt*F
z168-O|Bn5~-Xg>{*ne3WGFSVj;BQe#+W&jJ|Ef=E|LLoy{1s01=(!Psdz`<`1=Bk~
j-#Xo&&NOMM52+|5{I5Gk`ueG^B>%6u{_n@UkM`eR<d^q+

literal 0
HcmV?d00001

diff --git a/tests/data/test-abidiff-exit/incompatible-changes/1/test-1-v1.cc b/tests/data/test-abidiff-exit/incompatible-changes/1/test-1-v1.cc
--- /dev/null
+++ b/tests/data/test-abidiff-exit/incompatible-changes/1/test-1-v1.cc
@@ -0,0 +1,15 @@ 
+// g++ -g -Wall -c *.cc
+
+struct S0
+{
+  int inserted;
+  int m0;
+  char m1;
+};
+
+S0
+fun0()
+{
+  S0 s = {};
+  return s;
+}
diff --git a/tests/data/test-abidiff-exit/incompatible-changes/1/test-1-v1.o b/tests/data/test-abidiff-exit/incompatible-changes/1/test-1-v1.o
new file mode 100644
index 0000000000000000000000000000000000000000..0350277574c21c30efa35178ccc7619c12fd7c8d
GIT binary patch
literal 3248
zcmcguO>7%g5T57tI!-omlemJ0AjLsN^oL#B!A;XtDMpd0qXG&+5vUTFwY|0%>~&>t
zqEL|F0+Pw4NWCDzjSDv<jvT4fiaU2Mm3nNY9+0R6GwXTI`gKteLX5OKGvEBYdGmgD
zKP|oXYD@@_B;XPpX%YqaVd6+G24WG8LmGC=gS+M1rF#V3F5M?qJ}liU4@wUYOZNw*
zN2onKeEm^*@XNbDe~nfhM3TH>^jfA@n9Pu(y_JJ$A(HPQ7AIV26C{J^<RBi1anZ?x
zo^%jQf*#jh&xeFakW)~vm<;A(5x^uz5Z@&GAdCdrVqd+3S!X~?t}ly=#sy<5y=EXh
zC!SBG4Q*+0X->>f%svgErG=I>jCF&&L>ddjsMJs$2I(ikFfJJyPBOt_3ahci%L~%c
zOKqhoVe!QE1uVQk;|2-0(y<d*&Wlu1P;StvK%$o{eFU)ZCUPAca0a;$;*Zn}F`79(
zC@cj{h>4}xv0>UEP8TpaQng8;C$8vIcXg56i^VX?_4-cFcj{2NT4?NfxqYBFTz+FW
zvw8Mx{(L5%x6WC)%t~&hkUO8hkU6#E)H7w<XM=g}bjIxXd!Dn=bUdf$)=;&3wbsVL
z+N!x)F!xt7W)o^Hy9e1;x8r2%-TDV^w(0uWwp+EUZqs(#+3lT|@~efFtnc*weztD=
zb|9K)ue*(g=^UWH>(#oQYqsxJ+m4ADy{6O8=7D0&yt$vZYPJ7mjIjaX^5*7x<`g#U
z^grlTuq608&VsnU1L9y-EKW}(Z{Yepi#R<*!9I8;HTy+ub0*P3hanvKrlpU=gFmB;
zTI5N`P0qVdjnU8&McVLqK4#J&IEfK>=rRdeHJA)(N1_IJ7$Zo7=?IkS#}gMp8XSv2
z$$#cCoHERZ`ZGFvV{1G*8+iJLG=(fYYnhpFnjPLD0nIZfoSwH?e@ekwg=bix^&FjA
zl+Q3uIb;n4T@2yjuC^4s$$Ce@WqrPa%Uqu@uGS;xPW9;QLu{61)&Duh$)BD&>vRVa
zN&Kgw3VG%dzr(tmubMx@cIsKUZ(#L5>iBjQx!)V|mXv(wzz2)&8nCMUK3F}cZCiDx
zy4S3@UZab)K(?#Zp0ht@wtK<lGlsQY&ygWGgcJ#`1Ug<`9S6T$me=(i3oi__@7uKx
zIf>J%G<tT2zH$EnEn*Jpkz6O4vdF?{pR-QBVOmCoF!d&o`zP#6vKs#aVzf{HZ9J{N
zniC<A<9|y^h*V$NSM)Pc4Ec~)=FOVqfH}m-Po63IE)#9wqvj-hioq{Q36bi%jW!h{
z_nQpnLa`*OzE=>7s(+goRK`>Nbjzys)A>?!A_TV>+$AMMs&55tQR9Ec<G;_bG(O!G
z>iE|Xqnxr%6a!k|!`YSqb2+}`A0r+W|2fD1`h@tyzlp!f8#4QZ_?sNBxWPc((Ci@V
zmj2&!{McQD*bR<fla9<~|0Mh!3Q_(4jr%Y6DfOSeb~0Y#RF66~LU4!2Z*jqN|I;^6
hji)t@nre>EkNm!&TR`gksjjH_-?{!DIZiS){x3a|3-bT~

literal 0
HcmV?d00001

diff --git a/tests/data/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr1-output-1.txt b/tests/data/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr1-output-1.txt
--- a/tests/data/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr1-output-1.txt
+++ b/tests/data/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr1-output-1.txt
@@ -1,7 +1,7 @@ 
 Functions changes summary: 0 Removed, 0 Changed, 0 Added function
 Variables changes summary: 0 Removed, 1 Changed, 0 Added variable
 
-1 Changed variable:
+1 variable with incompatible sub-type changes:
 
   [C] 'int S::* pm' was changed to 'char S::* pm' at test-ptr-to-mbr1-v1.cc:6:1:
     type of variable changed:
diff --git a/tests/data/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr2-output-1.txt b/tests/data/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr2-output-1.txt
index 91c0f670..2b79b7f4 100644
--- a/tests/data/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr2-output-1.txt
+++ b/tests/data/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr2-output-1.txt
@@ -1,7 +1,7 @@ 
 Functions changes summary: 0 Removed, 0 Changed, 0 Added function
 Variables changes summary: 0 Removed, 1 Changed, 0 Added variable
 
-1 Changed variable:
+1 variable with incompatible sub-type changes:
 
   [C] 'int S::* pm' was changed to 'int T::* pm' at test-ptr-to-mbr2-v1.cc:6:1:
     type of variable changed:
diff --git a/tests/data/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr3-output-1.txt b/tests/data/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr3-output-1.txt
index 939fae6c..7e9264a3 100644
--- a/tests/data/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr3-output-1.txt
+++ b/tests/data/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr3-output-1.txt
@@ -1,7 +1,7 @@ 
 Functions changes summary: 0 Removed, 0 Changed, 0 Added function
 Variables changes summary: 0 Removed, 1 Changed, 0 Added variable
 
-1 Changed variable:
+1 variable with incompatible sub-type changes:
 
   [C] 'int S::* pm' was changed to 'signed char U::* pm' at test-ptr-to-mbr3-v1.cc:6:1:
     type of variable changed:
diff --git a/tests/data/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr4-output-1.txt b/tests/data/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr4-output-1.txt
index 617257b0..0bccc491 100644
--- a/tests/data/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr4-output-1.txt
+++ b/tests/data/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr4-output-1.txt
@@ -1,7 +1,7 @@ 
 Functions changes summary: 0 Removed, 0 Changed, 0 Added function
 Variables changes summary: 0 Removed, 1 Changed, 0 Added variable
 
-1 Changed variable:
+1 variable with incompatible sub-type changes:
 
   [C] 'int S::* pm' was changed to 'double S::* pm' at test-ptr-to-mbr4-v1.cc:7:1:
     type of variable changed:
diff --git a/tests/data/test-abidiff-exit/test-changed-var-1-report-1.txt b/tests/data/test-abidiff-exit/test-changed-var-1-report-1.txt
new file mode 100644
index 00000000..e8b52306
--- /dev/null
+++ b/tests/data/test-abidiff-exit/test-changed-var-1-report-1.txt
@@ -0,0 +1,24 @@ 
+Functions changes summary: 0 Removed, 0 Changed, 0 Added function
+Variables changes summary: 0 Removed, 2 Changed, 0 Added variables
+
+1 variable with incompatible sub-type changes:
+
+  [C] 'S0 v0' was changed at test-changed-var-1-v1.cc:14:1:
+    size of symbol changed from 8 to 24
+    type of variable changed:
+      type size changed from 64 to 192 (in bits)
+      1 data member insertion:
+        'long long int added_member', at offset 64 (in bits) at test-changed-var-1-v1.cc:4:1
+      1 data member change:
+        'char m1' offset changed from 32 to 128 (in bits) (by +96 bits)
+
+1 Changed variable:
+
+  [C] 'S1 v1' was changed at test-changed-var-1-v1.cc:16:1:
+    type of variable changed:
+      type size hasn't changed
+      1 data member change:
+        type of 'int m1' changed:
+          type name changed from 'int' to 'unsigned int'
+          type size hasn't changed
+
diff --git a/tests/data/test-abidiff-exit/test-changed-var-1-v0.cc b/tests/data/test-abidiff-exit/test-changed-var-1-v0.cc
new file mode 100644
index 00000000..2debc179
--- /dev/null
+++ b/tests/data/test-abidiff-exit/test-changed-var-1-v0.cc
@@ -0,0 +1,15 @@ 
+struct S0
+{
+  int m0;
+  char m1;
+};
+
+struct S1
+{
+  char m0 = 0;
+  int m1 = 0;
+};
+
+S0 v0;
+
+S1 v1;
diff --git a/tests/data/test-abidiff-exit/test-changed-var-1-v0.o b/tests/data/test-abidiff-exit/test-changed-var-1-v0.o
new file mode 100644
index 0000000000000000000000000000000000000000..de2628f2ba312d31c40925fff7e8bfd8e0c0412f
GIT binary patch
literal 2712
zcmbtVJ8u&~5T5heiG#@tOArW<GXfDF_cA64pae@1BnX5e9(8oK5BtE6=zN$U3QD9<
zP(VRR!JnX`gPtG2Z=j}tne}eG*_;J}k#6UkZ)SF8_jd1I-ner!Wf&mEfE5^6k_DI<
z8Q?O9WjF-W@CI=Pj4V-U8VWQ>N!@qBSV7BZxxhvVA@m@fy@4nVnRF&>$1q~>*;DsD
z7;TE^F&@IB5Aeh^u$~L!C(%E~aNxpv9!%arIH1572bR5BFs|jU<Zk7casa8k!Lqr6
zAPZR|55P*hQHAua{Pm-$8SH4<I5UyYvANl~sUx_s(~!%p<QT4QM8FBGbsV1*FVC0F
zkvbI7$Uqj(qc#lV=fpTE+EsiI%<&CQ8FQ)0{xm#!?e0T!^}+>j(eym~vhA8hw^(u)
zy({MYy`W~U`>}9Xm(Q72D}LGzmg_+~h{7tGepGENZ!axa3ni;pG_5*R8-4_F(2Xrb
z?RrqNdVXYiR?oGoRd5=eR^Ze+wa1}T4`ZhpR{Tm>_rs>Maqp71P%1iG5oLEB8moRc
z=sKl;O&i+APzS87u3k0gaZ}Fy#eVP&OdM#d)9~Y0l9MH#bUYg3?dmxUJxRj)Cx4%d
zfpTdSFN0CV8bAhP14BU!@C+vigM$ey^-rgCzc3izM;=3FT3MGo(I*5iZK;Q!D7>6_
z8D-o7%vV=0D-*A-@(|i2#M2|?umF-jDs1YPgm_tt>~$JYh^P5C$Uu44SNu)O9*Eje
zcy+gA&ooa)#E?2AF!A)r`7dhxD`9&Y|3TPbcb~Unzk)iB`nn-e9Bjv6*ZkNAyVC7~
z9R*F_t_78+_06#TsDnO^{YoVYdVAb{L|1%oN;7N+G6hRWNc1MRtDROWz|XJU?!<wO
zSIz3ie)Wm$^uP2hX4Bo1`za?YOQ31~NmRH3V&e20S5{(FsOO(WC!LRB`BQ4Lh*c?i
zfBKx{FVleXwy$<aJ(kV|{SV8#5q+@1f06*71wV<JD0!CgC&XnLM}1CmeB)jKUudcH
zSUR6NN3kVAnq(-V$KFO?QvXxpQpi53fBKr~{nwDw=R^t~2y%f8MfBKB^d;4w7xm?R
zr}}i?_4-@L(VQ+ms_ckD4^<MetS|Ko!Rh(mMZl*&<i8%0|6cs@oj>Hi6Zu*gd=dFN
zFZ-4}*-4>a1=$b@Qy53zMScHhPxZTl6u9(KP)t4!2EG0?x{~s@#QXa=NaaY+{|%K^
B(b)h1

literal 0
HcmV?d00001

diff --git a/tests/data/test-abidiff-exit/test-changed-var-1-v1.cc b/tests/data/test-abidiff-exit/test-changed-var-1-v1.cc
--- /dev/null
+++ b/tests/data/test-abidiff-exit/test-changed-var-1-v1.cc
@@ -0,0 +1,16 @@ 
+struct S0
+{
+  int m0;
+  long long added_member;
+  char m1;
+};
+
+struct S1
+{
+  char m0 = 0;
+  unsigned int m1 = 0;
+};
+
+S0 v0;
+
+S1 v1;
diff --git a/tests/data/test-abidiff-exit/test-changed-var-1-v1.o b/tests/data/test-abidiff-exit/test-changed-var-1-v1.o
new file mode 100644
index 0000000000000000000000000000000000000000..8c35ff9efafa0ec2b012bac7973eb73b9bd579b7
GIT binary patch
literal 2872
zcmb_e&5zqe6n|qUtXs2bwvnKvg>|Y{{j?pY>2AAdOQaRFRjaD%svMB2l@m`Bm)I$`
zH!4C1frLQf${)Z12@V{31O5a486-G!fcNZ~#GQ52O7uy7AHVlC9?u*3i}&w*pfLuL
z7+i;iB~gIiUR&t>T<ybASc6|suLCm(suODylceu<;267uCW|_tuaE|LC01MAMcrVL
z2X*5kRGY9;tA}w0nvoaMSRSbFdSDn|VE~mloQI<7f!QRm23l<eCDdjeXuN~UA)QR3
z+RTHdkIDi9whFqj)n@OS*UVe3t0sVU8cg%LsW$-h7Sj#WEZl8_wXjBS9^bCrYQ1+{
zJBBa1#?CZaroMh+z4<1-5Y}vLnTwJuq9pCgNqjVX@LhARvMvI3^j$#782hKON`gKC
zKB%md3L0D2jud6cg#9=TM==j9+OQjUA6PpVFM6An=Q&rLj@9jSd!0@1nsx3zhTQZs
z;jpiqx9lj}kNNh9$2<v#X!^-;y#4g*hP~0VXI;x4fgc1s*o$~H;0X-JegczeJhE~|
z{oL_1;%+bv9*6EI%-l&h@CV_@4=3)u`<K0qUe|q+WIWAMm-x_6dFu9nbQ{aXBOcf@
zKe0V~<~hURE3db-5!~3>*|N^zew}}bt;#og8KbXKgTMc+^6QlogvU!91T{xTPZjCd
zp^EfkgbuiL$S0u!KXd>iKnFbj6{N%K6)45yj8u>gs|V1x5Lqj|7fwx1Zwp-7^PyP!
z(QvMDj%D0o%r9L<^Uj3RTgsIjMV*LndN#>GdZQ3?T$n)XC8Ai_i|igTBw7DqVZw((
zN_;A8>6iFpfq$*U3lqK<3Y{mpc7lE?;pJVI?@smeYf{9W5|VIw?g{&nf`21yPr-i>
zHaO|0QRWX&W=SE(Qp@<$44lBvd~gP73Qoc&z7z1l{%9|ZA5GDh>;7Pn@Y!>2KcTUI
zK4lWdT&7?PsS>=G+rw!TalCJwc$#qsr`Aq0fB3On>Hm@^Fq`&V?x!r)mx?0uTeyU^
zQ725D+<qyhtg88E(MjiQS-w?HM!l)n^!?PD6w)V#^sEqbuEx^2pxdQCk0_L%#g$`-
zgd+$OBxgd-?KWa+O{(x0F{DolG3RP5olg~`U|)b186{F<Z=<hj{m;Zu$aT{C=~h(N
zA0VdIL<qhV;075bQe*efSJnRy(f_8%rT%m;sr{cIMm0P5l<8N|=<_m&y6i9IX9836
zd*UbI_ZQ@Uw<P~hk?+1BpYAQWmU8Gx^*{@!8cVilRZa&><c~!{6TNgVs{2QKTGi@X
b`Y1?N&KFGWzlN@={HC}Neq5yHnwtL~o6qMO

literal 0
HcmV?d00001

diff --git a/tests/data/test-abidiff-exit/test-crc-report.txt b/tests/data/test-abidiff-exit/test-crc-report.txt
--- a/tests/data/test-abidiff-exit/test-crc-report.txt
+++ b/tests/data/test-abidiff-exit/test-crc-report.txt
@@ -1,12 +1,12 @@ 
 Functions changes summary: 0 Removed, 1 Changed (1 filtered out), 0 Added functions
 Variables changes summary: 0 Removed, 1 Changed, 0 Added variable
 
-1 function with some indirect sub-type change:
+1 function with incompatible sub-type changes:
 
-  [C] 'function void func1(E)' has some indirect sub-type changes:
+  [C] 'function void func1(E)' has some sub-type changes:
     CRC (modversions) changed from 0x10000001 to 0x10000002
 
-1 Changed variable:
+1 variable with incompatible sub-type changes:
 
   [C] 'int var1' was changed:
     CRC (modversions) changed from 0x30000001 to 0x30000002
diff --git a/tests/data/test-abidiff-exit/test-enumerator-changes2-report-1.txt b/tests/data/test-abidiff-exit/test-enumerator-changes2-report-1.txt
new file mode 100644
index 00000000..9666a8fd
--- /dev/null
+++ b/tests/data/test-abidiff-exit/test-enumerator-changes2-report-1.txt
@@ -0,0 +1,3 @@ 
+Functions changes summary: 0 Removed, 0 Changed (1 filtered out), 0 Added function
+Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+
diff --git a/tests/data/test-abidiff-exit/test-enumerator-changes2-v0.cc b/tests/data/test-abidiff-exit/test-enumerator-changes2-v0.cc
new file mode 100644
index 00000000..f6a2cb66
--- /dev/null
+++ b/tests/data/test-abidiff-exit/test-enumerator-changes2-v0.cc
@@ -0,0 +1,15 @@ 
+enum E
+{
+  FIRST_E,
+  SECOND_E = 1,
+  THIRD_E = 2,
+  FOURTH_E = 3,
+  FIFTH_E = 4
+};
+
+enum E
+foo()
+{
+  enum E e = FIRST_E;
+  return e;
+}
diff --git a/tests/data/test-abidiff-exit/test-enumerator-changes2-v0.o b/tests/data/test-abidiff-exit/test-enumerator-changes2-v0.o
new file mode 100644
index 0000000000000000000000000000000000000000..515d10bc6b9193df218ecf2b67ee95de44eb99c3
GIT binary patch
literal 3304
zcmcIm&2Jl35TEC@lQi47NsJ&R6>$-Wv}M;HO_Q`GsZnqmD<}<aA|#~BUE6DWX}qrN
zO%#d*H$Kz@RDv547Y=ad(i0aBT=@q$R^rN;N-*>Gjk9?y3IZ|GzM1*W=lirjEWf#)
z5CWJ4tiqATD8R3yM{-GuC3prhu)Fc;lb^~@33*t4dgsSSD5OA)5s;waJPlErj3`DK
zMw53C5Mo3!X_NKCo)S_v<d}qHQg)GQ^?D#o3EGitoLPJ|;)0kMCtKpt9%i2hBYn<9
zZA!eH&X~sB?A(-?9-Vv+z(@*XY}GW)O6Hn*-Mngw3_$WFFwIrdNaJK|apSBp7TWxD
zB}0LwnFnV9Mizh#l}us=tG!AUWk+%Wq(lREHUyNgg**jga1pr>;`j6fF`5{DD9p(@
zCd6FgOqf>2r39QBs)i|2<D2^_v64t&$i6@D+P>S&dVT=ww|1*L8?`d5SE{#nkl!w^
z-P(Esg`JH`mH2vPT{_&{+Rd(Ax>Q)o77F$iJD)A)iwpUs!qx126_af^fihTEE@Z84
zu<yGoZP$1EUISI9-{`CyE-zY(3)Vp~Yqg>F&Sl)B1ITrHT{qY4HQ)7eZ7;~}d3C4m
zwH<FSw_UwlSX?OP0(TG$a!n_2q-deN>9tyxd*}r~M$7g0yKdhJdVQ<Was0MBC|U=3
zyV3Z+)1OcsZmz9e%g*E4UHAvfCbtgnOi1EE6~y7Bm_0o@_BrnIIfUsWlBebM^yEj0
zwTY2UbO_<tkq$@_e)}WNXvE%RJo4&{>M;gd;>f@Xab&<q9E@2ak4418fKw6eNHhSi
zW(*l{ItHcw@m|J|0cT=R@}Kw%o<(FjvOdEbdcvOb!R9>~$2`$h;7WwkY?tsOnhqHd
zPG3ps&nnKiQsH?e(EbkZI?5LnPX62jK{p~e)#bcp4SzxDn;QO#(%;f>p3mDFo>Tf=
z4Oc4Qt1F56q<%gQRR|Q<=f!JC{wd`{jQ2(Ne^L36KYcZ&(+f<*_}8Hd1;rWvLFv~O
z*Yjr;PHP`sf3OGdbpxl4Jm`nK!&2ZL24K@m26lZg0K4z*Id;>n@3(87-|C@F%1*uB
zcMp!4oxXh6j$wPA?{Wy1V3FXO)Em8S*TrYv_IrVA<1=Ip0;h3LC2>2oR^REmY9jxU
z&0;*Q5$_YHD=C5ZiE;9c(s@(}(_fhFs8dAN<LP|TdH=WZwEuceD#!J|Bqc(+FP$rT
z1xpbh5|`Cs-Btlph>;)PP5M_rw1S_Wlkg`rAbBAhj=C@Psbl24rNI0!G8A-Qy6<uQ
zf1);&<Eejoz4iW^i0L^If)5l}B_%?-FWt|$`j1upyDFCI(|e)UzmFK@<UUc9^s_4T
z83T%Qedg~Y9v5Fzm;09!;vfD^{A=n!@_Wc>xGwWAR6N_6-_sAYGH@LGeTM>J$KE2;
z@2mJ_c2u0#kKu1nh+F>|+H52~r?md`E6VYV$JM5|Z&m${YM6fK=+{|~r#+3E>ZH0q
X^JtHfK7Z;fE<UgN|2`UwvL62@!!iw@

literal 0
HcmV?d00001

diff --git a/tests/data/test-abidiff-exit/test-enumerator-changes2-v1.cc b/tests/data/test-abidiff-exit/test-enumerator-changes2-v1.cc
--- /dev/null
+++ b/tests/data/test-abidiff-exit/test-enumerator-changes2-v1.cc
@@ -0,0 +1,15 @@ 
+enum E
+{
+  FIRST_ENUMERATOR,
+  SECOND_ENUMERATOR = 1,
+  THIRD_ENUMERATOR = 2,
+  FOURTH_ENUMERATOR = 3,
+  FIFTH_ENUMERATOR = 4
+};
+
+enum E
+foo()
+{
+  enum E e = FIRST_ENUMERATOR;
+  return e;
+}
diff --git a/tests/data/test-abidiff-exit/test-enumerator-changes2-v1.o b/tests/data/test-abidiff-exit/test-enumerator-changes2-v1.o
new file mode 100644
index 0000000000000000000000000000000000000000..db0295256dc0d70d15378518acc680ed45391da4
GIT binary patch
literal 3344
zcmbtW&2Jl35TCbeJ88CYoftt&DrJj6q%FIS(=<(6C3R$+#tJ0CO$0)!oVC5N7wk2%
z*HI`E+>lT?PzfZEkhpMx6H>2;3kR<K2ave*58zBCn0fo2yLnk;L`T}4ncsZA&)rW-
zZ>(#Kfg}d2@Klp1KxX`@T;O5>o`WpxZG86lx6%_r?w6k2{q+F~NnqStBlH5jqLhg!
zdI`o7cM)JL#TmEp`e9ERmv#P5Kq4_l4#|UV7ns38n@5B%nVEf?a)C`wkWG8g#_V&T
zr_URxO|e(fSwo+lnVn+OW0@BK^aRt#R}I4`XKxrcjq3)>0wi7r!&o)+G#0bjt#kT#
zX!FzMECm+M-a7}7S_Ek*XSK6f?KP^%n~6*p>asI#ioCW^PQo}`Le3cbD?Le!28Is`
zvwVyio7K*QX?bjt!KtCD8!S1oIY_b<O~a6Z-}jon+b}&pfIFq)_SWmw($?OarOMjw
zb_I4f%9UfldU<_!BkFN`YtJlRzMQ{i=JWPdd){1_Us#;KmcMS!RWR*_69|KK^`dEY
zf`RX@G+p2Ad398sUcI$)w7g_3En0^QrqzV%yH{|z4q?4qxw9KBw7$JpIbJ$&`+?>9
zgO1yCf^N^Mw;aFe_7|+fyj`zDuGQ_hxkk6~o|kKSL9Xr9oSN5kymoG<awWgCxR9d^
z{anKd94=aDZ+Hg>mV4v{&m2FZy%A=(T`b-(=Wu#2{)d^xvlSA%R{?gEVKb-4#=pSb
za2{cLi1@BrOJ_dSij%2LbO_<tH*KT@{P}mBQI9?Gcr?UbR%3Lu#F35_;z);79E@4`
zaXw+w;nWF?03GlM$B+)EV^H$P^BY4toQXlnfAR!wA~GGBpW#U!vD|Xo%Qcz6JkeQ@
zl?bQNuHi#89Wo%C9!bv&LE^JQe^GE+-{GBr@+E<jzwCjaTM?Y<ek1gfg3JCk6<pSR
zOTm8>`r8UVFZ6u{7b@WG%!&G>e(3u_6oib=d~{rL4#__$e2B?)QRm?$;Y0rPRE17A
zHIc->3suMqF7aQ4ep7HYzbSC)G1@2C{SP~VQ$rr~Lf(>6;2s5F(=7#dt=|W`=e8ZY
z;noJts^=ec(Z*$`R_nQk$IMQTUx~-Cw&%Mt1WQPf;40Va-A>2F&w=fC1J}kI$m$19
z{e6+dZB-9?PRA7kc}6ya@ia$ron*R#5ac>ZoP48n0Tsg38)hf!6p_{VSJ6iM{r|?(
z`l~sqoUH#9DG^eAX<yMTScv$LxGy&AjtH1SjQr%;q`wEE6@1j3gg>Sik{7b!TlJ+r
zRg9ds1UNs83<cGf&U;+{KZymE@zg)v-fI61#MGP!!N&rukP;!)m(FKg{XazgeGyCb
z>Aq0we}EX}lzpPe>5(Y(vjhZ}^(FrZ@woWU#o_*aMEw1KiTA{Y%#DcuQp786@U^<3
zg@f!{`u`x}kKILx$@pdID7c(I34f15-24~Br&{h)nt%F=%6N%WKWc4+;F0LRB^svh
k9DSYDcv{oAp)QN_Gl%vlspF@<;^N;C{XdKbqpZgN1A(_4YybcN

literal 0
HcmV?d00001

diff --git a/tests/data/test-abidiff-exit/test-enumerator-changes3-report-1.txt b/tests/data/test-abidiff-exit/test-enumerator-changes3-report-1.txt
--- /dev/null
+++ b/tests/data/test-abidiff-exit/test-enumerator-changes3-report-1.txt
@@ -0,0 +1,3 @@ 
+Functions changes summary: 0 Removed, 0 Changed (1 filtered out), 0 Added function
+Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+
diff --git a/tests/data/test-abidiff-exit/test-enumerator-changes3-report-2.txt b/tests/data/test-abidiff-exit/test-enumerator-changes3-report-2.txt
new file mode 100644
index 00000000..c41c8507
--- /dev/null
+++ b/tests/data/test-abidiff-exit/test-enumerator-changes3-report-2.txt
@@ -0,0 +1,18 @@ 
+Functions changes summary: 0 Removed, 1 Changed, 0 Added function
+Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+
+1 function with some indirect sub-type change:
+
+  [C] 'function E foo(void)' at test-enumerator-changes3-v0.cc:11:1 has some indirect sub-type changes:
+    return type changed:
+      type size hasn't changed
+      2 enumerator insertions:
+        'E::SIXTH_ENUMERATOR' value '5'
+        'E::LAST_ENUMERATOR' value '6'
+      5 enumerator changes:
+      from 'E::FIRST_E = 0' to 'E::FIRST_ENUMERATOR = 0' at test-enumerator-changes3-v1.cc:1:1
+      from 'E::SECOND_E = 1' to 'E::SECOND_ENUMERATOR = 1' at test-enumerator-changes3-v1.cc:1:1
+      from 'E::THIRD_E = 2' to 'E::THIRD_ENUMERATOR = 2' at test-enumerator-changes3-v1.cc:1:1
+      from 'E::FOURTH_E = 3' to 'E::FOURTH_ENUMERATOR = 3' at test-enumerator-changes3-v1.cc:1:1
+      from 'E::FIFTH_E = 4' to 'E::FIFTH_ENUMERATOR = 4' at test-enumerator-changes3-v1.cc:1:1
+
diff --git a/tests/data/test-abidiff-exit/test-enumerator-changes3-v0.cc b/tests/data/test-abidiff-exit/test-enumerator-changes3-v0.cc
new file mode 100644
index 00000000..f6a2cb66
--- /dev/null
+++ b/tests/data/test-abidiff-exit/test-enumerator-changes3-v0.cc
@@ -0,0 +1,15 @@ 
+enum E
+{
+  FIRST_E,
+  SECOND_E = 1,
+  THIRD_E = 2,
+  FOURTH_E = 3,
+  FIFTH_E = 4
+};
+
+enum E
+foo()
+{
+  enum E e = FIRST_E;
+  return e;
+}
diff --git a/tests/data/test-abidiff-exit/test-enumerator-changes3-v0.o b/tests/data/test-abidiff-exit/test-enumerator-changes3-v0.o
new file mode 100644
index 0000000000000000000000000000000000000000..00ef608f222a630a1b0dcb20178e7eb41602e959
GIT binary patch
literal 3304
zcmbtW&2Jl35TEC@lQi47NsJ&R6>%#NY0IwdBu&zmq(Q-Mte`ZwiI9*gcWrO%rSZD5
z*HI`E-1txrPzi2GTsXj)OHW)laOEH1SgBXeRDzkeZ=B6zQ4k$z-^~2x^L^T%6yGT&
zga9T1t8k<-3h;FJNM4iT8oU4**xmTz$*;v{ggh)hyYtH<6jC5Y2uRRyo`xumM--z7
z!^t}c2r(p?w8{EmPYEd-a!f)pDZ5DRbvhtS3EGitoLPK3<boI*C0pXrK4zZ<BYn<9
zZ9=@3&X~r`^vr~q93FoOz(@*XWYsjya^{+O-Mngw3_$W#FwIrdNaJK|apSBp659N9
zIYWVKQxDDp3@rc~%9+FzR(pdg%8uj$NQnmSYyc=>3wa7g;1Y5n#GmOgVl*-QP?(W(
zOo*ApnJ}%4O9?nNPz_V0MmPH@v64t&NZ;>yP2X)~JwJfbt=-DbMzsi~a^?08^4rDr
zTU&3Vu(MIF5HFQW(&6UTZg&0h<-$_7P_VDq`RrVNZXv%^xSE}<V6qJ-PzLMD#jMp1
z`o6o;bbYt$)lqf2_14Pa@}jl4U>(e5ttM38pT|u)fWYkqmh1Q1Zr2GqU8~-5{HEKR
zw+`}ly$-onr|sq%oyG@VuIUB2eXr)!yr$#r=e8^Jg~f%r9A)U`8cyIy(L#H}+uO6;
zLoayl_!HVY!3;Oo*RN$~aqTYthh>vnhj%6<@t^|Ya9m8E9v=A$cljK`^byI^@>Y8M
z)5QAN&?Y*BaO_A2Bnf}~6=yVJZ!#Wvbw>3V11)i6V1+m`U?>j8ERn||;$gt4h;}3z
zfLAky3^*NwQvY}_W5|FrF(~<u{R7V;G8tK)!3{lO&-q~Uo{VCi=qhj}!fCck_z_Kp
z3<#%>=|v?lKBM%P6{r0j+;x;MDV+Sd2ZC-yaH`9BiyHol(l<5yb)~<n;XI%BG(4yD
zyBe-kz*koi^-2AF7OD^^uFs3tko;51hZygR?tek~kUxD@rPB*c#Q1li3I)X(|5@qR
z71#4;6;5j(U4O89AGQOhhCJwoyv0)B9tL33Qw4Ud*8{uj?mKqFt@WE#&)@5yP0CKK
z)^!h#nVqhD7ms24p6_x9mSB<Ks?_V9cH6~g-u63zYvVIy^#Z4UPbG0%)xECMcGX0l
zlTBkhtr71Nr(073?-S$X8>RE85T?H{+fk>8tjE*&r1SoN<7xl(oK%kMe?v-ybYD7G
z^a`#;d`MhYhjm*8Odv*nd^hP|0nrM6dQQTh(17HHY%uD+)TfS-^OgehgUC?Oed)f(
z_5ZorP>!em>Gjt8Zy=`UL<l}sV1<+j>ArM7<LW<F_3x@!s!#8QUjIH~l#}~JQPOX!
z(3cD-&h?ppgm_$hRbB4iPl$i`FY#}x1Ih0pr{TKHzgF>VXMRsV(8|DZ?Dr!IgdKZ}
zP`|I@m)TKqUO$GvM<H(gr)aa0_?*)E)2}GUGagr);(k!|TdHCDougl8J)ZV7ZmQ$z
Y{>-91O8We%uekWU>i?%`Fv@!T-vg=*f&c&j

literal 0
HcmV?d00001

diff --git a/tests/data/test-abidiff-exit/test-enumerator-changes3-v1.cc b/tests/data/test-abidiff-exit/test-enumerator-changes3-v1.cc
--- /dev/null
+++ b/tests/data/test-abidiff-exit/test-enumerator-changes3-v1.cc
@@ -0,0 +1,17 @@ 
+enum E
+{
+  FIRST_ENUMERATOR,
+  SECOND_ENUMERATOR = 1,
+  THIRD_ENUMERATOR = 2,
+  FOURTH_ENUMERATOR = 3,
+  FIFTH_ENUMERATOR = 4,
+  SIXTH_ENUMERATOR = 5,
+  LAST_ENUMERATOR
+};
+
+enum E
+foo()
+{
+  enum E e = FIRST_ENUMERATOR;
+  return e;
+}
diff --git a/tests/data/test-abidiff-exit/test-enumerator-changes3-v1.o b/tests/data/test-abidiff-exit/test-enumerator-changes3-v1.o
new file mode 100644
index 0000000000000000000000000000000000000000..4cbd23599b125ac11d36dbd3fbdfaff29c1d1292
GIT binary patch
literal 3440
zcmcIm&2Jl35TEC@oiuJ7C$69+6>$-Wv}M<ElBQou>L@skm68-E5vWpS*7n9;h}V_9
zi9$Kh6B6`NB*Y2Chq%C%3vl3q5J>zBaO4l@nMyG8c3!%ESri0fq<u5<o0&KBzQ%sL
zbYnRt1Sk@)0FO0=0^AvVEElC%gcFd3t(A9w|Ectdko%=aw}1E;g#-xc9V7G%4PnZJ
z6r%(KaTft0l9EZA%pcSgld>VlxEvF5OhP<9K+cKnP6x!W1T7gI3@VHGDCvM086sQk
z{T<9S2}b&K3bj%3TsoUFCdMa5#n?dRNdO}*jKPIeDpk&2NnK4{PKhi){8>n)7E(qU
zlUd^0DPu6OdFgVN0*fc_o&reDf-;n|v6GnX1<ELk32hzfsxoN`4QnVTU=YqB7ef4z
z9wtT$!w-cCxyG27h>Zl(%2?cvV+X1+ED}Sjy9qHLi($yF*K?bm)5y7=4;$rIH&?2q
zwXK&*mBr2V3T%{?*4JJPBbzJbN*}OXUha>%zP6QHI)A=!F;^&97p$q=^wjk1)WyQ(
z+++pwtk^yq%nN68X4~KOocX5XIbFAos@<)(=JzknnRBz|-gM4vLiN@Rp5GqaSlrkQ
zSF&8LXu$ebrN5MXtJ8M!jZWirH{W#q{El0*Yi`qack(wYGljX?>Adgs{9e9c`?eHK
zv^U)CZPVFzeITRhc)M+<Yx|w9S#Q~1)9KBadj+drhyQu{BeKKwrKKymN!;$U|6r%-
zBAk%70WZqk3W)uT7(YHR_yBLrX~gLxk~eQLop~p=G@M*ThX9To>9WP);h#}PBeFx_
z^Wpoh#~5gdA_Fr-kpaml7-x}B{*cXpV}~#T48Ug|K?WR;K*=B9cmx?R5`mKc@F6^h
z$XIB94qp2aC$3(CI+G!sC%g+P6XCSl3VuXm0RzJ6E3*CsbA_`CPq9Gfd(byfKF2uu
zs~QNp7Q!j-cdVB*{At!#HGGQomo@ws)?d-^Mb>X?xLSW*!@pu3JG&&RKYSbZHT-kd
z?=jc+LG3xslVBfW>Kt|dXV{1Q>8r9%-JeL|p9Crtm@E8y)~_<x=g%=tXB9p#uzGK{
zeY=L-?*_c3B;VQh!J@tgR;||qtLyC8R>P_7Hmk0;-9ej_?OLtt?Dd)LuIz$+*pBNt
zDg;v~k>IM->z#Jn!Jin*>-dg^P0Q^0cKr>W#A#KxyLQ{*h5Sc0j`6fd>YUVcMHbXK
zDV%)6bOsf|^p12h>=csq_~+3^@8jRb)A{RjQaY9YGg3mN`_jFlu2~HEkobTv>pcz_
zMU4E^Tc&>`MDzIRa}xfL1|&CN2czywb?O*7-(qm;ATkhiU+NE0^=G)Xt9YuPAie$u
zV)~p2!Fvp<zDO96?o018Du0plzeYhwl%M*Dp8pPFG^eT)MM=MMqTdw2T;*5%EySbZ
zzvah$RQ&zFiT{u<Wd4Z!A8@?p20!W-njKW#%KuA_@9RZ~{mk)~lp}Mse+vErg{b}i
zl=olVQ`&#})m8Bdr+W0<2nCZOYjMH!yGXz0dOV$J)KXjgekRc#CVl->S5*8rT>sbM
JV3hUvzW|1EDqR2o

literal 0
HcmV?d00001

diff --git a/tests/data/test-abidiff-exit/test-enumerator-changes4-report-1.txt b/tests/data/test-abidiff-exit/test-enumerator-changes4-report-1.txt
--- /dev/null
+++ b/tests/data/test-abidiff-exit/test-enumerator-changes4-report-1.txt
@@ -0,0 +1,13 @@ 
+Functions changes summary: 0 Removed, 1 Changed, 0 Added function
+Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+
+1 function with incompatible sub-type changes:
+
+  [C] 'function E foo(void)' at test-enumerator-changes4-v0.cc:13:1 has some sub-type changes:
+    return type changed:
+      type size hasn't changed
+      1 enumerator insertion:
+        'E::SEVENTH_ENUMERATOR' value '6'
+      1 enumerator change:
+        'E::LAST_ENUMERATOR' from value '6' to '7' at test-enumerator-changes4-v1.cc:1:1
+
diff --git a/tests/data/test-abidiff-exit/test-enumerator-changes4-v0.cc b/tests/data/test-abidiff-exit/test-enumerator-changes4-v0.cc
new file mode 100644
index 00000000..a6722144
--- /dev/null
+++ b/tests/data/test-abidiff-exit/test-enumerator-changes4-v0.cc
@@ -0,0 +1,17 @@ 
+enum E
+{
+  FIRST_ENUMERATOR,
+  SECOND_ENUMERATOR = 1,
+  THIRD_ENUMERATOR = 2,
+  FOURTH_ENUMERATOR = 3,
+  FIFTH_ENUMERATOR = 4,
+  SIXTH_ENUMERATOR = 5,
+  LAST_ENUMERATOR
+};
+
+enum E
+foo()
+{
+  enum E e = FIRST_ENUMERATOR;
+  return e;
+}
diff --git a/tests/data/test-abidiff-exit/test-enumerator-changes4-v0.o b/tests/data/test-abidiff-exit/test-enumerator-changes4-v0.o
new file mode 100644
index 0000000000000000000000000000000000000000..e0b02c230a71e68a97445db13b865a6b1d78e6f2
GIT binary patch
literal 3440
zcmbtW&2Jl35TEC@oiy7xAFiM!6>$-Ww8d*XP17$WbrhV&N=b^72vn&uYkOla#Ouo5
zM4=q$2?=^B65<5nLtNm>1vvClA&~eN;K(1)GnHWG?YwmTvM7j-v~Om9GxKKN*Vylu
zt}n%e07U}k;fbbDfZKyl<f0Uda17G0x%}auzmy&ma<BCG*2B+HNPv*uF+xw#5T?<P
zVw7MY?jj&WQZi|i`GcBbQa0ommt#VXNr=Y>$T_jq>3|rPpe3V&L1hu2B^?kWLu8A6
zyp5Trz(}1mQ5zF4rP8J`IWajV#s@~91u){m7@Rjvvz)$cUNJA3A`K9K5lnO5G*Xz%
z5?4<cgMrOUmD3bhJbvc{Kyn6@p`4B#$84`qMp;Z~>rhvfNmFQ8ML7Y3a0a;$;;+;&
zF<KaYC``&V#>8Z7B$!sl;&vR_SB+tj7+Tp$h`Cq{Lw3BL+w`19#`SzyFTc65TrI6`
zzE-L%Y^+say|lQt`f3>2ST0xkfTi+Mf6TSj&CKH2vxN(pLcuz3<ulXy>6!e6!lleq
z1@kQ1J{z*<PiL}if5&s?nvUmm-8!mvx89oDyEvPjoyqP_XR=MG-aLorw+q)7);GeH
zER`!7u(nz0FU5Cye%A4J+D_N@JKb!(WqVDhhcoA`dL44DPTR>fI*qs8T+{V)+iuOS
zxlP;M&fTb-E6mPJ=V*pru3`JO6tie=xLaFUXV3MYI{uLI4l%>E#l_2+DctVU|6!-;
zA{>*q0WZp(3W&W?F>!QY@IKy{lZewtByZkAYV?EH;&5^W9RfIVq{|kEM}J2djmQpx
z&xh~39%G;-iVVyUMFu3JV4Ouh`2#isjvT-UFaV!<1Q~EN0wsTZ;}K-QNCZm$!w2vT
zBIBX`*?;YaoVa=k>P&`kp71WHOoY>FEBFzO2Mh?OPth|hD14Ij=a|#^?)MFp&oEB@
zss@6thH%RJ6YC`nf1dRf4bQXwx`zM8`WqU)!1^r>SL?59_;;*hXO~3vhi}84hJVfa
zUFP~es6D5766`}voulsm0{f6ZeO1<}`x7bri$H|}bA>-({R(q^{tV-ER^jsktM_i(
zw`<7#Zopeg@|`^&ENX0E)p|X!y3V$3HJsW`v+8<V9kfZ=uGPBEZlBri$}ZZ6ZM&YM
zLNJ9A39d@L-f6cT{E4x=j_+95w6Z<luD`>RIIZed*KRw!kf&r57*Bho&Ph#IWI>&i
z!pS#Gr%)kG??^YoP9a&3e;IA`KK^e!oxeUOrBnI8A|*t+FWoEZn#GV0iTC-k-sONX
z#K=#*W%@@#G>4x)C*hB1Kym}NKkB|zr;d^HO$PJ(k%6H5Qh$i5f0SFhil_Ps((7*^
zrq78Ge8iyYi-ZyBzVtq$@)tS(TNH#u`KgcS`EMgebE-N~l=M3%`a=QCRer_aLp&<}
zM}FLg#ozmv_)qyl<_^jK3CC-0@UwoQ*+JE<{J-V+zFvgbuN;3-IWkxKr{Hf;h}!=z
zdH>ZtrTwR0T@|lzsz=X_P%tU778gvvi}Y)*$J3ccEw#n(XA13M($`OQMaBQX^?x4@
IMp=*l2b+E>JOBUy

literal 0
HcmV?d00001

diff --git a/tests/data/test-abidiff-exit/test-enumerator-changes4-v1.cc b/tests/data/test-abidiff-exit/test-enumerator-changes4-v1.cc
--- /dev/null
+++ b/tests/data/test-abidiff-exit/test-enumerator-changes4-v1.cc
@@ -0,0 +1,18 @@ 
+enum E
+{
+  FIRST_ENUMERATOR,
+  SECOND_ENUMERATOR = 1,
+  THIRD_ENUMERATOR = 2,
+  FOURTH_ENUMERATOR = 3,
+  FIFTH_ENUMERATOR = 4,
+  SIXTH_ENUMERATOR = 5,
+  SEVENTH_ENUMERATOR = 6,
+  LAST_ENUMERATOR
+};
+
+enum E
+foo()
+{
+  enum E e = FIRST_ENUMERATOR;
+  return e;
+}
diff --git a/tests/data/test-abidiff-exit/test-enumerator-changes4-v1.o b/tests/data/test-abidiff-exit/test-enumerator-changes4-v1.o
new file mode 100644
index 0000000000000000000000000000000000000000..414d0497935cb0af5303e19173edfcac270943a0
GIT binary patch
literal 3488
zcmbtWO>7%g5T56?oiy9HNnAlnD(oT<X^Yo!nx=nB>c}{am68-E0fbb!YkOla#Ouo5
zM4?E)sS@f1Bn}*qKmrLkaX=jDr3X$(h&vTRLgEM~4pf4f=XvS+Wl>NW$!})9`F+3Z
zw~JR7BSL^80rT)sQz*bEgAe7r6!UNtlCZJ#?yuh!9}se<_~81zPf>`0klqnOPtXvg
zk$_?pVIbN@K!~_x(kAQodWuNdkYiMiF*(NNH~`V;0ENUh+iegD30g8oZ&0<wM{x(l
z$Pn2g?{8tfNiY(}P1HukGl`^Wq$X0MVr*dKaR4JKjKO)+G)u{g<|XrjDUtxur@=Jm
zO(TKDEOGgmG1#+tiBggR^W(RU0mNrO8A{2>I97X(D#~U83y8YvOqv423d%7Ugj2|c
z5Pv0xiP6OHheAruF(OitBfYdT78m8vo@yjSY-o8qCgvg$4B7U&Zo_lxY1i{%t@O(J
zQl+@E@j|h@u)bP`wPIm)<@tW(rQ%Az)A~}W+~>1cTI~0@va*pboIag9m(Jy^v({94
zdTM%R>Rj$Zda{hAmu#O6nX@O;nU=rpIdcuib2@GfRl8Gb&h4I`&CJeZcBa#r22@@>
zgIl@-R~OdSgUv0L${Mh`QSNWWce;MY@wQt|$M)NuOs#2q4X2Blb5^Ye*=D=tWb5tv
zYi_pT`q?eFYFFKc?QUhSmCxj6XQs21p_{GSzAeQJ+UxG-X2#id{r??*Kzj$6;Yy)!
zF+GXPeeyr7G@gy4@_gXYxm5<SJ0d0y4-CGCXXrTM^dpjIaUn5sJ5m^qFQY>b4jt+E
zMd6RX!;D7g%Yhe)Z-5?Spe2k9tPn;9#KU0BA|HW$HUkdr!w4_{FMbFaa5w}df4ub}
zWWbRSl>CSH;b}z10_(GP{}0%3brIB_3}K$&DyT|?(`+655smd25KccukFlWe6zfkg
zr~Tb~Nl-q;IQgp{2)Z1=sqXiz7d8Az)|WNB!1{|CexLQ1HGG}*>l&`+U(@g@)?E$%
zmi3N?vkGr%_&2QIX0ES~+6!8r82b=Y`>Xpu#Xf5NE3DIZf=J;X_f*I+SNL7lFEQ8i
zrx~X`4DKUX-8WjkT}AG9dc3J5-`VxSqW2E0YPSnk$Jw&2x>Mb5R9tVfjW#LU)oRDt
z=`-6M`MCCBTdwD*5G<iYf-6$5wOcI*KSq|<_8kk~vP{>vYp-(>r&-zT*e!LCc|MQI
zCNPlJNbQr#lV?Hglfub2NGDJsOn<4a1)T!29{()b=-xbPJng@plgg?3pOX?G-IvZ4
zy{7qq4~bv!Vf~N;MiC=Fb;s$y3(*|@^qhqMNduC)Up;NVFZCG~e}lm(706uorFSE&
z|2#kWDxUf$NbkRnn4S|Mpl={ixySZK-IwlXSpAz^{{}}=eR>D=`Zp1yoT^V0CH=yM
zepdi<RbTNp5f6+1kuUd82gKj`m-w&vKxPk!|A6B)H@L4KXm(J2EB`M!zV9tU>}QTY
zuN;}H^;7U?D1@#554`^BoYMN!*I30XochsgBLw4=6sgG#)Ay3T@_Ib&Y1mZX;rla*
W_8{r=r@q4Cf8+kY4hEyF$NvM_B{Kp5

literal 0
HcmV?d00001

diff --git a/tests/data/test-abidiff-exit/test-enumerator-changes5-report-1.txt b/tests/data/test-abidiff-exit/test-enumerator-changes5-report-1.txt
--- /dev/null
+++ b/tests/data/test-abidiff-exit/test-enumerator-changes5-report-1.txt
@@ -0,0 +1,14 @@ 
+Functions changes summary: 0 Removed, 1 Changed, 0 Added function
+Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+
+1 function with incompatible sub-type changes:
+
+  [C] 'function E foo(void)' at test-enumerator-changes5-v0.cc:14:1 has some sub-type changes:
+    return type changed:
+      type size hasn't changed
+      2 enumerator deletions:
+        'E::SIXTH_ENUMERATOR' value '5'
+        'E::SEVENTH_ENUMERATOR' value '6'
+      1 enumerator change:
+        'E::LAST_ENUMERATOR' from value '7' to '5' at test-enumerator-changes5-v1.cc:1:1
+
diff --git a/tests/data/test-abidiff-exit/test-enumerator-changes5-v0.cc b/tests/data/test-abidiff-exit/test-enumerator-changes5-v0.cc
new file mode 100644
index 00000000..aea70235
--- /dev/null
+++ b/tests/data/test-abidiff-exit/test-enumerator-changes5-v0.cc
@@ -0,0 +1,18 @@ 
+enum E
+{
+  FIRST_ENUMERATOR,
+  SECOND_ENUMERATOR = 1,
+  THIRD_ENUMERATOR = 2,
+  FOURTH_ENUMERATOR = 3,
+  FIFTH_ENUMERATOR = 4,
+  SIXTH_ENUMERATOR = 5,
+  SEVENTH_ENUMERATOR = 6,
+  LAST_ENUMERATOR
+};
+
+enum E
+foo()
+{
+  enum E e = FIRST_ENUMERATOR;
+  return e;
+}
diff --git a/tests/data/test-abidiff-exit/test-enumerator-changes5-v0.o b/tests/data/test-abidiff-exit/test-enumerator-changes5-v0.o
new file mode 100644
index 0000000000000000000000000000000000000000..e41564690a2f9208d9e57c58ca4ae25ea0ee132a
GIT binary patch
literal 3488
zcmcImO>7%g5T56?oiuLTB(5MO6>$-Wv}M<Jnxub9>c}{am68-E0fbb!YkOla#Ouo5
zM4?E)sS@f1Bn}*qKmrLkaX=j5!hsVK;!cH-kT}AL1C?Ord0x7HSrk->k^E-no0&KB
z=KZYSEM8lR2my)&EWiUzp#UEZK9KWL%)@a=!RGSYzkXM|PsrWk{TttYj6w{A^o|gE
ziiRMK1QeqP1JO1DLc}GLHkrRyQ$)&!9HVlK$uTa+0f<HiC?vMkZi7fl(2{fX29-;E
z5O+X~43RDJ?l$I|0wZ}cf!e5eDw#?clM|DpVr*dKQ2-+<jKPIOB2h|RN?cA{Oo$Xf
z^hro077|7hlUd@*31hHl^OB_$1?I<Zp8$x@fHIU)k#WrS3}uwX1R99Cs!W;!!z#)#
z7=$y(g%E!whl$a`@Q1>rTw_E`MvnESm9f~ABm1h66tSU|otT)9L@;E>>$(lksi$4f
zhxO7+8_SjA>gIFB^5Vu?8P<!1wbf_)kr#@q{Z1RprE;IoQfaB*<Lc^Wx^VVv?tD6z
zvu3SqdOABjlRclin4T(Q>Sfz!gE@OTZMOU!&zWyHp3`w_sM?)cbAIo_oH;jR?oOx8
z22@@?hg-S}*A~||g2gSB${Mh?S?(_-(`>h#Oub!y#mzKaKeO#t?W)_b-R;cv^10mH
z%yh<gx_&oPw|!fRCfe)n)|Tn)xjvB5biAFG)3N<_$E-DNui<oO&E2e3tHJ*~{UO=m
zYN2o`J%#N){U17wXXCg$A9!?bmqF}}h>4>EgYV!OI*B;_h~!yZOpe@%6o%s~=+J{h
zM>>8{_~Y*|qY?UY;DzEFpvM?!2_pkDgpmR9Fc@c%kH7(&0Y?sC1Q>u9KZFc88iJBP
z-ue(S;8+Ms{=*0GG$Lbx{_NlXLpEGp1hpqaI8U$(Dih(fS_gkbV?73h(=X5ZBg_@f
zDm=yl?eG3eg7O*0$zRn#(3JpAdB119sNs*ZzM|m;)}Pn#d#t~x;Tx>q&~UZ>nucdt
zcQyQL);k)`D!ifLU$K6Nx!xbO7u25^`w&z6tNTB}KC1r}*6BMzr0@@WD&&|e{2SIU
zGuP)&GfsOL+()pwueE%;irnw?cvDHfv*&|F&mmaVZWpYMvu#^-r@GUqxZYM9ZBn+Y
z)sC~<XSO@?aqPpkUC&V=m_msJSEOERw^|N<j4ZG1I~KlWX4kiCuks{Lv$EB(Tk0V5
zdLEWdU?BBK?UR}(&w|<~g_CcPPN71W{!(2JIt64s{%N$)y?NMp+JAjcN~iLFN=krq
zUpiOxn&tyOB!0$+^?eQ)MU4E^9jE^;MDzI5=Op}38j#fe>S+gksm`$Yn+#@EAamW9
z-i@&O^Zewic&eWuz5Y64`kV*>eFKTgJ+?pUzH~ps^55e8H#w5>(>ti=zl9jhsp>>g
z(l4CocLgw4`4xX1@v!(G`EvhsNc`P@iT{ERWag0g_c&g2gM0dcW(QTb^8cLU``#kN
ze&+ZK%8|M1pMpO@A*}yDaR1dgrT){`Sj8)x>d|u}1miR*Qj-g&?<IZZ^?2ITu%*7m
Z_h$<2LDJVxb%n+M#`S+03`SXx{|CnjGa~>1

literal 0
HcmV?d00001

diff --git a/tests/data/test-abidiff-exit/test-enumerator-changes5-v1.cc b/tests/data/test-abidiff-exit/test-enumerator-changes5-v1.cc
--- /dev/null
+++ b/tests/data/test-abidiff-exit/test-enumerator-changes5-v1.cc
@@ -0,0 +1,16 @@ 
+enum E
+{
+  FIRST_ENUMERATOR,
+  SECOND_ENUMERATOR = 1,
+  THIRD_ENUMERATOR = 2,
+  FOURTH_ENUMERATOR = 3,
+  FIFTH_ENUMERATOR = 4,
+  LAST_ENUMERATOR
+};
+
+enum E
+foo()
+{
+  enum E e = FIRST_ENUMERATOR;
+  return e;
+}
diff --git a/tests/data/test-abidiff-exit/test-enumerator-changes5-v1.o b/tests/data/test-abidiff-exit/test-enumerator-changes5-v1.o
new file mode 100644
index 0000000000000000000000000000000000000000..47484375bf43c428d9dc9d71ed58c04834874e19
GIT binary patch
literal 3392
zcmbtWO>7%g5T56?lQf&SNnAloD%nLK(w1GvX_EdasiWXDR!S1wL`X=LS=(!SAzoMZ
zItt;?3qqh?sDy+NNJxka7lg!(0~ZclICDedf`r70GnHWGd0tq*EDE9{`OVBXGjHa-
zdGD<s6z;6WgaAbXmf;^wp#b@jkSxVKoPiYVuD}254~55sJS;rE_x(pGBtS^-7@-$v
z2-8GJF$ypouOcACkYv&(^Y?3tN!gHNT#gBd$A`%+QE#_Fj7iXzas5HfFFqY|K_o}X
z7JIaZIcC5}o;OjO6wfD9rjedbPl~DGiKhXKxG+YRP17u<ZkRXC>!wHn#GeDxTsDm)
zCbPw@bH+&D<|m6O3e2B9JO?l|56VzX#m-{37b&AGCbVg&tIDJ)G;E@rfDyQaTnO=J
za-0|~41Xx3<r-rm9Xs8hR>md-oH|mCF_9SE=q1EbEQTRHzw0%8x0dnz0PYr6w>DoY
z7dCfaE|gYwwo0(GUMvj&YsIyl^{~h7&E3rE<;%INnOx3ZuxB%Kvvc#aS98}hGbNmM
z-3i!WEnLi4t)S<-OAXg|J6;u4r&Db%9b8+q7U!+~xs26-@@rSHUHfon<?c>6&swph
z0b9GJ!BPUZ8(6O2Yq=dKXm_k?)A1W_cfs1v+0`m!o9&jHt+i`!c-e**WcR#^Q}G&(
zx0l^6UCAxZ&t++bZnowGjub7l*Svb&au2-ViQ`Ww?*ud4UR}MBnZfP8_#bu}`+i3D
z9*@Og3B<vKm>wG*`2f$ydBo{QB+uDOa^l_C>iEzGI`rYlk&adz{`f1(XhgmQcv<*#
z>oEpeqR7AuQDneS6pXXT3x3RIz^P*x0S4fujvxcZB2e<j8y!IgoQ^=rfBYDpL1Zel
zKSy`_godk&pn5Wj^MrRnWg?tbyMjNWsXhb3>8I!^78IUl{Tb%e-=kLo<x7l{zp8<t
zTOpkCe#v@4!&QA78m{ubqT%1N{;G!0vVKp)KW4qI;jBVO!ymDJ$Xs8q+FM$0f_;do
ze(C<tvX9!&GVAoF6Dj<&z6v?!3jdDvo6Pn3GmKMD!hHd|`&KJ(D#(LQpEs2hxCa5)
z^nQU|>2|^HxO<LWb1S_@+4Jjdv`N{iR66edfZ6HD$8rGM^L$r@U<xG?T$XyZ-D<h`
z;jsO7;M({$S>3>?zR8og&2qitv|L`u6S8THr#(`AQq$#GP<>K3`G)BNDun4T&vw`;
zB<t}nppEXq|Ba{q>vK{%mH!h`LZtiBxuVxGAMzpbfDdbv111q8KXqs6e+JPK{`5Hs
z|D6UTug{J~-IwarF>>BvaP}y&FX+DX4n)=e3pZ57Q~mU+>-E<V)8|A8-eIsrN{Dn{
zx}Q<`C-@WcI>%Cede`*)_YtExRh=kG`iT?$r~u|Fzv6Er9u@yNU+$kzh=2Gm@elYw
zW>1L!kmEHs_)0&}?4asa{`AfhHt-gq{x!#6Q;y8l{weqi6r%S3KJULer?mg{bye{S
vkIGGR|Hk>%`KRw6eYN#?>S@$cxB33epgm0b`l+s{`1iQ}Z^FSS>+ydBK8qwg

literal 0
HcmV?d00001

diff --git a/tests/data/test-abidiff-exit/test-enumerator-changes6-report-1.txt b/tests/data/test-abidiff-exit/test-enumerator-changes6-report-1.txt
--- /dev/null
+++ b/tests/data/test-abidiff-exit/test-enumerator-changes6-report-1.txt
@@ -0,0 +1,11 @@ 
+Functions changes summary: 0 Removed, 1 Changed, 0 Added function
+Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+
+1 function with incompatible sub-type changes:
+
+  [C] 'function E foo(void)' at test-enumerator-changes6-v0.cc:14:1 has some sub-type changes:
+    return type changed:
+      type size hasn't changed
+      1 enumerator deletion:
+        'E::LAST_ENUMERATOR' value '7'
+
diff --git a/tests/data/test-abidiff-exit/test-enumerator-changes6-v0.cc b/tests/data/test-abidiff-exit/test-enumerator-changes6-v0.cc
new file mode 100644
index 00000000..aea70235
--- /dev/null
+++ b/tests/data/test-abidiff-exit/test-enumerator-changes6-v0.cc
@@ -0,0 +1,18 @@ 
+enum E
+{
+  FIRST_ENUMERATOR,
+  SECOND_ENUMERATOR = 1,
+  THIRD_ENUMERATOR = 2,
+  FOURTH_ENUMERATOR = 3,
+  FIFTH_ENUMERATOR = 4,
+  SIXTH_ENUMERATOR = 5,
+  SEVENTH_ENUMERATOR = 6,
+  LAST_ENUMERATOR
+};
+
+enum E
+foo()
+{
+  enum E e = FIRST_ENUMERATOR;
+  return e;
+}
diff --git a/tests/data/test-abidiff-exit/test-enumerator-changes6-v0.o b/tests/data/test-abidiff-exit/test-enumerator-changes6-v0.o
new file mode 100644
index 0000000000000000000000000000000000000000..069b703bb6f4482037622ea1ae37b98308d40985
GIT binary patch
literal 3488
zcmbtWO>7%g5T56?oiuLTB(5MO6>$-Wv}M<Jnx=nB>c}{am68-E0fbb!YkOla#Ouo5
zM4?E)sS@f1Bn}*qKmrLkaX=jDr3X$(h&vTRLgEM~4pf4f=XvS+Wl>NW$!})9nRzpB
z-p~5&;?>275THoFJUrAC3h>F`Lpd+SJRF4-Y%IO|>vzQmgxo1UxPI?b6k;HxcZARr
zGz4iRpcq9Mh_(?BA}*P<$^5;VB2qTw7?op8j&V5-Kr}i)A+gPN8$?oqmYkzEs9fTs
zxC3Hjh-{Jfw=mxn7|G)a)JDZK$yCCaoR}OHV*?|P0~k?Z49+JKiBjrf;!@&5LZkqq
zPeURxpD>b`%o3N68G}8Wmn@|yFh73l7(jdml%bT0jAORvD5ESU&_L8xWzrNFR#1+?
zAe=%jg!n5tOpF$WKNKeA8Y5yda-=t{jK!uL+Eb0Bhz%`o$HZJDf+5>p*KK%CJ?(lv
ztd(9_U#b*WHeM)}7uHwHuvRRrt~}q5yi{E2cUoU6mHT`aON;#;S5`LCh0~{V=hC^H
zb=JzJr?b;D*>kxI>8UcNUb1~Qm}gI>&6dCIIdcuib2@GfRl8Gb&h4I`HD_nco$0jM
zfXb_9a7%aK>cZN3u(-uiSp!x#%KfGIPS-abZ@cAmY`@(xYfam0INe!uCu`MekZHDC
zPNv?jzvgBduAkX*t9I3G*zQ*5TKP<Fc4j(5Gjua`+qb1?qP^~JZko=n>;Lcg1IjzV
z3|9(;i|HwB_sRdzX*?T8<@vy)bE^zucSKAa9vFNN&(Lwi=|?2b;zDxdcBC*IUq*)>
z96HkRi^3m&hZ&8~mjf>p-vB+vKuZ`Im?4Y|h=;*Ai+lw3*$g<e4<o<;y!atxz~K;-
z{PEU@kO4<RQ1Tz%ho=!43-o92{vWX6>LRE;8NzvjT~L__r`0<6BO2>5Ae?@R9%Dh_
zldM0%oc4F`B|-TV<K(YuAn0-cr@Y^@Uexd>Szp%h0_!ho_<h!2*6?-KuWPtke@(-)
zth*ZiE$bZ(XBFPk@NZbZ&0Oz~+6(GWjD3iy{nh=SVjtE23hVTpAX50pJr#1y6@HiX
zOU(88(~Q#|2KN!H?i(%Nt|Iq4J>FE3@9g?u(R&A0wc7=&<80Yh-KlOjDz3NLMw^uF
zYPI9+^qK9Bd|dmmE!T5Y2&PaX!4;|3+O3v@A0x|a`;LWgnc4O2+Uq=t)2wWE?3Oyn
zyq-s86BtN6Qv0Ol$+MvLN#W!hq!XwRroU9zf=&ThkAD_zbZ;Itp7vj#lhUdDpOX?G
z-IvZ4y{7qq4~bv!Vf~N;MiC=Fb;s$y3(*|@^f?LtlLjPpzk1q!U#c@K{sx0t706uo
zrFSE&{yabVDxT^mNUy(+m_8>$K;J;3a*yqex-Z?&u>3bU{|%0${PYg$`EMddbE-N~
zl=KTH`dtCcRer_aL_941N50%Y9T0!#U*f;w1DQD>{sWHJ+~B@`pxHsyt^B{__`bIY
zv7b5qymDl&`lsN}PzdY)58QusPO1O&HCFKor+W0<2*Ef_iqzzS>3d0Ec|D%?G;FEw
a@co%Wdyw??Q(a;4zj6Iv2ZK@8<NpBw5Hkh<

literal 0
HcmV?d00001

diff --git a/tests/data/test-abidiff-exit/test-enumerator-changes6-v1.cc b/tests/data/test-abidiff-exit/test-enumerator-changes6-v1.cc
--- /dev/null
+++ b/tests/data/test-abidiff-exit/test-enumerator-changes6-v1.cc
@@ -0,0 +1,17 @@ 
+enum E
+{
+  FIRST_ENUMERATOR,
+  SECOND_ENUMERATOR = 1,
+  THIRD_ENUMERATOR = 2,
+  FOURTH_ENUMERATOR = 3,
+  FIFTH_ENUMERATOR = 4,
+  SIXTH_ENUMERATOR = 5,
+  SEVENTH_ENUMERATOR = 6,
+};
+
+enum E
+foo()
+{
+  enum E e = FIRST_ENUMERATOR;
+  return e;
+}
diff --git a/tests/data/test-abidiff-exit/test-enumerator-changes6-v1.o b/tests/data/test-abidiff-exit/test-enumerator-changes6-v1.o
new file mode 100644
index 0000000000000000000000000000000000000000..993751879b32884837423b4a02bb556920e61794
GIT binary patch
literal 3440
zcmcIm&2Jl35TEC@oiy9HNsOQ+6>$-Wv}M<Enx<b$>dH8c6-bJc0IF1(wY{+y;&o+j
zqEHU>gao}5i3<`4khpM0NF0C*2RQK;fW(DApl2$<%-ebC`ejj2B}UpeGryU6Gw*Bc
z_sTCXC4>M)0v6$srci*}!;j>m6pQc#WMOmpgFk;RKP2Q{`QfdfK0_e|LV70%Jw-#5
z#v+PQhM}Z~fDmcPq)p}zYf4DjkYiGgDLJMgnH(bL)K<3(VpM{*j1C8tMSPleK^z+)
zTjHZ_%rp%~=A?<*xOhI3HI1pssc|teH1-sLkrc-8qG_6y>}B(cdC3%6faG&vnv159
z!DP0$dcqhEZGNVbrNH9xJ0}3rbD#{BY~na(dyz8AVj^3Ix~fc?BEu@mDHw(`$b}Gp
zWk!k7!tg_3O0F>>rV_`(X=N;K$B}*27!|3Jm7SDWNF*?1$M1VB-)-hRKY;bh8ym~D
z^6KU*<?6MKwJNNaOKYny4I;0VR|lOomMhf(pQXyupvU#q&0Oj1*}{cfp<ti4XL7SM
zvvV^S3YT)zRZP9?1Z=R*pUzpGV8?eCTCVT*yauXHuhCxEyEt#n&sn>(IjaS=o9FOI
zcVVegUEhdSx3sod9Za2XcROyr*=@e%<y&5m-}dTG-D^4CcK$~7Tw#80HXpeCpr3C#
zfg?o=?M-iM%X0U;0LW;${!Yj3IYGB)HQJ8fa{KevZozIe;D4U}knC{1RJxp-#_c`*
zA9fbsVo2gn6~x|{m^?Z(d>?PjNrdSmk~i;KX6*e$X*9ip4j~*n(q&7+gTLd9Mr?<`
z=fn41k1@~^M+RnyBLmWLFwP>M`~jN*M-E^F7=X__h733wgOWeK@fb4TSPV-3qX+OD
zA`_AQ*?;Ya9Jjjm>P$v(p6D*9OoY>FUHph9LI#A>S7iN3<_c#Oo@Rm0cfW6-e1>uI
zS2YlHHG)&#A6PGI_%p1pXn2YBS2g@s)?e4~4c2dIxLSWh!)I8>&Mt}SkKTqo4gZ$)
zyUg`{P<u}Eq}Yd;I!E3AS@t1+`f99G_a{>L=b;J(<_iCj^()Nv`E!iZSw+ta?EX8Q
zz^Nk-dLeHsDRB1!u&L>RUGMk7?z!8J-E`|at(xa=b<rker(W;5y8~vYCtKhEw(a?@
z3c(agB)BH^Mz_;(@h8UiyMb$C$Fll?(|DUFaoe@6p3_kmme=#RY!U-$kJLG-d5SEk
zb5c0@M(GqPgy|jWM${=H>+vt3jo!!O#?$%hb5c5$|4ULLr2EpnqOMtt_>g#?FY8?n
z7)Ol!)LW*1Bt#4N>2nhPfCeNlWc#D;OLgiPIp1V(W<N3%bYJQZarKXJYgh49KS6r^
zO~mv$5rPjHtdbHT-Iv~HT>c{Gf0JV=KlKqk|82x*PE{w0l78bvf3U8Y%CGplXo!pd
zo*(z`Dv-H~Q~ch)#DBsUGJi<?#~iP@!7uuSW(Sp5`G3vv1HA|_6@O7VGFSVj;IB}K
z+y5_k|J6OE{ik1D6|ZorN6(E=I4QC=7fip4^lPri)0xICwaxEm8tqZi*H3lD#ec{3
Le-jNxS&#n*1(_>0

literal 0
HcmV?d00001

diff --git a/tests/data/test-abidiff-exit/test-ld-2.28-210.so--ld-2.28-211.so.txt b/tests/data/test-abidiff-exit/test-ld-2.28-210.so--ld-2.28-211.so.txt
--- a/tests/data/test-abidiff-exit/test-ld-2.28-210.so--ld-2.28-211.so.txt
+++ b/tests/data/test-abidiff-exit/test-ld-2.28-210.so--ld-2.28-211.so.txt
@@ -1,7 +1,7 @@ 
 Functions changes summary: 0 Removed, 0 Changed, 0 Added function
 Variables changes summary: 0 Removed, 1 Changed, 0 Added variable
 
-1 Changed variable:
+1 variable with incompatible sub-type changes:
 
   [C] 'rtld_global_ro _rtld_global_ro' was changed at rtld.c:345:1:
     type of variable changed:
diff --git a/tests/data/test-abidiff-exit/test-leaf-more-report.txt b/tests/data/test-abidiff-exit/test-leaf-more-report.txt
index c0a692c6..e2ea85bc 100644
--- a/tests/data/test-abidiff-exit/test-leaf-more-report.txt
+++ b/tests/data/test-abidiff-exit/test-leaf-more-report.txt
@@ -26,7 +26,7 @@  Removed/Changed/Added variables summary: 1 Removed, 1 Changed, 1 Added variable
 
   [A] 'long int added_var'    {added_var}
 
-1 Changed variable:
+1 variable with incompatible sub-type changes:
 
   [C] 'int directly_changed_var' was changed to 'long int directly_changed_var':
     size of symbol changed from 4 to 8
diff --git a/tests/data/test-abidiff-exit/test-leaf-stats-report.txt b/tests/data/test-abidiff-exit/test-leaf-stats-report.txt
index e17b461b..b93e2a7c 100644
--- a/tests/data/test-abidiff-exit/test-leaf-stats-report.txt
+++ b/tests/data/test-abidiff-exit/test-leaf-stats-report.txt
@@ -10,7 +10,7 @@  Removed/Changed/Added variables summary: 0 Removed, 1 Changed, 0 Added variable
       type name changed from 'int' to 'long int'
       type size changed from 32 to 64 (in bits)
 
-1 Changed variable:
+1 variable with incompatible sub-type changes:
 
   [C] 'int changed_var' was changed to 'long int changed_var':
     size of symbol changed from 4 to 8
diff --git a/tests/data/test-abidiff-exit/test-net-change-report0.txt b/tests/data/test-abidiff-exit/test-net-change-report0.txt
index e087c15f..0f353ef5 100644
--- a/tests/data/test-abidiff-exit/test-net-change-report0.txt
+++ b/tests/data/test-abidiff-exit/test-net-change-report0.txt
@@ -5,17 +5,19 @@  Variables changes summary: 1 Removed, 1 Changed, 1 Added variables
 
   [D] 'function int fun_removed(void)'    {fun_removed}
 
-1 Added function:
-
-  [A] 'function long int fun_added(void)'    {fun_added}
+1 function with incompatible sub-type changes:
 
-2 functions with some indirect sub-type change:
-
-  [C] 'function int fun_changed(void)' has some indirect sub-type changes:
+  [C] 'function int fun_changed(void)' has some sub-type changes:
     return type changed:
       type name changed from 'int' to 'long int'
       type size changed from 32 to 64 (in bits)
 
+1 Added function:
+
+  [A] 'function long int fun_added(void)'    {fun_added}
+
+1 function with some indirect sub-type change:
+
   [C] 'function void victim(type_changed*)' has some indirect sub-type changes:
     parameter 1 of type 'type_changed*' has sub-type changes:
       in pointed to type 'struct type_changed':
@@ -29,11 +31,7 @@  Variables changes summary: 1 Removed, 1 Changed, 1 Added variables
 
   [D] 'int var_removed'    {var_removed}
 
-1 Added variable:
-
-  [A] 'long int var_added'    {var_added}
-
-1 Changed variable:
+1 variable with incompatible sub-type changes:
 
   [C] 'int var_changed' was changed to 'long int var_changed':
     size of symbol changed from 4 to 8
@@ -41,3 +39,7 @@  Variables changes summary: 1 Removed, 1 Changed, 1 Added variables
       type name changed from 'int' to 'long int'
       type size changed from 32 to 64 (in bits)
 
+1 Added variable:
+
+  [A] 'long int var_added'    {var_added}
+
diff --git a/tests/data/test-abidiff-exit/test-net-change-report2.txt b/tests/data/test-abidiff-exit/test-net-change-report2.txt
index c6fd8079..6c1ee9dd 100644
--- a/tests/data/test-abidiff-exit/test-net-change-report2.txt
+++ b/tests/data/test-abidiff-exit/test-net-change-report2.txt
@@ -26,7 +26,7 @@  Removed/Changed/Added variables summary: 1 Removed, 1 Changed, 1 Added variable
 
   [A] 'long int var_added'    {var_added}
 
-1 Changed variable:
+1 variable with incompatible sub-type changes:
 
   [C] 'int var_changed' was changed to 'long int var_changed':
     size of symbol changed from 4 to 8
diff --git a/tests/data/test-abidiff-exit/test1-voffset-change-report0.txt b/tests/data/test-abidiff-exit/test1-voffset-change-report0.txt
index 4d832e2d..b43f400f 100644
--- a/tests/data/test-abidiff-exit/test1-voffset-change-report0.txt
+++ b/tests/data/test-abidiff-exit/test1-voffset-change-report0.txt
@@ -1,16 +1,23 @@ 
 Functions changes summary: 0 Removed, 1 Changed (1 filtered out), 0 Added functions
 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 
-1 function with some indirect sub-type change:
+1 function with incompatible sub-type changes:
 
-  [C] 'method virtual int C::virtual_func0()' has some indirect sub-type changes:
+  [C] 'method virtual int C::virtual_func0()' has some sub-type changes:
     the vtable offset of method virtual int C::virtual_func0() changed from 0 to 1
       note that this is an ABI incompatible change to the vtable of class C
     implicit parameter 0 of type 'C*' has sub-type changes:
       in pointed to type 'class C':
         type size hasn't changed
-        1 member function changes (1 filtered):
+        2 member function changes:
+          'method virtual int C::virtual_func0()' has some sub-type changes:
+            the vtable offset of method virtual int C::virtual_func0() changed from 0 to 1
+              note that this is an ABI incompatible change to the vtable of class C
+            implicit parameter 0 of type 'C*' has sub-type changes:
+              pointed to type 'class C' changed, as being reported
           'method virtual char C::virtual_func1()' has some sub-type changes:
             the vtable offset of method virtual char C::virtual_func1() changed from 1 to 0
               note that this is an ABI incompatible change to the vtable of class C
+            implicit parameter 0 of type 'C*' has sub-type changes:
+              pointed to type 'class C' changed, as being reported
 
diff --git a/tests/data/test-abidiff/test-crc-report-0-1.txt b/tests/data/test-abidiff/test-crc-report-0-1.txt
index 0a6438f5..4ff0ef92 100644
--- a/tests/data/test-abidiff/test-crc-report-0-1.txt
+++ b/tests/data/test-abidiff/test-crc-report-0-1.txt
@@ -1,12 +1,12 @@ 
 Functions changes summary: 0 Removed, 1 Changed, 0 Added function
 Variables changes summary: 0 Removed, 2 Changed, 0 Added variables
 
-1 function with some indirect sub-type change:
+1 function with incompatible sub-type changes:
 
-  [C] 'function void exported_function(void)' has some indirect sub-type changes:
+  [C] 'function void exported_function(void)' has some sub-type changes:
     CRC (modversions) changed from (none) to 0xe52d5bcf
 
-2 Changed variables:
+2 variables with incompatible sub-type changes:
 
   [C] 'int exported_variable' was changed:
     CRC (modversions) changed from (none) to 0xee94d699
diff --git a/tests/data/test-abidiff/test-crc-report-1-0.txt b/tests/data/test-abidiff/test-crc-report-1-0.txt
index cb2fb86e..1bc678df 100644
--- a/tests/data/test-abidiff/test-crc-report-1-0.txt
+++ b/tests/data/test-abidiff/test-crc-report-1-0.txt
@@ -1,12 +1,12 @@ 
 Functions changes summary: 0 Removed, 1 Changed, 0 Added function
 Variables changes summary: 0 Removed, 2 Changed, 0 Added variables
 
-1 function with some indirect sub-type change:
+1 function with incompatible sub-type changes:
 
-  [C] 'function void exported_function(void)' has some indirect sub-type changes:
+  [C] 'function void exported_function(void)' has some sub-type changes:
     CRC (modversions) changed from 0xe52d5bcf to (none)
 
-2 Changed variables:
+2 variables with incompatible sub-type changes:
 
   [C] 'int exported_variable' was changed:
     CRC (modversions) changed from 0xee94d699 to (none)
diff --git a/tests/data/test-abidiff/test-crc-report-1-2.txt b/tests/data/test-abidiff/test-crc-report-1-2.txt
index 809e278f..a9d20950 100644
--- a/tests/data/test-abidiff/test-crc-report-1-2.txt
+++ b/tests/data/test-abidiff/test-crc-report-1-2.txt
@@ -1,8 +1,8 @@ 
 Functions changes summary: 0 Removed, 1 Changed, 0 Added function
 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 
-1 function with some indirect sub-type change:
+1 function with incompatible sub-type changes:
 
-  [C] 'function void exported_function(void)' has some indirect sub-type changes:
+  [C] 'function void exported_function(void)' has some sub-type changes:
     CRC (modversions) changed from 0xe52d5bcf to 0xe52d5bd0
 
diff --git a/tests/data/test-abidiff/test-namespace-report.txt b/tests/data/test-abidiff/test-namespace-report.txt
index d2c421ed..adaab647 100644
--- a/tests/data/test-abidiff/test-namespace-report.txt
+++ b/tests/data/test-abidiff/test-namespace-report.txt
@@ -1,7 +1,7 @@ 
 Functions changes summary: 0 Removed, 0 Changed, 0 Added function
 Variables changes summary: 0 Removed, 4 Changed, 0 Added variables
 
-4 Changed variables:
+4 variables with incompatible sub-type changes:
 
   [C] 'int v1' was changed:
     namespace changed from (none) to 'this'
diff --git a/tests/data/test-diff-dwarf/test20-add-fn-parm-report-0.txt b/tests/data/test-diff-dwarf/test20-add-fn-parm-report-0.txt
index 022d0d11..89cccf3e 100644
--- a/tests/data/test-diff-dwarf/test20-add-fn-parm-report-0.txt
+++ b/tests/data/test-diff-dwarf/test20-add-fn-parm-report-0.txt
@@ -1,8 +1,8 @@ 
 Functions changes summary: 0 Removed, 1 Changed, 0 Added function
 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 
-1 function with some indirect sub-type change:
+1 function with incompatible sub-type changes:
 
-  [C] 'function int add(int, int)' has some indirect sub-type changes:
+  [C] 'function int add(int, int)' has some sub-type changes:
     parameter 3 of type 'int' was added
 
diff --git a/tests/data/test-diff-dwarf/test24-added-fn-parms-report-0.txt b/tests/data/test-diff-dwarf/test24-added-fn-parms-report-0.txt
index 7a30831f..43785427 100644
--- a/tests/data/test-diff-dwarf/test24-added-fn-parms-report-0.txt
+++ b/tests/data/test-diff-dwarf/test24-added-fn-parms-report-0.txt
@@ -1,9 +1,9 @@ 
 Functions changes summary: 0 Removed, 1 Changed, 0 Added function
 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 
-1 function with some indirect sub-type change:
+1 function with incompatible sub-type changes:
 
-  [C] 'function void fun(void)' has some indirect sub-type changes:
+  [C] 'function void fun(void)' has some sub-type changes:
     parameter 1 of type 'unsigned int' was added
     parameter 2 of type 'char' was added
     parameter 3 of type 'int' was added
diff --git a/tests/data/test-diff-dwarf/test25-removed-fn-parms-report-0.txt b/tests/data/test-diff-dwarf/test25-removed-fn-parms-report-0.txt
index fab3a5f4..ce8aa496 100644
--- a/tests/data/test-diff-dwarf/test25-removed-fn-parms-report-0.txt
+++ b/tests/data/test-diff-dwarf/test25-removed-fn-parms-report-0.txt
@@ -1,9 +1,9 @@ 
 Functions changes summary: 0 Removed, 1 Changed, 0 Added function
 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 
-1 function with some indirect sub-type change:
+1 function with incompatible sub-type changes:
 
-  [C] 'function void fun(unsigned int, char, int)' has some indirect sub-type changes:
+  [C] 'function void fun(unsigned int, char, int)' has some sub-type changes:
     parameter 1 of type 'unsigned int' was removed
     parameter 2 of type 'char' was removed
     parameter 3 of type 'int' was removed
diff --git a/tests/data/test-diff-dwarf/test26-added-parms-before-variadic-report.txt b/tests/data/test-diff-dwarf/test26-added-parms-before-variadic-report.txt
index bfeb4f3b..2d774334 100644
--- a/tests/data/test-diff-dwarf/test26-added-parms-before-variadic-report.txt
+++ b/tests/data/test-diff-dwarf/test26-added-parms-before-variadic-report.txt
@@ -1,27 +1,27 @@ 
 Functions changes summary: 0 Removed, 4 Changed, 0 Added functions
 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 
-4 functions with some indirect sub-type change:
+4 functions with incompatible sub-type changes:
 
-  [C] 'function void fun1(const char*, ...)' has some indirect sub-type changes:
+  [C] 'function void fun1(const char*, ...)' has some sub-type changes:
     parameter 2 of type '...' changed:
       entity changed from 'variadic parameter type' to 'const char*'
       type size changed from 0 to 64 (in bits)
     parameter 3 of type '...' was added
 
-  [C] 'function void fun2(const char*, ...)' has some indirect sub-type changes:
+  [C] 'function void fun2(const char*, ...)' has some sub-type changes:
     parameter 2 of type '...' changed:
       entity changed from 'variadic parameter type' to 'const char*'
       type size changed from 0 to 64 (in bits)
     parameter 3 of type '...' was added
 
-  [C] 'function void fun3(const char*, const int*, ...)' has some indirect sub-type changes:
+  [C] 'function void fun3(const char*, const int*, ...)' has some sub-type changes:
     parameter 3 of type '...' changed:
       entity changed from 'variadic parameter type' to 'const int*'
       type size changed from 0 to 64 (in bits)
     parameter 4 of type '...' was added
 
-  [C] 'function void fun4(const char*, const int*, ...)' has some indirect sub-type changes:
+  [C] 'function void fun4(const char*, const int*, ...)' has some sub-type changes:
     parameter 3 of type '...' changed:
       entity changed from 'variadic parameter type' to 'const int*'
       type size changed from 0 to 64 (in bits)
diff --git a/tests/data/test-diff-dwarf/test28-vtable-changes-report-0.txt b/tests/data/test-diff-dwarf/test28-vtable-changes-report-0.txt
index d64a87b1..71aa419f 100644
--- a/tests/data/test-diff-dwarf/test28-vtable-changes-report-0.txt
+++ b/tests/data/test-diff-dwarf/test28-vtable-changes-report-0.txt
@@ -3,22 +3,22 @@  Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 Function symbols changes summary: 0 Removed, 0 Added function symbol not referenced by debug info
 Variable symbols changes summary: 0 Removed, 3 Added variable symbols not referenced by debug info
 
-2 Added functions:
-
-  [A] 'method virtual S::~S()'
-    note that this adds a new entry to the vtable of struct S
-  [A] 'method virtual S::~S()'
-    note that this adds a new entry to the vtable of struct S
-
-1 function with some indirect sub-type change:
+1 function with incompatible sub-type changes:
 
-  [C] 'method void S::bar()' has some indirect sub-type changes:
+  [C] 'method void S::bar()' has some sub-type changes:
     method void S::bar() is now declared virtual
       note that this is an ABI incompatible change to the vtable of struct S
     implicit parameter 0 of type 'S*' has sub-type changes:
       in pointed to type 'struct S':
         type struct S was a declaration-only type and is now a defined type
 
+2 Added functions:
+
+  [A] 'method virtual S::~S()'
+    note that this adds a new entry to the vtable of struct S
+  [A] 'method virtual S::~S()'
+    note that this adds a new entry to the vtable of struct S
+
 3 Added variable symbols not referenced by debug info:
 
   [A] _ZTI1S
diff --git a/tests/data/test-diff-dwarf/test30-vtable-changes-report-0.txt b/tests/data/test-diff-dwarf/test30-vtable-changes-report-0.txt
index 4f165923..c27782d4 100644
--- a/tests/data/test-diff-dwarf/test30-vtable-changes-report-0.txt
+++ b/tests/data/test-diff-dwarf/test30-vtable-changes-report-0.txt
@@ -1,14 +1,11 @@ 
 Functions changes summary: 0 Removed, 4 Changed, 1 Added functions
 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 
-1 Added function:
-
-  [A] 'method virtual void S::fvtable_breaker()'
-    note that this adds a new entry to the vtable of struct S
-
-4 functions with some indirect sub-type change:
+1 function with incompatible sub-type changes:
 
-  [C] 'method virtual void S::fn0()' has some indirect sub-type changes:
+  [C] 'method virtual void S::fn1()' has some sub-type changes:
+    the vtable offset of method virtual void S::fn1() changed from 3 to 4
+      note that this is an ABI incompatible change to the vtable of struct S
     implicit parameter 0 of type 'S*' has sub-type changes:
       in pointed to type 'struct S':
         type size hasn't changed
@@ -33,9 +30,14 @@  Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
             implicit parameter 0 of type 'S*' has sub-type changes:
               pointed to type 'struct S' changed, as being reported
 
-  [C] 'method virtual void S::fn1()' has some indirect sub-type changes:
-    the vtable offset of method virtual void S::fn1() changed from 3 to 4
-      note that this is an ABI incompatible change to the vtable of struct S
+1 Added function:
+
+  [A] 'method virtual void S::fvtable_breaker()'
+    note that this adds a new entry to the vtable of struct S
+
+3 functions with some indirect sub-type change:
+
+  [C] 'method virtual void S::fn0()' has some indirect sub-type changes:
     implicit parameter 0 of type 'S*' has sub-type changes:
       pointed to type 'struct S' changed, as reported earlier
 
diff --git a/tests/data/test-diff-dwarf/test31-vtable-changes-report-0.txt b/tests/data/test-diff-dwarf/test31-vtable-changes-report-0.txt
index debb12e9..3ec9d2b7 100644
--- a/tests/data/test-diff-dwarf/test31-vtable-changes-report-0.txt
+++ b/tests/data/test-diff-dwarf/test31-vtable-changes-report-0.txt
@@ -6,9 +6,9 @@  Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
   [D] 'method virtual void S::fn0()'
     note that this removes an entry from the vtable of struct S
 
-3 functions with some indirect sub-type change:
+1 function with incompatible sub-type changes:
 
-  [C] 'method virtual void S::fn1()' has some indirect sub-type changes:
+  [C] 'method virtual void S::fn1()' has some sub-type changes:
     the vtable offset of method virtual void S::fn1() changed from 3 to 2
       note that this is an ABI incompatible change to the vtable of struct S
     implicit parameter 0 of type 'S*' has sub-type changes:
@@ -32,6 +32,8 @@  Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
             implicit parameter 0 of type 'S*' has sub-type changes:
               pointed to type 'struct S' changed, as being reported
 
+2 functions with some indirect sub-type change:
+
   [C] 'method virtual S::~S()' has some indirect sub-type changes:
     implicit parameter 0 of type 'S*' has sub-type changes:
       pointed to type 'struct S' changed, as reported earlier
diff --git a/tests/data/test-diff-dwarf/test32-fnptr-changes-report-0.txt b/tests/data/test-diff-dwarf/test32-fnptr-changes-report-0.txt
index 2ba0e64a..bbe3f196 100644
--- a/tests/data/test-diff-dwarf/test32-fnptr-changes-report-0.txt
+++ b/tests/data/test-diff-dwarf/test32-fnptr-changes-report-0.txt
@@ -5,11 +5,20 @@  Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 
   [D] 'function void fn2(callback)'
 
+1 function with incompatible sub-type changes:
+
+  [C] 'function double (*fn1(void))(int)' has some sub-type changes:
+    return type changed:
+      in pointed to type 'function type double (int)':
+        return type changed:
+          type name changed from 'double' to 'int'
+          type size changed from 64 to 32 (in bits)
+
 1 Added function:
 
   [A] 'function void fn2(callback)'
 
-3 functions with some indirect sub-type change:
+2 functions with some indirect sub-type change:
 
   [C] 'function callback fn0(void)' has some indirect sub-type changes:
     return type changed:
@@ -19,13 +28,6 @@  Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
             type name changed from 'int' to 'void'
             type size changed from 32 to 0 (in bits)
 
-  [C] 'function double (*fn1(void))(int)' has some indirect sub-type changes:
-    return type changed:
-      in pointed to type 'function type double (int)':
-        return type changed:
-          type name changed from 'double' to 'int'
-          type size changed from 64 to 32 (in bits)
-
   [C] 'function void foo(S)' has some indirect sub-type changes:
     parameter 1 of type 'class S' has sub-type changes:
       type size hasn't changed
diff --git a/tests/data/test-diff-dwarf/test33-fnref-changes-report-0.txt b/tests/data/test-diff-dwarf/test33-fnref-changes-report-0.txt
index 1d76043e..270c7d17 100644
--- a/tests/data/test-diff-dwarf/test33-fnref-changes-report-0.txt
+++ b/tests/data/test-diff-dwarf/test33-fnref-changes-report-0.txt
@@ -5,11 +5,20 @@  Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 
   [D] 'function void fn2(const callback)'
 
+1 function with incompatible sub-type changes:
+
+  [C] 'function double (int)& fn1(void)' has some sub-type changes:
+    return type changed:
+      in referenced type 'function type double (int)':
+        return type changed:
+          type name changed from 'double' to 'int'
+          type size changed from 64 to 32 (in bits)
+
 1 Added function:
 
   [A] 'function void fn2(const callback)'
 
-3 functions with some indirect sub-type change:
+2 functions with some indirect sub-type change:
 
   [C] 'function callback fn0(void)' has some indirect sub-type changes:
     return type changed:
@@ -19,13 +28,6 @@  Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
             type name changed from 'int' to 'void'
             type size changed from 32 to 0 (in bits)
 
-  [C] 'function double (int)& fn1(void)' has some indirect sub-type changes:
-    return type changed:
-      in referenced type 'function type double (int)':
-        return type changed:
-          type name changed from 'double' to 'int'
-          type size changed from 64 to 32 (in bits)
-
   [C] 'function void foo(S&)' has some indirect sub-type changes:
     parameter 1 of type 'S&' has sub-type changes:
       in referenced type 'class S':
diff --git a/tests/data/test-diff-dwarf/test35-pr19173-libfoo-long-clang-report-0.txt b/tests/data/test-diff-dwarf/test35-pr19173-libfoo-long-clang-report-0.txt
index 8f7ae28d..66730b10 100644
--- a/tests/data/test-diff-dwarf/test35-pr19173-libfoo-long-clang-report-0.txt
+++ b/tests/data/test-diff-dwarf/test35-pr19173-libfoo-long-clang-report-0.txt
@@ -1,7 +1,7 @@ 
 Functions changes summary: 0 Removed, 0 Changed, 0 Added function
 Variables changes summary: 0 Removed, 1 Changed, 0 Added variable
 
-1 Changed variable:
+1 variable with incompatible sub-type changes:
 
   [C] 'char buggy_symbol[5]' was changed to 'char buggy_symbol[10]':
     size of symbol changed from 5 to 10
diff --git a/tests/data/test-diff-dwarf/test35-pr19173-libfoo-long-gcc-report-0.txt b/tests/data/test-diff-dwarf/test35-pr19173-libfoo-long-gcc-report-0.txt
index 8f7ae28d..66730b10 100644
--- a/tests/data/test-diff-dwarf/test35-pr19173-libfoo-long-gcc-report-0.txt
+++ b/tests/data/test-diff-dwarf/test35-pr19173-libfoo-long-gcc-report-0.txt
@@ -1,7 +1,7 @@ 
 Functions changes summary: 0 Removed, 0 Changed, 0 Added function
 Variables changes summary: 0 Removed, 1 Changed, 0 Added variable
 
-1 Changed variable:
+1 variable with incompatible sub-type changes:
 
   [C] 'char buggy_symbol[5]' was changed to 'char buggy_symbol[10]':
     size of symbol changed from 5 to 10
diff --git a/tests/data/test-diff-dwarf/test46-rust-report-0.txt b/tests/data/test-diff-dwarf/test46-rust-report-0.txt
index 652567e4..be80e749 100644
--- a/tests/data/test-diff-dwarf/test46-rust-report-0.txt
+++ b/tests/data/test-diff-dwarf/test46-rust-report-0.txt
@@ -1,9 +1,9 @@ 
 Functions changes summary: 0 Removed, 1 Changed, 0 Added function
 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 
-1 function with some indirect sub-type change:
+1 function with incompatible sub-type changes:
 
-  [C] 'function one::Foo one::foo(u32)' has some indirect sub-type changes:
+  [C] 'function one::Foo one::foo(u32)' has some sub-type changes:
     'function one::Foo one::foo(u32) {foo}' now becomes 'function two::Foo two::foo(u32, u32) {foo}'
     return type changed:
       type name changed from 'one::Foo' to 'two::Foo'
diff --git a/tests/data/test-diff-dwarf/test9-report.txt b/tests/data/test-diff-dwarf/test9-report.txt
index 8a87fc04..b88eb5c7 100644
--- a/tests/data/test-diff-dwarf/test9-report.txt
+++ b/tests/data/test-diff-dwarf/test9-report.txt
@@ -1,11 +1,7 @@ 
 Functions changes summary: 0 Removed, 0 Changed, 0 Added function
 Variables changes summary: 0 Removed, 1 Changed, 1 Added variables
 
-1 Added variable:
-
-  [A] 'unsigned int global_var2'
-
-1 Changed variable:
+1 variable with incompatible sub-type changes:
 
   [C] 'int global_var0' was changed to 'char global_var0':
     size of symbol changed from 4 to 1
@@ -13,3 +9,7 @@  Variables changes summary: 0 Removed, 1 Changed, 1 Added variables
       type name changed from 'int' to 'char'
       type size changed from 32 to 8 (in bits)
 
+1 Added variable:
+
+  [A] 'unsigned int global_var2'
+
diff --git a/tests/data/test-diff-filter/libtest45-basic-type-change-report-0.txt b/tests/data/test-diff-filter/libtest45-basic-type-change-report-0.txt
index bef70c68..4d6e09d8 100644
--- a/tests/data/test-diff-filter/libtest45-basic-type-change-report-0.txt
+++ b/tests/data/test-diff-filter/libtest45-basic-type-change-report-0.txt
@@ -1,9 +1,9 @@ 
 Functions changes summary: 0 Removed, 4 Changed, 0 Added functions
 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 
-4 functions with some indirect sub-type change:
+4 functions with incompatible sub-type changes:
 
-  [C] 'function int& foo0(S0&)' at test45-basic-type-change-v0.cc:25:1 has some indirect sub-type changes:
+  [C] 'function int& foo0(S0&)' at test45-basic-type-change-v0.cc:25:1 has some sub-type changes:
     return type changed:
       in referenced type 'int':
         type name changed from 'int' to 'char'
@@ -17,7 +17,7 @@  Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
               type name changed from 'int' to 'char'
               type size changed from 32 to 8 (in bits)
 
-  [C] 'function int* foo1(S1&)' at test45-basic-type-change-v0.cc:29:1 has some indirect sub-type changes:
+  [C] 'function int* foo1(S1&)' at test45-basic-type-change-v0.cc:29:1 has some sub-type changes:
     return type changed:
       in pointed to type 'int':
         type name changed from 'int' to 'char'
@@ -31,7 +31,7 @@  Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
               type name changed from 'int' to 'char'
               type size changed from 32 to 8 (in bits)
 
-  [C] 'function const int foo2(S2&)' at test45-basic-type-change-v0.cc:33:1 has some indirect sub-type changes:
+  [C] 'function const int foo2(S2&)' at test45-basic-type-change-v0.cc:33:1 has some sub-type changes:
     return type changed:
       'const int' changed to 'const char'
     parameter 1 of type 'S2&' has sub-type changes:
@@ -43,8 +43,10 @@  Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
               type name changed from 'int' to 'char'
               type size changed from 32 to 8 (in bits)
 
-  [C] 'function int foo3(S2&)' at test45-basic-type-change-v0.cc:37:1 has some indirect sub-type changes:
+  [C] 'function int foo3(S2&)' at test45-basic-type-change-v0.cc:37:1 has some sub-type changes:
     return type changed:
       type name changed from 'int' to 'char'
       type size changed from 32 to 8 (in bits)
+    parameter 1 of type 'S2&' has sub-type changes:
+      referenced type 'struct S2' changed at test45-basic-type-change-v0.cc:18:1, as reported earlier
 
diff --git a/tests/data/test-diff-filter/test-PR27569-report-0.txt b/tests/data/test-diff-filter/test-PR27569-report-0.txt
index 99febd66..69eb352b 100644
--- a/tests/data/test-diff-filter/test-PR27569-report-0.txt
+++ b/tests/data/test-diff-filter/test-PR27569-report-0.txt
@@ -1,9 +1,9 @@ 
 Functions changes summary: 0 Removed, 1 Changed, 0 Added function
 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 
-1 function with some indirect sub-type change:
+1 function with incompatible sub-type changes:
 
-  [C] 'function void device_add_disk(gendisk*)' at genhd.h:420:1 has some indirect sub-type changes:
+  [C] 'function void device_add_disk(gendisk*)' at genhd.h:420:1 has some sub-type changes:
     CRC (modversions) changed from 0x8afa957c to 0xa3bc03c
     parameter 2 of type 'int' was added
 
diff --git a/tests/data/test-diff-filter/test-PR28013-fn-variadic.c.report.txt b/tests/data/test-diff-filter/test-PR28013-fn-variadic.c.report.txt
index bb37e10f..82894c1e 100644
--- a/tests/data/test-diff-filter/test-PR28013-fn-variadic.c.report.txt
+++ b/tests/data/test-diff-filter/test-PR28013-fn-variadic.c.report.txt
@@ -1,16 +1,18 @@ 
 Functions changes summary: 0 Removed, 3 Changed, 0 Added functions
 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 
-3 functions with some indirect sub-type change:
+2 functions with incompatible sub-type changes:
 
-  [C] 'function int foo1(int, int)' has some indirect sub-type changes:
+  [C] 'function int foo1(int, int)' has some sub-type changes:
     parameter 3 of type '...' was added
 
+  [C] 'function int foo3(int, int, ...)' has some sub-type changes:
+    parameter 3 of type '...' was removed
+
+1 function with some indirect sub-type change:
+
   [C] 'function int foo2(int, int)' has some indirect sub-type changes:
     parameter 2 of type 'int' changed:
       type name changed from 'int' to 'variadic parameter type'
       type size changed from 32 to 0 (in bits)
 
-  [C] 'function int foo3(int, int, ...)' has some indirect sub-type changes:
-    parameter 3 of type '...' was removed
-
diff --git a/tests/data/test-diff-filter/test15-0-report.txt b/tests/data/test-diff-filter/test15-0-report.txt
index ae7488e8..a8dce8cc 100644
--- a/tests/data/test-diff-filter/test15-0-report.txt
+++ b/tests/data/test-diff-filter/test15-0-report.txt
@@ -10,3 +10,7 @@  Variables changes summary: 0 Removed, 1 Changed (1 filtered out), 0 Added variab
         1 data member insertion:
           'unsigned int m2', at offset 64 (in bits)
 
+  [C] 'S* var2' was changed:
+    type of variable changed:
+      pointed to type 'struct S' changed, as reported earlier
+
diff --git a/tests/data/test-diff-filter/test30-pr18904-rvalueref-report0.txt b/tests/data/test-diff-filter/test30-pr18904-rvalueref-report0.txt
index 7d5d160f..c80af390 100644
--- a/tests/data/test-diff-filter/test30-pr18904-rvalueref-report0.txt
+++ b/tests/data/test-diff-filter/test30-pr18904-rvalueref-report0.txt
@@ -1451,6 +1451,15 @@  Variable symbols changes summary: 0 Removed, 0 Added variable symbol not referen
   [D] 'const char* prefix'
   [D] 'int timer_enabled'
 
+1 variable with incompatible sub-type changes:
+
+  [C] 'static const char* Engine::m_func_names[6]' was changed to 'static const char* Engine::m_func_names[7]':
+    size of symbol changed from 48 to 56
+    type of variable changed:
+      type name changed from 'const char*[6]' to 'const char*[7]'
+      array type size changed from 384 to 448
+      array type subrange 1 changed length from 6 to 7
+
 11 Added variables:
 
   [A] 'COIRESULT (* COI::EngineGetInfo)(COIENGINE, uint32_t, COI_ENGINE_INFO*)'
@@ -1465,15 +1474,6 @@  Variable symbols changes summary: 0 Removed, 0 Added variable symbol not referen
   [A] 'MYOVarTableList __offload_myo_var_tables'
   [A] 'MYOVarTableList __offload_myo_vtable_tables'
 
-1 Changed variable:
-
-  [C] 'static const char* Engine::m_func_names[6]' was changed to 'static const char* Engine::m_func_names[7]':
-    size of symbol changed from 48 to 56
-    type of variable changed:
-      type name changed from 'const char*[6]' to 'const char*[7]'
-      array type size changed from 384 to 448
-      array type subrange 1 changed length from 6 to 7
-
 7 Removed function symbols not referenced by debug info:
 
   [D] _ZN7VarListD1Ev
diff --git a/tests/data/test-diff-filter/test30-pr18904-rvalueref-report1.txt b/tests/data/test-diff-filter/test30-pr18904-rvalueref-report1.txt
index e6ae0734..a033cf84 100644
--- a/tests/data/test-diff-filter/test30-pr18904-rvalueref-report1.txt
+++ b/tests/data/test-diff-filter/test30-pr18904-rvalueref-report1.txt
@@ -1451,6 +1451,15 @@  Variable symbols changes summary: 0 Removed, 0 Added variable symbol not referen
   [D] 'const char* prefix'
   [D] 'int timer_enabled'
 
+1 variable with incompatible sub-type changes:
+
+  [C] 'static const char* Engine::m_func_names[6]' was changed to 'static const char* Engine::m_func_names[7]' at offload_engine.cpp:49:1:
+    size of symbol changed from 48 to 56
+    type of variable changed:
+      type name changed from 'const char*[6]' to 'const char*[7]'
+      array type size changed from 384 to 448
+      array type subrange 1 changed length from 6 to 7
+
 11 Added variables:
 
   [A] 'COIRESULT (* COI::EngineGetInfo)(COIENGINE, uint32_t, COI_ENGINE_INFO*)'
@@ -1465,15 +1474,6 @@  Variable symbols changes summary: 0 Removed, 0 Added variable symbol not referen
   [A] 'MYOVarTableList __offload_myo_var_tables'
   [A] 'MYOVarTableList __offload_myo_vtable_tables'
 
-1 Changed variable:
-
-  [C] 'static const char* Engine::m_func_names[6]' was changed to 'static const char* Engine::m_func_names[7]' at offload_engine.cpp:49:1:
-    size of symbol changed from 48 to 56
-    type of variable changed:
-      type name changed from 'const char*[6]' to 'const char*[7]'
-      array type size changed from 384 to 448
-      array type subrange 1 changed length from 6 to 7
-
 7 Removed function symbols not referenced by debug info:
 
   [D] _ZN7VarListD1Ev
diff --git a/tests/data/test-diff-filter/test30-pr18904-rvalueref-report2.txt b/tests/data/test-diff-filter/test30-pr18904-rvalueref-report2.txt
index e71d5e4c..6c390d50 100644
--- a/tests/data/test-diff-filter/test30-pr18904-rvalueref-report2.txt
+++ b/tests/data/test-diff-filter/test30-pr18904-rvalueref-report2.txt
@@ -1451,6 +1451,15 @@  Variable symbols changes summary: 0 Removed, 0 Added variable symbol not referen
   [D] 'const char* prefix'
   [D] 'int timer_enabled'
 
+1 variable with incompatible sub-type changes:
+
+  [C] 'static const char* Engine::m_func_names[6]' was changed to 'static const char* Engine::m_func_names[7]' at offload_engine.cpp:49:1:
+    size of symbol changed from 0x6 to 0x7
+    type of variable changed:
+      type name changed from 'const char*[6]' to 'const char*[7]'
+      array type size changed from 0x180 to 0x1c0
+      array type subrange 1 changed length from 6 to 7
+
 11 Added variables:
 
   [A] 'COIRESULT (* COI::EngineGetInfo)(COIENGINE, uint32_t, COI_ENGINE_INFO*)'
@@ -1465,15 +1474,6 @@  Variable symbols changes summary: 0 Removed, 0 Added variable symbol not referen
   [A] 'MYOVarTableList __offload_myo_var_tables'
   [A] 'MYOVarTableList __offload_myo_vtable_tables'
 
-1 Changed variable:
-
-  [C] 'static const char* Engine::m_func_names[6]' was changed to 'static const char* Engine::m_func_names[7]' at offload_engine.cpp:49:1:
-    size of symbol changed from 0x6 to 0x7
-    type of variable changed:
-      type name changed from 'const char*[6]' to 'const char*[7]'
-      array type size changed from 0x180 to 0x1c0
-      array type subrange 1 changed length from 6 to 7
-
 7 Removed function symbols not referenced by debug info:
 
   [D] _ZN7VarListD1Ev
diff --git a/tests/data/test-diff-filter/test35-pr18754-no-added-syms-report-0.txt b/tests/data/test-diff-filter/test35-pr18754-no-added-syms-report-0.txt
index 1a4a16a0..a69ca996 100644
--- a/tests/data/test-diff-filter/test35-pr18754-no-added-syms-report-0.txt
+++ b/tests/data/test-diff-filter/test35-pr18754-no-added-syms-report-0.txt
@@ -367,7 +367,7 @@  Variable symbols changes summary: 0 Removed, 0 Added variable symbol not referen
   [D] 'const char* prefix'
   [D] 'int timer_enabled'
 
-1 Changed variable:
+1 variable with incompatible sub-type changes:
 
   [C] 'static const char* Engine::m_func_names[6]' was changed to 'static const char* Engine::m_func_names[7]':
     size of symbol changed from 48 to 56
diff --git a/tests/data/test-diff-filter/test35-pr18754-no-added-syms-report-1.txt b/tests/data/test-diff-filter/test35-pr18754-no-added-syms-report-1.txt
index 8d0e68bb..5ef8035f 100644
--- a/tests/data/test-diff-filter/test35-pr18754-no-added-syms-report-1.txt
+++ b/tests/data/test-diff-filter/test35-pr18754-no-added-syms-report-1.txt
@@ -88,7 +88,7 @@  Variable symbols changes summary: 0 Removed, 0 Added variable symbol not referen
   [D] 'function void std::__unguarded_linear_insert<VarList::BufEntry*,__gnu_cxx::__ops::_Val_comp_iter<bool(*)(constVarList::BufEntry&,constVarList::BufEntry&)>>(VarList::BufEntry*, __gnu_cxx::__ops::_Val_comp_iter<bool(*)(constVarList::BufEntry&,constVarList::BufEntry&)>)'
   [D] 'function void write_message(FILE*, int, __va_list_tag*)'
 
-1 Changed variable:
+1 variable with incompatible sub-type changes:
 
   [C] 'static const char* Engine::m_func_names[6]' was changed to 'static const char* Engine::m_func_names[7]':
     size of symbol changed from 48 to 56
diff --git a/tests/data/test-diff-filter/test41-report-0.txt b/tests/data/test-diff-filter/test41-report-0.txt
index 2b540394..35fb8d8a 100644
--- a/tests/data/test-diff-filter/test41-report-0.txt
+++ b/tests/data/test-diff-filter/test41-report-0.txt
@@ -14,6 +14,57 @@  Variable symbols changes summary: 0 Removed, 0 Added variable symbol not referen
   [D] 'method std::pair<bool,longunsignedint> std::tr1::__detail::_Prime_rehash_policy::_M_need_rehash(std::size_t, std::size_t, std::size_t) const'    {_ZNKSt3tr18__detail20_Prime_rehash_policy14_M_need_rehashEmmm}
   [D] 'method std::tr1::__shared_count<(__gnu_cxx::_Lock_policy)2>& std::tr1::__shared_count<(__gnu_cxx::_Lock_policy)2>::operator=(const std::tr1::__shared_count<(__gnu_cxx::_Lock_policy)2>&)'    {_ZNSt3tr114__shared_countILN9__gnu_cxx12_Lock_policyE2EEaSERKS3_}
 
+2 functions with incompatible sub-type changes:
+
+  [C] 'method void std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>::_M_initialize_map(std::size_t)' at stl_deque.h:679:1 has some sub-type changes:
+    'method void std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>::_M_initialize_map(std::size_t) {_ZNSt11_Deque_baseINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE17_M_initialize_mapEm}' now becomes 'method void std::_Deque_base<std::__cxx11::basic_string<char>,std::allocator<std::__cxx11::basic_string<char>>>::_M_initialize_map(std::size_t) {_ZNSt11_Deque_baseINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE17_M_initialize_mapEm}'
+    implicit parameter 0 of type 'std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>*' changed:
+      in pointed to type 'class std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>' at stl_deque.h:458:1:
+        type name changed from 'std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>' to 'std::_Deque_base<std::__cxx11::basic_string<char>,std::allocator<std::__cxx11::basic_string<char>>>'
+        type size hasn't changed
+        1 data member change:
+          type of 'std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>::_Deque_impl _M_impl' changed:
+            type name changed from 'std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>::_Deque_impl' to 'std::_Deque_base<std::__cxx11::basic_string<char>,std::allocator<std::__cxx11::basic_string<char>>>::_Deque_impl'
+            type size hasn't changed
+            1 base class deletion:
+              class std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>> at allocator.h:108:1
+            1 base class insertion:
+              class std::allocator<std::__cxx11::basic_string<char>> at allocator.h:108:1
+            3 data member changes:
+              type of 'std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>::_Map_pointer _M_map' changed:
+                typedef name changed from std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>::_Map_pointer to std::_Deque_base<std::__cxx11::basic_string<char>,std::allocator<std::__cxx11::basic_string<char>>>::_Map_pointer at stl_deque.h:542:1
+                underlying type 'typedef std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>::_Map_pointer' at stl_deque.h:123:1 changed:
+                  typedef name changed from std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>::_Map_pointer to std::_Deque_iterator<std::__cxx11::basic_string<char>,std::__cxx11::basic_string<char>&,std::__cxx11::basic_string<char>*>::_Map_pointer at stl_deque.h:112:1
+                  underlying type 'typedef std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>::__ptr_to' at stl_deque.h:116:1 changed:
+                    entity changed from 'typedef std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>::__ptr_to' to 'std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>**'
+                    type size hasn't changed
+              and name of 'std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>::_Deque_impl::_M_map' changed to 'std::_Deque_base<std::__cxx11::basic_string<char>,std::allocator<std::__cxx11::basic_string<char>>>::_Deque_impl::_M_map' at stl_deque.h:550:1
+              type of 'std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>::iterator _M_start' changed:
+                typedef name changed from std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>::iterator to std::_Deque_base<std::__cxx11::basic_string<char>,std::allocator<std::__cxx11::basic_string<char>>>::iterator at stl_deque.h:485:1
+                underlying type 'struct std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>' at stl_deque.h:106:1 changed:
+                  type name changed from 'std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>' to 'std::_Deque_iterator<std::__cxx11::basic_string<char>,std::__cxx11::basic_string<char>&,std::__cxx11::basic_string<char>*>'
+                  type size hasn't changed
+                  4 data member changes:
+                    type of 'std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>::_Elt_pointer _M_cur' changed:
+                      typedef name changed from std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>::_Elt_pointer to std::_Deque_iterator<std::__cxx11::basic_string<char>,std::__cxx11::basic_string<char>&,std::__cxx11::basic_string<char>*>::_Elt_pointer at stl_deque.h:111:1
+                      underlying type 'typedef std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>::__ptr_to' at stl_deque.h:116:1 changed:
+                        entity changed from 'typedef std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>::__ptr_to' to 'std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*'
+                        type size hasn't changed
+                    and name of 'std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>::_M_cur' changed to 'std::_Deque_iterator<std::__cxx11::basic_string<char>,std::__cxx11::basic_string<char>&,std::__cxx11::basic_string<char>*>::_M_cur' at stl_deque.h:137:1
+                    type of 'std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>::_Elt_pointer _M_first' changed, as reported earlier
+                    and name of 'std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>::_M_first' changed to 'std::_Deque_iterator<std::__cxx11::basic_string<char>,std::__cxx11::basic_string<char>&,std::__cxx11::basic_string<char>*>::_M_first' at stl_deque.h:138:1
+                    type of 'std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>::_Elt_pointer _M_last' changed, as reported earlier
+                    and name of 'std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>::_M_last' changed to 'std::_Deque_iterator<std::__cxx11::basic_string<char>,std::__cxx11::basic_string<char>&,std::__cxx11::basic_string<char>*>::_M_last' at stl_deque.h:139:1
+                    type of 'std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>::_Map_pointer _M_node' changed, as reported earlier
+                    and name of 'std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>::_M_node' changed to 'std::_Deque_iterator<std::__cxx11::basic_string<char>,std::__cxx11::basic_string<char>&,std::__cxx11::basic_string<char>*>::_M_node' at stl_deque.h:140:1
+              and name of 'std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>::_Deque_impl::_M_start' changed to 'std::_Deque_base<std::__cxx11::basic_string<char>,std::allocator<std::__cxx11::basic_string<char>>>::_Deque_impl::_M_start' at stl_deque.h:552:1
+              type of 'std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>::iterator _M_finish' changed, as reported earlier
+              and name of 'std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>::_Deque_impl::_M_finish' changed to 'std::_Deque_base<std::__cxx11::basic_string<char>,std::allocator<std::__cxx11::basic_string<char>>>::_Deque_impl::_M_finish' at stl_deque.h:553:1
+          and name of 'std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>::_M_impl' changed to 'std::_Deque_base<std::__cxx11::basic_string<char>,std::allocator<std::__cxx11::basic_string<char>>>::_M_impl' at stl_deque.h:631:1
+
+  [C] 'method virtual void std::tr1::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_destroy()' at shared_ptr.h:120:1 has some sub-type changes:
+    method virtual void std::tr1::_Sp_counted_base<__gnu_cxx::_Lock_policy::_S_atomic>::_M_destroy() is not declared inline anymore
+
 16 Added functions:
 
   [A] 'method std::__cxx11::string abigail::xml_writer::write_context::get_id_for_class_tmpl(const abigail::ir::class_tdecl_sptr&)'    {_ZN7abigail10xml_writer13write_context21get_id_for_class_tmplB5cxx11ERKNSt3tr110shared_ptrINS_2ir11class_tdeclEEE}
@@ -34,7 +85,7 @@  Variable symbols changes summary: 0 Removed, 0 Added variable symbol not referen
     note that this adds a new entry to the vtable of class std::tr1::_Sp_counted_base<__gnu_cxx::_Lock_policy::_S_atomic>
   [A] 'function void std::tr1::__enable_shared_from_this_helper<__gnu_cxx::_Lock_policy::_S_atomic>(const std::tr1::__shared_count<__gnu_cxx::_Lock_policy::_S_atomic>&, ...)'    {_ZNSt3tr132__enable_shared_from_this_helperILN9__gnu_cxx12_Lock_policyE2EEEvRKNS_14__shared_countIXT_EEEz}
 
-5 functions with some indirect sub-type change:
+3 functions with some indirect sub-type change:
 
   [C] 'method abigail::interned_string abigail::xml_writer::write_context::get_id_for_type(abigail::ir::type_base*) const' at abg-writer.cc:247:1 has some indirect sub-type changes:
     return type changed:
@@ -99,47 +150,6 @@  Variable symbols changes summary: 0 Removed, 0 Added variable symbol not referen
           1 base class insertion:
             class std::tr1::__shared_ptr<abigail::ir::corpus,__gnu_cxx::_Lock_policy::_S_atomic> at shared_ptr.h:539:1
 
-  [C] 'method void std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>::_M_initialize_map(std::size_t)' at stl_deque.h:679:1 has some indirect sub-type changes:
-    'method void std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>::_M_initialize_map(std::size_t) {_ZNSt11_Deque_baseINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE17_M_initialize_mapEm}' now becomes 'method void std::_Deque_base<std::__cxx11::basic_string<char>,std::allocator<std::__cxx11::basic_string<char>>>::_M_initialize_map(std::size_t) {_ZNSt11_Deque_baseINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE17_M_initialize_mapEm}'
-    implicit parameter 0 of type 'std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>*' changed:
-      in pointed to type 'class std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>' at stl_deque.h:458:1:
-        type name changed from 'std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>' to 'std::_Deque_base<std::__cxx11::basic_string<char>,std::allocator<std::__cxx11::basic_string<char>>>'
-        type size hasn't changed
-        1 data member change:
-          type of 'std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>::_Deque_impl _M_impl' changed:
-            type name changed from 'std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>::_Deque_impl' to 'std::_Deque_base<std::__cxx11::basic_string<char>,std::allocator<std::__cxx11::basic_string<char>>>::_Deque_impl'
-            type size hasn't changed
-            1 base class deletion:
-              class std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>> at allocator.h:108:1
-            1 base class insertion:
-              class std::allocator<std::__cxx11::basic_string<char>> at allocator.h:108:1
-            2 data member changes (1 filtered):
-              type of 'std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>::_Map_pointer _M_map' changed:
-                typedef name changed from std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>::_Map_pointer to std::_Deque_base<std::__cxx11::basic_string<char>,std::allocator<std::__cxx11::basic_string<char>>>::_Map_pointer at stl_deque.h:542:1
-                underlying type 'typedef std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>::_Map_pointer' at stl_deque.h:123:1 changed:
-                  typedef name changed from std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>::_Map_pointer to std::_Deque_iterator<std::__cxx11::basic_string<char>,std::__cxx11::basic_string<char>&,std::__cxx11::basic_string<char>*>::_Map_pointer at stl_deque.h:112:1
-                  underlying type 'typedef std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>::__ptr_to' at stl_deque.h:116:1 changed:
-                    entity changed from 'typedef std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>::__ptr_to' to 'std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>**'
-                    type size hasn't changed
-              and name of 'std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>::_Deque_impl::_M_map' changed to 'std::_Deque_base<std::__cxx11::basic_string<char>,std::allocator<std::__cxx11::basic_string<char>>>::_Deque_impl::_M_map' at stl_deque.h:550:1
-              type of 'std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>::iterator _M_start' changed:
-                typedef name changed from std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>::iterator to std::_Deque_base<std::__cxx11::basic_string<char>,std::allocator<std::__cxx11::basic_string<char>>>::iterator at stl_deque.h:485:1
-                underlying type 'struct std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>' at stl_deque.h:106:1 changed:
-                  type name changed from 'std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>' to 'std::_Deque_iterator<std::__cxx11::basic_string<char>,std::__cxx11::basic_string<char>&,std::__cxx11::basic_string<char>*>'
-                  type size hasn't changed
-                  1 data member changes (3 filtered):
-                    type of 'std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>::_Elt_pointer _M_cur' changed:
-                      typedef name changed from std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>::_Elt_pointer to std::_Deque_iterator<std::__cxx11::basic_string<char>,std::__cxx11::basic_string<char>&,std::__cxx11::basic_string<char>*>::_Elt_pointer at stl_deque.h:111:1
-                      underlying type 'typedef std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>::__ptr_to' at stl_deque.h:116:1 changed:
-                        entity changed from 'typedef std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>::__ptr_to' to 'std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*'
-                        type size hasn't changed
-                    and name of 'std::_Deque_iterator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>&,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>*>::_M_cur' changed to 'std::_Deque_iterator<std::__cxx11::basic_string<char>,std::__cxx11::basic_string<char>&,std::__cxx11::basic_string<char>*>::_M_cur' at stl_deque.h:137:1
-              and name of 'std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>::_Deque_impl::_M_start' changed to 'std::_Deque_base<std::__cxx11::basic_string<char>,std::allocator<std::__cxx11::basic_string<char>>>::_Deque_impl::_M_start' at stl_deque.h:552:1
-          and name of 'std::_Deque_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>::_M_impl' changed to 'std::_Deque_base<std::__cxx11::basic_string<char>,std::allocator<std::__cxx11::basic_string<char>>>::_M_impl' at stl_deque.h:631:1
-
-  [C] 'method virtual void std::tr1::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_destroy()' at shared_ptr.h:120:1 has some indirect sub-type changes:
-    method virtual void std::tr1::_Sp_counted_base<__gnu_cxx::_Lock_policy::_S_atomic>::_M_destroy() is not declared inline anymore
-
 1 Removed function symbol not referenced by debug info:
 
   [D] _ZN7abigail10xml_writer13write_contextD1Ev
diff --git a/tests/data/test-diff-filter/test5-2-report.txt b/tests/data/test-diff-filter/test5-2-report.txt
index e2f5f0ba..12a68911 100644
--- a/tests/data/test-diff-filter/test5-2-report.txt
+++ b/tests/data/test-diff-filter/test5-2-report.txt
@@ -1,13 +1,19 @@ 
 Functions changes summary: 0 Removed, 2 Changed (2 filtered out), 0 Added functions
 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 
-2 functions with some indirect sub-type change:
+1 function with incompatible sub-type changes:
 
-  [C] 'method C0::C0()' has some indirect sub-type changes:
+  [C] 'method virtual unsigned int C0::vfn2(char)' has some sub-type changes:
+    return type changed:
+      type name changed from 'unsigned int' to 'int'
+      type size hasn't changed
     implicit parameter 0 of type 'C0*' has sub-type changes:
       in pointed to type 'class C0':
         type size hasn't changed
-        1 member function changes (1 filtered):
+        2 member function changes:
+          'method virtual int C0::vfn1()' has some sub-type changes:
+            implicit parameter 0 of type 'C0*' has sub-type changes:
+              pointed to type 'class C0' changed, as being reported
           'method virtual unsigned int C0::vfn2(char)' has some sub-type changes:
             return type changed:
               type name changed from 'unsigned int' to 'int'
@@ -16,8 +22,9 @@  Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
               pointed to type 'class C0' changed, as being reported
         no data member change (1 filtered);
 
-  [C] 'method virtual unsigned int C0::vfn2(char)' has some indirect sub-type changes:
-    return type changed:
-      type name changed from 'unsigned int' to 'int'
-      type size hasn't changed
+1 function with some indirect sub-type change:
+
+  [C] 'method C0::C0()' has some indirect sub-type changes:
+    implicit parameter 0 of type 'C0*' has sub-type changes:
+      pointed to type 'class C0' changed, as reported earlier
 
diff --git a/tests/data/test-diff-filter/test6-report.txt b/tests/data/test-diff-filter/test6-report.txt
index 5327622d..4ec94308 100644
--- a/tests/data/test-diff-filter/test6-report.txt
+++ b/tests/data/test-diff-filter/test6-report.txt
@@ -1,9 +1,9 @@ 
 Functions changes summary: 0 Removed, 1 Changed, 0 Added function
 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 
-1 function with some indirect sub-type change:
+1 function with incompatible sub-type changes:
 
-  [C] 'function return_type foo(void)' has some indirect sub-type changes:
+  [C] 'function return_type foo(void)' has some sub-type changes:
     return type changed:
       underlying type 'unsigned char' changed:
         type name changed from 'unsigned char' to 'unsigned int'
diff --git a/tests/data/test-diff-filter/test7-report.txt b/tests/data/test-diff-filter/test7-report.txt
index 268ae2ef..878ec46a 100644
--- a/tests/data/test-diff-filter/test7-report.txt
+++ b/tests/data/test-diff-filter/test7-report.txt
@@ -1,9 +1,9 @@ 
 Functions changes summary: 0 Removed, 1 Changed, 0 Added function
 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 
-1 function with some indirect sub-type change:
+1 function with incompatible sub-type changes:
 
-  [C] 'function return_type foo(void)' has some indirect sub-type changes:
+  [C] 'function return_type foo(void)' has some sub-type changes:
     return type changed:
       type name changed from 'return_type' to 'other_return_type'
       type size hasn't changed
diff --git a/tests/data/test-diff-pkg/nss-3.23.0-1.0.fc23.x86_64-report-0.txt b/tests/data/test-diff-pkg/nss-3.23.0-1.0.fc23.x86_64-report-0.txt
index d53ea66c..aece3819 100644
--- a/tests/data/test-diff-pkg/nss-3.23.0-1.0.fc23.x86_64-report-0.txt
+++ b/tests/data/test-diff-pkg/nss-3.23.0-1.0.fc23.x86_64-report-0.txt
@@ -43,7 +43,7 @@ 
               'SSLAuthType authType', at offset 736 (in bits) at sslt.h:250:1
             no data member changes (2 filtered);
 
-  1 Changed variable:
+  1 variable with incompatible sub-type changes:
 
     [C] 'const PRUint16 SSL_ImplementedCiphers[74]' was changed to 'const PRUint16 SSL_ImplementedCiphers[69]' at sslenum.c:51:1:
       size of symbol changed from 148 to 138
diff --git a/tests/data/test-diff-suppr/PR31646/test-PR31646-result-1.txt b/tests/data/test-diff-suppr/PR31646/test-PR31646-result-1.txt
index a2216256..f7b67ae1 100644
--- a/tests/data/test-diff-suppr/PR31646/test-PR31646-result-1.txt
+++ b/tests/data/test-diff-suppr/PR31646/test-PR31646-result-1.txt
@@ -1,9 +1,9 @@ 
 Functions changes summary: 0 Removed, 1 Changed, 0 Added function
 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 
-1 function with some indirect sub-type change:
+1 function with incompatible sub-type changes:
 
-  [C] 'function opaque* fun(type&)' at test-PR31646-v0.cc:15:1 has some indirect sub-type changes:
+  [C] 'function opaque* fun(type&)' at test-PR31646-v0.cc:15:1 has some sub-type changes:
     return type changed:
       entity changed from 'opaque*' to 'void'
       type size changed from 64 to 0 (in bits)
diff --git a/tests/data/test-diff-suppr/PR31646/test-PR31646-result-3.txt b/tests/data/test-diff-suppr/PR31646/test-PR31646-result-3.txt
index 2433dcd2..9c9ebae9 100644
--- a/tests/data/test-diff-suppr/PR31646/test-PR31646-result-3.txt
+++ b/tests/data/test-diff-suppr/PR31646/test-PR31646-result-3.txt
@@ -1,9 +1,9 @@ 
 Functions changes summary: 0 Removed, 1 Changed, 0 Added function
 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 
-1 function with some indirect sub-type change:
+1 function with incompatible sub-type changes:
 
-  [C] 'function opaque* fun(type&)' at test-PR31646-v0.cc:15:1 has some indirect sub-type changes:
+  [C] 'function opaque* fun(type&)' at test-PR31646-v0.cc:15:1 has some sub-type changes:
     return type changed:
       entity changed from 'opaque*' to 'void'
       type size changed from 64 to 0 (in bits)
diff --git a/tests/data/test-diff-suppr/test-has-data-member-inserted-between-1-report-2.txt b/tests/data/test-diff-suppr/test-has-data-member-inserted-between-1-report-2.txt
index 605fb3c2..9b373f9d 100644
--- a/tests/data/test-diff-suppr/test-has-data-member-inserted-between-1-report-2.txt
+++ b/tests/data/test-diff-suppr/test-has-data-member-inserted-between-1-report-2.txt
@@ -1,7 +1,7 @@ 
 Functions changes summary: 0 Removed, 0 Changed, 0 Added function
 Variables changes summary: 0 Removed, 1 Changed, 0 Added variable
 
-1 Changed variable:
+1 variable with incompatible sub-type changes:
 
   [C] 'S s' was changed at test-has-data-member-inserted-between-1-v2.c:11:1:
     type of variable changed:
diff --git a/tests/data/test-diff-suppr/test-has-data-member-inserted-between-1-report-3.txt b/tests/data/test-diff-suppr/test-has-data-member-inserted-between-1-report-3.txt
index e87aa121..10994d34 100644
--- a/tests/data/test-diff-suppr/test-has-data-member-inserted-between-1-report-3.txt
+++ b/tests/data/test-diff-suppr/test-has-data-member-inserted-between-1-report-3.txt
@@ -1,7 +1,7 @@ 
 Functions changes summary: 0 Removed, 0 Changed, 0 Added function
 Variables changes summary: 0 Removed, 1 Changed, 0 Added variable
 
-1 Changed variable:
+1 variable with incompatible sub-type changes:
 
   [C] 'S s' was changed at test-has-data-member-inserted-between-1-v3.c:11:1:
     size of symbol changed from 20 to 24
diff --git a/tests/data/test-diff-suppr/test-has-data-member-inserted-between-1-report-4.txt b/tests/data/test-diff-suppr/test-has-data-member-inserted-between-1-report-4.txt
index dccae160..b8ecfefa 100644
--- a/tests/data/test-diff-suppr/test-has-data-member-inserted-between-1-report-4.txt
+++ b/tests/data/test-diff-suppr/test-has-data-member-inserted-between-1-report-4.txt
@@ -1,7 +1,7 @@ 
 Functions changes summary: 0 Removed, 0 Changed, 0 Added function
 Variables changes summary: 0 Removed, 1 Changed, 0 Added variable
 
-1 Changed variable:
+1 variable with incompatible sub-type changes:
 
   [C] 'S s' was changed at test-has-data-member-inserted-between-1-v4.c:10:1:
     type of variable changed:
diff --git a/tests/data/test-diff-suppr/test-has-strict-flexible-array-data-member-conversion-report-1.txt b/tests/data/test-diff-suppr/test-has-strict-flexible-array-data-member-conversion-report-1.txt
index b4ea5bf1..ddca37b2 100644
--- a/tests/data/test-diff-suppr/test-has-strict-flexible-array-data-member-conversion-report-1.txt
+++ b/tests/data/test-diff-suppr/test-has-strict-flexible-array-data-member-conversion-report-1.txt
@@ -1,4 +1,4 @@ 
 Functions changes summary: 0 Removed, 0 Changed, 0 Added function
-Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
-Unreachable types summary: 0 removed, 0 changed (1 filtered out), 0 added type
+Variables changes summary: 0 Removed, 0 Changed (1 filtered out), 0 Added variable
+Unreachable types summary: 0 removed, 0 changed, 0 added type
 
diff --git a/tests/data/test-diff-suppr/test-has-strict-flexible-array-data-member-conversion-report-2.txt b/tests/data/test-diff-suppr/test-has-strict-flexible-array-data-member-conversion-report-2.txt
index 8a6e7286..9151cbbd 100644
--- a/tests/data/test-diff-suppr/test-has-strict-flexible-array-data-member-conversion-report-2.txt
+++ b/tests/data/test-diff-suppr/test-has-strict-flexible-array-data-member-conversion-report-2.txt
@@ -1,16 +1,18 @@ 
 Functions changes summary: 0 Removed, 0 Changed, 0 Added function
-Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
-Unreachable types summary: 0 removed, 1 changed, 0 added type
+Variables changes summary: 0 Removed, 1 Changed, 0 Added variable
+Unreachable types summary: 0 removed, 0 changed, 0 added type
 
-1 changed type unreachable from any public interface:
+1 variable with incompatible sub-type changes:
 
-  [C] 'struct foo' changed:
-    type size changed from 64 to 32 (in bits)
-    1 data member change:
-      type of 'int flex[1]' changed:
-        type name changed from 'int[1]' to 'int[]'
-        array type size changed from 32 to 'unknown'
-        array type subrange 1 changed length from 1 to 'unknown'
-        array subrange changed: 
-          known sized range '<anonymous range>[1]' changed to unknown sized range '<anonymous range>[]'
+  [C] 'foo S' was changed at test-has-strict-flexible-array-data-member-conversion-v1.c:11:1:
+    size of symbol changed from 8 to 4
+    type of variable changed:
+      type size changed from 64 to 32 (in bits)
+      1 data member change:
+        type of 'int flex[1]' changed:
+          type name changed from 'int[1]' to 'int[]'
+          array type size changed from 32 to 'unknown'
+          array type subrange 1 changed length from 1 to 'unknown'
+          array subrange changed: 
+            known sized range '<anonymous range>[1]' changed to unknown sized range '<anonymous range>[]'
 
diff --git a/tests/data/test-diff-suppr/test-has-strict-flexible-array-data-member-conversion-v0.o b/tests/data/test-diff-suppr/test-has-strict-flexible-array-data-member-conversion-v0.o
index 8d0a755d353d580e6afb96dc55a021322caf5a93..3f75f07fe7d543abafe54e496a19ccafc770f6c7 100644
GIT binary patch
literal 2856
zcmc&$&2Ah;5U$?wdM8Zm#94{I5IjL362#2@;GZO5vyvf+l?YjhazetI+3j5q?9Ny-
zV`B>m9w1j9AO{Y-0UUW09s#&=fU2G@yVD*^NIp<fcU65=)m7Ww)w4f*{`h`F2w)Ph
z38xyP06)*4$^#`1;2JDJfpQasOOT4Yp^SQJjI#_}(R4pUz&QfZYLNtUGzqu$NXgB)
zW|EdLPo^(%v}giw-4?M+PeFK>-zLc+U6EK4?=7}HXZiZ_)z<(TZQ;0{chCFSyX%QI
z=2`&9t<>%I9S<`iuxJ9!cfs>EJqIhF7h=0jQLUS>-R_{btBs48bj4Wd(>EHgWB#{r
zG*lhxcPq)9`lvL)g%6MmA^u)mAV%AR1BGR^Qw_1)xKb^ng2z*N1P{J==5O`Z{a!Cz
z4ZD87+h6If_wM?)p2(5^Fe<enSiS8Bv+^L78xxtzJQ<=I<-@&=qdRNC+DdTP_k#&c
zvvlGgq(w4GF`PEJvzN_eXOxY;PCApM>`aq5ijzr{OglSIKI*Nl^gE?2%Azxh%1DX9
zC>f7~;$VM22QmeFQ4tg+rYr+0If<t-i1Iu-4k#v=$yqG(V3?(cGB1)W4Gz2E@c&DE
zftumL*491$7M{uN|8OAc5YL<F#OL78f9mW`ZO7py)|bqVanMpnPSsauOb!^$Ygipn
z4Q3#f=)k2j7y%AoYt)bfmupb+$Ns4y2NuqtpCGbi{H~M6y1?;0#Wi`IS5P*0fh!=K
zer*#6(Y1;J;WRe2{;Gv*72Y&(&PC9=ft$Pem4#D{L}|s;P2k!H;+m-zu95I}XhPyT
zk1G{E)SU5OwBEDuzqAfvaXc%d7<rjje2=A49+ePMQ$rXR1%$brM&U@t2b0|-9cO4$
zaumn8JbcL<<xx73FNaK%RB{NWV3FWmr4O^&OyV0ArdcUN>^gjAqTx4O>4o@pjHVvs
z{p7_4ELdE<&<1uBWy0*v8yG&OXve>gM!Fy8#hZ7B*0FUuKYLB`8_<OGZN*Mz+n4SI
zeRT&X9+mLB`V<5FrtvGt3F7?pxg*-ZVXsLz->>gUG067aL7R<{`>F<gQVg<vAEB+T
z{ujC_xK65{UNyV^5n}e52*EQAu90Gp?YoP%y8OTD{10_3<)?nP^Y0@@Yj$y%^js&B
zCWtcUXa1eW?D#*lL%@!D9afn?KPUc%zK|Uq$Bg5c|ES~H&it``p|yeI*pGDMzYfE&
tqvLmUz*V%+`)BVT?P*=A7j!5{{7zTe>He|4ghE|BKL|guqvm$~{{k@068``I

delta 851
zcmZ`%J#5oJ6uz@#`y4l+#!3T}QdbBm0rCe$iAoEpf>g2q6{<imgd}xRlVDelUCKhm
z0!0kaJ~6N%b;$}N6JkJOWMQTob0;JQxN|NYB5~4t@B7~Sbno3ye`4EsliJ#r(BUeF
zsEo$Z5#&%D2|2+mjD?sxq2;=WV5v;GxQVdBz(9`4QV6ApWIH~RS>+Bjg*k)>QCLuK
zBdkqPP*z38!-aKxCT?hAd@??sL`X2ONHlFuyR2b@_K6{pFj6&28f`{toYI|x5}e2B
zNw&R!mZ``1Pdr9FW^+@+urDmIuC1=MN%4Ga>Bfp#DHP0N_EI(vpYYTzGt)LRt)5?R
zb~5Xp>sw9V^)fx*bDcKoQfCHE&u%-`s>x233wqv#+(UQmk?ZCjyI!ZaUT<2tuHC3N
z>~`Jm!Ykoq8ZA{Sb7pF#5jcJ@XqLGcgskwiP|D_K(|m*v@+nvozv3t?iwU?EIRV+o
zQFWfqtfPa!1a=}fu?+i>WOeuqQCd@}m8r3%4+0wIhp(C#$-m?LI4nxZh1roRr|8~D
z{sreYkL+g0;H`9eSAL+cT8*Gx>)MWmvLS}&at(gT?|~>L^c53(@J%V|=HNS_&wP^@
z=p?6p<ZJ_~q=-}Sj9lF%L_KyW`c9HkjWP_2*if&BpAn(^peoZd9hRq-=jvhD<EkI<
zQk|aJ_>by|Fwmc6Drt+USPx-OpwBP?ccZC9pG!)7!#EYugGbK^KSlTwy`ui+hkDKC
F`3H`mf?WUr

diff --git a/tests/data/test-diff-suppr/test-has-strict-flexible-array-data-member-conversion-v1.o b/tests/data/test-diff-suppr/test-has-strict-flexible-array-data-member-conversion-v1.o
diff --git a/tests/data/test-diff-suppr/test10-changed-parm-c-report-0.txt b/tests/data/test-diff-suppr/test10-changed-parm-c-report-0.txt
index 9aaf6a7f..6fb203ae 100644
--- a/tests/data/test-diff-suppr/test10-changed-parm-c-report-0.txt
+++ b/tests/data/test-diff-suppr/test10-changed-parm-c-report-0.txt
@@ -1,9 +1,9 @@ 
 Functions changes summary: 0 Removed, 1 Changed, 0 Added function
 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 
-1 function with some indirect sub-type change:
+1 function with incompatible sub-type changes:
 
-  [C] 'function int foo(int, int)' has some indirect sub-type changes:
+  [C] 'function int foo(int, int)' has some sub-type changes:
     return type changed:
       type name changed from 'int' to 'float'
       type size hasn't changed
diff --git a/tests/data/test-diff-suppr/test30-report-0.txt b/tests/data/test-diff-suppr/test30-report-0.txt
index dff96302..df2e0b39 100644
--- a/tests/data/test-diff-suppr/test30-report-0.txt
+++ b/tests/data/test-diff-suppr/test30-report-0.txt
@@ -6,16 +6,18 @@  Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
   [D] 'method virtual int non_defined_class::virtual_func_to_be_removed()'    {_ZN17non_defined_class26virtual_func_to_be_removedEv}
     note that this removes an entry from the vtable of class non_defined_class
 
+1 function with incompatible sub-type changes:
+
+  [C] 'method virtual int non_defined_class::virtual_func0()' at test30-priv-lib-v0.h:14:1 has some sub-type changes:
+    the vtable offset of method virtual int non_defined_class::virtual_func0() changed from 3 to 4
+      note that this is an ABI incompatible change to the vtable of class non_defined_class
+
 1 Added function:
 
   [A] 'method virtual int non_defined_class::virtual_func_inserted()'    {_ZN17non_defined_class21virtual_func_insertedEv}
     note that this adds a new entry to the vtable of class non_defined_class
 
-2 functions with some indirect sub-type change:
-
-  [C] 'method virtual int non_defined_class::virtual_func0()' at test30-priv-lib-v0.h:14:1 has some indirect sub-type changes:
-    the vtable offset of method virtual int non_defined_class::virtual_func0() changed from 3 to 4
-      note that this is an ABI incompatible change to the vtable of class non_defined_class
+1 function with some indirect sub-type change:
 
   [C] 'function int public_function(S*)' at test30-pub-lib-v0.cc:21:1 has some indirect sub-type changes:
     parameter 1 of type 'S*' has sub-type changes:
diff --git a/tests/test-abicompat.cc b/tests/test-abicompat.cc
index 58de88aa..5caac187 100644
--- a/tests/test-abicompat.cc
+++ b/tests/test-abicompat.cc
@@ -184,7 +184,8 @@  InOutSpec in_out_specs[] =
     "data/test-abicompat/libtest7-fn-changed-libapp-v1.so",
     "",
     "--show-base-names --no-show-locs --no-redundant",
-    abigail::tools_utils::ABIDIFF_ABI_CHANGE,
+    abigail::tools_utils::ABIDIFF_ABI_CHANGE
+    | abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE,
     "data/test-abicompat/test7-fn-changed-report-0.txt",
     "output/test-abicompat/test7-fn-changed-report-0.txt",
   },
@@ -195,7 +196,8 @@  InOutSpec in_out_specs[] =
     "data/test-abicompat/libtest7-fn-changed-libapp-btf-v1.so",
     "",
     "--show-base-names --no-show-locs --no-redundant --btf",
-    abigail::tools_utils::ABIDIFF_ABI_CHANGE,
+    abigail::tools_utils::ABIDIFF_ABI_CHANGE
+    | abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE,
     "data/test-abicompat/test7-fn-changed-report-0.1.txt",
     "output/test-abicompat/test7-fn-changed-report-0.1.txt",
   },
diff --git a/tests/test-abidiff-exit.cc b/tests/test-abidiff-exit.cc
index 83d98b70..17cf0a5f 100644
--- a/tests/test-abidiff-exit.cc
+++ b/tests/test-abidiff-exit.cc
@@ -167,7 +167,8 @@  InOutSpec in_out_specs[] =
     "",
     "",
     "--no-show-locs --leaf-changes-only",
-    abigail::tools_utils::ABIDIFF_ABI_CHANGE,
+    abigail::tools_utils::ABIDIFF_ABI_CHANGE
+    | abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE,
     "data/test-abidiff-exit/test-leaf-stats-report.txt",
     "output/test-abidiff-exit/test-leaf-stats-report.txt"
   },
@@ -533,7 +534,8 @@  InOutSpec in_out_specs[] =
     "",
     "",
     "",
-    abigail::tools_utils::ABIDIFF_ABI_CHANGE,
+    abigail::tools_utils::ABIDIFF_ABI_CHANGE
+    | abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE,
     "data/test-abidiff-exit/test-crc-report.txt",
     "output/test-abidiff-exit/test-crc-report.txt"
   },
@@ -608,7 +610,8 @@  InOutSpec in_out_specs[] =
     "",
     "",
     "--no-default-suppression",
-    abigail::tools_utils::ABIDIFF_ABI_CHANGE,
+    abigail::tools_utils::ABIDIFF_ABI_CHANGE
+    | abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE,
     "data/test-abidiff-exit/test-ld-2.28-210.so--ld-2.28-211.so.txt",
     "output/test-abidiff-exit/test-ld-2.28-210.so--ld-2.28-211.so.txt"
   },
@@ -638,7 +641,8 @@  InOutSpec in_out_specs[] =
     "",
     "",
     "--no-default-suppression",
-    abigail::tools_utils::ABIDIFF_ABI_CHANGE,
+    abigail::tools_utils::ABIDIFF_ABI_CHANGE
+    | abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE,
     "data/test-abidiff-exit/PR30048-test-report-0.txt",
     "output/test-abidiff-exit/PR30048-test-report-0.txt"
   },
@@ -653,7 +657,8 @@  InOutSpec in_out_specs[] =
     "",
     "",
     "--no-default-suppression",
-    abigail::tools_utils::ABIDIFF_ABI_CHANGE,
+    abigail::tools_utils::ABIDIFF_ABI_CHANGE
+    | abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE,
     "data/test-abidiff-exit/PR30048-test-2-report-1.txt",
     "output/test-abidiff-exit/PR30048-test-2-report-1.txt"
   },
@@ -923,7 +928,8 @@  InOutSpec in_out_specs[] =
     "",
     "",
     "--no-default-suppression",
-    abigail::tools_utils::ABIDIFF_ABI_CHANGE,
+    abigail::tools_utils::ABIDIFF_ABI_CHANGE
+    | abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE,
     "data/test-abidiff-exit/ada-subrange/test1-ada-subrange/test1-ada-subrange-report-1.txt",
     "output/test-abidiff-exit/ada-subrange/test1-ada-subrange/test1-ada-subrange-report-1.txt"
   },
@@ -938,7 +944,8 @@  InOutSpec in_out_specs[] =
     "",
     "",
     "--no-default-suppression --leaf-changes-only",
-    abigail::tools_utils::ABIDIFF_ABI_CHANGE,
+    abigail::tools_utils::ABIDIFF_ABI_CHANGE
+    | abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE,
     "data/test-abidiff-exit/ada-subrange/test1-ada-subrange/test1-ada-subrange-report-2.txt",
     "output/test-abidiff-exit/ada-subrange/test1-ada-subrange/test1-ada-subrange-report-2.txt"
   },
@@ -953,7 +960,8 @@  InOutSpec in_out_specs[] =
     "",
     "",
     "--no-default-suppression",
-    abigail::tools_utils::ABIDIFF_ABI_CHANGE,
+    abigail::tools_utils::ABIDIFF_ABI_CHANGE
+    | abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE,
     "data/test-abidiff-exit/ada-subrange/test2-ada-subrange-redundant/test2-ada-subrange-redundant-report-1.txt",
     "output/test-abidiff-exit/ada-subrange/test2-ada-subrange-redundant/test2-ada-subrange-redundant-report-1.txt"
   },
@@ -968,7 +976,8 @@  InOutSpec in_out_specs[] =
     "",
     "",
     "--no-default-suppression --leaf-changes-only",
-    abigail::tools_utils::ABIDIFF_ABI_CHANGE,
+    abigail::tools_utils::ABIDIFF_ABI_CHANGE
+    | abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE,
     "data/test-abidiff-exit/ada-subrange/test2-ada-subrange-redundant/test2-ada-subrange-redundant-report-2.txt",
     "output/test-abidiff-exit/ada-subrange/test2-ada-subrange-redundant/test2-ada-subrange-redundant-report-2.txt"
   },
@@ -1032,6 +1041,99 @@  InOutSpec in_out_specs[] =
     "data/test-abidiff-exit/test-enumerator-changes1-report-1.txt",
     "output/test-abidiff-exit/test-enumerator-changes1-report-1.txt"
   },
+  {
+    "data/test-abidiff-exit/test-enumerator-changes2-v0.o",
+    "data/test-abidiff-exit/test-enumerator-changes2-v1.o",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "--no-default-suppression",
+    abigail::tools_utils::ABIDIFF_OK,
+    "data/test-abidiff-exit/test-enumerator-changes2-report-1.txt",
+    "output/test-abidiff-exit/test-enumerator-changes2-report-1.txt"
+  },
+  {
+    "data/test-abidiff-exit/test-enumerator-changes3-v0.o",
+    "data/test-abidiff-exit/test-enumerator-changes3-v1.o",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "--no-default-suppression",
+    abigail::tools_utils::ABIDIFF_OK,
+    "data/test-abidiff-exit/test-enumerator-changes3-report-1.txt",
+    "output/test-abidiff-exit/test-enumerator-changes3-report-1.txt"
+  },
+  {
+    "data/test-abidiff-exit/test-enumerator-changes3-v0.o",
+    "data/test-abidiff-exit/test-enumerator-changes3-v1.o",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "--no-default-suppression --harmless",
+    abigail::tools_utils::ABIDIFF_ABI_CHANGE,
+    "data/test-abidiff-exit/test-enumerator-changes3-report-2.txt",
+    "output/test-abidiff-exit/test-enumerator-changes3-report-2.txt"
+  },
+  {
+    "data/test-abidiff-exit/test-enumerator-changes4-v0.o",
+    "data/test-abidiff-exit/test-enumerator-changes4-v1.o",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "--no-default-suppression",
+    abigail::tools_utils::ABIDIFF_ABI_CHANGE
+    | abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE,
+    "data/test-abidiff-exit/test-enumerator-changes4-report-1.txt",
+    "output/test-abidiff-exit/test-enumerator-changes4-report-1.txt"
+  },
+  {
+    "data/test-abidiff-exit/test-enumerator-changes5-v0.o",
+    "data/test-abidiff-exit/test-enumerator-changes5-v1.o",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "--no-default-suppression",
+    abigail::tools_utils::ABIDIFF_ABI_CHANGE
+    | abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE,
+    "data/test-abidiff-exit/test-enumerator-changes5-report-1.txt",
+    "output/test-abidiff-exit/test-enumerator-changes5-report-1.txt"
+  },
+  {
+    "data/test-abidiff-exit/test-enumerator-changes6-v0.o",
+    "data/test-abidiff-exit/test-enumerator-changes6-v1.o",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "--no-default-suppression",
+    abigail::tools_utils::ABIDIFF_ABI_CHANGE
+    | abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE,
+    "data/test-abidiff-exit/test-enumerator-changes6-report-1.txt",
+    "output/test-abidiff-exit/test-enumerator-changes6-report-1.txt"
+  },
   {
     "data/test-abidiff-exit/test-anonymous-enums-change-v0.o",
     "data/test-abidiff-exit/test-anonymous-enums-change-v1.o",
@@ -1226,7 +1328,8 @@  InOutSpec in_out_specs[] =
     "",
     "",
     "--no-default-suppression",
-    abigail::tools_utils::ABIDIFF_ABI_CHANGE,
+    abigail::tools_utils::ABIDIFF_ABI_CHANGE
+    | abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE,
     "data/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr1-output-1.txt",
     "output/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr1-output-1.txt"
   },
@@ -1241,7 +1344,8 @@  InOutSpec in_out_specs[] =
     "",
     "",
     "--no-default-suppression",
-    abigail::tools_utils::ABIDIFF_ABI_CHANGE,
+    abigail::tools_utils::ABIDIFF_ABI_CHANGE
+    | abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE,
     "data/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr2-output-1.txt",
     "output/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr2-output-1.txt"
   },
@@ -1256,7 +1360,8 @@  InOutSpec in_out_specs[] =
     "",
     "",
     "--no-default-suppression",
-    abigail::tools_utils::ABIDIFF_ABI_CHANGE,
+    abigail::tools_utils::ABIDIFF_ABI_CHANGE
+    | abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE,
     "data/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr3-output-1.txt",
     "output/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr3-output-1.txt"
   },
@@ -1271,7 +1376,8 @@  InOutSpec in_out_specs[] =
     "",
     "",
     "--no-default-suppression",
-    abigail::tools_utils::ABIDIFF_ABI_CHANGE,
+    abigail::tools_utils::ABIDIFF_ABI_CHANGE
+    | abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE,
     "data/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr4-output-1.txt",
     "output/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr4-output-1.txt"
   },
@@ -1410,6 +1516,38 @@  InOutSpec in_out_specs[] =
     "data/test-abidiff-exit/non-del-anon-dm/non-regr/report0.txt",
     "output/test-abidiff-exit/non-del-anon-dm/non-regr/report0.txt"
   },
+  {
+    "data/test-abidiff-exit/incompatible-changes/1/test-1-v0.o",
+    "data/test-abidiff-exit/incompatible-changes/1/test-1-v1.o",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "--no-default-suppression",
+    abigail::tools_utils::ABIDIFF_ABI_CHANGE
+    | abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE,
+    "data/test-abidiff-exit/incompatible-changes/1/report0.txt",
+    "output/test-abidiff-exit/incompatible-changes/1/report0.txt"
+  },
+  {
+    "data/test-abidiff-exit/test-changed-var-1-v0.o",
+    "data/test-abidiff-exit/test-changed-var-1-v1.o",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "--no-default-suppression",
+    abigail::tools_utils::ABIDIFF_ABI_CHANGE
+    | abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE,
+    "data/test-abidiff-exit/test-changed-var-1-report-1.txt",
+    "output/test-abidiff-exit/test-changed-var-1-report-1.txt"
+  },
 #ifdef WITH_BTF
   {
     "data/test-abidiff-exit/btf/test0-v0.o",
@@ -1422,7 +1560,8 @@  InOutSpec in_out_specs[] =
     "",
     "",
     "--no-default-suppression --btf",
-    abigail::tools_utils::ABIDIFF_ABI_CHANGE,
+    abigail::tools_utils::ABIDIFF_ABI_CHANGE
+    | abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE,
     "data/test-abidiff-exit/btf/test0-report-1.txt",
     "output/test-abidiff-exit/btf/test0-report-1.txt"
   },
@@ -1437,7 +1576,8 @@  InOutSpec in_out_specs[] =
     "",
     "",
     "--no-default-suppression --harmless --btf",
-    abigail::tools_utils::ABIDIFF_ABI_CHANGE,
+    abigail::tools_utils::ABIDIFF_ABI_CHANGE
+    | abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE,
     "data/test-abidiff-exit/btf/test0-report-2.txt",
     "output/test-abidiff-exit/btf/test0-report-2.txt"
   },