Bug 24139 - Support suppressing some enumerator changes
authorDodji Seketeli <dodji@redhat.com>
Wed, 30 Jan 2019 12:46:29 +0000 (13:46 +0100)
committerDodji Seketeli <dodji@redhat.com>
Thu, 31 Jan 2019 08:20:06 +0000 (09:20 +0100)
This patch teaches the suppression specification subsystem how to
ignore changes of some enumerators in particular.

The patch adds a new property to the [suppress_type] section which is:

    changed_enumerators = enumerator1, enumerator2, etc

This property is taken into accound iff the current suppress_type does
have the 'type_kind = enum' property.

Changes to enum types that match the new 'changed_enumerators'
property are suppressed.

* doc/manuals/libabigail-concepts.rst: Document the new
'changed_enumerators' property.
* include/abg-suppression.h
(type_suppression::{g, s}et_changed_enumerator_names): Declare two
new member functions.
* src/abg-suppression-priv.h
(type_suppression::priv::changed_enumerator_names_): Add a new
data member.
* src/abg-suppression.cc
(type_suppression::{g,s}et_changed_enumerator_names): Define two
new member functions.
(type_suppression::suppresses_diff): Support evaluating the new
'changed_enumerators = <vector of changed enumerators>'.
(read_type_suppression): Read the new list
property'changed_enumerators" and store it into the
type_suppression using the new
type_suppression::set_changed_enumerator_names ().
* tests/data/test-diff-suppr/libtest4{0,1}-enumerator-changes-v{0,1}.so:
Add new test inpujts.
* tests/data/test-diff-suppr/test4{0,1}-enumerator-changes-0.suppr:
Add a new suppr spec for this new test.
* tests/data/test-diff-suppr/test4{0,1}-enumerator-changes-report-0.txt:
The default report.
* tests/data/test-diff-suppr/test4{0,1}-enumerator-changes-v{0,1}.cc:
Add Source code of libtest4{0,1}-enumerator-changes-v{0,1}.so.
* tests/data/Makefile.am: Add the test files above to source
distribution.
* tests/test-diff-suppr.cc: Add the test input files above to the
harness.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
18 files changed:
doc/manuals/libabigail-concepts.rst
include/abg-suppression.h
src/abg-suppression-priv.h
src/abg-suppression.cc
tests/data/Makefile.am
tests/data/test-diff-suppr/libtest40-enumerator-changes-v0.so [new file with mode: 0755]
tests/data/test-diff-suppr/libtest40-enumerator-changes-v1.so [new file with mode: 0755]
tests/data/test-diff-suppr/libtest41-enumerator-changes-v0.so [new file with mode: 0755]
tests/data/test-diff-suppr/libtest41-enumerator-changes-v1.so [new file with mode: 0755]
tests/data/test-diff-suppr/test40-enumerator-changes-0.suppr [new file with mode: 0644]
tests/data/test-diff-suppr/test40-enumerator-changes-report-0.txt [new file with mode: 0644]
tests/data/test-diff-suppr/test40-enumerator-changes-v0.cc [new file with mode: 0644]
tests/data/test-diff-suppr/test40-enumerator-changes-v1.cc [new file with mode: 0644]
tests/data/test-diff-suppr/test41-enumerator-changes-0.suppr [new file with mode: 0644]
tests/data/test-diff-suppr/test41-enumerator-changes-report-0.txt [new file with mode: 0644]
tests/data/test-diff-suppr/test41-enumerator-changes-v0.cc [new file with mode: 0644]
tests/data/test-diff-suppr/test41-enumerator-changes-v1.cc [new file with mode: 0644]
tests/test-diff-suppr.cc

index 9befae4..aeb99aa 100644 (file)
@@ -560,6 +560,22 @@ The potential properties of this sections are listed below:
  string that might be used by a tool to refer to a type suppression in
  error messages.
 
+.. _suppr_changed_enumerators_label:
+
+* ``changed_enumerators``
+
+  Usage:
+
+    ``changed_enumerators`` ``=`` <list-of-enumerators>
+    
+  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`` is a comma-separated list of
+  the enumerators that the user expects to change.  For instance: ::
+
+      changed_enumerators = LAST_ENUMERATORS0, LAST_ENUMERATOR1
+
 ``[suppress_function]``
 $$$$$$$$$$$$$$$$$$$$$$$$
 
index d51e1c3..867970c 100644 (file)
@@ -254,6 +254,12 @@ public:
   void
   set_source_location_to_keep_regex_str(const string&);
 
+  const vector<string>&
+  get_changed_enumerator_names() const;
+
+  void
+  set_changed_enumerator_names(const vector<string>&);
+
   virtual bool
   suppresses_diff(const diff* diff) const;
 
index ec7e1b0..45e6793 100644 (file)
@@ -683,6 +683,7 @@ class type_suppression::priv
   unordered_set<string>                source_locations_to_keep_;
   string                               source_location_to_keep_regex_str_;
   mutable sptr_utils::regex_t_sptr     source_location_to_keep_regex_;
+  mutable vector<string>               changed_enumerator_names_;
 
   priv();
 
index 9f8118d..8544826 100644 (file)
@@ -26,6 +26,8 @@
 /// libabigail.
 
 #include "abg-internal.h"
+#include <algorithm>
+
 // <headers defining libabigail's API go under here>
 ABG_BEGIN_EXPORT_DECLARATIONS
 
@@ -573,6 +575,26 @@ void
 type_suppression::set_source_location_to_keep_regex_str(const string& r)
 {priv_->source_location_to_keep_regex_str_ = r;}
 
+/// Getter of the vector of the 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 changed enumerators that are supposed to
+/// be suppressed.
+const vector<string>&
+type_suppression::get_changed_enumerator_names() const
+{return priv_->changed_enumerator_names_;}
+
+/// Setter of the vector of 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 changed enumerators that are supposed
+/// to be suppressed.
+void
+type_suppression::set_changed_enumerator_names(const vector<string>& n)
+{priv_->changed_enumerator_names_ = n;}
+
 /// Evaluate this suppression specification on a given diff node and
 /// say if the diff node should be suppressed or not.
 ///
@@ -754,6 +776,39 @@ type_suppression::suppresses_diff(const diff* diff) const
        }
     }
 
+  const enum_diff* enum_dif = dynamic_cast<const enum_diff*>(d);
+  if (// We are looking at an enum diff node which ...
+      enum_dif
+      //... carries no deleted enumerator ... "
+      && enum_dif->deleted_enumerators().empty()
+      // ... carries no size change ...
+      && (enum_dif->first_enum()->get_size_in_bits()
+         == enum_dif->second_enum()->get_size_in_bits())
+      // ... 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.
+      bool matched = true;
+      for (string_changed_enumerator_map::const_iterator i =
+            enum_dif->changed_enumerators().begin();
+          i != enum_dif->changed_enumerators().end();
+          ++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 (!matched)
+       return false;
+    }
+
   return true;
 }
 
@@ -1689,6 +1744,30 @@ read_type_suppression(const ini::config::section& section)
        return nil;
     }
 
+  /// Support 'changed_enumerators = foo, bar, baz'
+  ///
+  /// Note that this constraint is valid only if we have:
+  ///   'type_kind = enum'.
+  ///
+  /// If the current type is an enum and if it carries changed
+  /// enumerators listed in the changed_enumerators property value
+  /// then it should be suppressed.
+
+  ini::property_sptr changed_enumerators_prop =
+    section.find_property("changed_enumerators");
+
+  vector<string> changed_enumerator_names;
+  if (changed_enumerators_prop)
+    {
+      if (ini::list_property_sptr p =
+         is_list_property(changed_enumerators_prop))
+       changed_enumerator_names =
+         p->get_value()->get_content();
+      else if (ini::simple_property_sptr p =
+              is_simple_property(changed_enumerators_prop))
+       changed_enumerator_names.push_back(p->get_value()->as_string());
+    }
+
   if (file_name_regex_str.empty()
       && file_name_not_regex_str.empty()
       && soname_regex_str.empty()
@@ -1743,6 +1822,10 @@ read_type_suppression(const ini::config::section& section)
           || !srcloc_not_in.empty())))
     suppr->set_drops_artifact_from_ir(true);
 
+  if (suppr->get_type_kind() == type_suppression::ENUM_TYPE_KIND
+      && !changed_enumerator_names.empty())
+    suppr->set_changed_enumerator_names(changed_enumerator_names);
+
   return suppr;
 }
 
index f9f68d7..56a42d4 100644 (file)
@@ -1169,6 +1169,18 @@ test-diff-suppr/test39-opaque-type-v0.o \
 test-diff-suppr/test39-opaque-type-v1.o \
 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/libtest41-enumerator-changes-v0.so \
+test-diff-suppr/libtest41-enumerator-changes-v1.so \
+test-diff-suppr/test40-enumerator-changes-0.suppr \
+test-diff-suppr/test40-enumerator-changes-report-0.txt \
+test-diff-suppr/test40-enumerator-changes-v0.cc \
+test-diff-suppr/test40-enumerator-changes-v1.cc \
+test-diff-suppr/test41-enumerator-changes-0.suppr \
+test-diff-suppr/test41-enumerator-changes-report-0.txt \
+test-diff-suppr/test41-enumerator-changes-v0.cc \
+test-diff-suppr/test41-enumerator-changes-v1.cc \
 \
 test-diff-dwarf-abixml/test0-pr19026-libvtkIOSQL-6.1.so.1 \
 test-diff-dwarf-abixml/test0-pr19026-libvtkIOSQL-6.1.so.1.abi \
diff --git a/tests/data/test-diff-suppr/libtest40-enumerator-changes-v0.so b/tests/data/test-diff-suppr/libtest40-enumerator-changes-v0.so
new file mode 100755 (executable)
index 0000000..c9486ad
Binary files /dev/null and b/tests/data/test-diff-suppr/libtest40-enumerator-changes-v0.so differ
diff --git a/tests/data/test-diff-suppr/libtest40-enumerator-changes-v1.so b/tests/data/test-diff-suppr/libtest40-enumerator-changes-v1.so
new file mode 100755 (executable)
index 0000000..103013d
Binary files /dev/null and b/tests/data/test-diff-suppr/libtest40-enumerator-changes-v1.so differ
diff --git a/tests/data/test-diff-suppr/libtest41-enumerator-changes-v0.so b/tests/data/test-diff-suppr/libtest41-enumerator-changes-v0.so
new file mode 100755 (executable)
index 0000000..8ae3c14
Binary files /dev/null and b/tests/data/test-diff-suppr/libtest41-enumerator-changes-v0.so differ
diff --git a/tests/data/test-diff-suppr/libtest41-enumerator-changes-v1.so b/tests/data/test-diff-suppr/libtest41-enumerator-changes-v1.so
new file mode 100755 (executable)
index 0000000..27a5af8
Binary files /dev/null and b/tests/data/test-diff-suppr/libtest41-enumerator-changes-v1.so differ
diff --git a/tests/data/test-diff-suppr/test40-enumerator-changes-0.suppr b/tests/data/test-diff-suppr/test40-enumerator-changes-0.suppr
new file mode 100644 (file)
index 0000000..0cd6d71
--- /dev/null
@@ -0,0 +1,3 @@
+[suppress_type]
+ type_kind = enum
+ changed_enumerators = enum_count
diff --git a/tests/data/test-diff-suppr/test40-enumerator-changes-report-0.txt b/tests/data/test-diff-suppr/test40-enumerator-changes-report-0.txt
new file mode 100644 (file)
index 0000000..9666a8f
--- /dev/null
@@ -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-diff-suppr/test40-enumerator-changes-v0.cc b/tests/data/test-diff-suppr/test40-enumerator-changes-v0.cc
new file mode 100644 (file)
index 0000000..0913d33
--- /dev/null
@@ -0,0 +1,11 @@
+enum EnumType
+{
+  e0,
+  e1,
+  e2,
+  enum_count
+};
+
+void
+foo(EnumType)
+{}
diff --git a/tests/data/test-diff-suppr/test40-enumerator-changes-v1.cc b/tests/data/test-diff-suppr/test40-enumerator-changes-v1.cc
new file mode 100644 (file)
index 0000000..523b452
--- /dev/null
@@ -0,0 +1,13 @@
+enum EnumType
+{
+  e0,
+  e1,
+  e2,
+  e3,
+  e4,
+  enum_count
+};
+
+void
+foo(EnumType)
+{}
diff --git a/tests/data/test-diff-suppr/test41-enumerator-changes-0.suppr b/tests/data/test-diff-suppr/test41-enumerator-changes-0.suppr
new file mode 100644 (file)
index 0000000..e6bdf77
--- /dev/null
@@ -0,0 +1,4 @@
+[suppress_type]
+ type_kind = enum
+ name = EnumType1
+ changed_enumerators = enum_count
\ No newline at end of file
diff --git a/tests/data/test-diff-suppr/test41-enumerator-changes-report-0.txt b/tests/data/test-diff-suppr/test41-enumerator-changes-report-0.txt
new file mode 100644 (file)
index 0000000..57399c5
--- /dev/null
@@ -0,0 +1,26 @@
+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:
+
+  [C]'function void bar(EnumType1)' at test41-enumerator-changes-v1.cc:24:1 has some indirect sub-type changes:
+    parameter 1 of type 'enum EnumType1' has sub-type changes:
+      type size hasn't changed
+      1 enumerator insertion:
+        'EnumType1::ee3_inserted' value '3'
+
+      1 enumerator change:
+        'EnumType1::eenum_count' from value '3' to '4' at test41-enumerator-changes-v1.cc:10:1
+
+
+  [C]'function void foo(EnumType0)' at test41-enumerator-changes-v1.cc:20:1 has some indirect sub-type changes:
+    parameter 1 of type 'enum EnumType0' has sub-type changes:
+      type size hasn't changed
+      1 enumerator insertion:
+        'EnumType0::e3_inserted' value '3'
+
+      1 enumerator change:
+        'EnumType0::enum_count' from value '3' to '4' at test41-enumerator-changes-v1.cc:1:1
+
+
+
diff --git a/tests/data/test-diff-suppr/test41-enumerator-changes-v0.cc b/tests/data/test-diff-suppr/test41-enumerator-changes-v0.cc
new file mode 100644 (file)
index 0000000..d1bac83
--- /dev/null
@@ -0,0 +1,23 @@
+enum EnumType0
+{
+  e0,
+  e1,
+  e2,
+  enum_count
+};
+
+enum EnumType1
+{
+  ee0,
+  ee1,
+  ee2,
+  eenum_count
+};
+
+void
+foo(EnumType0)
+{}
+
+void
+bar(EnumType1)
+{}
diff --git a/tests/data/test-diff-suppr/test41-enumerator-changes-v1.cc b/tests/data/test-diff-suppr/test41-enumerator-changes-v1.cc
new file mode 100644 (file)
index 0000000..1c83d16
--- /dev/null
@@ -0,0 +1,25 @@
+enum EnumType0
+{
+  e0,
+  e1,
+  e2,
+  e3_inserted,
+  enum_count
+};
+
+enum EnumType1
+{
+  ee0,
+  ee1,
+  ee2,
+  ee3_inserted,
+  eenum_count
+};
+
+void
+foo(EnumType0)
+{}
+
+void
+bar(EnumType1)
+{}
index f38bfcd..8cbb8b7 100644 (file)
@@ -1728,6 +1728,26 @@ InOutSpec in_out_specs[] =
     "data/test-diff-suppr/test39-opaque-type-report-0.txt",
     "output/test-diff-suppr/test39-opaque-type-report-0.txt"
   },
+  {
+    "data/test-diff-suppr/libtest40-enumerator-changes-v0.so",
+    "data/test-diff-suppr/libtest40-enumerator-changes-v1.so",
+    "",
+    "",
+    "data/test-diff-suppr/test40-enumerator-changes-0.suppr",
+    "--no-default-suppression",
+    "data/test-diff-suppr/test40-enumerator-changes-report-0.txt",
+    "output/test-diff-suppr/test40-enumerator-changes-report-0.txt"
+  },
+  {
+    "data/test-diff-suppr/libtest41-enumerator-changes-v0.so",
+    "data/test-diff-suppr/libtest41-enumerator-changes-v1.so",
+    "",
+    "",
+    "data/test-diff-suppr/test41-enumerator-changes-0.suppr",
+    "--no-default-suppression",
+    "data/test-diff-suppr/test41-enumerator-changes-report-0.txt",
+    "output/test-diff-suppr/test41-enumerator-changes-report-0.txt"
+  },
   // This should be the last entry
   {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
 };