[5/5,abidiff] Treat function type changes as local.

Message ID 20200312063036.29419-6-gprocida@google.com
State Committed
Headers
Series More whitespace and leaf-changes-only fixes |

Commit Message

Giuliano Procida March 12, 2020, 6:30 a.m. UTC
  In leaf-changes-only mode, if the type of a struct's function pointer
member changes it currently gets categorised as a non-local change and
so is not reported. The change to any function passing such a struct
is considered non-local and also not reported.

This patch broadens the definition of local changes to include these
cases and so have them be reported in leaf-changes-only mode. It may
be the first of a sequence of such patches,

	* src/abg-ir.cc (types_have_similar_structure): Always compare
	function types (instead of just returning true) regardless of
        whether they are components of pointer-to-function or
        reference-to-function types.
	* tests/data/Makefile.am: Add new test case files.
	* tests/data/test-abidiff-exit/test-leaf2-report.txt: New test
	case.
	* tests/data/test-abidiff-exit/test-leaf2-v0.cc: Ditto.
	* tests/data/test-abidiff-exit/test-leaf2-v0.o: Ditto.
	* tests/data/test-abidiff-exit/test-leaf2-v1.cc: Ditto.
	* tests/data/test-abidiff-exit/test-leaf2-v1.o: Ditto.
	* tests/test-abidiff-exit.cc: Run new test case.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-ir.cc                                 |  34 +++++++++---------
 tests/data/Makefile.am                        |   5 +++
 .../test-abidiff-exit/test-leaf2-report.txt   |  12 +++++++
 tests/data/test-abidiff-exit/test-leaf2-v0.cc |   6 ++++
 tests/data/test-abidiff-exit/test-leaf2-v0.o  | Bin 0 -> 2840 bytes
 tests/data/test-abidiff-exit/test-leaf2-v1.cc |   6 ++++
 tests/data/test-abidiff-exit/test-leaf2-v1.o  | Bin 0 -> 2952 bytes
 tests/test-abidiff-exit.cc                    |   9 +++++
 8 files changed, 55 insertions(+), 17 deletions(-)
 create mode 100644 tests/data/test-abidiff-exit/test-leaf2-report.txt
 create mode 100644 tests/data/test-abidiff-exit/test-leaf2-v0.cc
 create mode 100644 tests/data/test-abidiff-exit/test-leaf2-v0.o
 create mode 100644 tests/data/test-abidiff-exit/test-leaf2-v1.cc
 create mode 100644 tests/data/test-abidiff-exit/test-leaf2-v1.o
  

Comments

Matthias Männich March 14, 2020, 8:45 p.m. UTC | #1
On Thu, Mar 12, 2020 at 06:30:36AM +0000, Android Kernel Team wrote:
>In leaf-changes-only mode, if the type of a struct's function pointer
>member changes it currently gets categorised as a non-local change and
>so is not reported. The change to any function passing such a struct
>is considered non-local and also not reported.
>
>This patch broadens the definition of local changes to include these
>cases and so have them be reported in leaf-changes-only mode. It may
>be the first of a sequence of such patches,
>

This actually fixes a bug as well:

  $ abidiff tests/data/test-abidiff-exit/test-leaf2-v{0,1}.o

reports the detailed change and exits with rc=4. Correct as I think.

In contrast:

  $ abidiff tests/data/test-abidiff-exit/test-leaf2-v{0,1}.o --leaf-changes-only

reported nothing with rc=4, but does consistently emit a difference now.

So, I believe, whenever we come to the conclusion that rc=4 is the right
way to exit, we need to report something in either mode. That makes me
think we should actually make this an ABG_ASSERT.

And I also believe therefore that this patch is correct:
Reviewed-by: Matthias Maennich <maennich@google.com>

Thanks for working on this!

Cheers,
Matthias

>	* src/abg-ir.cc (types_have_similar_structure): Always compare
>	function types (instead of just returning true) regardless of
>        whether they are components of pointer-to-function or
>        reference-to-function types.
>	* tests/data/Makefile.am: Add new test case files.
>	* tests/data/test-abidiff-exit/test-leaf2-report.txt: New test
>	case.
>	* tests/data/test-abidiff-exit/test-leaf2-v0.cc: Ditto.
>	* tests/data/test-abidiff-exit/test-leaf2-v0.o: Ditto.
>	* tests/data/test-abidiff-exit/test-leaf2-v1.cc: Ditto.
>	* tests/data/test-abidiff-exit/test-leaf2-v1.o: Ditto.
>	* tests/test-abidiff-exit.cc: Run new test case.
>
>Signed-off-by: Giuliano Procida <gprocida@google.com>
>---
> src/abg-ir.cc                                 |  34 +++++++++---------
> tests/data/Makefile.am                        |   5 +++
> .../test-abidiff-exit/test-leaf2-report.txt   |  12 +++++++
> tests/data/test-abidiff-exit/test-leaf2-v0.cc |   6 ++++
> tests/data/test-abidiff-exit/test-leaf2-v0.o  | Bin 0 -> 2840 bytes
> tests/data/test-abidiff-exit/test-leaf2-v1.cc |   6 ++++
> tests/data/test-abidiff-exit/test-leaf2-v1.o  | Bin 0 -> 2952 bytes
> tests/test-abidiff-exit.cc                    |   9 +++++
> 8 files changed, 55 insertions(+), 17 deletions(-)
> create mode 100644 tests/data/test-abidiff-exit/test-leaf2-report.txt
> create mode 100644 tests/data/test-abidiff-exit/test-leaf2-v0.cc
> create mode 100644 tests/data/test-abidiff-exit/test-leaf2-v0.o
> create mode 100644 tests/data/test-abidiff-exit/test-leaf2-v1.cc
> create mode 100644 tests/data/test-abidiff-exit/test-leaf2-v1.o
>
>diff --git a/src/abg-ir.cc b/src/abg-ir.cc
>index 3b1577a8..2cb76ffc 100644
>--- a/src/abg-ir.cc
>+++ b/src/abg-ir.cc
>@@ -22745,25 +22745,25 @@ types_have_similar_structure(const type_base* first, const type_base* second)
>   if (const function_type* ty1 = is_function_type(first))
>     {
>       const function_type* ty2 = is_function_type(second);
>-      if (!was_indirect_type)
>-	{
>-	  if (!types_have_similar_structure(ty1->get_return_type(),
>-					    ty2->get_return_type()))
>-	    return false;
>+      if (!ty2)
>+	return false;
>
>-	  if (ty1->get_parameters().size() != ty2->get_parameters().size())
>-	    return false;
>+      if (!types_have_similar_structure(ty1->get_return_type(),
>+					ty2->get_return_type()))
>+	return false;
>
>-	  for (function_type::parameters::const_iterator
>-		 i = ty1->get_parameters().begin(),
>-		 j = ty2->get_parameters().begin();
>-	       (i != ty1->get_parameters().end()
>-		&& j != ty2->get_parameters().end());
>-	       ++i, ++j)
>-	    if (!types_have_similar_structure((*i)->get_type(),
>-					      (*j)->get_type()))
>-	      return false;
>-	}
>+      if (ty1->get_parameters().size() != ty2->get_parameters().size())
>+	return false;
>+
>+      for (function_type::parameters::const_iterator
>+	     i = ty1->get_parameters().begin(),
>+	     j = ty2->get_parameters().begin();
>+	   (i != ty1->get_parameters().end()
>+	    && j != ty2->get_parameters().end());
>+	   ++i, ++j)
>+	if (!types_have_similar_structure((*i)->get_type(),
>+					  (*j)->get_type()))
>+	  return false;
>
>       return true;
>     }
>diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
>index bf76ca2e..3b4b614b 100644
>--- a/tests/data/Makefile.am
>+++ b/tests/data/Makefile.am
>@@ -120,6 +120,11 @@ test-abidiff-exit/test-leaf1-v0.o \
> test-abidiff-exit/test-leaf1-v1.cc \
> test-abidiff-exit/test-leaf1-v1.o \
> test-abidiff-exit/test-leaf1-report.txt \
>+test-abidiff-exit/test-leaf2-v0.cc \
>+test-abidiff-exit/test-leaf2-v0.o \
>+test-abidiff-exit/test-leaf2-v1.cc \
>+test-abidiff-exit/test-leaf2-v1.o \
>+test-abidiff-exit/test-leaf2-report.txt \
> test-abidiff-exit/test-leaf3-v0.c \
> test-abidiff-exit/test-leaf3-v0.o \
> test-abidiff-exit/test-leaf3-v1.c \
>diff --git a/tests/data/test-abidiff-exit/test-leaf2-report.txt b/tests/data/test-abidiff-exit/test-leaf2-report.txt
>new file mode 100644
>index 00000000..2765b469
>--- /dev/null
>+++ b/tests/data/test-abidiff-exit/test-leaf2-report.txt
>@@ -0,0 +1,12 @@
>+Leaf changes summary: 1 artifact changed
>+Changed leaf types summary: 1 leaf type changed
>+Removed/Changed/Added functions summary: 0 Removed, 0 Changed, 0 Added function
>+Removed/Changed/Added variables summary: 0 Removed, 0 Changed, 0 Added variable
>+
>+'struct ops' changed:
>+  type size hasn't changed
>+  there are data member changes:
>+    type 'void (int)*' of 'ops::munge' changed:
>+      pointer type changed from: 'void (int)*' to: 'char (long int, bool)*'
>+
>+
>diff --git a/tests/data/test-abidiff-exit/test-leaf2-v0.cc b/tests/data/test-abidiff-exit/test-leaf2-v0.cc
>new file mode 100644
>index 00000000..b75dd84c
>--- /dev/null
>+++ b/tests/data/test-abidiff-exit/test-leaf2-v0.cc
>@@ -0,0 +1,6 @@
>+struct ops {
>+  void (*munge)(int x);
>+};
>+
>+void register_ops(const ops&) {
>+}
>diff --git a/tests/data/test-abidiff-exit/test-leaf2-v0.o b/tests/data/test-abidiff-exit/test-leaf2-v0.o
>new file mode 100644
>index 0000000000000000000000000000000000000000..211a33884f30755929210fee5d328e5b7e6c24e1
>GIT binary patch
>literal 2840
>zcmb_e-ESL35TEtg@g>)|PE4UukT4QZs&a>&R#DO_#b9Vsm7=IpQB?_<vvd9s@j2X`
>zOUk!YgwzM5AP@x!iHE-M$p64Uf-2Excthd=X7+ZR_2%+|SjjsxzxmwRkMn15ym=)j
>z1n>}W84e{z0dCD4@(sy0paP3<bL;-^TlYWt>)@SVzd<-JRkn<f@)AfVN8@v&y%=mE
>z>@5T>Qi$AKOB&=|B!ycz&CmqJd|?nKVB6PGm?cCMv}yo2uK4i)m2))ZzV3q~V}n=_
>z&zCBWRa!1Bh{a<0Db!YkWjoGA=aRGThzb@k4^}A^uU6JDUj7BRig@9aAoWZ^O2y~E
>zaV|TS4Pc){mMmsH@yZhWhB8Cr^n=%y$Zd|?a;LGtva*Jks5bmz1Ud7>OJJF46B!H6
>z;4H-7rFop?USWR)Bte|GyMf<baqrZ;PDlC_o`Kmk0g6u+#J!w_PMdGttTxY`t6!+D
>zdn;bOx>BpJ*K6l%Rd<+-!(gKqgh4dupy)@P{>J{=s=Ioj>h`K`*N^XpoqjY5N8{KX
>zhaU{W9XIjYyFq-kfY$B$N)+@4aS}u=+~6D6&eJx(oDBCs$6+`QdjY^^vw5-l;_E?s
>z;D>2tZhiHvQKMWIJdqL*AKn15Ulz+JiuM7v;c3L_M?*I8)l&J(TyuWr3L2zv=1eCv
>z4}boXrNoY9!MG8V&Q9sA^Z-v`Bv|S?m<kJ~j_*WmL2<(CjFp~x9g@5?Ir-Bn3+AT*
>zC0S5920w8GUqob4>%-)L9yxW#Y`TibE1g4`c~Wsk!sVSN5XVAFfbqALe9FK-Rq~Re
>zv}5}2oYn00b8tz+DK9-1G`cC7<h`flp@H|5{Jx@QUS1>BUr;tg%8EDbSC7G~3a2&c
>z>jE#nJH-2kG>KB$XD$i$6YzHY#0Re($KXZ5uJ7#x?QyR)2)iTHN#1X_qu|bz+K+s^
>zk<%`_gD_whOaWeJG#m!_5_{n&2|RpL+&J+&@2NmRztxTWAzthMV=QA3>J|5sV>T2s
>zIgd&vTYWr>0%7vgqA9Lvyv~~b^yJdH`LF(U^fhBrKF<Gu1Z|kM^r4^+XhX9h_FeT=
>z{X^k&t_b2Yj$a!&HgGm$lH!rn0(_+?6VrAZ6(&ZuBL&vjQBl*D)|plRwz?GTPxaHQ
>zXV$-im>Clx_(_4ABxu95rN0tc`9D|rxlfdz-T^cJ9%2-e>qJ(L$12fx3@FO^nSO+L
>zmjB1<GSm6e2m3Mo0+r0`b`Pf>gF}sJ`-Ac~&3{(F+M%oDc>N52i%eGkzR&0%eO1_>
>z`%3kgxheK<3fxu&(|b=}E7PC$#Jqb5L5+&S!S8!29qkpx&GP?6)&Gzk6*c?!FWH5~
>ARsaA1
>
>literal 0
>HcmV?d00001
>
>diff --git a/tests/data/test-abidiff-exit/test-leaf2-v1.cc b/tests/data/test-abidiff-exit/test-leaf2-v1.cc
>new file mode 100644
>index 00000000..f308a343
>--- /dev/null
>+++ b/tests/data/test-abidiff-exit/test-leaf2-v1.cc
>@@ -0,0 +1,6 @@
>+struct ops {
>+  char (*munge)(long x, bool gunk);
>+};
>+
>+void register_ops(const ops&) {
>+}
>diff --git a/tests/data/test-abidiff-exit/test-leaf2-v1.o b/tests/data/test-abidiff-exit/test-leaf2-v1.o
>new file mode 100644
>index 0000000000000000000000000000000000000000..9db3ed5e8f997d9c8455f8361449ce516edc840a
>GIT binary patch
>literal 2952
>zcmbtV&2Jl35TECb<4v|PPE4UukXR(XqOwbzR#DO_C17Y06;M^F5<(zrZEtL=_HMMh
>z4k@Sti3+7BiiA`l^~QmZ180s%T)4qM!5wZO4rS);8|V4Oxxkb5&CG8;ciz{>Z@hW6
>zAO!Fba0QMfMge}AKIXS1y9HHPfSWt_e&4xw=db(k|NK3|Q&MHi2stl-d~!6t5bvj8
>z3t{gdXpuq`W)Gynl!v4k;6&eam!=peC<$3a$u8znfrxFth4T!tqNo)K!0E)pZ%{c)
>zQ{js)I5H)OdGTDi>R9Ea^1N6mRh~p`Ramy;Tyicu8;+=AU2|ZSb8)x2j`60Rhh4;r
>zXT@%n45o`xE<Fp5a|L5zIgcSrHZ#6>Ws$ujnPcnRgVz?xZI;{$=di?zvWAzaI{Yw#
>zoO$A(V3}zh84F&(S%`nib2!UI#KsHA!Zh>xVX(LA9n}0*OZpU_hM7D8icb{9rv(e0
>z2E(Wm!uH!Y-TL|SwTteCzv|cA)s@;tZRNs>>kYDD6mE9HC`@`S6oaJI-8@`h^VTl9
>zUdQ$Jg7kLO>Lzg%4^wX#eb9^AUKTX_VG7MS?w_osA4eUx7iI8rHrR*8yS3FM?DWzs
>zOd7Z)Zd|)S8>7_?63}sg?Rx!^`{L_ivlm2pnO<#e*(ey`arv{@g%59lIIM`JGbQ^z
>zcI7F=>7yZg`f9oIS)o2ReH9IIc;bw%xT*hqG)ajKoCM>#j2b<rxAKiXhLK>YV`C~T
>z7~9VywFRXSuQOJD40K5H*61jVt1Ors2b5$1ZsZBWf-@)31w<CKK8*J3iA{LQQmcsk
>zr?V(CPb$txI304<&65%b<3TRMSw$KDNXd(e(u(P;v#i<c`{1&M%gaT{Z3BOx<XZ-w
>zD48kO^Pa-*81@g9eAmD~QSy<ZX8qg`iZ8E4Wmh@He(e<8RXFuV?+^It?ExNWq*;>F
>zE^}FUn1SC8vH<*Mnu4E%{lIUB&0(j}i}qsFNj_*clki|n9V7u>JmW6?UKFwmrU1Vc
>z4+bIL6n+$Ep^ul8mu5lhmI@Sh8+%DG2vy<#lPsY>^_Kg|;kFbr+Sf`ZTYWr(0%7tg
>z(-hY<US~~zy2)w({a61Q`kFB*ALsvp1Z|kM^#0I;y`|X@d!%0Rb>%?&iXc8K_=w4|
>ziL)7#6n{%Cz~_oGF>SA-!o<k-NP#QtsHka6|2e7tpVXmXf2yBuPqY3uVrEQ);70{+
>zlb{XLwt>1y`TtP)xlfdz?h`ZrK4KJ;>qJ(LM=H^G3@FO^nbJKs$^Tn*m}!6MgZ-G^
>zMJ4mP-LGSp!Li1){Yv?p=D#Um{n%A<{QnGpiOi(_+3G;*{iD~3{TZiv%-j^)RtM_3
>qDwy64di6|yS`+i^Aq4MGQ8<=!GMdf*r?`{+T~+_rBhQ>M{r?5A)6WtB
>
>literal 0
>HcmV?d00001
>
>diff --git a/tests/test-abidiff-exit.cc b/tests/test-abidiff-exit.cc
>index 45258a9f..6b91e833 100644
>--- a/tests/test-abidiff-exit.cc
>+++ b/tests/test-abidiff-exit.cc
>@@ -139,6 +139,15 @@ InOutSpec in_out_specs[] =
>     "data/test-abidiff-exit/test-leaf1-report.txt",
>     "output/test-abidiff-exit/test-leaf1-report.txt"
>   },
>+  {
>+    "data/test-abidiff-exit/test-leaf2-v0.o",
>+    "data/test-abidiff-exit/test-leaf2-v1.o",
>+    "",
>+    "--no-show-locs --leaf-changes-only",
>+    abigail::tools_utils::ABIDIFF_ABI_CHANGE,
>+    "data/test-abidiff-exit/test-leaf2-report.txt",
>+    "output/test-abidiff-exit/test-leaf2-report.txt"
>+  },
>   {
>     "data/test-abidiff-exit/test-leaf3-v0.o",
>     "data/test-abidiff-exit/test-leaf3-v1.o",
>-- 
>2.25.1.481.gfbce0eb801-goog
>
>
  
Dodji Seketeli March 17, 2020, 4:15 p.m. UTC | #2
Hello Giuliano,

Giuliano Procida <gprocida@google.com> a ?crit:

> In leaf-changes-only mode, if the type of a struct's function pointer
> member changes it currently gets categorised as a non-local change and
> so is not reported. The change to any function passing such a struct
> is considered non-local and also not reported.
>
> This patch broadens the definition of local changes to include these
> cases and so have them be reported in leaf-changes-only mode. It may
> be the first of a sequence of such patches,
>
> 	* src/abg-ir.cc (types_have_similar_structure): Always compare
> 	function types (instead of just returning true) regardless of
>         whether they are components of pointer-to-function or
>         reference-to-function types.
> 	* tests/data/Makefile.am: Add new test case files.
> 	* tests/data/test-abidiff-exit/test-leaf2-report.txt: New test
> 	case.
> 	* tests/data/test-abidiff-exit/test-leaf2-v0.cc: Ditto.
> 	* tests/data/test-abidiff-exit/test-leaf2-v0.o: Ditto.
> 	* tests/data/test-abidiff-exit/test-leaf2-v1.cc: Ditto.
> 	* tests/data/test-abidiff-exit/test-leaf2-v1.o: Ditto.
> 	* tests/test-abidiff-exit.cc: Run new test case.

This is great, I like it!

Applied to master.

Thanks!
  

Patch

diff --git a/src/abg-ir.cc b/src/abg-ir.cc
index 3b1577a8..2cb76ffc 100644
--- a/src/abg-ir.cc
+++ b/src/abg-ir.cc
@@ -22745,25 +22745,25 @@  types_have_similar_structure(const type_base* first, const type_base* second)
   if (const function_type* ty1 = is_function_type(first))
     {
       const function_type* ty2 = is_function_type(second);
-      if (!was_indirect_type)
-	{
-	  if (!types_have_similar_structure(ty1->get_return_type(),
-					    ty2->get_return_type()))
-	    return false;
+      if (!ty2)
+	return false;
 
-	  if (ty1->get_parameters().size() != ty2->get_parameters().size())
-	    return false;
+      if (!types_have_similar_structure(ty1->get_return_type(),
+					ty2->get_return_type()))
+	return false;
 
-	  for (function_type::parameters::const_iterator
-		 i = ty1->get_parameters().begin(),
-		 j = ty2->get_parameters().begin();
-	       (i != ty1->get_parameters().end()
-		&& j != ty2->get_parameters().end());
-	       ++i, ++j)
-	    if (!types_have_similar_structure((*i)->get_type(),
-					      (*j)->get_type()))
-	      return false;
-	}
+      if (ty1->get_parameters().size() != ty2->get_parameters().size())
+	return false;
+
+      for (function_type::parameters::const_iterator
+	     i = ty1->get_parameters().begin(),
+	     j = ty2->get_parameters().begin();
+	   (i != ty1->get_parameters().end()
+	    && j != ty2->get_parameters().end());
+	   ++i, ++j)
+	if (!types_have_similar_structure((*i)->get_type(),
+					  (*j)->get_type()))
+	  return false;
 
       return true;
     }
diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
index bf76ca2e..3b4b614b 100644
--- a/tests/data/Makefile.am
+++ b/tests/data/Makefile.am
@@ -120,6 +120,11 @@  test-abidiff-exit/test-leaf1-v0.o \
 test-abidiff-exit/test-leaf1-v1.cc \
 test-abidiff-exit/test-leaf1-v1.o \
 test-abidiff-exit/test-leaf1-report.txt \
+test-abidiff-exit/test-leaf2-v0.cc \
+test-abidiff-exit/test-leaf2-v0.o \
+test-abidiff-exit/test-leaf2-v1.cc \
+test-abidiff-exit/test-leaf2-v1.o \
+test-abidiff-exit/test-leaf2-report.txt \
 test-abidiff-exit/test-leaf3-v0.c \
 test-abidiff-exit/test-leaf3-v0.o \
 test-abidiff-exit/test-leaf3-v1.c \
diff --git a/tests/data/test-abidiff-exit/test-leaf2-report.txt b/tests/data/test-abidiff-exit/test-leaf2-report.txt
new file mode 100644
index 00000000..2765b469
--- /dev/null
+++ b/tests/data/test-abidiff-exit/test-leaf2-report.txt
@@ -0,0 +1,12 @@ 
+Leaf changes summary: 1 artifact changed
+Changed leaf types summary: 1 leaf type changed
+Removed/Changed/Added functions summary: 0 Removed, 0 Changed, 0 Added function
+Removed/Changed/Added variables summary: 0 Removed, 0 Changed, 0 Added variable
+
+'struct ops' changed:
+  type size hasn't changed
+  there are data member changes:
+    type 'void (int)*' of 'ops::munge' changed:
+      pointer type changed from: 'void (int)*' to: 'char (long int, bool)*'
+
+
diff --git a/tests/data/test-abidiff-exit/test-leaf2-v0.cc b/tests/data/test-abidiff-exit/test-leaf2-v0.cc
new file mode 100644
index 00000000..b75dd84c
--- /dev/null
+++ b/tests/data/test-abidiff-exit/test-leaf2-v0.cc
@@ -0,0 +1,6 @@ 
+struct ops {
+  void (*munge)(int x);
+};
+
+void register_ops(const ops&) {
+}
diff --git a/tests/data/test-abidiff-exit/test-leaf2-v0.o b/tests/data/test-abidiff-exit/test-leaf2-v0.o
new file mode 100644
index 0000000000000000000000000000000000000000..211a33884f30755929210fee5d328e5b7e6c24e1
GIT binary patch
literal 2840
zcmb_e-ESL35TEtg@g>)|PE4UukT4QZs&a>&R#DO_#b9Vsm7=IpQB?_<vvd9s@j2X`
zOUk!YgwzM5AP@x!iHE-M$p64Uf-2Excthd=X7+ZR_2%+|SjjsxzxmwRkMn15ym=)j
z1n>}W84e{z0dCD4@(sy0paP3<bL;-^TlYWt>)@SVzd<-JRkn<f@)AfVN8@v&y%=mE
z>@5T>Qi$AKOB&=|B!ycz&CmqJd|?nKVB6PGm?cCMv}yo2uK4i)m2))ZzV3q~V}n=_
z&zCBWRa!1Bh{a<0Db!YkWjoGA=aRGThzb@k4^}A^uU6JDUj7BRig@9aAoWZ^O2y~E
zaV|TS4Pc){mMmsH@yZhWhB8Cr^n=%y$Zd|?a;LGtva*Jks5bmz1Ud7>OJJF46B!H6
z;4H-7rFop?USWR)Bte|GyMf<baqrZ;PDlC_o`Kmk0g6u+#J!w_PMdGttTxY`t6!+D
zdn;bOx>BpJ*K6l%Rd<+-!(gKqgh4dupy)@P{>J{=s=Ioj>h`K`*N^XpoqjY5N8{KX
zhaU{W9XIjYyFq-kfY$B$N)+@4aS}u=+~6D6&eJx(oDBCs$6+`QdjY^^vw5-l;_E?s
z;D>2tZhiHvQKMWIJdqL*AKn15Ulz+JiuM7v;c3L_M?*I8)l&J(TyuWr3L2zv=1eCv
z4}boXrNoY9!MG8V&Q9sA^Z-v`Bv|S?m<kJ~j_*WmL2<(CjFp~x9g@5?Ir-Bn3+AT*
zC0S5920w8GUqob4>%-)L9yxW#Y`TibE1g4`c~Wsk!sVSN5XVAFfbqALe9FK-Rq~Re
zv}5}2oYn00b8tz+DK9-1G`cC7<h`flp@H|5{Jx@QUS1>BUr;tg%8EDbSC7G~3a2&c
z>jE#nJH-2kG>KB$XD$i$6YzHY#0Re($KXZ5uJ7#x?QyR)2)iTHN#1X_qu|bz+K+s^
zk<%`_gD_whOaWeJG#m!_5_{n&2|RpL+&J+&@2NmRztxTWAzthMV=QA3>J|5sV>T2s
zIgd&vTYWr>0%7vgqA9Lvyv~~b^yJdH`LF(U^fhBrKF<Gu1Z|kM^r4^+XhX9h_FeT=
z{X^k&t_b2Yj$a!&HgGm$lH!rn0(_+?6VrAZ6(&ZuBL&vjQBl*D)|plRwz?GTPxaHQ
zXV$-im>Clx_(_4ABxu95rN0tc`9D|rxlfdz-T^cJ9%2-e>qJ(L$12fx3@FO^nSO+L
zmjB1<GSm6e2m3Mo0+r0`b`Pf>gF}sJ`-Ac~&3{(F+M%oDc>N52i%eGkzR&0%eO1_>
z`%3kgxheK<3fxu&(|b=}E7PC$#Jqb5L5+&S!S8!29qkpx&GP?6)&Gzk6*c?!FWH5~
ARsaA1

literal 0
HcmV?d00001

diff --git a/tests/data/test-abidiff-exit/test-leaf2-v1.cc b/tests/data/test-abidiff-exit/test-leaf2-v1.cc
new file mode 100644
index 00000000..f308a343
--- /dev/null
+++ b/tests/data/test-abidiff-exit/test-leaf2-v1.cc
@@ -0,0 +1,6 @@ 
+struct ops {
+  char (*munge)(long x, bool gunk);
+};
+
+void register_ops(const ops&) {
+}
diff --git a/tests/data/test-abidiff-exit/test-leaf2-v1.o b/tests/data/test-abidiff-exit/test-leaf2-v1.o
new file mode 100644
index 0000000000000000000000000000000000000000..9db3ed5e8f997d9c8455f8361449ce516edc840a
GIT binary patch
literal 2952
zcmbtV&2Jl35TECb<4v|PPE4UukXR(XqOwbzR#DO_C17Y06;M^F5<(zrZEtL=_HMMh
z4k@Sti3+7BiiA`l^~QmZ180s%T)4qM!5wZO4rS);8|V4Oxxkb5&CG8;ciz{>Z@hW6
zAO!Fba0QMfMge}AKIXS1y9HHPfSWt_e&4xw=db(k|NK3|Q&MHi2stl-d~!6t5bvj8
z3t{gdXpuq`W)Gynl!v4k;6&eam!=peC<$3a$u8znfrxFth4T!tqNo)K!0E)pZ%{c)
zQ{js)I5H)OdGTDi>R9Ea^1N6mRh~p`Ramy;Tyicu8;+=AU2|ZSb8)x2j`60Rhh4;r
zXT@%n45o`xE<Fp5a|L5zIgcSrHZ#6>Ws$ujnPcnRgVz?xZI;{$=di?zvWAzaI{Yw#
zoO$A(V3}zh84F&(S%`nib2!UI#KsHA!Zh>xVX(LA9n}0*OZpU_hM7D8icb{9rv(e0
z2E(Wm!uH!Y-TL|SwTteCzv|cA)s@;tZRNs>>kYDD6mE9HC`@`S6oaJI-8@`h^VTl9
zUdQ$Jg7kLO>Lzg%4^wX#eb9^AUKTX_VG7MS?w_osA4eUx7iI8rHrR*8yS3FM?DWzs
zOd7Z)Zd|)S8>7_?63}sg?Rx!^`{L_ivlm2pnO<#e*(ey`arv{@g%59lIIM`JGbQ^z
zcI7F=>7yZg`f9oIS)o2ReH9IIc;bw%xT*hqG)ajKoCM>#j2b<rxAKiXhLK>YV`C~T
z7~9VywFRXSuQOJD40K5H*61jVt1Ors2b5$1ZsZBWf-@)31w<CKK8*J3iA{LQQmcsk
zr?V(CPb$txI304<&65%b<3TRMSw$KDNXd(e(u(P;v#i<c`{1&M%gaT{Z3BOx<XZ-w
zD48kO^Pa-*81@g9eAmD~QSy<ZX8qg`iZ8E4Wmh@He(e<8RXFuV?+^It?ExNWq*;>F
zE^}FUn1SC8vH<*Mnu4E%{lIUB&0(j}i}qsFNj_*clki|n9V7u>JmW6?UKFwmrU1Vc
z4+bIL6n+$Ep^ul8mu5lhmI@Sh8+%DG2vy<#lPsY>^_Kg|;kFbr+Sf`ZTYWr(0%7tg
z(-hY<US~~zy2)w({a61Q`kFB*ALsvp1Z|kM^#0I;y`|X@d!%0Rb>%?&iXc8K_=w4|
ziL)7#6n{%Cz~_oGF>SA-!o<k-NP#QtsHka6|2e7tpVXmXf2yBuPqY3uVrEQ);70{+
zlb{XLwt>1y`TtP)xlfdz?h`ZrK4KJ;>qJ(LM=H^G3@FO^nbJKs$^Tn*m}!6MgZ-G^
zMJ4mP-LGSp!Li1){Yv?p=D#Um{n%A<{QnGpiOi(_+3G;*{iD~3{TZiv%-j^)RtM_3
qDwy64di6|yS`+i^Aq4MGQ8<=!GMdf*r?`{+T~+_rBhQ>M{r?5A)6WtB

literal 0
HcmV?d00001

diff --git a/tests/test-abidiff-exit.cc b/tests/test-abidiff-exit.cc
index 45258a9f..6b91e833 100644
--- a/tests/test-abidiff-exit.cc
+++ b/tests/test-abidiff-exit.cc
@@ -139,6 +139,15 @@  InOutSpec in_out_specs[] =
     "data/test-abidiff-exit/test-leaf1-report.txt",
     "output/test-abidiff-exit/test-leaf1-report.txt"
   },
+  {
+    "data/test-abidiff-exit/test-leaf2-v0.o",
+    "data/test-abidiff-exit/test-leaf2-v1.o",
+    "",
+    "--no-show-locs --leaf-changes-only",
+    abigail::tools_utils::ABIDIFF_ABI_CHANGE,
+    "data/test-abidiff-exit/test-leaf2-report.txt",
+    "output/test-abidiff-exit/test-leaf2-report.txt"
+  },
   {
     "data/test-abidiff-exit/test-leaf3-v0.o",
     "data/test-abidiff-exit/test-leaf3-v1.o",