[applied] Bug 30971 - Wrong interpretation of "has_data_member_inserted_at"

Message ID 87jzrlk5fi.fsf@redhat.com
State New
Headers
Series [applied] Bug 30971 - Wrong interpretation of "has_data_member_inserted_at" |

Commit Message

Dodji Seketeli Oct. 17, 2023, 8:40 a.m. UTC
  Hello,

Consider the following construct:

    struct foo
    {
      long x;
      long y;
    };

Then change one of the types (but keep the size the same):

    struct foo
    {
      long x;
      unsigned long y;
    };

If I abidiff this with no suppressions, I get:

      [C] 'struct foo' changed:
	type size hasn't changed
	1 data member change:
	  type of 'long int y' changed:
	    type name changed from 'long int' to 'unsigned long int'
	    type size hasn't changed

However, it seems like if I add any struct suppression involving data member
insertions, it filters out the change. For example:

    [suppress_type]
	    type_kind = struct
	    has_data_member_inserted_at = offset_of(not_present)

The "not_present" member isn't in "struct foo", so I would expect the diff to
still be emitted, but it is not:

    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

This is because during the evaluation of the
"has_data_member_inserted_at" property, we fail to take into account
that if no data member got inserted, evaluation of the
"has_data_member_inserted_at" predicate is falsified, and thus, the
type suppression is falsified.

While looking at this, I also realized that when a data member
replaces another one, we fail to consider that change as a data member
insertion and so the evaluation of the "has_data_member_inserted_at"
predicate is wrongly falsified.

This patch fixes these two related issues.

	* include/abg-comparison.h
	(class_or_union_diff::changed_data_members): Declare new accessor.
	function.
	* src/abg-comparison.cc
	(class_or_union_diff::changed_data_members): Define new accessor.
	function.
	* src/abg-suppression.cc (type_suppression::suppresses_diff): If
	the type suppression specification contains a
	has_data_member_inserted_* property and yet the class contains no
	data member inserted or replacing an existing one, then the type
	suppression is falsified in the context of the current change.
	Also, when a data member replaces an existing one, consider that
	as an insertion for which the has_data_member_inserted_* predicate
	should be evaluated.  Stop considering deleted data members
	because considering replaced data member is really what we meant.
	* tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-report.[1-3].txt:
	New reference test output files.
	* tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-report.txt:
	Likewise.
	* tests/data/test-diff-suppr/test-has-data-member-inserted-at-{2,3}-v{0,1}.o:
	New input test binaries.
	* tests/data/test-diff-suppr/test-has-data-member-inserted-at-{2,3}-v{0,1}.c:
	Source code of the new input test binaries.
	* tests/data/test-diff-suppr/test-has-data-member-inserted-at-2.2.suppr:
	New input test suppression specification.
	* tests/data/test-diff-suppr/test-has-data-member-inserted-at-2.suppr: Likewise.
	* tests/data/Makefile.am: Add the new test material above to
	source distribution.
	* tests/test-diff-suppr.cc (in_out_specs): Add the test input
	above to this test harness.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Tested-by: John Moon <quic_johmoo@quicinc.com>

Applied to the master branch.
---
 include/abg-comparison.h                      |   9 ++--
 src/abg-comparison.cc                         |  10 +++++
 src/abg-suppression.cc                        |  18 +++++---
 tests/data/Makefile.am                        |  14 ++++++
 ...has-data-member-inserted-at-2-report.1.txt |  13 ++++++
 ...has-data-member-inserted-at-2-report.2.txt |  11 +++++
 ...has-data-member-inserted-at-2-report.3.txt |   4 ++
 ...t-has-data-member-inserted-at-2-report.txt |  13 ++++++
 .../test-has-data-member-inserted-at-2-v0.c   |  10 +++++
 .../test-has-data-member-inserted-at-2-v0.o   | Bin 0 -> 3120 bytes
 .../test-has-data-member-inserted-at-2-v1.c   |  10 +++++
 .../test-has-data-member-inserted-at-2-v1.o   | Bin 0 -> 3168 bytes
 ...test-has-data-member-inserted-at-2.2.suppr |   3 ++
 .../test-has-data-member-inserted-at-2.suppr  |   3 ++
 .../test-has-data-member-inserted-at-3-v0.c   |  10 +++++
 .../test-has-data-member-inserted-at-3-v0.o   | Bin 0 -> 3152 bytes
 .../test-has-data-member-inserted-at-3-v1.c   |  11 +++++
 .../test-has-data-member-inserted-at-3-v1.o   | Bin 0 -> 3168 bytes
 tests/test-diff-suppr.cc                      |  40 ++++++++++++++++++
 19 files changed, 170 insertions(+), 9 deletions(-)
 create mode 100644 tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-report.1.txt
 create mode 100644 tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-report.2.txt
 create mode 100644 tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-report.3.txt
 create mode 100644 tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-report.txt
 create mode 100644 tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-v0.c
 create mode 100644 tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-v0.o
 create mode 100644 tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-v1.c
 create mode 100644 tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-v1.o
 create mode 100644 tests/data/test-diff-suppr/test-has-data-member-inserted-at-2.2.suppr
 create mode 100644 tests/data/test-diff-suppr/test-has-data-member-inserted-at-2.suppr
 create mode 100644 tests/data/test-diff-suppr/test-has-data-member-inserted-at-3-v0.c
 create mode 100644 tests/data/test-diff-suppr/test-has-data-member-inserted-at-3-v0.o
 create mode 100644 tests/data/test-diff-suppr/test-has-data-member-inserted-at-3-v1.c
 create mode 100644 tests/data/test-diff-suppr/test-has-data-member-inserted-at-3-v1.o

new file mode 100644
index 00000000..95a0537b
new file mode 100644
index 00000000..03dbb2c9
new file mode 100644
index 00000000..87ad3b64
index 4e63b2cc..1a06e043 100644
  

Patch

diff --git a/include/abg-comparison.h b/include/abg-comparison.h
index 15ce1651..9155cc54 100644
--- a/include/abg-comparison.h
+++ b/include/abg-comparison.h
@@ -1711,6 +1711,12 @@  public:
   const string_decl_base_sptr_map&
   deleted_data_members() const;
 
+  const unsigned_var_diff_sptr_map&
+  changed_data_members() const;
+
+  const var_diff_sptrs_type&
+  sorted_changed_data_members() const;
+
   const edit_script&
   member_fns_changes() const;
 
@@ -1726,9 +1732,6 @@  public:
   const string_member_function_sptr_map&
   inserted_member_fns() const;
 
-  const var_diff_sptrs_type&
-  sorted_changed_data_members() const;
-
   size_t
   count_filtered_changed_data_members(bool local_only = false) const;
 
diff --git a/src/abg-comparison.cc b/src/abg-comparison.cc
index 1207729c..16afd556 100644
--- a/src/abg-comparison.cc
+++ b/src/abg-comparison.cc
@@ -5359,6 +5359,16 @@  const string_member_function_sptr_map&
 class_or_union_diff::inserted_member_fns() const
 {return get_priv()->inserted_member_functions_;}
 
+/// Getter of the map of data members that got replaced by another
+/// data member.  The key of the map is the offset at which the
+/// element got replaced and the value is a pointer to the @ref
+/// var_diff representing the replacement of the data member.
+///
+/// @return sorted vector of changed data member.
+const unsigned_var_diff_sptr_map&
+class_or_union_diff::changed_data_members() const
+{return get_priv()->changed_dm_;}
+
 /// Getter of the sorted vector of data members that got replaced by
 /// another data member.
 ///
diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 254d6ae4..7053e728 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -946,6 +946,13 @@  type_suppression::suppresses_diff(const diff* diff) const
 	      const class_decl_sptr& first_type_decl =
 		klass_diff->first_class_decl();
 
+	      if (klass_diff->inserted_data_members().empty()
+		  && klass_diff->changed_data_members().empty())
+		// So there is a has_data_member_inserted_* clause,
+		// but no data member was inserted.  That means the
+		// clause is falsified.
+		return false;
+
 	      // All inserted data members must be in an allowed
 	      // insertion range.
 	      for (const auto& m : klass_diff->inserted_data_members())
@@ -963,16 +970,15 @@  type_suppression::suppresses_diff(const diff* diff) const
 		    return false;
 		}
 
-	      // Similarly, all deleted data members must be in an
-	      // allowed insertion range.
-	      for (const auto& m : klass_diff->deleted_data_members())
+	      // Similarly, each data member that replaced another one
+	      // must be in an allowed insertion range.
+	      for (const auto& m : klass_diff->changed_data_members())
 		{
-		  decl_base_sptr member = m.second;
+		  var_decl_sptr member = m.second->second_var();
 		  bool matched = false;
 
 		  for (const auto& range : get_data_member_insertion_ranges())
-		    if (is_data_member_offset_in_range(is_var_decl(member),
-						       range,
+		    if (is_data_member_offset_in_range(member, range,
 						       first_type_decl.get()))
 		      matched = true;
 
diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
index 6031b48d..d1c767b3 100644
--- a/tests/data/Makefile.am
+++ b/tests/data/Makefile.am
@@ -1895,6 +1895,20 @@  test-diff-dwarf-abixml/PR25409-librte_bus_dpaa.so.20.0.abi \
 test-diff-dwarf-abixml/PR25409-librte_bus_dpaa.so.20.0-report-0.txt \
 test-diff-suppr/test-has-data-member-inserted-at-1-report-2.txt \
 test-diff-suppr/test-has-data-member-inserted-at-1.2.suppr \
+test-diff-suppr/test-has-data-member-inserted-at-2-report.1.txt \
+test-diff-suppr/test-has-data-member-inserted-at-2-report.2.txt \
+test-diff-suppr/test-has-data-member-inserted-at-2-report.3.txt \
+test-diff-suppr/test-has-data-member-inserted-at-2-report.txt \
+test-diff-suppr/test-has-data-member-inserted-at-2-v0.c \
+test-diff-suppr/test-has-data-member-inserted-at-2-v0.o \
+test-diff-suppr/test-has-data-member-inserted-at-2-v1.c \
+test-diff-suppr/test-has-data-member-inserted-at-2-v1.o \
+test-diff-suppr/test-has-data-member-inserted-at-2.2.suppr \
+test-diff-suppr/test-has-data-member-inserted-at-2.suppr \
+test-diff-suppr/test-has-data-member-inserted-at-3-v0.c \
+test-diff-suppr/test-has-data-member-inserted-at-3-v0.o \
+test-diff-suppr/test-has-data-member-inserted-at-3-v1.c \
+test-diff-suppr/test-has-data-member-inserted-at-3-v1.o \
 \
 test-lookup-syms/test0.cc		\
 test-lookup-syms/test0.o		\
diff --git a/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-report.1.txt b/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-report.1.txt
new file mode 100644
index 00000000..41cf8103
--- /dev/null
+++ b/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-report.1.txt
@@ -0,0 +1,13 @@ 
+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
+
+1 changed type unreachable from any public interface:
+
+  [C] 'struct foo' changed:
+    type size hasn't changed
+    1 data member change:
+      type of 'long int y' changed:
+        type name changed from 'long int' to 'unsigned long int'
+        type size hasn't changed
+
diff --git a/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-report.2.txt b/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-report.2.txt
new file mode 100644
index 00000000..f9672be2
--- /dev/null
+++ b/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-report.2.txt
@@ -0,0 +1,11 @@ 
+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
+
+1 changed type unreachable from any public interface:
+
+  [C] 'struct foo' changed:
+    type size hasn't changed
+    1 data member insertion:
+      'char z', at offset 72 (in bits) at test-has-data-member-inserted-at-3-v1.c:5:1
+
diff --git a/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-report.3.txt b/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-report.3.txt
new file mode 100644
index 00000000..b4ea5bf1
--- /dev/null
+++ b/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-report.3.txt
@@ -0,0 +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
+
diff --git a/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-report.txt b/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-report.txt
new file mode 100644
index 00000000..41cf8103
--- /dev/null
+++ b/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-report.txt
@@ -0,0 +1,13 @@ 
+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
+
+1 changed type unreachable from any public interface:
+
+  [C] 'struct foo' changed:
+    type size hasn't changed
+    1 data member change:
+      type of 'long int y' changed:
+        type name changed from 'long int' to 'unsigned long int'
+        type size hasn't changed
+
diff --git a/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-v0.c b/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-v0.c
new file mode 100644
index 00000000..352509f4
--- /dev/null
+++ b/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-v0.c
@@ -0,0 +1,10 @@ 
+struct foo
+{
+  long x;
+  long y;
+};
+
+int
+foo()
+{
+}
diff --git a/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-v0.o b/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-v0.o
new file mode 100644
index 0000000000000000000000000000000000000000..9c264e4b831fe1fe735a8a9f27e42f82d3ce3ea9
GIT binary patch
literal 3120
zcmcgtL2nyX5T56?6PHa=C$6Avin2i<nyPOdo2rC_6hlPQQdB{u9ynC)+J3gTc-PVH
zIymLP4GD4Sfg=YbxNznVAh>YkCvf2oXAWg%J<r`fHfjVCBfXuOZ)V=idvD&`&)$9i
zdO--#B;Xo6(KHIMIsZg%reYJ$Ko#!Z_~Q3R_kR8ap%REPSqk)dkv>_<#Dmovji4e#
z`8Ilp30TBI96^zUG8D@t0!rj2$|5F(Nlzobo-3C8Fu|}zu*%!(V#j`Cy?nE}Wn%@)
z;+3VUZLO`YEsK@;$_oHiRaj-)-nP-r7FB@a%V68rY-<VgxbW6FoFlc}tWrqx?89>a
zbL>OQx{M=T8P=C2T~HPy`8tjg`d&gVg!pS|kr-_)4iwhXT`q{V!s+R>Xu${pr)KK;
zTLlYUhoi9X&{Fqr-*xutuRHa+`<h#K8k>zqz22xh7w@R9bHhv6Ag^pVGDyau+U=`Q
zMScfWFX{|-CtFwL)hqI_;mE!td*Mi`p&$66mnb<7$Fb_lu4<3_GC4X>G1La5K-IdV
z?gPKp_mkStZ+mUO@A<=8&!4EcmZ&(1Yh5q#Qc-sOUQfp3gM$djBnMtB$tnXCv{fYi
zFji55S-eCx<l&~<`CoFJv=-Rk+uL?7;x=!bV2{)D!aFb}@$e3Iaz(5z%$FbG(Oy89
z22t7~Z!c9oFYGPOy@L)@IQL6kQG`Dq=NYjX@?fyIF-@a|mOQdBLmpW$mj~l4`Au%Y
zsbl={4(5;r3pps>O~6Z-Ll&IQLCJsdANU3$E1CV7ReaLJr?&=4pUrb9XLmzqB%D^Q
zSH6NW5#co6Bn9dDDVyP}!g&_xBxe^L<x7my9J&UAKFr`cCqW+L<~+J)nkRik*{^bp
z|4WRMKaDQy^xP3?{F_t*s5962FRbq{H|ud2r?qC+3vPTABwibN5>5F)ONp8!;L^hZ
zZaa>_jnvR{)0e5`hrJQn=#^@D?RKONpE7%q7xwY#%7zU6Q0Wj%p+$mQsoog{fx`FI
z4M&M`@%qa+@j4&#Bx=y=MP8tIA^(xBVm$4UJ|{h0lZ9E|vQEBPT1SO2^Jed7oief+
z|0>$3zy57JoxeFJrPKL8B_%_qFZC6@KFy2|i4|_v9~oapPJa3>oMn6$xj849eqwu{
zxn`#C2WT)c^4(x?QwK6PeQzP2SO2eEzmBK+=W&?z)BQ5%L<l}&@I6v8Wcs$ymX}{Q
z)P0Vn{PbR!`414IIdz>Vrt~c*I?@1honLc0-@Nz>e7XO4M*Nq@#4m6|)}9gn6~`NH
zuwynfJLtN#|MwjK)LVpDljFCvBXhlf8vYK2y#2q=7h3lz?LYm!biBr?9y2#WFyZ_I
oE|~r+^j9?F=}hyM`WqF6B&TflHP=sd<;739{vT$MQ^Ab?8>|oucmMzZ

literal 0
HcmV?d00001

diff --git a/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-v1.c b/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-v1.c
--- /dev/null
+++ b/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-v1.c
@@ -0,0 +1,10 @@ 
+struct foo
+{
+  long x;
+  unsigned long y;
+};
+
+int
+foo()
+{
+}
diff --git a/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-v1.o b/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2-v1.o
new file mode 100644
index 0000000000000000000000000000000000000000..5031d6a80991e37cd83625272433d94f4462f6e2
GIT binary patch
literal 3168
zcmcguPj4GV6o2Ej6PImLC$6AvK-nNFl8RZ!rj(G95{TNgw5m`<Q7_0@+hcpdUPs<_
zlmrPR4oHYg4jegf-~e3t2wdPB@CCTT4T%H1H-6)8hOHWb#FKX4d%yR0X5Nnd$<2GW
zazcP10XN{0W>A3L=|}RW7B}HMl;Oec&wo9B|HqFJDu5`G#i7@8^h#4I9`fzM07^m>
z-$4&?0FD+w972BXJ%oyoD^P4s2NlR$6vYuiOeUN7YARm{qXg5;V4C$Maov5*y;ELu
zG5Q5?mx?!BXBK;!6PIVpuCutXI49<(OV0r0%fczT?z&46qKy6f@Ww^Vp@BPP^4q*{
zbP-?*6S<g&R`(J<Io*U_E4Kq+8kzts+(KT!1zkZdg!prIh8XQIJ}4~e&CZF%+_`aD
z9aj)=W};rYn{&{$H;6hOEmaGnC=NT3YH4Kq{sV8T`l?s0`Y-!cueMsNRjakCx4eT6
zw}XTY^6H8w`^hL$8yyv?Vc0}97&f~b2W!{lwX1T!=E;sH+tEO(Uf2(#AW?D@jbhc3
zE!7xxWOBHtVyJWneN|}<S|5a!PMB1BVIydSognO0+TnqUD~XDexY7!eK#Q^!w%alu
z?d=VLOtKrqlB}|?`VBRdVHB%jf>nY<*5rQGZ~iYePTLD?Z*8r6%ec)er`ThCg6H)c
zkN9W@C%hyU&Q2GP@vNUkoE{=QGjGn8KFe**OudB;V>t6oW0Hs8|H?ArbY#K!Ax>uK
zgxwi`q9-s?9ITK<4oqdi=$}3H4xD+6KYo=N<iObsl={IhH-j8Fmw}T1%s=oIMCMcb
zGwJxWXHS<8k~y2FP)_fLsYp1jdI2Az`7r~+>3N;?r!AaSxWodTWct*ur2I_}1ns2o
z^lm@2aAWH-Zs#{^p&s>}%YLQD_&?9MSyzj7x)+HI{<YQss>}`k6YJNR+x>Wq(;lSv
z0sQ!|p9Br$$#BfOMoQE{0zTa*;5XtJ{GsXvzP_;PVbmU=jV`Zx&}a<R{t0t145AL+
zXz7q%7%3BiC5%XLUF*$3zpwBj_M<_fe7qH8oCM7eIf?4l+ryx*cp?9h(LB)}nR7Df
zHd&a=GwbA=rX^Ge(?7~7!*)tei+22rXr#IOxAAoTc225i>VHZ~ifmt+E4r07Q$8dv
z^RWKH_#ATbGvCMs#y61LImz@h+dIq+vwihH6k|;BRd!rWVI<n|cM;3#-yEokr~aq$
zvHPd*%g%`q>@xT^DJimj>uAfWzsdu(%du3S?h3p99%7W!^ogRT@43(y24HUL8~zdE
zS@Ey%$Nk$A;wgVt{AC`<$`j(h<ao;s-n9ps9ZcWG|2vL9aTg)>kmJ{kBXhHV2L1+x
zto=Xc{Wo(;`%k}WCf?xGk6jxfIOh6YZkT>==-1MYr!&o3>L1h;k{q+i+g?BQl@<Rj
N_y5BraxB>Ke*+&j6Tbie

literal 0
HcmV?d00001

diff --git a/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2.2.suppr b/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2.2.suppr
--- /dev/null
+++ b/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2.2.suppr
@@ -0,0 +1,3 @@ 
+[suppress_type]
+        type_kind = struct
+        has_data_member_inserted_at = end
diff --git a/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2.suppr b/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2.suppr
new file mode 100644
index 00000000..f789d71f
--- /dev/null
+++ b/tests/data/test-diff-suppr/test-has-data-member-inserted-at-2.suppr
@@ -0,0 +1,3 @@ 
+[suppress_type]
+        type_kind = struct
+        has_data_member_inserted_at = offset_of(not_present)
diff --git a/tests/data/test-diff-suppr/test-has-data-member-inserted-at-3-v0.c b/tests/data/test-diff-suppr/test-has-data-member-inserted-at-3-v0.c
new file mode 100644
index 00000000..b44b70d6
--- /dev/null
+++ b/tests/data/test-diff-suppr/test-has-data-member-inserted-at-3-v0.c
@@ -0,0 +1,10 @@ 
+struct foo
+{
+  long x;
+  char y;
+};
+
+int
+foo()
+{
+}
diff --git a/tests/data/test-diff-suppr/test-has-data-member-inserted-at-3-v0.o b/tests/data/test-diff-suppr/test-has-data-member-inserted-at-3-v0.o
new file mode 100644
index 0000000000000000000000000000000000000000..d2f4b4f01aa6d68b7d6f75d3e8b221e250d038a4
GIT binary patch
literal 3152
zcmcguL2nyX5T56?6PImLCq|GqpllF`q+-{xTa}QKVu)x`imFm65*OsI?Pq(zUR%5C
zC<zi&9FP!~9yoB|z<~=~`3YR$AMgi|IF@q{FteWLzPxOu2qZ>Y&&)S7Z|2R;d+X2N
zeg9@o2v8*820YOe3UGJ!iCj;`Iy?(y*x&o=kB1-q@)<$}5Jj?B^z$P9=%mF%zB3#`
zNr>Vd^bm(&5eIPu`F-R?$Q26&<irfI0(py~I3|TjttP&k$rpk!!RR@#id(DVy8Xs#
z@m6`$#`u@Pwr|+hJl3=zUYRf3*2?nAf>@j_Jr9sC3#(|`TQ)}6qKtVwc<Umrkpj2M
z<X2xhz6dbG>(K6A!zY&(k?xht0Z;`^0Tyl|FW{CgBNswEo}VK|9mWTRm9*J8v68zm
zSvHL;2sk%YFWt^r=(>An-`T0Y?o_MZ6|d^lHfptMwN`c3?#Z^Z=O=7%udX}pAQ^{p
zyDLK(1uazlsMXs(+`Q&qyXqd)9JlMZop9*NelQ3^KauV@9LKWlwq<kNb(5o!jG;da
zyAHLs)$=2$^o9djX%E{U2bFG+RQf^FZw6gI=vO+yp^PhujFY(1_7gu9-FDFFxbb*2
zihxXR&yQWQx&t|A%E%4ESVjrv^b_}rd$8fP{+AqQtp#>>cD9@~Z2I~cIu3XiCM1sU
z;Y63j^7+}~LwvU{AWRQYIwNn-m%hyH%+0)m4ih-@m&PIwfBl_h#A(Qa@!(Bo=7imv
z9LW<HDHdkPA`8-UcgkcvWy&o$cgmLl3-AzTkOk*6Q1Zu<nn4y^$Uw<|?i9X`$fDMt
z>A5`Xi>J#5NxhqAP}aMlG7_%udXa*V2&d;wQjngTuqn<eTw;OVr2f_}YyPSRf<Dl2
z$~$8HLjylzy~o^KU+slzOfOmXD?P>kCC1gh+N{$(NTl%ZQw^ZXT;ad6ex12lkHa|i
zK<@*1@zEgho5+)B!h1?e<Y59HT_)f);~2b1_I)qCyBa~*8KRBuv4-DlM)Kf<*^m6N
zi<g@o(howZLNJ9A32vl%Yd9E4ya>H;m`D$=1UF9n)+fA(>@_-(KajkU|Hzgxo_eI-
zlUlCM!gQWlCtsabQ6Vh-2y2F2P1Z#-{#7*6-2K~ldjIB{luzaVf)tHRUz#hrmFk)g
ziAy}Jzcapoocz=oSz>$}xw$5peq(!=xnid8T{M^&`ED?{p#qtkzPAz2s{aw!ui~lx
zS$xd;>3o@MA_Vste2)~3Oy36Dvhq7TQ1>~O^3y$H<{u$OYpOa?Oz9_1M1S;jQu!7C
z6pdN&YkasL>A~zvkc$7BWi$U04`hX$HBxbke}gt9Yi_V>4m2B0-yb>t#9f5g9>;I$
zi=wRhr{Et@$m;(C?!TH->OXzeRJ_8e9y2#W@PPC8xM2F;(AUz8r+1pQ)jz2yBzMB5
Vzvlj_uB`ZPx&EK0krTm;{|ACK53T?J

literal 0
HcmV?d00001

diff --git a/tests/data/test-diff-suppr/test-has-data-member-inserted-at-3-v1.c b/tests/data/test-diff-suppr/test-has-data-member-inserted-at-3-v1.c
--- /dev/null
+++ b/tests/data/test-diff-suppr/test-has-data-member-inserted-at-3-v1.c
@@ -0,0 +1,11 @@ 
+struct foo
+{
+  long x;
+  char y;
+  char z;
+};
+
+int
+foo()
+{
+}
diff --git a/tests/data/test-diff-suppr/test-has-data-member-inserted-at-3-v1.o b/tests/data/test-diff-suppr/test-has-data-member-inserted-at-3-v1.o
new file mode 100644
index 0000000000000000000000000000000000000000..7f8e9f376f6f89c6f1ccccedfdc0cdad07eb2d2d
GIT binary patch
literal 3168
zcmcgtL2nyX5T56?6Nhb5Cq~c`P&O1qQt{TYQ<XF&#SlSKwW?603WNmi+J3ed>~+{(
zM@f+2fCNHZa^T2;0|z)GegPNGocIIW;fBNkX4doE&FfZ;Kw_lbnfYes&Fs8+Z$Ekc
z_8U1NK$CzQa9`6Xz`g1Fay=32@Hmv=?(P@AoxJ<g=Li)*6v<-I>lu2bDHRX-&Tt4N
zA&PIIhd2a_IEW+2zlXdij-f!p4CIOhvgE`Ru>ysO8SyD8OnO=I^;Ev#2Qe-)3s!M+
zSzNcTEf;T=H*Ac54s82|ZOvhE^WyorvTZFbF3pRD>C%$``LeKzw!LX%ge}UL$Awoe
z;u;BXvrK;V3&$4$rg$Ct%op*=B}F73&E){-f+he9yT}Vrgv-c<5P!|h5~Eh*gThkM
z^_*DBogXio#1#b0OjK(|+{#(#ymRNSvt513saD-}x9Zf^YPD*$R&`ePRNLA0Vm8Pt
ztBxGRqd;wSRiHw@g{l{}dRvDZSLM|!@}TC(t|L3aP^!K^@B=Saaukdr)s}759Cc-U
zw67xQ4}-2l&29C(5GuXlKvmkq_WORN>&KP8-}IV(*Yo?8j(@14O01$ds<ge>OGMfB
zI~^H~_V+^|lk9nsB&!^#K~sg&4<Z%DnA3~px;&`5t^Xy*S!;ov?d?rx1)IKlhK?uO
z26#5cB#!rR!b@WD+;s5-xA<v<=^;u+<<+^;XSwa!sn^h93}?P+I`Z(x-&sZ+i7Xfo
z;$(DA*{$&rJ%y2CVTLTSAUS>yn5>5kyM-q=i!8vim_Zht%Rs3fJg^yL!TAi7{AVA)
zR}ooA^=EQC&$|0`=OF35c?{)rH*`kA(_g(nK}dwt^D-$&PmI|FXBD1efp#*zYnN00
zx(0&YN#T@tpLNf`k68bZxw*dn7OFA1YuT^#5dUWx*WcA<ovuS7jenD909EE1|C#mc
z%*}cn#;FJCK7bn?4Pvi}JPyaar=?gO#^BP80&X*kzztR3bCV0K;Rl@|+UPQCc+F<0
z4o;c9&<nbF!=*#|exP&+rqCk6jYMw^2Lpw-p&JZi<>I{{qu6VGz>BC}qZ4`q#UJt?
z*&@bMkMut2<?1X<=9zW!P17<ege5=alwl_&r$saV1vJv!{o8oje{)UBr}KYFN{UQh
znk%}M>M0)*S9n-|Wqckv`ROxqf$=Tm=9*;sh3#GDnwh?DqQS(-_Zow1I*_^PdkgWb
z`t^qDc&dLIAG3ZsU*?(!fzRM=Qc`64Hqe%pe~ky~9>-FCx<}0X`-st+x=s`m`jHcT
ztO4dazvdqyo)y2&hx_+O#M69a#b4rqtUMzAD~>nZV9y+AcF=We|L-~e)Ln$w+Z?~4
z9hvL?Y4}?dvig6*{nv9!{ina0j@LNVW9CK(PB?#$3#R`K{VmOS+S9C0{gaA9l4CY`
Uo8M1$WyOET_5U!591CXrKe{#$x&QzG

literal 0
HcmV?d00001

diff --git a/tests/test-diff-suppr.cc b/tests/test-diff-suppr.cc
--- a/tests/test-diff-suppr.cc
+++ b/tests/test-diff-suppr.cc
@@ -2276,6 +2276,46 @@  InOutSpec in_out_specs[] =
     "data/test-diff-suppr/test-has-data-member-inserted-at-1-report-2.txt",
     "output/test-diff-suppr/test-has-data-member-inserted-at-1-report-2.txt"
   },
+  {
+    "data/test-diff-suppr/test-has-data-member-inserted-at-2-v0.o",
+    "data/test-diff-suppr/test-has-data-member-inserted-at-2-v1.o",
+    "",
+    "",
+    "data/test-diff-suppr/test-has-data-member-inserted-at-2.suppr",
+    "--drop-private-types --no-default-suppression --non-reachable-types",
+    "data/test-diff-suppr/test-has-data-member-inserted-at-2-report.txt",
+    "output/test-diff-suppr/test-has-data-member-inserted-at-2-report.txt"
+  },
+  {
+    "data/test-diff-suppr/test-has-data-member-inserted-at-2-v0.o",
+    "data/test-diff-suppr/test-has-data-member-inserted-at-2-v1.o",
+    "",
+    "",
+    "data/test-diff-suppr/test-has-data-member-inserted-at-2.2.suppr",
+    "--drop-private-types --no-default-suppression --non-reachable-types",
+    "data/test-diff-suppr/test-has-data-member-inserted-at-2-report.1.txt",
+    "output/test-diff-suppr/test-has-data-member-inserted-at-2-report.1.txt"
+  },
+  {
+    "data/test-diff-suppr/test-has-data-member-inserted-at-3-v0.o",
+    "data/test-diff-suppr/test-has-data-member-inserted-at-3-v1.o",
+    "",
+    "",
+    "data/test-diff-suppr/test-has-data-member-inserted-at-2.suppr",
+    "--drop-private-types --no-default-suppression --non-reachable-types",
+    "data/test-diff-suppr/test-has-data-member-inserted-at-2-report.2.txt",
+    "output/test-diff-suppr/test-has-data-member-inserted-at-2-report.2.txt"
+  },
+  {
+    "data/test-diff-suppr/test-has-data-member-inserted-at-3-v0.o",
+    "data/test-diff-suppr/test-has-data-member-inserted-at-3-v1.o",
+    "",
+    "",
+    "data/test-diff-suppr/test-has-data-member-inserted-at-2.2.suppr",
+    "--drop-private-types --no-default-suppression --non-reachable-types",
+    "data/test-diff-suppr/test-has-data-member-inserted-at-2-report.3.txt",
+    "output/test-diff-suppr/test-has-data-member-inserted-at-2-report.3.txt"
+  },
   // This should be the last entry
   {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
 };