[applied,to,check-uapi-support] suppression: Add "changed_enumerators_regexp" property

Message ID 87msx0hf57.fsf@redhat.com
State New
Headers
Series [applied,to,check-uapi-support] suppression: Add "changed_enumerators_regexp" property |

Commit Message

Dodji Seketeli Oct. 2, 2023, 9:45 p.m. UTC
  Hello,

Currently, users are able to suppress changes to enumerator variants
matching names specified in "changed_enumerators", but can't specify
regular expressions.

A common pattern when using enums is to have the final enum variant
labeled as "*_MAX" or "*_LAST" so that users of the enum can have a
way to determine how many variants there are. In these cases, when
expanding an enum, the last variant will change, but that's an
expected result that users may not want to flag as an ABI-breaking
change.

For example, if you have a change like this:

enum foo {
        FOO,
        BAR,
        FOOBAR_MAX,
};

...

enum foo {
        FOO,
        BAR,
        BAZ,
        FOOBAR_MAX,
};

abidiff reports:

1 changed type unreachable from any public interface:

  [C] 'enum foo' changed:
    type size hasn't changed
    1 enumerator insertion:
      'foo::BAZ' value '2'
    1 enumerator change:
      'foo::FOOBAR_MAX' from value '2' to '3' at test_2.c:1:1

With a new changed_enumerators_regexp property, users can specify a
suppression which stops abidiff from emitting this diff for any
members which match the regular expressions in the list:

[suppress_type]
  type_kind = enum
  changed_enumerators_regexp = .*_MAX$, .*_LAST$, .*_NUM$, .*_NBITS$

	* include/abg-suppression.h
	(type_suppression::{g,s}et_changed_enumerators_regexp): Declare new
	accessor functions.
	* src/abg-suppression-priv.h
	(type_suppression::priv::changed_enumerators_regexp_): Define new
	data member.
	* src/abg-suppression.cc
	(type_suppression::{g,s}et_changed_enumerators_regexp): Define new
	accessor function.
	(type_suppression::suppresses_diff): For a type suppression to
	match an enum_diff, the names of all changed enumerators must
	match either the names returned by
	type_suppression::get_changed_enumerator_names or one of the
	regexps returned by the new member function
	type_suppression::get_changed_enumerators_regexp.
	(read_type_suppression): Parse the new
	'changed_enumerators_regexp' property to set the
	type_suppression::get_changed_enumerators_regexp property.
	* doc/manuals/libabigail-concepts.rst: Add an entry for the new
	'changed_enumerators_regexp' property.
	* tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-[1-5].suppr:
	Add new test suppression files.
	* tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-[0-5].txt:
	Add new test reference output files.
	* tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v{0,1}.c:
	Add source code for new binary test input files.
	* tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v{0,1}.o:
	Add new binary test input files.
	* tests/data/Makefile.am: Add the new test files to the source
	distribution.
	* tests/test-diff-suppr.cc (in_out_specs): Add the new test input
	files to this test harness.

Signed-off-by: John Moon <quic_johmoo@quicinc.com>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Applied to the WIP branch https://sourceware.org/git/?p=libabigail.git;a=shortlog;h=refs/heads/users/dodji/check-uapi-support
---
 doc/manuals/libabigail-concepts.rst           |  25 ++++++
 include/abg-suppression.h                     |   6 ++
 src/abg-suppression-priv.h                    |   1 +
 src/abg-suppression.cc                        |  84 +++++++++++++++---
 tests/data/Makefile.am                        |  15 ++++
 ...merator-changes-enumerator-changes-1.suppr |   3 +
 ...merator-changes-enumerator-changes-2.suppr |   3 +
 ...merator-changes-enumerator-changes-3.suppr |   3 +
 ...merator-changes-enumerator-changes-4.suppr |   3 +
 ...merator-changes-enumerator-changes-5.suppr |   3 +
 ...or-changes-enumerator-changes-report-0.txt |  29 ++++++
 ...or-changes-enumerator-changes-report-1.txt |  21 +++++
 ...or-changes-enumerator-changes-report-2.txt |  21 +++++
 ...or-changes-enumerator-changes-report-3.txt |  13 +++
 ...or-changes-enumerator-changes-report-4.txt |  21 +++++
 ...or-changes-enumerator-changes-report-5.txt |   3 +
 ...enumerator-changes-enumerator-changes-v0.c |  37 ++++++++
 ...enumerator-changes-enumerator-changes-v0.o | Bin 0 -> 3944 bytes
 ...enumerator-changes-enumerator-changes-v1.c |  40 +++++++++
 ...enumerator-changes-enumerator-changes-v1.o | Bin 0 -> 4064 bytes
 tests/test-diff-suppr.cc                      |  60 +++++++++++++
 21 files changed, 381 insertions(+), 10 deletions(-)
 create mode 100644 tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-1.suppr
 create mode 100644 tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-2.suppr
 create mode 100644 tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-3.suppr
 create mode 100644 tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-4.suppr
 create mode 100644 tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-5.suppr
 create mode 100644 tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-0.txt
 create mode 100644 tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-1.txt
 create mode 100644 tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-2.txt
 create mode 100644 tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-3.txt
 create mode 100644 tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-4.txt
 create mode 100644 tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-5.txt
 create mode 100644 tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v0.c
 create mode 100644 tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v0.o
 create mode 100644 tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v1.c
 create mode 100644 tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v1.o

new file mode 100644
index 00000000..e7f1bcc7
index 11be9b9a..46f29242 100644
  

Patch

diff --git a/doc/manuals/libabigail-concepts.rst b/doc/manuals/libabigail-concepts.rst
index f8b5f105..f850252b 100644
--- a/doc/manuals/libabigail-concepts.rst
+++ b/doc/manuals/libabigail-concepts.rst
@@ -353,6 +353,31 @@  The potential properties of this sections are listed below:
       changed_enumerators = LAST_ENUMERATORS0, LAST_ENUMERATOR1
 
 
+.. _suppr_changed_enumerators_regexp_label:
+
+* ``changed_enumerators_regexp``
+
+  Usage:
+
+    ``changed_enumerators_regexp`` ``=`` <list-of-enumerator-regular-expressions>
+
+  Suppresses change reports involving changes in the value of
+  enumerators of a given enum type.  This property is applied if the
+  ``type_kind`` property is set to the value ``enum``, at least.  The
+  value of the ``changed_enumerators_regexp`` property is a
+  comma-separated list of regular expressions that should match the
+  names of the enumerators that the user expects to change.  For
+  instance: ::
+
+      changed_enumerators_regexp = .*_MAX$, .*_LAST$, .*_NUM$, .*_NBITS$
+
+  In the example above, change reports to any enumerator which name
+  ends with _MAX, _LAST, _NUM or _NBITS will be suppressed.
+
+  Note that for this property to be applied to changes to an enum
+  type, the size of the enum type must *NOT* have changed.
+
+
 * ``drop``
 
  Usage:
diff --git a/include/abg-suppression.h b/include/abg-suppression.h
index 9449d06d..d6283eb8 100644
--- a/include/abg-suppression.h
+++ b/include/abg-suppression.h
@@ -330,6 +330,12 @@  public:
   void
   set_changed_enumerator_names(const vector<string>&);
 
+  const vector<regex::regex_t_sptr>&
+  get_changed_enumerators_regexp() const;
+
+  void
+  set_changed_enumerators_regexp(const vector<regex::regex_t_sptr>&);
+
   virtual bool
   suppresses_diff(const diff* diff) const;
 
diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
index cf66a9f1..351c5965 100644
--- a/src/abg-suppression-priv.h
+++ b/src/abg-suppression-priv.h
@@ -585,6 +585,7 @@  class type_suppression::priv
   string				source_location_to_keep_regex_str_;
   mutable regex::regex_t_sptr		source_location_to_keep_regex_;
   mutable vector<string>		changed_enumerator_names_;
+  mutable vector<regex::regex_t_sptr>	changed_enumerators_regexp_;
 
   priv();
 
diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 4ed42e82..22adfa8c 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -770,6 +770,28 @@  void
 type_suppression::set_changed_enumerator_names(const vector<string>& n)
 {priv_->changed_enumerator_names_ = n;}
 
+/// Getter of the vector of the regular expression strings for changed
+/// enumerators that are supposed to be suppressed. Note that this
+/// will be "valid" only if the type suppression has the
+/// 'type_kind = enum' property.
+///
+/// @return the vector of the regular expression strings that are
+/// supposed to match enumertor names to be suppressed.
+const vector<regex::regex_t_sptr>&
+type_suppression::get_changed_enumerators_regexp() const
+{return priv_->changed_enumerators_regexp_;}
+
+/// Setter of the vector of the regular expression strings for changed
+/// enumerators that are supposed to be suppressed. Note that this
+/// will be "valid" only if the type suppression has the
+/// 'type_kind = enum' property.
+///
+/// @param n the vector of the regular expression strings that are
+/// supposed to match enumertor names to be suppressed.
+void
+type_suppression::set_changed_enumerators_regexp(const vector<regex::regex_t_sptr>& n)
+{priv_->changed_enumerators_regexp_ = n;}
+
 /// Evaluate this suppression specification on a given diff node and
 /// say if the diff node should be suppressed or not.
 ///
@@ -996,9 +1018,12 @@  type_suppression::suppresses_diff(const diff* diff) const
       // ... and yet carries some changed enumerators!
       && !enum_dif->changed_enumerators().empty())
     {
-      // Make sure that all changed enumerators are listed in the
-      // vector of enumerator names returned by the
-      // get_changed_enumerator_names() member function.
+
+      // Make sure that all changed enumerators are either:
+      //  1. listed in the vector of enumerator names returned
+      //     by the get_changed_enumerator_names() member function
+      //  2. match a regular expression returned by the
+      //     get_changed_enumerators_regexp() member function
       bool matched = true;
       for (string_changed_enumerator_map::const_iterator i =
 	     enum_dif->changed_enumerators().begin();
@@ -1006,13 +1031,20 @@  type_suppression::suppresses_diff(const diff* diff) const
 	   ++i)
 	{
 	  matched &= true;
-	  if (std::find(get_changed_enumerator_names().begin(),
-			get_changed_enumerator_names().end(),
-			i->first) == get_changed_enumerator_names().end())
-	    {
-	      matched &= false;
-	      break;
-	    }
+	  if ((std::find(get_changed_enumerator_names().begin(),
+			 get_changed_enumerator_names().end(),
+			 i->first) == get_changed_enumerator_names().end())
+	     &&
+	      (std::find_if(get_changed_enumerators_regexp().begin(),
+			    get_changed_enumerators_regexp().end(),
+			    [&] (const regex_t_sptr& enum_regexp)
+		{
+		  return regex::match(enum_regexp, i->first);
+		}) == get_changed_enumerators_regexp().end()))
+	  {
+	    matched &= false;
+	    break;
+	  }
 	}
       if (!matched)
 	return false;
@@ -2154,6 +2186,34 @@  read_type_suppression(const ini::config::section& section)
 	changed_enumerator_names.push_back(p->get_value()->as_string());
     }
 
+  /// Support 'changed_enumerators_regexp = .*_foo, bar_[0-9]+, baz'
+  ///
+  /// If the current type is an enum and if it carries changed
+  /// enumerators that match regular expressions listed in the
+  /// changed_enumerators_regexp property value then it should be
+  /// suppressed.
+
+  ini::property_sptr changed_enumerators_regexp_prop =
+    section.find_property("changed_enumerators_regexp");
+
+  vector<regex_t_sptr> changed_enumerators_regexp;
+  if (changed_enumerators_regexp_prop)
+    {
+      if (ini::list_property_sptr p =
+	  is_list_property(changed_enumerators_regexp_prop))
+      {
+	for (string e : p->get_value()->get_content())
+	  changed_enumerators_regexp.push_back(regex::compile(e));
+      }
+      else if (ini::simple_property_sptr p =
+	       is_simple_property(changed_enumerators_regexp_prop))
+      {
+	changed_enumerators_regexp.push_back(
+	  regex::compile(p->get_value()->as_string())
+	);
+      }
+    }
+
   if (section.get_name() == "suppress_type")
     result.reset(new type_suppression(label_str, name_regex_str, name_str));
   else if (section.get_name() == "allow_type")
@@ -2217,6 +2277,10 @@  read_type_suppression(const ini::config::section& section)
       && !changed_enumerator_names.empty())
     result->set_changed_enumerator_names(changed_enumerator_names);
 
+  if (result->get_type_kind() == type_suppression::ENUM_TYPE_KIND
+      && !changed_enumerators_regexp.empty())
+    result->set_changed_enumerators_regexp(changed_enumerators_regexp);
+
   return result;
 }
 
diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
index b3434da5..1632e2ab 100644
--- a/tests/data/Makefile.am
+++ b/tests/data/Makefile.am
@@ -1755,6 +1755,21 @@  test-diff-suppr/test39-public-headers-dir/test39-header-v0.h \
 test-diff-suppr/test39-public-headers-dir/test39-header-v1.h \
 test-diff-suppr/libtest40-enumerator-changes-v0.so \
 test-diff-suppr/libtest40-enumerator-changes-v1.so \
+test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-1.suppr \
+test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-2.suppr \
+test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-3.suppr \
+test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-4.suppr \
+test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-5.suppr \
+test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-0.txt \
+test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-1.txt \
+test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-2.txt \
+test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-3.txt \
+test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-4.txt \
+test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-5.txt \
+test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v0.c \
+test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v1.c \
+test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v0.o \
+test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v1.o \
 test-diff-suppr/libtest41-enumerator-changes-v0.so \
 test-diff-suppr/libtest41-enumerator-changes-v1.so \
 test-diff-suppr/test40-enumerator-changes-0.suppr \
diff --git a/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-1.suppr b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-1.suppr
new file mode 100644
index 00000000..cbe76ab8
--- /dev/null
+++ b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-1.suppr
@@ -0,0 +1,3 @@ 
+[suppress_type]
+  type_kind = enum
+  changed_enumerators_regexp = ^.*_LAST$
diff --git a/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-2.suppr b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-2.suppr
new file mode 100644
index 00000000..0ab63c10
--- /dev/null
+++ b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-2.suppr
@@ -0,0 +1,3 @@ 
+[suppress_type]
+  type_kind = enum
+  changed_enumerators_regexp = ^.*_MAX$
diff --git a/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-3.suppr b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-3.suppr
new file mode 100644
index 00000000..e8bb9117
--- /dev/null
+++ b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-3.suppr
@@ -0,0 +1,3 @@ 
+[suppress_type]
+  type_kind = enum
+  changed_enumerators_regexp = ^.*_LAST$, ^.*_MAX$
\ No newline at end of file
diff --git a/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-4.suppr b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-4.suppr
new file mode 100644
index 00000000..492dd336
--- /dev/null
+++ b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-4.suppr
@@ -0,0 +1,3 @@ 
+[suppress_type]
+  type_kind = enum
+  changed_enumerators_regexp = ^LAST_.*$
\ No newline at end of file
diff --git a/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-5.suppr b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-5.suppr
new file mode 100644
index 00000000..3ee5d407
--- /dev/null
+++ b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-5.suppr
@@ -0,0 +1,3 @@ 
+[suppress_type]
+  type_kind = enum
+  changed_enumerators_regexp = ^.*_LAST$, ^.*_MAX$, ^LAST_.*$
\ No newline at end of file
diff --git a/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-0.txt b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-0.txt
new file mode 100644
index 00000000..26435de3
--- /dev/null
+++ b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-0.txt
@@ -0,0 +1,29 @@ 
+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:
+
+  [C] 'function void fun0(Enum0)' at test40.1-enumerator-changes-enumerator-changes-v0.c:25:1 has some indirect sub-type changes:
+    parameter 1 of type 'enum Enum0' has sub-type changes:
+      type size hasn't changed
+      1 enumerator insertion:
+        'Enum0::ENUM0_E1' value '1'
+      1 enumerator change:
+        'Enum0::ENOM0_LAST' from value '1' to '2' at test40.1-enumerator-changes-enumerator-changes-v1.c:6:1
+
+  [C] 'function void fun1(Enum1)' at test40.1-enumerator-changes-enumerator-changes-v0.c:30:1 has some indirect sub-type changes:
+    parameter 1 of type 'enum Enum1' has sub-type changes:
+      type size hasn't changed
+      1 enumerator insertion:
+        'Enum1::ENUM1_E1' value '1'
+      1 enumerator change:
+        'Enum1::ENUM1_MAX' from value '1' to '2' at test40.1-enumerator-changes-enumerator-changes-v1.c:13:1
+
+  [C] 'function void fun2(Enum2)' at test40.1-enumerator-changes-enumerator-changes-v0.c:35:1 has some indirect sub-type changes:
+    parameter 1 of type 'enum Enum2' has sub-type changes:
+      type size hasn't changed
+      1 enumerator insertion:
+        'Enum2::ENUM2_E1' value '1'
+      1 enumerator change:
+        'Enum2::LAST_ENUM1_ENUMERATOR' from value '1' to '2' at test40.1-enumerator-changes-enumerator-changes-v1.c:20:1
+
diff --git a/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-1.txt b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-1.txt
new file mode 100644
index 00000000..ff415ac5
--- /dev/null
+++ b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-1.txt
@@ -0,0 +1,21 @@ 
+Functions changes summary: 0 Removed, 2 Changed (1 filtered out), 0 Added functions
+Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+
+2 functions with some indirect sub-type change:
+
+  [C] 'function void fun1(Enum1)' at test40.1-enumerator-changes-enumerator-changes-v0.c:30:1 has some indirect sub-type changes:
+    parameter 1 of type 'enum Enum1' has sub-type changes:
+      type size hasn't changed
+      1 enumerator insertion:
+        'Enum1::ENUM1_E1' value '1'
+      1 enumerator change:
+        'Enum1::ENUM1_MAX' from value '1' to '2' at test40.1-enumerator-changes-enumerator-changes-v1.c:13:1
+
+  [C] 'function void fun2(Enum2)' at test40.1-enumerator-changes-enumerator-changes-v0.c:35:1 has some indirect sub-type changes:
+    parameter 1 of type 'enum Enum2' has sub-type changes:
+      type size hasn't changed
+      1 enumerator insertion:
+        'Enum2::ENUM2_E1' value '1'
+      1 enumerator change:
+        'Enum2::LAST_ENUM1_ENUMERATOR' from value '1' to '2' at test40.1-enumerator-changes-enumerator-changes-v1.c:20:1
+
diff --git a/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-2.txt b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-2.txt
new file mode 100644
index 00000000..7e4093ca
--- /dev/null
+++ b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-2.txt
@@ -0,0 +1,21 @@ 
+Functions changes summary: 0 Removed, 2 Changed (1 filtered out), 0 Added functions
+Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+
+2 functions with some indirect sub-type change:
+
+  [C] 'function void fun0(Enum0)' at test40.1-enumerator-changes-enumerator-changes-v0.c:25:1 has some indirect sub-type changes:
+    parameter 1 of type 'enum Enum0' has sub-type changes:
+      type size hasn't changed
+      1 enumerator insertion:
+        'Enum0::ENUM0_E1' value '1'
+      1 enumerator change:
+        'Enum0::ENOM0_LAST' from value '1' to '2' at test40.1-enumerator-changes-enumerator-changes-v1.c:6:1
+
+  [C] 'function void fun2(Enum2)' at test40.1-enumerator-changes-enumerator-changes-v0.c:35:1 has some indirect sub-type changes:
+    parameter 1 of type 'enum Enum2' has sub-type changes:
+      type size hasn't changed
+      1 enumerator insertion:
+        'Enum2::ENUM2_E1' value '1'
+      1 enumerator change:
+        'Enum2::LAST_ENUM1_ENUMERATOR' from value '1' to '2' at test40.1-enumerator-changes-enumerator-changes-v1.c:20:1
+
diff --git a/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-3.txt b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-3.txt
new file mode 100644
index 00000000..9f4bbcb2
--- /dev/null
+++ b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-3.txt
@@ -0,0 +1,13 @@ 
+Functions changes summary: 0 Removed, 1 Changed (2 filtered out), 0 Added functions
+Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+
+1 function with some indirect sub-type change:
+
+  [C] 'function void fun2(Enum2)' at test40.1-enumerator-changes-enumerator-changes-v0.c:35:1 has some indirect sub-type changes:
+    parameter 1 of type 'enum Enum2' has sub-type changes:
+      type size hasn't changed
+      1 enumerator insertion:
+        'Enum2::ENUM2_E1' value '1'
+      1 enumerator change:
+        'Enum2::LAST_ENUM1_ENUMERATOR' from value '1' to '2' at test40.1-enumerator-changes-enumerator-changes-v1.c:20:1
+
diff --git a/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-4.txt b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-4.txt
new file mode 100644
index 00000000..e09641c6
--- /dev/null
+++ b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-4.txt
@@ -0,0 +1,21 @@ 
+Functions changes summary: 0 Removed, 2 Changed (1 filtered out), 0 Added functions
+Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+
+2 functions with some indirect sub-type change:
+
+  [C] 'function void fun0(Enum0)' at test40.1-enumerator-changes-enumerator-changes-v0.c:25:1 has some indirect sub-type changes:
+    parameter 1 of type 'enum Enum0' has sub-type changes:
+      type size hasn't changed
+      1 enumerator insertion:
+        'Enum0::ENUM0_E1' value '1'
+      1 enumerator change:
+        'Enum0::ENOM0_LAST' from value '1' to '2' at test40.1-enumerator-changes-enumerator-changes-v1.c:6:1
+
+  [C] 'function void fun1(Enum1)' at test40.1-enumerator-changes-enumerator-changes-v0.c:30:1 has some indirect sub-type changes:
+    parameter 1 of type 'enum Enum1' has sub-type changes:
+      type size hasn't changed
+      1 enumerator insertion:
+        'Enum1::ENUM1_E1' value '1'
+      1 enumerator change:
+        'Enum1::ENUM1_MAX' from value '1' to '2' at test40.1-enumerator-changes-enumerator-changes-v1.c:13:1
+
diff --git a/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-5.txt b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-5.txt
new file mode 100644
index 00000000..97239c74
--- /dev/null
+++ b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-5.txt
@@ -0,0 +1,3 @@ 
+Functions changes summary: 0 Removed, 0 Changed (3 filtered out), 0 Added functions
+Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+
diff --git a/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v0.c b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v0.c
new file mode 100644
index 00000000..7b32ee8b
--- /dev/null
+++ b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v0.c
@@ -0,0 +1,37 @@ 
+/**
+ * compile this with:
+ *   gcc -g -c test40.1-enumerator-changes-enumerator-changes-v0.c
+ */
+
+enum Enum0
+{
+  ENUM0_E0,
+  ENOM0_LAST
+};
+
+enum Enum1
+{
+  ENUM1_E0,
+  ENUM1_MAX
+};
+
+enum Enum2
+{
+  ENUM2_E0,
+  LAST_ENUM1_ENUMERATOR
+};
+
+void
+fun0(enum Enum0 p __attribute__((unused)))
+{
+}
+
+void
+fun1(enum Enum1 p __attribute__((unused)))
+{
+}
+
+void
+fun2(enum Enum2 p __attribute__((unused)))
+{
+}
diff --git a/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v0.o b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v0.o
new file mode 100644
index 0000000000000000000000000000000000000000..8234f05d0e157a66a88be438cbe4a1f17c2fa01f
GIT binary patch
literal 3944
zcmc&$&2Jl35TEthaf%b?t3XUj<4{o2s$PGP21rTbD3~T9Ng*^65+Cl`UVl(~ZQ1K6
z1OYu26*#mKhaNa0AtVGvAWod%!e0QKI8li!M+69FcIT}(&l?Hl!dUxe<~JX2-rIR^
z{Z4N4*?^*eAO)78rwJ6GdS6e@+F}+?!UXKD-@JG8t-o%)`n{j@2YQA;8Ki&^4G+`c
zrPCfIK=KAY12i~Q*rNgi!7v$JkD+U_hie+YA)A5}dWHrfu@L2>&rwrbaE5XPZr8!~
za|`PE{pk3eexCj8Qk0mxO+8P{7Sq@ZlsQnNry`g;sHoB9nQ&w#xG}Lfqg;$UH8Y@0
z;N&4t2N@XKm<UV)1T|$PrbZc5W@BT@csM(G5F`K4nDSV3BBD-DO%pu&Aa2#85Q!{D
z)F?ohLnD|!(hJ0L&QnSF0N8KBmS}L->LQM?i7bS^=a4Ik@@I6I7_Ao{6sGN^2bAf+
zh?CY13n_5IRn?f%&EhYhVnA;D@>VLpx%%Q2=$f5c#WYIsnrXqM?cMlV`iXctt<7uc
zcqWy3JhhOz5TDyYhjrazLn3oFo@iKI(^#q)rqQkyQPtbU>eBv`3yFpK#9k(zs6cLe
zcPo?6r66Z^8#tnxvQ-q)Jz;D0C7@FB<bXJixt-N3mv^AtH8V7%X>ih{?PM89R+|kY
zS!$MEuO%xrD_O4<^g^wo*XqfZZWXIWCutcStCKA0mTrrQQmtH0bh@op8^|=D($Wb7
zD>K@<)odq<Ro$!@9Y1I<r4|2&8IMyXTv}UOjL+eVJo_KsBDTp%yH&7@4t7A<A62G?
z!h^T4olYT650QPIR->ag0&BwqIdnjbY)_LB=_vavj@j4FranfU9E9Kh=`$dJt?LIP
z?zZ_MyNVV+Qk|Qn&!oaYA4Y%*_6^f#Q{hA(=J?|!<3lP8`Jj{^Zwnt%VZ;X||KUFT
z0wUv{{SkNIBI80Ae1&oG{sn%lvtb`kaZodMZQ^31yxv_El@m_8hgYmk<ID-CXPNZ}
zB%D=vhz05h@7q7;@fS4^l=R><Z<F;U3GcGLCgH3CUByJAe(|PXa9|hzhV{IJzs<TK
z;qS6um+)^{KalV;>(?dxHtQmvsPhxXKVUBQO}zgvq&%Oo{<Y*!`G|gUn7iIDS^tH(
z$j_?V0~Bxn^I*g15&n-bPX6??SwAn~cUezM_^+&AWG>eeXPkP++do+e7wf$$;bPxF
z>%7sh^a66L?eMCQEMwmSjlMvj6*?Wz+D2X1N=Bhu$=A$s6K%Gv7Yc1-?~qw<+h3zY
zSiNQ%A_S)pBEflEFE$$u13%-M*|ZD|zX6Gkr5CSp5~G?gxAlf-JYLUn*%SuSo_fzV
z<;v24B>$BmUoXv|LYRC*zvgxF$a4HF+UR^AH=g=M&PmgW`Tr)xL$WXRA^ktidVEOy
zfj4B7n`#U(@)LKFxbNuRk#iyhFEjWaDISu2>A$axk^4OcQ=V87W#8uz^Q-@7E>y%*
z{b79M`b$1J5rX@9-Bh2K<oW4d^qYT>KdDzanC2%)p1*|{<rH<IXp_P7e<uLuVt&Ej
zMBFcamK$nPI35xI{t@vjv?wI;y>YbO{)@C9qCv>Qhq%e{UW{bf_fy7rxvqPQ<M&;}
z5ybup_+u2vH7fw-Ro?$~)@lDo@DcH%f2kgMZVLI0=fA@R(|4Wz-N^AYjeK?yg6n*K
Yo*~6U^7^SRzxcac|5u(^66N@R0n{#JCIA2c

literal 0
HcmV?d00001

diff --git a/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v1.c b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v1.c
--- /dev/null
+++ b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v1.c
@@ -0,0 +1,40 @@ 
+/**
+ * compile this with:
+ *   gcc -g -c test40.1-enumerator-changes-enumerator-changes-v1.c
+ */
+
+enum Enum0
+{
+  ENUM0_E0,
+  ENUM0_E1,
+  ENOM0_LAST
+};
+
+enum Enum1
+{
+  ENUM1_E0,
+  ENUM1_E1,
+  ENUM1_MAX
+};
+
+enum Enum2
+{
+  ENUM2_E0,
+  ENUM2_E1,
+  LAST_ENUM1_ENUMERATOR
+};
+
+void
+fun0(enum Enum0 p __attribute__((unused)))
+{
+}
+
+void
+fun1(enum Enum1 p __attribute__((unused)))
+{
+}
+
+void
+fun2(enum Enum2 p __attribute__((unused)))
+{
+}
diff --git a/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v1.o b/tests/data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v1.o
new file mode 100644
index 0000000000000000000000000000000000000000..5438d75e9486777259484d9feec98fba7ff0f3f2
GIT binary patch
literal 4064
zcmc&$&2Jl35P$1+oD?@s(o~R;Kx_m}TGi_h(f}z*9R<@w<f94+^Z>YPdt;mW3wxcW
zMF_;9qQIf8IFt_|B)A}PsKh_OhXfZcoH!x%0218b1QJLv^LEDGJZ~hF3uEnjGr#%G
zyxI5VeKo!Eq)*cXizenp$6{27J9l;TlvGpVs2CPoOV@tB_R8Papa0rR3qq<Mq4i-v
z4>tE<<Cgnfh7a|1cmmisRmj$<&nE)@UZk{n{g=FXZNkx8-UL6UIfe}iznb>J7hvgi
zaSZeNZj^=OMZl2K;r#+O@FLGZk33nHHtv)RSceI$af4Vwn-Y3xJP0v<O%KgSdV>-F
z^6+d#I~{y163~VrX^+tR2pC!(_KgVPH?%XOdWb-6a&$;L(wiE&GK&13A?=~ia8REZ
zn?QK*9+<obMKCxY)I&n_QfLtJ2RngK&Pgl@9wFq~NDUkJa<oBER^aIY?g{8MP5Ud<
zj~%`*JfKX-SNCZXz5ypKcpyR(huWq-uC-F|^XU+fURz&{XI2)T-W08Bvs9>B`EaRf
zi}c#oY9h0`a9*5U+X^ox9tkHB#<Y<LC*#S7<1_J7;i(OvE}1qtqRHdoXvJ<-t+|3#
zwHl=ym}VnaoZEeLCOR`6-ARU{1<IR_OC^~>rP``EW?Y&uFenLTItnlo0;|k8g<+fC
zSlC?O5ZkS45}O1zPCAHzq)8Dg)+$ykU(3H(iWN$BtX#^P*;2tQm1A|&&K0d@%(j|#
zGnO}PQ>xK?X?r``Y}M-xfv)Mek%(H5%xai+tr5)?&1%7FdO<r0Blkayc#tZ^*~P`#
z@D!}<@&B-_atFa3<A`=;Luk8$+SuXVzU#2r#sS6$MV_{W(BM_yVt*hF1i;YuI66W0
z^FQafJ^keB>TsX?#qa-gIRJo-?F9qgJ_LLGI(WQ9ckZ1omo5Tb7y`O;|8)6uai|M(
z_;3Yzh%OF$pqL--5)aYEfCq~F{x19!AV*yD!#CtC;cRn%hHzeg#t(En<O$`onv}Ki
zwTF4#v&xktj<ffGWMl1)Adb&G*>_XVIGN&JQgBDOSO0{I&ov+vbKyAd>txR<_#0#|
zD)<eumld2$v7z9+1D;jz@5#0lyiWE-1%Hq1mlPcSxTNeV_zz@XRq)GXzpdaOlYLXc
zKO_5H1^<fd52@$*=Y900!vB`+ZxlYRC(5r*C)XU;<vX%}qn`7V+1^VSFTZ%mF}M$(
z_ZRP<2Juc(&-iV!6AJzl*{7*j>j@K%dk`O%6e*1J`(99Ro;P7MFIQ|c3%%WN`XXz#
zwQCCl|ICDuZ8n9`u*#;9x3aB5rc~XoflumYHrudv_PEW4{A1gLl}lBNLtqG25za_E
zSF2Pk_*gKiHQO@a?<Cr^&D=#wVihyn4YR@<nBM20-53PooVxD_%$33hMEzhwu3I8t
zAg12*FStoAU5%dvAKnuOjmQ0>=EUK6`~k(OnDRprzk*X3<dQ#WLeA5s8Ui2k_)g>V
zkN20F6Vp@(d=m|qsN8elQ!%9fL15e!i>k_f3NWww&*5PP;drbczv9*U^MI*20TPq+
z-dLYoRBi^GUgN(;<6od)93LTd{5oKmlj{Uk$|V~AM+T_p@wtB)aIg4H+E61*+$a96
zed5dbQXu@l<yf7$;<WF8gLUR$|31aLG1OJ=r-ae#w&@>HJpaG2gXfR!Pe4IxiUI2H
z(EKlvjq{IRGaS$R7wb{S#*h)Z+;36A_<ew1NoqU}qn=%W#BDl1PoUuv_5HCfulOmt
Mus?UjqN>LK3)#(YJ^%m!

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
@@ -1836,6 +1836,66 @@  InOutSpec in_out_specs[] =
     "data/test-diff-suppr/test40-enumerator-changes-report-0.txt",
     "output/test-diff-suppr/test40-enumerator-changes-report-0.txt"
   },
+  {
+    "data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v0.o",
+    "data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v1.o",
+    "",
+    "",
+    "",
+    "--no-default-suppression",
+    "data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-0.txt",
+    "output/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-0.txt"
+  },
+  {
+    "data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v0.o",
+    "data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v1.o",
+    "",
+    "",
+    "data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-1.suppr",
+    "--no-default-suppression",
+    "data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-1.txt",
+    "output/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-1.txt"
+  },
+  {
+    "data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v0.o",
+    "data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v1.o",
+    "",
+    "",
+    "data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-2.suppr",
+    "--no-default-suppression",
+    "data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-2.txt",
+    "output/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-2.txt"
+  },
+  {
+    "data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v0.o",
+    "data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v1.o",
+    "",
+    "",
+    "data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-3.suppr",
+    "--no-default-suppression",
+    "data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-3.txt",
+    "output/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-3.txt"
+  },
+  {
+    "data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v0.o",
+    "data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v1.o",
+    "",
+    "",
+    "data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-4.suppr",
+    "--no-default-suppression",
+    "data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-4.txt",
+    "output/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-4.txt"
+  },
+  {
+    "data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v0.o",
+    "data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-v1.o",
+    "",
+    "",
+    "data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-5.suppr",
+    "--no-default-suppression",
+    "data/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-5.txt",
+    "output/test-diff-suppr/test40.1-enumerator-changes-enumerator-changes-report-5.txt"
+  },
   {
     "data/test-diff-suppr/libtest41-enumerator-changes-v0.so",
     "data/test-diff-suppr/libtest41-enumerator-changes-v1.so",