@@ -2828,6 +2828,10 @@ public:
set_enum_type(enum_type_decl*);
}; // end class enum_type_def::enumerator
+bool
+is_enumerator_present_in_enum(const enum_type_decl::enumerator &enr,
+ const enum_type_decl &enom);
+
bool
equals(const typedef_decl&, const typedef_decl&, change_kind*);
@@ -14,6 +14,7 @@
#include <libgen.h>
#include <algorithm>
#include <sstream>
+#include <set>
#include "abg-comparison-priv.h"
#include "abg-reporter-priv.h"
@@ -9609,6 +9610,81 @@ corpus_diff::priv::ensure_lookup_tables_populated()
added_unreachable_types_[repr] = t;
}
}
+
+ // Handle anonymous enums that got changed. An anonymous enum is
+ // designated by its flat textual representation. So a change to
+ // any of its enumerators results in a different enum. That is
+ // represented by a deletion of the previous anonymous enum, and
+ // the addition of a new one. For the user however, it's the same
+ // enum that changed. Let's massage this "added/removed" pattern
+ // to show what the user expects, namely, a changed anonymous
+ // enum.
+ {
+ std::set<enum_type_decl_sptr> deleted_anon_enums;
+ std::set<enum_type_decl_sptr> added_anon_enums;
+
+ for (auto entry : deleted_unreachable_types_)
+ if (is_enum_type(entry.second)
+ && is_enum_type(entry.second)->get_is_anonymous())
+ deleted_anon_enums.insert(is_enum_type(entry.second));
+
+ for (auto entry : added_unreachable_types_)
+ if (is_enum_type(entry.second)
+ && is_enum_type(entry.second)->get_is_anonymous())
+ added_anon_enums.insert(is_enum_type(entry.second));
+
+ string_type_base_sptr_map added_anon_enum_to_erase;
+ string_type_base_sptr_map removed_anon_enum_to_erase;
+
+ // Look for deleted anonymous enums which have enumerators
+ // present in an added anonymous enums ...
+ for (auto deleted_enum : deleted_anon_enums)
+ {
+ // Look for any enumerator of 'deleted_enum' that is also
+ // present in an added anonymous enum.
+ for (auto enr : deleted_enum->get_enumerators())
+ {
+ bool this_enum_got_changed = false;
+ for (auto added_enum : added_anon_enums)
+ {
+ if (is_enumerator_present_in_enum(enr, *added_enum))
+ {
+ // So the enumerator 'enr' from the
+ // 'deleted_enum' enum is also present in the
+ // 'added_enum' enum so we assume that
+ // 'deleted_enum' and 'added_enum' are the same
+ // enum that got changed. Let's represent it
+ // using a diff node.
+ diff_sptr d = compute_diff(deleted_enum,
+ added_enum, ctxt);
+ ABG_ASSERT(d->has_changes());
+ string repr =
+ abigail::ir::get_pretty_representation(is_type(deleted_enum),
+ /*internal=*/false);
+ changed_unreachable_types_[repr]= d;
+ this_enum_got_changed = true;
+ string r1 = abigail::ir::get_pretty_representation(is_type(deleted_enum));
+ string r2 = abigail::ir::get_pretty_representation(is_type(added_enum));
+ removed_anon_enum_to_erase[r1] = deleted_enum;
+ added_anon_enum_to_erase[r2] = added_enum;
+ break;
+ }
+ }
+ if (this_enum_got_changed)
+ break;
+ }
+ }
+
+ // Now remove the added/removed anonymous enums from their maps,
+ // as they are now represented as a changed enum, not an added
+ // and removed enum.
+
+ for (auto entry : added_anon_enum_to_erase)
+ added_unreachable_types_.erase(entry.first);
+
+ for (auto entry : removed_anon_enum_to_erase)
+ deleted_unreachable_types_.erase(entry.first);
+ }
}
}
@@ -18997,7 +18997,7 @@ enum_has_non_name_change(const enum_type_decl& l,
///
/// @return true iff the enumerator @p enr is present in the enum @p
/// enom.
-static bool
+bool
is_enumerator_present_in_enum(const enum_type_decl::enumerator &enr,
const enum_type_decl &enom)
{
@@ -356,6 +356,12 @@ 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-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 \
+test-abidiff-exit/test-anonymous-enums-change-v0.o \
+test-abidiff-exit/test-anonymous-enums-change-v1.c \
+test-abidiff-exit/test-anonymous-enums-change-v1.o \
\
test-diff-dwarf/test0-v0.cc \
test-diff-dwarf/test0-v0.o \
new file mode 100644
@@ -0,0 +1,16 @@
+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 (1 filtered out), 1 added types
+
+1 changed type unreachable from any public interface:
+
+ [C] 'enum {E4_0=0, E4_1=1, E4_2=2, E4_LAST_ELEMENT=3, }' changed:
+ type size hasn't changed
+ 2 enumerator deletions:
+ 'E4_2' value '2'
+ 'E4_LAST_ELEMENT' value '3'
+
+1 added type unreachable from any public interface:
+
+ [A] 'enum {E5_0=0, E5_1=1, }' at test-anonymous-enums-change-v1.c:26:1
+
new file mode 100644
@@ -0,0 +1,21 @@
+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, 2 changed, 1 added types
+
+2 changed types unreachable from any public interface:
+
+ [C] 'enum {E4_0=0, E4_1=1, E4_2=2, E4_LAST_ELEMENT=3, }' changed:
+ type size hasn't changed
+ 2 enumerator deletions:
+ 'E4_2' value '2'
+ 'E4_LAST_ELEMENT' value '3'
+
+ [C] 'enum {E3_0=0, E3_1=1, }' changed:
+ type size hasn't changed
+ 1 enumerator insertion:
+ 'E3_2' value '2'
+
+1 added type unreachable from any public interface:
+
+ [A] 'enum {E5_0=0, E5_1=1, }' at test-anonymous-enums-change-v1.c:26:1
+
new file mode 100644
@@ -0,0 +1,36 @@
+/*
+ * Compile this with:
+ * gcc -c -g -fno-eliminate-unused-debug-types test-anonymous-enums-change-v0.c
+ */
+
+enum
+ {
+ E1_0,
+ E1_1,
+ } v1;
+
+enum
+ {
+ E3_0,
+ E3_1,
+ };
+
+enum
+ {
+ E4_0,
+ E4_1,
+ E4_2,
+ E4_LAST_ELEMENT
+ };
+
+enum
+ {
+ E0_0,
+ E0_1,
+ } v0;
+
+enum
+ {
+ E2_0,
+ E2_1,
+ } v2;
new file mode 100644
GIT binary patch
literal 3296
zcmb_e&2Jl35P$2nNn4Y&sU^Nrl6BRJ1laZ3aYJd9U=*3O5Gn*kLR_4+{p>8*>)>6R
zL<kj$3kZo5Cr%u=At5A$ggC$@C+=|I!2i$_NE~41?ToW|-Y5t$(!QDb&DYzv^Txhc
z-+m!u7=p<V8{$Y~REV83M{-SxHE~hQi{C)b2}4=4h(E53v}CS<FoR2+Q>})`WoOXA
z9GAtpMG(%Ks3NI=*$zm@0u)^MSc8>IMy+NXx$uSN0ySK*h=E#-;?L8b6>;U;W1hlT
z7UtZgJnSoLY!qkm#q90EjiPZg|7_7T3h)M1VV)r%cf0W1qnSs9$j%#A=L&gqX<_NY
z!*DuRL_WWfH|HSrC3rIM2$48WrN>JJSPpDY0yhlfuen)d_=fO+utcxClsO-#QDLJX
z^t*v<TYeCUdb#1^QWkX=B^RY?WBd8n?l$V%^_S~+?xGHsYHX>9`YNicpl;oH-P$Za
zW0lKJ)hSyQx3cQ4x!0`aS0Vc?FCv3oS+VSXGz#Q;R|azEw?OrVt=;wg>udH})gD(Y
zyKC8<U|`Fh-}eJAlJ+PVg|cn8WpmWEqk}yeih2brSD<nv!^rl6L2%F?j6z!mqkd?&
zcD<l0?Xl~$L}_=>m!<Zg{gz+q`cbLpH@&9c_55C`DWgaZRdgI!!fauw?M0pvZSZXS
zosKQ{{pf$pbn2#0br4&dn>VawIQNx*ap>x6r!UwTS#kgGG^?3<qoI4L7xfquENNsy
zg)}n718Fd1QP+IRW{R^@7y_n%o0dYRcrXP;f4o!EWQy4-@G>CtiTC0+xk@<e%$Eu0
zd&>CfjS52zX3iL|G7!g~137t0yhFtCG+u-U>0-<T;`lH<L;~YQ(jQCUTnnL<1djQ+
zUP;5b-gONpRcw)f{lz&DdXsS659Y6tzC)bxI_d9dc$xHfHGGZq_ci<`=^tu1pTlPw
z4ue<G=NgU^80o8+shg4Pq8|z8{r^Dvp@#oN`Y*)se9n`MjK4MJ$t7^?LnOrUc^eg=
zr(-t3zayQ`iT!^iTsYxDKk}NuqhZW<S&HO-BpjT6!fA$~aE7wyIcn}U{Gc-c8_wW{
z*K7{u_?X!n;>0~3((?n!Ay9%vgd0k44f=fvKRr$`h@=Cv%nl>3#c#$N{%?E%!tiYQ
zJUL5^1&yO`lCVDz(<fRj>6DQ5_$R=I_v)m0eKJkv1m(o<r{_dd4Hux_V>VfJU+fFa
zS(|vo!VWdnpA>+-hkiT*;D3msby)SBXjmlh73Fob=)P#zG4u`yv`|Tq?)wth()Rxb
z{WS1CasLSE`)>oL=LAT6N+8b*#E^8~24HFR_o)6Y6&2rIoMU?ZJ<92lAG1R$bjSd4
zuFw2Ez){xYKgz@be^4AVj${4_7}DbJQA6@PKPevPBIjZs<X`IzO-9`pb=oR<#Oxc2
p|9}E60F1v6`uX9Rrj>H3f1ireO;)}B{0Z^j)A##w5*Z76{6Aj89Torp
literal 0
HcmV?d00001
@@ -0,0 +1,41 @@
+/*
+ * Compile this with:
+ * gcc -c -g -fno-eliminate-unused-debug-types test-anonymous-enums-change-v1.c
+ */
+
+enum
+ {
+ E1_0,
+ E1_1,
+ } v1;
+
+enum
+ {
+ E3_0,
+ E3_1,
+ E3_2
+ };
+
+enum
+ {
+ E4_0,
+ E4_1,
+ };
+
+enum
+ {
+ E5_0,
+ E5_1,
+ };
+
+enum
+ {
+ E0_0,
+ E0_1,
+ } v0;
+
+enum
+ {
+ E2_0,
+ E2_1,
+ } v2;
new file mode 100644
GIT binary patch
literal 3336
zcmb_eO>7%g5T5ngq^(JsG>D(JkTtX=q3o``aY6}7YAFqA1*#Ad7cORPKRXNdI`Xbf
zB7|Cr3j&D?91s^SaN>jnhe`->=$%u!aOsH)2gHd32bg&~FWEeAFhY#9Z)U#vdprBy
z*tfP`elcelpvZs?IMfsh@cxNIxhBOLoPjy`73BgL(wZmyacSfww}QeHElEzf8c@hj
zk%Kv^z^NxtIBAkfBm<_qD5V3WoJ))ky{8!y`0Qtyu=TYLo1-#3Mb28$OFxf$da!i&
zh$k3}V9uN`;zskvMro>8%HNn@D;X~opD&rlJibyD%o7Y0Zp>eOEcYlte$Kc!GhZ|p
z&MnM7g6+Bh#o|WMoWa!R@yX!>km|40lf^?;K-)9O4a4|zW||oF10NI?lGYdtxzkA+
z88!@~pc9Ig6@)QtRqAD0DzH^1X(d^tic6K$Dp{9FT23Snwr{>>ZC0MMDix>dR4lLT
zEtglzE7szxnD@FLv%&V3EV~yEL$Tfwp%?^BRQ*A7XMOL=s=ZpZN1kPOEV~`{ZP5*S
zLFmWA9)`n6wCt8>3_Etbzbhix@~FIr<zo@WwjcJx{a$|<*&-bFBD=ZchaF*$DozvJ
zoqkWat$ypx!0iOF+YK6iBk1@+*KLS676Tcb1iF+ha$A1vOVLKpR?u$SVlRmQ$4nD9
zJ<$QSH#gU;MeO_1zi7Jr&i}B`xyZxse`UFtnKv8{FCRrc#zadNnOGr<On4v*#w_yM
zkJ(H(IffBn0$#KXGU34tl>F&Rjgtw}W8jmB%%$E-y~#z!m9F?A<La6!eDZ0<A%`Pp
zL^l~p#h*es-6gd{!l@hA@F6;rFd&>BMGv!}@Dl51Q@E-{&{7Jg{HmU-;i}#h4QCa$
zS)lW!auD=7<7)pj^NHS&YqEE$yT*E3!>_XbwuWD3{ap<&v;L8W(?BKqBw?~=R9E%q
zOAW_)Ea@u^zr^}?%;|m8r|U<}{~OltY4{!1e_>8}PP0r*odN1wA%)ZVBvRk^twe=q
znJfHT)+-wR6YJna`@Pt2Add$L-%(O5_F`~oG=kHJB5($x>pOBN*MqR#M;i_3y5DFF
z#OR3GAJ8~H8qy6yp+c~P5(%zLz1i>e1pXp9VLuiQ4mvxE{ib>|wc-E9&tVw#R`pY5
zsVPC@<eR1vDun5iu9kL6$$I?LXrudfT)aN94(12vr0=KaBvXwRq~8*Du<E{aE+}X1
zz#|cM`B2T~5}nQ-`Kj4}e@`T><ErN*gUjG6((7>1eaWt4<b8`li<A`UzAvFIYyY?T
zCqwO%_D_(${}y6;PK4ld23JW*k?vbZTUPx~x&C#IrTR2a^!mGqQBF0NP?U6!3w^Hu
z=BmEp?;xHP|1p2JKPJR~cuf2Ud?4Kk@iZ^hUed02^aIUC-IsLUYC0T#;P~4dFpF0D
f-O&3-J<Tdr<MVs@NY?Sa&K(nfpTFN16XO2{KK~tO
literal 0
HcmV?d00001
@@ -1032,6 +1032,38 @@ 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-anonymous-enums-change-v0.o",
+ "data/test-abidiff-exit/test-anonymous-enums-change-v1.o",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "--no-default-suppression --non-reachable-types",
+ abigail::tools_utils::ABIDIFF_ABI_CHANGE
+ | abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE,
+ "data/test-abidiff-exit/test-anonymous-enums-change-report-v0.txt",
+ "output/test-abidiff-exit/test-anonymous-enums-change-report-v0.txt"
+ },
+ {
+ "data/test-abidiff-exit/test-anonymous-enums-change-v0.o",
+ "data/test-abidiff-exit/test-anonymous-enums-change-v1.o",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "--no-default-suppression --harmless --non-reachable-types",
+ abigail::tools_utils::ABIDIFF_ABI_CHANGE
+ | abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE,
+ "data/test-abidiff-exit/test-anonymous-enums-change-report-v1.txt",
+ "output/test-abidiff-exit/test-anonymous-enums-change-report-v1.txt"
+ },
#ifdef WITH_BTF
{
"data/test-abidiff-exit/btf/test0-v0.o",