Support the "name_not_regexp" property in the [suppress_type] section
authorDodji Seketeli <dodji@redhat.com>
Wed, 4 Sep 2019 08:36:31 +0000 (10:36 +0200)
committerDodji Seketeli <dodji@redhat.com>
Mon, 30 Sep 2019 12:56:52 +0000 (14:56 +0200)
When writting a suppression specification in which the user wants to
keep a family of types (whose names set is specified by a regular
expression) and suppress/drop all other types, one needs to write
something like:

[suppress_type]
  name_regexp = (?!the-regexp-of-the-types-to-keep)

It would be nicer (like what is done for other properties that take
regular expressions as value in suppression specifications) to be able
to write:

[suppress_type]
  name_not_regexp = the-regexp-of-types-to-keep

This patch does just that.

It augments the abigail::suppr::type_suppression type to make it carry
the new 'name_not_regex' property.  It updates the suppression engine
to take the 'name_not_regex' property into account when interpreting
instances of abigail::suppr::type_suppression.  The parser for type
suppression directives is updated to recognize the new name_not_regexp
property.  The manual has been updated accordingly to describe the new
property.  New regression tests have been added.

* doc/manuals/libabigail-concepts.rst: Update this to document the
new name_not_regexp property of the suppress_type directive.
* include/abg-suppression.h
(type_suppression::{g,s}et_type_name_not_regex_str): Declare new accessors.
* src/abg-suppression-priv.h
(type_suppression::priv::{type_name_not_regex_str_,
type_name_not_regex_}): Define new data members.
(type_suppression::priv::{get_type_name_not_regex,
set_type_name_not_regex, get_type_name_not_regex_str,
set_type_name_not_regex_str}): Define new member functions.
* src/abg-suppression.cc
(type_suppression::get_type_name_regex_str): Fix comments.
(type_suppression::{set_type_name_not_regex_str,
get_type_name_not_regex_str}): Define new data members.
(suppression_matches_type_name): Adapt to support the new
type_name_not_regex property.
(read_type_suppression): Support parsing the type_name_not_regexp
property.
* tests/data/test-diff-suppr/test42-negative-suppr-type-report-0.txt:
New test reference output.
* tests/data/test-diff-suppr/test42-negative-suppr-type-report-1.txt: Likewise.
* tests/data/test-diff-suppr/test42-negative-suppr-type-suppr-1.txt:
New test input.
* tests/data/test-diff-suppr/test42-negative-suppr-type-suppr-2.txt: Likewise.
* tests/data/test-diff-suppr/test42-negative-suppr-type-v0.{cc, o}: Likewise.
* tests/data/test-diff-suppr/test42-negative-suppr-type-v1.{cc,
o}: Likewise.
* tests/data/Makefile.am: Add the test files above to source
distribution.
* tests/test-diff-suppr.cc (int_out_specs): Add the new tests to
the harness.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
14 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/test42-negative-suppr-type-report-0.txt [new file with mode: 0644]
tests/data/test-diff-suppr/test42-negative-suppr-type-report-1.txt [new file with mode: 0644]
tests/data/test-diff-suppr/test42-negative-suppr-type-suppr-1.txt [new file with mode: 0644]
tests/data/test-diff-suppr/test42-negative-suppr-type-suppr-2.txt [new file with mode: 0644]
tests/data/test-diff-suppr/test42-negative-suppr-type-v0.cc [new file with mode: 0644]
tests/data/test-diff-suppr/test42-negative-suppr-type-v0.o [new file with mode: 0644]
tests/data/test-diff-suppr/test42-negative-suppr-type-v1.cc [new file with mode: 0644]
tests/data/test-diff-suppr/test42-negative-suppr-type-v1.o [new file with mode: 0644]
tests/test-diff-suppr.cc

index aeb99aa..a1835d1 100644 (file)
@@ -247,8 +247,9 @@ Note that for the ``[suppress_type]`` directive to work, at least one
 of the following properties must be provided:
 
   ``file_name_regexp``, ``file_name_not_regexp``, ``soname_regexp``,
-  ``soname_not_regexp``, ``name``, ``name_regexp``, ``type_kind``,
-  ``source_location_not_in``, ``source_location_not_regexp``.
+  ``soname_not_regexp``, ``name``, ``name_regexp``,
+  ``name_not_regexp``, ``type_kind``, ``source_location_not_in``,
+  ``source_location_not_regexp``.
 
 If none of the following properties are provided, then the
 ``[suppress_type]`` directive is simply ignored.
@@ -305,6 +306,18 @@ The potential properties of this sections are listed below:
  Suppresses change reports involving types whose name matches the
  regular expression specified as value of this property.
 
+
+* ``name_not_regexp``
+
+ Usage:
+
+   ``name_not_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>
+
+ Suppresses change reports involving types whose name does *NOT* match
+ the regular expression specified as value of this property.  Said
+ otherwise, this property specifies which types to keep, rather than
+ types to suppress from reports.
+
 * ``name``
 
  Usage:
index 415e74f..47dac5a 100644 (file)
@@ -201,6 +201,12 @@ public:
   get_type_name_regex_str() const;
 
   void
+  set_type_name_not_regex_str(const string& name_regex_str);
+
+  const string&
+  get_type_name_not_regex_str() const;
+
+  void
   set_type_name(const string& name);
 
   const string&
index f157c35..07e1718 100644 (file)
@@ -675,6 +675,8 @@ class type_suppression::priv
   string                               type_name_regex_str_;
   mutable sptr_utils::regex_t_sptr     type_name_regex_;
   string                               type_name_;
+  string                               type_name_not_regex_str_;
+  mutable sptr_utils::regex_t_sptr     type_name_not_regex_;
   bool                                 consider_type_kind_;
   type_suppression::type_kind          type_kind_;
   bool                                 consider_reach_kind_;
@@ -734,6 +736,56 @@ public:
   set_type_name_regex(sptr_utils::regex_t_sptr r)
   {type_name_regex_ = r;}
 
+  /// Get the regular expression object associated to the
+  /// 'type_name_not_regex' property of @ref type_suppression.
+  ///
+  /// If the regular expression object is not created, this method
+  /// creates it and returns it.
+  ///
+  /// If the 'type_name_not_regex' property of @ref type_suppression is
+  /// empty then this method returns nil.
+  const sptr_utils::regex_t_sptr
+  get_type_name_not_regex() const
+  {
+    if (!type_name_not_regex_)
+      {
+       if (!type_name_not_regex_str_.empty())
+         {
+           sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+           if (regcomp(r.get(),
+                       type_name_not_regex_str_.c_str(),
+                       REG_EXTENDED) == 0)
+             type_name_not_regex_ = r;
+         }
+      }
+    return type_name_not_regex_;
+  }
+
+  /// Setter for the type_name_not_regex object.
+  ///
+  /// @param r the new type_name_not_regex object.
+  void
+  set_type_name_not_regex(sptr_utils::regex_t_sptr r)
+  {type_name_not_regex_ = r;}
+
+  /// Getter for the string that denotes the 'type_name_not_regex'
+  /// property.
+  ///
+  /// @return the value of the string value of the
+  /// 'type_name_not_regex' property.
+  const string&
+  get_type_name_not_regex_str() const
+  {return type_name_not_regex_str_;}
+
+  /// Setter for the string that denotes the 'type_name_not_regex'
+  /// property.
+  ///
+  /// @return the value of the string value of the
+  /// 'type_name_not_regex' property.
+  void
+  set_type_name_not_regex_str(const string regex_str)
+  {type_name_not_regex_str_ = regex_str;}
+
   /// Getter for the source_location_to_keep_regex object.
   ///
   /// This function builds the regex if it's not yet built.
index e410d36..1c10c8e 100644 (file)
@@ -406,14 +406,36 @@ type_suppression::set_type_name_regex_str(const string& name_regex_str)
 /// Getter for the "type_name_regex" property of the type suppression
 /// specification.
 ///
-/// This returns a regular expression that specifies the family of
-/// types about which diff reports should be suppressed.
+/// This returns a regular expression string that specifies the family
+/// of types about which diff reports should be suppressed.
 ///
-/// @return the regular expression.
+/// @return the regular expression string.
 const string&
 type_suppression::get_type_name_regex_str() const
 {return priv_->type_name_regex_str_;}
 
+/// Setter for the "type_name_not_regex_str" property of the type
+/// suppression specification.
+///
+/// This returns a regular expression string that specifies the family
+/// of types that should be kept after suppression.
+///
+/// @param r the new regexp string.
+void
+type_suppression::set_type_name_not_regex_str(const string& r)
+{priv_->set_type_name_not_regex_str(r);}
+
+/// Getter for the "type_name_not_regex_str" property of the type
+/// suppression specification.
+///
+/// This returns a regular expression string that specifies the family
+/// of types that should be kept after suppression.
+///
+/// @return the new regexp string.
+const string&
+type_suppression::get_type_name_not_regex_str() const
+{return priv_->get_type_name_not_regex_str();}
+
 /// Setter for the name of the type about which diff reports should be
 /// suppressed.
 ///
@@ -921,7 +943,9 @@ bool
 suppression_matches_type_name(const type_suppression&  s,
                              const string&             type_name)
 {
-  if (!s.get_type_name().empty() || s.priv_->get_type_name_regex())
+  if (!s.get_type_name().empty()
+      || s.priv_->get_type_name_regex()
+      || s.priv_->get_type_name_not_regex())
     {
       // Check if there is an exact type name match.
       if (!s.get_type_name().empty())
@@ -936,12 +960,23 @@ suppression_matches_type_name(const type_suppression&     s,
          // If the qualified name of the considered type doesn't match
          // the regular expression of the type name, then this
          // suppression doesn't apply.
-         const sptr_utils::regex_t_sptr& type_name_regex =
-           s.priv_->get_type_name_regex();
-         if (type_name_regex && (regexec(type_name_regex.get(),
-                                         type_name.c_str(),
-                                         0, NULL, 0) != 0))
-           return false;
+         if (const sptr_utils::regex_t_sptr& type_name_regex =
+             s.priv_->get_type_name_regex())
+           {
+             if (regexec(type_name_regex.get(),
+                         type_name.c_str(),
+                         0, NULL, 0) != 0)
+               return false;
+           }
+
+         if (const sptr_utils::regex_t_sptr type_name_not_regex =
+             s.priv_->get_type_name_not_regex())
+           {
+             if (regexec(type_name_not_regex.get(),
+                         type_name.c_str(),
+                         0, NULL, 0) == 0)
+               return false;
+           }
        }
     }
 
@@ -1530,6 +1565,12 @@ read_type_suppression(const ini::config::section& section)
     ? name_regex_prop->get_value()->as_string()
     : "";
 
+  ini::simple_property_sptr name_not_regex_prop =
+    is_simple_property(section.find_property("name_not_regexp"));
+  string name_not_regex_str = name_not_regex_prop
+    ? name_not_regex_prop->get_value()->as_string()
+    : "";
+
   ini::simple_property_sptr name_prop =
     is_simple_property(section.find_property("name"));
   string name_str = name_prop
@@ -1774,6 +1815,8 @@ read_type_suppression(const ini::config::section& section)
       && soname_regex_str.empty()
       && soname_not_regex_str.empty()
       && (!name_regex_prop || name_regex_prop->get_value()->as_string().empty())
+      && (!name_not_regex_prop
+         || name_not_regex_prop->get_value()->as_string().empty())
       && (!name_prop || name_prop->get_value()->as_string().empty())
       && !consider_type_kind
       && srcloc_not_regexp_str.empty()
@@ -1798,6 +1841,9 @@ read_type_suppression(const ini::config::section& section)
   if (consider_data_member_insertion)
     suppr->set_data_member_insertion_ranges(insert_ranges);
 
+  if (!name_not_regex_str.empty())
+    suppr->set_type_name_not_regex_str(name_not_regex_str);
+
   if (!file_name_regex_str.empty())
     suppr->set_file_name_regex_str(file_name_regex_str);
 
index 57551db..70b290a 100644 (file)
@@ -1205,6 +1205,14 @@ 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-suppr/test42-negative-suppr-type-report-0.txt \
+test-diff-suppr/test42-negative-suppr-type-report-1.txt \
+test-diff-suppr/test42-negative-suppr-type-suppr-1.txt \
+test-diff-suppr/test42-negative-suppr-type-suppr-2.txt \
+test-diff-suppr/test42-negative-suppr-type-v0.cc \
+test-diff-suppr/test42-negative-suppr-type-v0.o \
+test-diff-suppr/test42-negative-suppr-type-v1.cc \
+test-diff-suppr/test42-negative-suppr-type-v1.o \
 test-diff-suppr/test43-suppr-direct-fn-subtype-suppr-1.txt \
 test-diff-suppr/test43-suppr-direct-fn-subtype-v0.cc \
 test-diff-suppr/test43-suppr-direct-fn-subtype-v0.o \
diff --git a/tests/data/test-diff-suppr/test42-negative-suppr-type-report-0.txt b/tests/data/test-diff-suppr/test42-negative-suppr-type-report-0.txt
new file mode 100644 (file)
index 0000000..a73ca07
--- /dev/null
@@ -0,0 +1,12 @@
+Functions changes summary: 0 Removed, 1 Changed (1 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 func0(type_to_keep)' at test42-negative-suppr-type-v1.cc:15:1 has some indirect sub-type changes:
+    parameter 1 of type 'struct type_to_keep' has sub-type changes:
+      type size changed from 32 to 64 (in bits)
+      1 data member insertion:
+        'char type_to_keep::m1', at offset 32 (in bits) at test42-negative-suppr-type-v1.cc:4:1
+
+
diff --git a/tests/data/test-diff-suppr/test42-negative-suppr-type-report-1.txt b/tests/data/test-diff-suppr/test42-negative-suppr-type-report-1.txt
new file mode 100644 (file)
index 0000000..a73ca07
--- /dev/null
@@ -0,0 +1,12 @@
+Functions changes summary: 0 Removed, 1 Changed (1 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 func0(type_to_keep)' at test42-negative-suppr-type-v1.cc:15:1 has some indirect sub-type changes:
+    parameter 1 of type 'struct type_to_keep' has sub-type changes:
+      type size changed from 32 to 64 (in bits)
+      1 data member insertion:
+        'char type_to_keep::m1', at offset 32 (in bits) at test42-negative-suppr-type-v1.cc:4:1
+
+
diff --git a/tests/data/test-diff-suppr/test42-negative-suppr-type-suppr-1.txt b/tests/data/test-diff-suppr/test42-negative-suppr-type-suppr-1.txt
new file mode 100644 (file)
index 0000000..93a8696
--- /dev/null
@@ -0,0 +1,3 @@
+[suppress_type]
+  name_not_regexp = type_to_keep
+
diff --git a/tests/data/test-diff-suppr/test42-negative-suppr-type-suppr-2.txt b/tests/data/test-diff-suppr/test42-negative-suppr-type-suppr-2.txt
new file mode 100644 (file)
index 0000000..aa6f67a
--- /dev/null
@@ -0,0 +1,2 @@
+[suppress_type]
+  name_regexp = type_to_suppress
diff --git a/tests/data/test-diff-suppr/test42-negative-suppr-type-v0.cc b/tests/data/test-diff-suppr/test42-negative-suppr-type-v0.cc
new file mode 100644 (file)
index 0000000..9469133
--- /dev/null
@@ -0,0 +1,20 @@
+struct type_to_keep
+{
+  int m0;
+};
+
+struct type_to_suppress
+{
+  int m0;
+};
+
+
+void
+func0(struct type_to_keep)
+{
+}
+
+void
+func1(struct type_to_suppress)
+{
+}
diff --git a/tests/data/test-diff-suppr/test42-negative-suppr-type-v0.o b/tests/data/test-diff-suppr/test42-negative-suppr-type-v0.o
new file mode 100644 (file)
index 0000000..a40c62f
Binary files /dev/null and b/tests/data/test-diff-suppr/test42-negative-suppr-type-v0.o differ
diff --git a/tests/data/test-diff-suppr/test42-negative-suppr-type-v1.cc b/tests/data/test-diff-suppr/test42-negative-suppr-type-v1.cc
new file mode 100644 (file)
index 0000000..bd18e5d
--- /dev/null
@@ -0,0 +1,22 @@
+struct type_to_keep
+{
+  int m0;
+  char m1;
+};
+
+struct type_to_suppress
+{
+  int m0;
+  char m1;
+};
+
+
+void
+func0(struct type_to_keep)
+{
+}
+
+void
+func1(struct type_to_suppress)
+{
+}
diff --git a/tests/data/test-diff-suppr/test42-negative-suppr-type-v1.o b/tests/data/test-diff-suppr/test42-negative-suppr-type-v1.o
new file mode 100644 (file)
index 0000000..6769db8
Binary files /dev/null and b/tests/data/test-diff-suppr/test42-negative-suppr-type-v1.o differ
index dfc8288..55f8f85 100644 (file)
@@ -1749,6 +1749,26 @@ InOutSpec in_out_specs[] =
     "output/test-diff-suppr/test41-enumerator-changes-report-0.txt"
   },
   {
+    "data/test-diff-suppr/test42-negative-suppr-type-v0.o",
+    "data/test-diff-suppr/test42-negative-suppr-type-v1.o",
+    "",
+    "",
+    "data/test-diff-suppr/test42-negative-suppr-type-suppr-1.txt",
+    "--no-default-suppression",
+    "data/test-diff-suppr/test42-negative-suppr-type-report-0.txt",
+    "output/test-diff-suppr/test42-negative-suppr-type-report-0.txt"
+  },
+  {
+    "data/test-diff-suppr/test42-negative-suppr-type-v0.o",
+    "data/test-diff-suppr/test42-negative-suppr-type-v1.o",
+    "",
+    "",
+    "data/test-diff-suppr/test42-negative-suppr-type-suppr-2.txt",
+    "--no-default-suppression",
+    "data/test-diff-suppr/test42-negative-suppr-type-report-1.txt",
+    "output/test-diff-suppr/test42-negative-suppr-type-report-1.txt"
+  },
+  {
     "data/test-diff-suppr/test43-suppr-direct-fn-subtype-v0.o",
     "data/test-diff-suppr/test43-suppr-direct-fn-subtype-v1.o",
     "",