public inbox for libabigail@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 00/21] Simplify regex and suppression parsing.
@ 2020-04-23 15:44 Giuliano Procida
  2020-04-23 15:44 ` [PATCH 01/21] Move regex definitions to own files Giuliano Procida
                   ` (22 more replies)
  0 siblings, 23 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-23 15:44 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

This patch series takes the suppression parsing very close to where it
can be translated into a table-driven format. It is mostly a series of
simplifications which are useful in their own right. I have tried to
keep each commit doing exactly one thing, to make reviewing easier.

These changes are not pure refactorings:

Escape names used in symbol whitelisting regex.
diff suppression: Fix handling of change kinds
abg-tools-utils.cc: Assert generated regexes OK.
Warn if user-supplied regexes fail to compile.

The rest should be.

Regards,
Giuliano.

Giuliano Procida (21):
  Move regex definitions to own files.
  Move libxml bits out of abg-sptr-utils.h.
  Simplify generation of symbol whitelist regex.
  Escape names used in symbol whitelisting regex.
  abg-suppression.cc: More uniform variable naming.
  diff suppression: Fix handling of change kinds.
  Add POSIX regex wrapper functions.
  Use regex::compile wrapper instead of regcomp.
  Use regex::match wrapper instead of regexec.
  Refactor read_parameter_spec_from_string logic.
  Compile suppression regexes earlier.
  Reduce direct access to suppression priv_ members.
  Move match methods from priv to suppression_base.
  Remove suppression types' priv class methods.
  abg-suppression.cc: More consistent regex matching.
  abg-tools-utils.cc: Assert generated regexes OK.
  Refactor suppression property string parsing.
  Refactor suppression property regex parsing.
  Warn if user-supplied regexes fail to compile.
  Default construct suppression types.
  Remove unused suppression type priv constructors.

 include/Makefile.am                           |    3 +-
 include/abg-libxml-utils.h                    |   21 +-
 src/abg-sptr-utils.cc => include/abg-regex.h  |   71 +-
 include/abg-sptr-utils.h                      |   66 +-
 include/abg-suppression.h                     |  182 +-
 src/Makefile.am                               |    2 +-
 src/abg-corpus-priv.h                         |   35 +-
 src/abg-corpus.cc                             |    2 +-
 src/abg-dwarf-reader.cc                       |    4 +-
 src/abg-reader.cc                             |    4 +-
 src/abg-regex.cc                              |  134 ++
 src/abg-suppression-priv.h                    |  723 +-------
 src/abg-suppression.cc                        | 1527 +++++++----------
 src/abg-tools-utils.cc                        |   26 +-
 .../test15-suppr-added-fn-report-5.txt        |    6 +-
 .../test16-suppr-removed-fn-report-5.txt      |   15 +-
 .../test17-suppr-added-var-report-5.txt       |   15 +-
 .../test18-suppr-removed-var-report-5.txt     |   15 +-
 tests/test-kmi-whitelist.cc                   |   70 +-
 19 files changed, 1017 insertions(+), 1904 deletions(-)
 rename src/abg-sptr-utils.cc => include/abg-regex.h (50%)
 create mode 100644 src/abg-regex.cc

-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH 01/21] Move regex definitions to own files.
  2020-04-23 15:44 [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
@ 2020-04-23 15:44 ` Giuliano Procida
  2020-04-23 15:44 ` [PATCH 02/21] Move libxml bits out of abg-sptr-utils.h Giuliano Procida
                   ` (21 subsequent siblings)
  22 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-23 15:44 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

As a prelude to adding wrapper and helper functions for regex
functionality, it makes sense to move the existing regex code (the
shared pointer type and its specialised deleter) to their own files.

This patch does this and also moves various entities into a new
namespace, abigail::regex. It removes the file abg-sptr-utils.cc which
only contained regex things.

There are no behavioural changes.

	* include/Makefile.am: Add abg-regex.h.
	* src/Makefile.am: Remove abg-sptr-utils.h, add abg-regex.cc
	* include/abg-sptr-utils.h (regex_t_sptr): Remove this
	typedef, from namespace abigail::sptr_utils.
	(regex_t_deleter): Remove this struct, from namespace
	abigail::sptr_utils. (build_sptr): Remove these template
	specialisations, in duplicate, for regex_t_sptr.
	* include/abg-regex.h: New file, introduces namespace
	abigail::regex. (regex_t_sptr): Add this typedef, to namespace
	abigail::regex. (regex_t_deleter): Add this struct, to
	namespace abigail::regex. (build_sptr): Add these template
	specialisations for regex_t_sptr
	* src/abg-sptr-utils.cc: Remove this file.
	* src/abg-regex.cc: Add new file with contents effectively
	the same as abg-sptr-utils.cc.
	* src/abg-corpus-priv.h: Update regex_t_sptr namespace
	qualification.
	* src/abg-corpus.cc: Ditto.
	* src/abg-suppression-priv.h: Ditto.
	* src/abg-suppression.cc: Ditto.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 include/Makefile.am                     |   3 +-
 include/abg-regex.h                     |  83 ++++++++++++++
 include/abg-sptr-utils.h                |  49 ---------
 src/Makefile.am                         |   2 +-
 src/abg-corpus-priv.h                   |   3 +-
 src/abg-corpus.cc                       |   2 +-
 src/{abg-sptr-utils.cc => abg-regex.cc} |  19 ++--
 src/abg-suppression-priv.h              | 137 ++++++++++++------------
 src/abg-suppression.cc                  |  73 ++++++-------
 9 files changed, 198 insertions(+), 173 deletions(-)
 create mode 100644 include/abg-regex.h
 rename src/{abg-sptr-utils.cc => abg-regex.cc} (84%)

diff --git a/include/Makefile.am b/include/Makefile.am
index ae97f674..b5475252 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -24,6 +24,7 @@ abg-cxx-compat.h	\
 abg-version.h		\
 abg-viz-common.h	\
 abg-viz-dot.h		\
-abg-viz-svg.h		
+abg-viz-svg.h		\
+abg-regex.h
 
 EXTRA_DIST = abg-version.h.in
diff --git a/include/abg-regex.h b/include/abg-regex.h
new file mode 100644
index 00000000..84c386a9
--- /dev/null
+++ b/include/abg-regex.h
@@ -0,0 +1,83 @@
+// -*- mode: C++ -*-
+//
+// Copyright (C) 2013-2020 Red Hat, Inc.
+//
+// This file is part of the GNU Application Binary Interface Generic
+// Analysis and Instrumentation Library (libabigail).  This library is
+// free software; you can redistribute it and/or modify it under the
+// terms of the GNU Lesser General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option) any
+// later version.
+
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Lesser Public License for more details.
+
+// You should have received a copy of the GNU Lesser General Public
+// License along with this program; see the file COPYING-LGPLV3.  If
+// not, see <http://www.gnu.org/licenses/>.
+
+/// @file
+///
+/// Wrappers around regex types and functions.
+
+#ifndef __ABG_REGEX_H__
+#define __ABG_REGEX_H__
+
+#include <regex.h>
+
+#include "abg-cxx-compat.h"
+#include "abg-sptr-utils.h"
+
+namespace abigail
+{
+
+/// Namespace for regex types and functions.
+namespace regex
+{
+
+/// A convenience typedef for a shared pointer of regex_t.
+typedef abg_compat::shared_ptr<regex_t> regex_t_sptr;
+
+/// A delete functor for a shared_ptr of regex_t.
+struct regex_t_deleter
+{
+  /// The operator called to de-allocate the pointer to regex_t
+  /// embedded in a shared_ptr<regex_t>
+  ///
+  /// @param r the pointer to regex_t to de-allocate.
+  void
+  operator()(::regex_t* r)
+  {
+    regfree(r);
+    delete r;
+  }
+};//end struct regex_deleter
+
+}// end namespace regex
+
+/// Specialization of sptr_utils::build_sptr for regex_t.
+///
+/// This is used to wrap a pointer to regex_t into a
+/// shared_ptr<regex_t>.
+///
+/// @param p the bare pointer to regex_t to wrap into a shared_ptr<regex_t>.
+///
+/// @return the shared_ptr<regex_t> that wraps @p p.
+template<>
+regex::regex_t_sptr
+sptr_utils::build_sptr<regex_t>(regex_t *p);
+
+/// Specialization of sptr_utils::build_sptr for regex_t.
+///
+/// This creates a pointer to regex_t and wraps it into a shared_ptr<regex_t>.
+///
+/// @return the shared_ptr<regex_t> wrapping the newly created regex_t*
+template<>
+regex::regex_t_sptr
+sptr_utils::build_sptr<regex_t>();
+
+}// end namespace abigail
+
+#endif //__ABG_REGEX_H__
diff --git a/include/abg-sptr-utils.h b/include/abg-sptr-utils.h
index 0adedbb3..9737fe5f 100644
--- a/include/abg-sptr-utils.h
+++ b/include/abg-sptr-utils.h
@@ -78,19 +78,6 @@ typedef shared_ptr<xmlChar> xml_char_sptr;
 template<>
 xml_char_sptr build_sptr<xmlChar>(xmlChar *p);
 
-/// A convenience typedef for a shared pointer of regex_t.
-typedef shared_ptr<regex_t> regex_t_sptr;
-
-/// Specialization of sptr_utils::build_sptr for regex_t.
-template<>
-regex_t_sptr
-build_sptr<regex_t>(regex_t *p);
-
-/// Specialization of sptr_utils::build_sptr for regex_t.
-template<>
-regex_t_sptr
-build_sptr<regex_t>();
-
 /// A deleter for shared pointers that ... doesn't delete the object
 /// managed by the shared pointer.
 struct noop_deleter
@@ -101,42 +88,6 @@ struct noop_deleter
   {}
 };
 
-/// A delete functor for a shared_ptr of regex_t.
-struct regex_t_deleter
-{
-  /// The operator called to de-allocate the pointer to regex_t
-  /// embedded in a shared_ptr<regex_t>
-  ///
-  /// @param r the pointer to regex_t to de-allocate.
-  void
-  operator()(::regex_t* r)
-  {
-    regfree(r);
-    delete r;
-  }
-};//end struct regex_deleter
-
-/// Specialization of sptr_utils::build_sptr for regex_t.
-///
-/// This is used to wrap a pointer to regex_t into a
-/// shared_ptr<regex_t>.
-///
-/// @param p the bare pointer to regex_t to wrap into a shared_ptr<regex_t>.
-///
-/// @return the shared_ptr<regex_t> that wraps @p p.
-template<>
-regex_t_sptr
-build_sptr<regex_t>(regex_t *p);
-
-/// Specialization of sptr_utils::build_sptr for regex_t.
-///
-/// This creates a pointer to regex_t and wraps it into a shared_ptr<regex_t>.
-///
-/// @return the shared_ptr<regex_t> wrapping the newly created regex_t*
-template<>
-regex_t_sptr
-build_sptr<regex_t>();
-
 }// end namespace sptr_utils
 }// end namespace abigail
 
diff --git a/src/Makefile.am b/src/Makefile.am
index fafab853..1153a5f8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -13,7 +13,6 @@ endif
 
 libabigail_la_SOURCES =			\
 abg-internal.h				\
-abg-sptr-utils.cc			\
 abg-traverse.cc				\
 abg-ir-priv.h				\
 abg-ir.cc				\
@@ -41,6 +40,7 @@ abg-workers.cc				\
 abg-tools-utils.cc			\
 abg-elf-helpers.h			\
 abg-elf-helpers.cc			\
+abg-regex.cc				\
 $(CXX11_SOURCES)
 
 libabigail_la_LIBADD = $(DEPS_LIBS)
diff --git a/src/abg-corpus-priv.h b/src/abg-corpus-priv.h
index 4cb2e43c..e65f7c8f 100644
--- a/src/abg-corpus-priv.h
+++ b/src/abg-corpus-priv.h
@@ -30,6 +30,7 @@
 #define __ABG_CORPUS_PRIV_H__
 
 #include "abg-sptr-utils.h"
+#include "abg-regex.h"
 #include "abg-internal.h"
 
 namespace abigail
@@ -42,7 +43,7 @@ namespace sptr_utils
 namespace ir
 {
 
-using sptr_utils::regex_t_sptr;
+using regex::regex_t_sptr;
 
 /// A convenience typedef for std::vector<regex_t_sptr>.
 typedef vector<regex_t_sptr> regex_t_sptrs_type;
diff --git a/src/abg-corpus.cc b/src/abg-corpus.cc
index 12f44fd1..2e9f304d 100644
--- a/src/abg-corpus.cc
+++ b/src/abg-corpus.cc
@@ -67,7 +67,7 @@ using zip_utils::open_archive;
 using zip_utils::open_file_in_archive;
 #endif // WITH_ZIP_ARCHIVE
 
-using sptr_utils::regex_t_sptr;
+using regex::regex_t_sptr;
 
 /// Constructor of @ref corpus::exported_decls_builder.
 ///
diff --git a/src/abg-sptr-utils.cc b/src/abg-regex.cc
similarity index 84%
rename from src/abg-sptr-utils.cc
rename to src/abg-regex.cc
index 2a6739a8..13f5841d 100644
--- a/src/abg-sptr-utils.cc
+++ b/src/abg-regex.cc
@@ -24,13 +24,11 @@
 ///
 
 #include "abg-sptr-utils.h"
+#include "abg-regex.h"
 
 namespace abigail
 {
 
-namespace sptr_utils
-{
-
 /// Specialization of sptr_utils::build_sptr for regex_t.
 ///
 /// This is used to wrap a pointer to regex_t into a
@@ -40,9 +38,9 @@ namespace sptr_utils
 ///
 /// @return the shared_ptr<regex_t> that wraps @p p.
 template<>
-regex_t_sptr
-build_sptr<regex_t>(regex_t *p)
-{return regex_t_sptr(p, regex_t_deleter());}
+regex::regex_t_sptr
+sptr_utils::build_sptr<regex_t>(regex_t *p)
+{return regex::regex_t_sptr(p, regex::regex_t_deleter());}
 
 /// Specialization of sptr_utils::build_sptr for regex_t.
 ///
@@ -50,9 +48,8 @@ build_sptr<regex_t>(regex_t *p)
 ///
 /// @return the shared_ptr<regex_t> wrapping the newly created regex_t*
 template<>
-regex_t_sptr
-build_sptr<regex_t>()
-{return build_sptr(new regex_t);}
+regex::regex_t_sptr
+sptr_utils::build_sptr<regex_t>()
+{return sptr_utils::build_sptr(new regex_t);}
 
-}
-}
+}//end namespace abigail
diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
index 1a9a7207..c37ceff6 100644
--- a/src/abg-suppression-priv.h
+++ b/src/abg-suppression-priv.h
@@ -31,6 +31,7 @@
 #include "abg-fwd.h"
 #include "abg-suppression.h"
 #include "abg-sptr-utils.h"
+#include "abg-regex.h"
 
 namespace abigail
 {
@@ -47,13 +48,13 @@ class suppression_base::priv
   bool					drops_artifact_;
   string				label_;
   string				file_name_regex_str_;
-  mutable sptr_utils::regex_t_sptr	file_name_regex_;
+  mutable regex::regex_t_sptr		file_name_regex_;
   string				file_name_not_regex_str_;
-  mutable sptr_utils::regex_t_sptr	file_name_not_regex_;
+  mutable regex::regex_t_sptr		file_name_not_regex_;
   string				soname_regex_str_;
-  mutable sptr_utils::regex_t_sptr	soname_regex_;
+  mutable regex::regex_t_sptr		soname_regex_;
   string				soname_not_regex_str_;
-  mutable sptr_utils::regex_t_sptr	soname_not_regex_;
+  mutable regex::regex_t_sptr		soname_not_regex_;
 
 public:
   priv()
@@ -87,14 +88,14 @@ public:
   ///
   /// If the 'file_name_regex' property of @ref suppression_base is
   /// empty then this method returns nil.
-  const sptr_utils::regex_t_sptr&
+  const regex::regex_t_sptr&
   get_file_name_regex() const
   {
     if (!file_name_regex_)
       {
 	if (!file_name_regex_str_.empty())
 	  {
-	    sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	    if (regcomp(r.get(),
 			file_name_regex_str_.c_str(),
 			REG_EXTENDED) == 0)
@@ -112,14 +113,14 @@ public:
   ///
   /// If the 'file_name_not_regex' property of @ref suppression_base
   /// is empty then this method returns nil.
-  const sptr_utils::regex_t_sptr&
+  const regex::regex_t_sptr&
   get_file_name_not_regex() const
   {
     if (!file_name_not_regex_)
       {
 	if (!file_name_not_regex_str_.empty())
 	  {
-	    sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	    if (regcomp(r.get(),
 			file_name_not_regex_str_.c_str(),
 			REG_EXTENDED) == 0)
@@ -137,14 +138,14 @@ public:
   ///
   /// If the 'soname_regex' property of @ref suppression_base is empty
   /// then this method returns nil.
-  const sptr_utils::regex_t_sptr&
+  const regex::regex_t_sptr&
   get_soname_regex() const
   {
     if (!soname_regex_)
       {
 	if (!soname_regex_str_.empty())
 	  {
-	    sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	    if (regcomp(r.get(),
 			soname_regex_str_.c_str(),
 			REG_EXTENDED) == 0)
@@ -162,14 +163,14 @@ public:
   ///
   /// If the 'soname_not_regex' property of @ref suppression_base is
   /// empty then this method returns nil.
-  const sptr_utils::regex_t_sptr&
+  const regex::regex_t_sptr&
   get_soname_not_regex() const
   {
     if (!soname_not_regex_)
       {
 	if (!soname_not_regex_str_.empty())
 	  {
-	    sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	    if (regcomp(r.get(),
 			soname_not_regex_str_.c_str(),
 			REG_EXTENDED) == 0)
@@ -192,14 +193,14 @@ public:
   matches_soname(const string& soname) const
   {
     bool has_regexp = false;
-    if (sptr_utils::regex_t_sptr regexp = get_soname_regex())
+    if (regex::regex_t_sptr regexp = get_soname_regex())
       {
 	has_regexp = true;
 	if (regexec(regexp.get(), soname.c_str(), 0, NULL, 0) != 0)
 	  return false;
       }
 
-    if (sptr_utils::regex_t_sptr regexp = get_soname_not_regex())
+    if (regex::regex_t_sptr regexp = get_soname_not_regex())
       {
 	has_regexp = true;
 	if (regexec(regexp.get(), soname.c_str(), 0, NULL, 0) == 0)
@@ -227,7 +228,7 @@ public:
   {
     bool has_regexp = false;
 
-    if (sptr_utils::regex_t_sptr regexp = get_file_name_regex())
+    if (regex::regex_t_sptr regexp = get_file_name_regex())
       {
 	has_regexp = true;
 	if (regexec(regexp.get(), binary_name.c_str(),
@@ -235,7 +236,7 @@ public:
 	  return false;
       }
 
-    if (sptr_utils::regex_t_sptr regexp = get_file_name_not_regex())
+    if (regex::regex_t_sptr regexp = get_file_name_not_regex())
       {
 	has_regexp = true;
 	if (regexec(regexp.get(), binary_name.c_str(),
@@ -263,7 +264,7 @@ class function_suppression::parameter_spec::priv
   size_t				index_;
   string				type_name_;
   string				type_name_regex_str_;
-  mutable sptr_utils::regex_t_sptr	type_name_regex_;
+  mutable regex::regex_t_sptr		type_name_regex_;
 
   priv()
     : index_()
@@ -277,12 +278,12 @@ class function_suppression::parameter_spec::priv
     : index_(i), type_name_(tn), type_name_regex_str_(tn_regex)
   {}
 
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_type_name_regex() const
   {
     if (!type_name_regex_ && !type_name_regex_str_.empty())
       {
-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	if (regcomp(r.get(),
 		    type_name_regex_str_.c_str(),
 		    REG_EXTENDED) == 0)
@@ -302,21 +303,21 @@ struct function_suppression::priv
   change_kind				change_kind_;
   string				name_;
   string				name_regex_str_;
-  mutable sptr_utils::regex_t_sptr	name_regex_;
+  mutable regex::regex_t_sptr		name_regex_;
   string				name_not_regex_str_;
-  mutable sptr_utils::regex_t_sptr	name_not_regex_;
+  mutable regex::regex_t_sptr		name_not_regex_;
   string				return_type_name_;
   string				return_type_regex_str_;
-  mutable sptr_utils::regex_t_sptr	return_type_regex_;
+  mutable regex::regex_t_sptr		return_type_regex_;
   parameter_specs_type			parm_specs_;
   string				symbol_name_;
   string				symbol_name_regex_str_;
-  mutable sptr_utils::regex_t_sptr	symbol_name_regex_;
+  mutable regex::regex_t_sptr		symbol_name_regex_;
   string				symbol_name_not_regex_str_;
-  mutable sptr_utils::regex_t_sptr	symbol_name_not_regex_;
+  mutable regex::regex_t_sptr		symbol_name_not_regex_;
   string				symbol_version_;
   string				symbol_version_regex_str_;
-  mutable sptr_utils::regex_t_sptr	symbol_version_regex_;
+  mutable regex::regex_t_sptr		symbol_version_regex_;
   bool					allow_other_aliases_;
 
   priv():
@@ -356,12 +357,12 @@ struct function_suppression::priv
   ///
   /// @return a pointer to the regular expression object of
   /// function_suppression::priv::name_regex_str_..
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_name_regex() const
   {
     if (!name_regex_ && !name_regex_str_.empty())
       {
-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	if (regcomp(r.get(),
 		    name_regex_str_.c_str(),
 		    REG_EXTENDED) == 0)
@@ -379,12 +380,12 @@ struct function_suppression::priv
   ///
   /// @return a pointer to the regular expression object of
   /// function_suppression::priv::name_not_regex_str_..
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_name_not_regex() const
   {
     if (!name_not_regex_ && !name_not_regex_str_.empty())
       {
-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	if (regcomp(r.get(),
 		    name_not_regex_str_.c_str(),
 		    REG_EXTENDED) == 0)
@@ -402,12 +403,12 @@ struct function_suppression::priv
   ///
   /// @return a pointer to the regular expression object of
   /// function_suppression::priv::return_type_regex_str_.
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_return_type_regex() const
   {
     if (!return_type_regex_ && !return_type_regex_str_.empty())
       {
-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	if (regcomp(r.get(),
 		    return_type_regex_str_.c_str(),
 		    REG_EXTENDED) == 0)
@@ -425,12 +426,12 @@ struct function_suppression::priv
   ///
   /// @return a pointer to the regular expression object of
   /// function_suppression::priv::symbol_name_regex_str_.
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_symbol_name_regex() const
   {
     if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
       {
-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	if (regcomp(r.get(),
 		    symbol_name_regex_str_.c_str(),
 		    REG_EXTENDED) == 0)
@@ -448,12 +449,12 @@ struct function_suppression::priv
   ///
   /// @return a pointer to the regular expression object of
   /// function_suppression::priv::symbol_name_not_regex_str_.
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_symbol_name_not_regex() const
   {
     if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
       {
-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	if (regcomp(r.get(),
 		    symbol_name_not_regex_str_.c_str(),
 		    REG_EXTENDED) == 0)
@@ -471,12 +472,12 @@ struct function_suppression::priv
   ///
   /// @return a pointer to the regular expression object of
   /// function_suppression::priv::symbol_version_regex_str_.
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_symbol_version_regex() const
   {
     if (!symbol_version_regex_ && ! symbol_version_regex_str_.empty())
       {
-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	if (regcomp(r.get(),
 		    symbol_version_regex_str_.c_str(),
 		    REG_EXTENDED) == 0)
@@ -561,20 +562,20 @@ struct variable_suppression::priv
   change_kind				change_kind_;
   string				name_;
   string				name_regex_str_;
-  mutable sptr_utils::regex_t_sptr	name_regex_;
+  mutable regex::regex_t_sptr		name_regex_;
   string				name_not_regex_str_;
-  mutable sptr_utils::regex_t_sptr	name_not_regex_;
+  mutable regex::regex_t_sptr		name_not_regex_;
   string				symbol_name_;
   string				symbol_name_regex_str_;
-  mutable sptr_utils::regex_t_sptr	symbol_name_regex_;
+  mutable regex::regex_t_sptr		symbol_name_regex_;
   string				symbol_name_not_regex_str_;
-  mutable sptr_utils::regex_t_sptr	symbol_name_not_regex_;
+  mutable regex::regex_t_sptr		symbol_name_not_regex_;
   string				symbol_version_;
   string				symbol_version_regex_str_;
-  mutable sptr_utils::regex_t_sptr	symbol_version_regex_;
+  mutable regex::regex_t_sptr		symbol_version_regex_;
   string				type_name_;
   string				type_name_regex_str_;
-  mutable sptr_utils::regex_t_sptr	type_name_regex_;
+  mutable regex::regex_t_sptr		type_name_regex_;
 
   priv(const string& name,
        const string& name_regex_str,
@@ -604,12 +605,12 @@ struct variable_suppression::priv
   ///
   /// @return a pointer to the regular expression object of
   /// variable_suppression::priv::name_regex_str_.
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_name_regex() const
   {
     if (!name_regex_ && !name_regex_str_.empty())
       {
-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	if (regcomp(r.get(),
 		    name_regex_str_.c_str(),
 		    REG_EXTENDED) == 0)
@@ -627,12 +628,12 @@ struct variable_suppression::priv
   ///
   /// @return a pointer to the regular expression object of
   /// variable_suppression::priv::name_not_regex_str_..
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_name_not_regex() const
   {
     if (!name_not_regex_ && !name_not_regex_str_.empty())
       {
-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	if (regcomp(r.get(),
 		    name_not_regex_str_.c_str(),
 		    REG_EXTENDED) == 0)
@@ -650,12 +651,12 @@ struct variable_suppression::priv
   ///
   /// @return a pointer to the regular expression object of
   /// variable_suppression::priv::symbol_name_regex_str_.
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_symbol_name_regex() const
   {
     if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
       {
-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	if (regcomp(r.get(),
 		    symbol_name_regex_str_.c_str(),
 		    REG_EXTENDED) == 0)
@@ -673,12 +674,12 @@ struct variable_suppression::priv
   ///
   /// @return a pointer to the regular expression object of
   /// variable_suppression::priv::symbol_name_not_regex_str_.
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_symbol_name_not_regex() const
   {
     if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
       {
-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	if (regcomp(r.get(), symbol_name_not_regex_str_.c_str(),
 		    REG_EXTENDED) == 0)
 	  symbol_name_not_regex_ = r;
@@ -695,12 +696,12 @@ struct variable_suppression::priv
   ///
   /// @return a pointer to the regular expression object of
   /// variable_suppression::priv::symbol_version_regex_str_.
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_symbol_version_regex()  const
   {
     if (!symbol_version_regex_ && !symbol_version_regex_str_.empty())
       {
-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	if (regcomp(r.get(),
 		    symbol_version_regex_str_.c_str(),
 		    REG_EXTENDED) == 0)
@@ -718,12 +719,12 @@ struct variable_suppression::priv
   ///
   /// @return a pointer to the regular expression object of
   /// variable_suppression::priv::type_name_regex_str_.
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_type_name_regex() const
   {
     if (!type_name_regex_ && !type_name_regex_str_.empty())
       {
-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	if (regcomp(r.get(),
 		    type_name_regex_str_.c_str(),
 		    REG_EXTENDED) == 0)
@@ -766,18 +767,18 @@ variable_is_suppressed(const ReadContextType&	ctxt,
 class type_suppression::priv
 {
   string				type_name_regex_str_;
-  mutable sptr_utils::regex_t_sptr	type_name_regex_;
+  mutable regex::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_;
+  mutable regex::regex_t_sptr		type_name_not_regex_;
   bool					consider_type_kind_;
   type_suppression::type_kind		type_kind_;
   bool					consider_reach_kind_;
   type_suppression::reach_kind		reach_kind_;
   type_suppression::insertion_ranges	insertion_ranges_;
-  unordered_set<string>		source_locations_to_keep_;
+  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 regex::regex_t_sptr		source_location_to_keep_regex_;
   mutable vector<string>		changed_enumerator_names_;
 
   priv();
@@ -805,14 +806,14 @@ public:
   ///
   /// If the 'type_name_regex' property of @ref type_suppression is
   /// empty then this method returns nil.
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_type_name_regex() const
   {
     if (!type_name_regex_)
       {
 	if (!type_name_regex_str_.empty())
 	  {
-	    sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	    if (regcomp(r.get(),
 			type_name_regex_str_.c_str(),
 			REG_EXTENDED) == 0)
@@ -826,7 +827,7 @@ public:
   ///
   /// @param r the new type_name_regex object.
   void
-  set_type_name_regex(sptr_utils::regex_t_sptr r)
+  set_type_name_regex(regex::regex_t_sptr r)
   {type_name_regex_ = r;}
 
   /// Get the regular expression object associated to the
@@ -837,14 +838,14 @@ public:
   ///
   /// If the 'type_name_not_regex' property of @ref type_suppression is
   /// empty then this method returns nil.
-  const sptr_utils::regex_t_sptr
+  const regex::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>();
+	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	    if (regcomp(r.get(),
 			type_name_not_regex_str_.c_str(),
 			REG_EXTENDED) == 0)
@@ -858,7 +859,7 @@ public:
   ///
   /// @param r the new type_name_not_regex object.
   void
-  set_type_name_not_regex(sptr_utils::regex_t_sptr r)
+  set_type_name_not_regex(regex::regex_t_sptr r)
   {type_name_not_regex_ = r;}
 
   /// Getter for the string that denotes the 'type_name_not_regex'
@@ -882,14 +883,14 @@ public:
   /// Getter for the source_location_to_keep_regex object.
   ///
   /// This function builds the regex if it's not yet built.
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_source_location_to_keep_regex() const
   {
     if (!source_location_to_keep_regex_)
       {
 	if (!source_location_to_keep_regex_str_.empty())
 	  {
-	    sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	    if (regcomp(r.get(),
 			source_location_to_keep_regex_str_.c_str(),
 			REG_EXTENDED) == 0)
@@ -903,7 +904,7 @@ public:
   ///
   /// @param r the new regex object.
   void
-  set_source_location_to_keep_regex(sptr_utils::regex_t_sptr r)
+  set_source_location_to_keep_regex(regex::regex_t_sptr r)
   {source_location_to_keep_regex_ = r;}
 
   friend class type_suppression;
diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index d3ccb63c..f26c9208 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -49,6 +49,7 @@ namespace suppr
 {
 
 using abg_compat::dynamic_pointer_cast;
+using regex::regex_t_sptr;
 
 // <suppression_base stuff>
 
@@ -990,7 +991,7 @@ 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.
-	  if (const sptr_utils::regex_t_sptr& type_name_regex =
+	  if (const regex_t_sptr& type_name_regex =
 	      s.priv_->get_type_name_regex())
 	    {
 	      if (regexec(type_name_regex.get(),
@@ -999,7 +1000,7 @@ suppression_matches_type_name(const type_suppression&	s,
 		return false;
 	    }
 
-	  if (const sptr_utils::regex_t_sptr type_name_not_regex =
+	  if (const regex_t_sptr type_name_not_regex =
 	      s.priv_->get_type_name_not_regex())
 	    {
 	      if (regexec(type_name_not_regex.get(),
@@ -1050,8 +1051,7 @@ suppression_matches_type_location(const type_suppression&	s,
       unsigned loc_line = 0, loc_column = 0;
       loc.expand(loc_path, loc_line, loc_column);
 
-      if (sptr_utils::regex_t_sptr regexp =
-	  s.priv_->get_source_location_to_keep_regex())
+      if (regex_t_sptr regexp = s.priv_->get_source_location_to_keep_regex())
 	if (regexec(regexp.get(), loc_path.c_str(), 0, NULL, 0) == 0)
 	  return false;
 
@@ -2500,7 +2500,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
 
   // check if the "name_regexp" property matches.
-  const sptr_utils::regex_t_sptr name_regex = priv_->get_name_regex();
+  const regex_t_sptr name_regex = priv_->get_name_regex();
   if (name_regex)
     {
       if (regexec(name_regex.get(),
@@ -2535,7 +2535,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
 
   // check if the "name_not_regexp" property matches.
-  const sptr_utils::regex_t_sptr name_not_regex = priv_->get_name_not_regex();
+  const regex_t_sptr name_not_regex = priv_->get_name_not_regex();
   if (name_not_regex)
     {
       if (regexec(name_not_regex.get(),
@@ -2585,8 +2585,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
   else
     {
-      const sptr_utils::regex_t_sptr return_type_regex =
-	priv_->get_return_type_regex();
+      const regex_t_sptr return_type_regex = priv_->get_return_type_regex();
       if (return_type_regex
 	  && (regexec(return_type_regex.get(),
 		      fn_return_type_name.c_str(),
@@ -2626,15 +2625,14 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
   else if (sym)
     {
-      const sptr_utils::regex_t_sptr symbol_name_regex =
-	priv_->get_symbol_name_regex();
+      const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
       if (symbol_name_regex
 	  && (regexec(symbol_name_regex.get(),
 		      fn_sym_name.c_str(),
 		      0, NULL, 0) != 0))
 	return false;
 
-      const sptr_utils::regex_t_sptr symbol_name_not_regex =
+      const regex_t_sptr symbol_name_not_regex =
 	priv_->get_symbol_name_not_regex();
       if (symbol_name_not_regex
 	  && (regexec(symbol_name_not_regex.get(),
@@ -2678,7 +2676,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
   else if (sym)
     {
-      const sptr_utils::regex_t_sptr symbol_version_regex =
+      const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
       if (symbol_version_regex
 	  && (regexec(symbol_version_regex.get(),
@@ -2720,7 +2718,7 @@ function_suppression::suppresses_function(const function_decl* fn,
 	    }
 	  else
 	    {
-	      const sptr_utils::regex_t_sptr parm_type_name_regex =
+	      const regex_t_sptr parm_type_name_regex =
 		(*p)->priv_->get_type_name_regex();
 	      if (parm_type_name_regex)
 		{
@@ -2813,8 +2811,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
     }
   else if (!get_symbol_name_regex_str().empty())
     {
-      const sptr_utils::regex_t_sptr symbol_name_regex =
-	priv_->get_symbol_name_regex();
+      const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
       if (symbol_name_regex
 	  && (regexec(symbol_name_regex.get(),
 		      sym_name.c_str(),
@@ -2832,7 +2829,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
     }
   else if (!get_symbol_version_regex_str().empty())
     {
-      const sptr_utils::regex_t_sptr symbol_version_regex =
+      const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
       if (symbol_version_regex
 	  && (regexec(symbol_version_regex.get(),
@@ -2927,12 +2924,12 @@ bool
 suppression_matches_function_name(const suppr::function_suppression& s,
 				  const string& fn_name)
 {
-  if (sptr_utils::regex_t_sptr regexp = s.priv_->get_name_regex())
+  if (regex_t_sptr regexp = s.priv_->get_name_regex())
     {
       if (regexec(regexp.get(), fn_name.c_str(), 0, NULL, 0) != 0)
 	return false;
     }
-  else if (sptr_utils::regex_t_sptr regexp = s.priv_->get_name_not_regex())
+  else if (regex_t_sptr regexp = s.priv_->get_name_not_regex())
     {
       if (regexec(regexp.get(), fn_name.c_str(), 0, NULL, 0) == 0)
 	return false;
@@ -2963,12 +2960,12 @@ bool
 suppression_matches_function_sym_name(const suppr::function_suppression& s,
 				      const string& fn_linkage_name)
 {
-  if (sptr_utils::regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
+  if (regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
     {
       if (regexec(regexp.get(), fn_linkage_name.c_str(), 0, NULL, 0) != 0)
 	return false;
     }
-  else if (sptr_utils::regex_t_sptr regexp = s.priv_->get_symbol_name_not_regex())
+  else if (regex_t_sptr regexp = s.priv_->get_symbol_name_not_regex())
     {
       if (regexec(regexp.get(), fn_linkage_name.c_str(), 0, NULL, 0) == 0)
 	return false;
@@ -2996,12 +2993,12 @@ bool
 suppression_matches_variable_name(const suppr::variable_suppression& s,
 				  const string& var_name)
 {
-  if (sptr_utils::regex_t_sptr regexp = s.priv_->get_name_regex())
+  if (regex_t_sptr regexp = s.priv_->get_name_regex())
     {
       if (regexec(regexp.get(), var_name.c_str(), 0, NULL, 0) != 0)
 	return false;
     }
-  else if (sptr_utils::regex_t_sptr regexp = s.priv_->get_name_not_regex())
+  else if (regex_t_sptr regexp = s.priv_->get_name_not_regex())
     {
       if (regexec(regexp.get(), var_name.c_str(), 0, NULL, 0) == 0)
 	return false;
@@ -3030,12 +3027,12 @@ bool
 suppression_matches_variable_sym_name(const suppr::variable_suppression& s,
 				      const string& var_linkage_name)
 {
-  if (sptr_utils::regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
+  if (regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
     {
       if (regexec(regexp.get(), var_linkage_name.c_str(), 0, NULL, 0) != 0)
 	return false;
     }
-  else if (sptr_utils::regex_t_sptr regexp =
+  else if (regex_t_sptr regexp =
 	   s.priv_->get_symbol_name_not_regex())
     {
       if (regexec(regexp.get(), var_linkage_name.c_str(), 0, NULL, 0) == 0)
@@ -3065,7 +3062,7 @@ bool
 suppression_matches_type(const suppr::type_suppression& s,
 			 const string& type_name)
 {
-  if (sptr_utils::regex_t_sptr regexp = s.priv_->get_type_name_regex())
+  if (regex_t_sptr regexp = s.priv_->get_type_name_regex())
     {
       if (regexec(regexp.get(), type_name.c_str(), 0, NULL, 0) != 0)
 	return false;
@@ -3780,14 +3777,13 @@ variable_suppression::suppresses_variable(const var_decl* var,
       // "name_regex" and "name_not_regex" properties match
       if (get_name().empty())
 	{
-	  const sptr_utils::regex_t_sptr name_regex = priv_->get_name_regex();
+	  const regex_t_sptr name_regex = priv_->get_name_regex();
 	  if (name_regex
 	      && (regexec(name_regex.get(), var_name.c_str(),
 			  0, NULL, 0) != 0))
 	    return false;
 
-	  const sptr_utils::regex_t_sptr name_not_regex =
-	    priv_->get_name_not_regex();
+	  const regex_t_sptr name_not_regex = priv_->get_name_not_regex();
 	  if (name_not_regex
 	      && (regexec(name_not_regex.get(), var_name.c_str(),
 			  0, NULL, 0) == 0))
@@ -3805,14 +3801,13 @@ variable_suppression::suppresses_variable(const var_decl* var,
     }
   else
     {
-      const sptr_utils::regex_t_sptr sym_name_regex =
-	priv_->get_symbol_name_regex();
+      const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
       if (sym_name_regex
 	  && (regexec(sym_name_regex.get(), var_sym_name.c_str(),
 		      0, NULL, 0) != 0))
 	return false;
 
-      const sptr_utils::regex_t_sptr sym_name_not_regex =
+      const regex_t_sptr sym_name_not_regex =
 	priv_->get_symbol_name_not_regex();
       if (sym_name_not_regex
 	  && (regexec(sym_name_not_regex.get(), var_sym_name.c_str(),
@@ -3830,7 +3825,7 @@ variable_suppression::suppresses_variable(const var_decl* var,
     }
   else
     {
-      const sptr_utils::regex_t_sptr symbol_version_regex =
+      const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
       if (symbol_version_regex
 	  && (regexec(symbol_version_regex.get(),
@@ -3852,8 +3847,7 @@ variable_suppression::suppresses_variable(const var_decl* var,
     {
       if (get_type_name().empty())
 	{
-	  const sptr_utils::regex_t_sptr type_name_regex =
-	    priv_->get_type_name_regex();
+	  const regex_t_sptr type_name_regex = priv_->get_type_name_regex();
 	  if (type_name_regex
 	      && (regexec(type_name_regex.get(), var_type_name.c_str(),
 			  0, NULL, 0) != 0))
@@ -3946,8 +3940,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
     }
   else if (!get_symbol_name_regex_str().empty())
     {
-      const sptr_utils::regex_t_sptr sym_name_regex =
-	priv_->get_symbol_name_regex();
+      const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
       if (sym_name_regex
 	  && (regexec(sym_name_regex.get(), sym_name.c_str(),
 		      0, NULL, 0) != 0))
@@ -3965,7 +3958,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
     }
   else if (!get_symbol_version_regex_str().empty())
     {
-      const sptr_utils::regex_t_sptr symbol_version_regex =
+      const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
       if (symbol_version_regex
 	  && (regexec(symbol_version_regex.get(),
@@ -4275,16 +4268,14 @@ file_suppression::suppresses_file(const string& file_path)
 
   bool has_regexp = false;
 
-  if (sptr_utils::regex_t_sptr regexp =
-      suppression_base::priv_->get_file_name_regex())
+  if (regex_t_sptr regexp = suppression_base::priv_->get_file_name_regex())
     {
       has_regexp = true;
       if (regexec(regexp.get(), fname.c_str(), 0, NULL, 0) != 0)
 	return false;
     }
 
-  if (sptr_utils::regex_t_sptr regexp =
-      suppression_base::priv_->get_file_name_not_regex())
+  if (regex_t_sptr regexp = suppression_base::priv_->get_file_name_not_regex())
     {
       has_regexp = true;
       if (regexec(regexp.get(), fname.c_str(), 0, NULL, 0) == 0)
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH 02/21] Move libxml bits out of abg-sptr-utils.h.
  2020-04-23 15:44 [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
  2020-04-23 15:44 ` [PATCH 01/21] Move regex definitions to own files Giuliano Procida
@ 2020-04-23 15:44 ` Giuliano Procida
  2020-04-23 15:44 ` [PATCH 03/21] Simplify generation of symbol whitelist regex Giuliano Procida
                   ` (20 subsequent siblings)
  22 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-23 15:44 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

The header file abg-sptr-utils.h contains generic things relating to
shared pointers. It also contains shared pointer typedefs (in the
sptr_utils namespace) and template specialisations for XML types.

The last of these more naturally belong in abg-libxml-utils.h (and in
the xml namespace). This patch moves them.

There are no behavioural changes.

	* include/abg-sptr-utils.h: Remove reader_sptr and
	xml_char_sptr typedefs, from namespace
	sptr_utils. (build_sptr): Remove corresponding template
	function specialisations for these types.
	* include/abg-libxml-utils.h: Add reader_sptr and
	xml_char_sptr typedefs, to namespace xml. (build_sptr): Add
	corresponding template function specialisations for these
	types.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 include/abg-libxml-utils.h | 21 +++++++++++++++++++--
 include/abg-sptr-utils.h   | 17 +----------------
 2 files changed, 20 insertions(+), 18 deletions(-)

diff --git a/include/abg-libxml-utils.h b/include/abg-libxml-utils.h
index 6331bde5..1e46d950 100644
--- a/include/abg-libxml-utils.h
+++ b/include/abg-libxml-utils.h
@@ -23,7 +23,10 @@
 #ifndef __ABG_LIBXML_UTILS_H__
 #define __ABG_LIBXML_UTILS_H__
 
+#include <libxml/xmlreader.h>
+
 #include <istream>
+
 #include "abg-sptr-utils.h"
 #include "abg-cxx-compat.h"
 
@@ -36,8 +39,12 @@ namespace xml
 
 using sptr_utils::build_sptr;
 using abg_compat::shared_ptr;
-using sptr_utils::reader_sptr;
-using sptr_utils::xml_char_sptr;
+
+/// A convenience typedef for a shared pointer of xmlTextReader.
+typedef shared_ptr<xmlTextReader> reader_sptr;
+
+/// A convenience typedef for a shared pointer of xmlChar.
+typedef shared_ptr<xmlChar> xml_char_sptr;
 
 /// This functor is used to instantiate a shared_ptr for the
 /// xmlTextReader.
@@ -121,5 +128,15 @@ std::string
 unescape_xml_comment(const std::string& str);
 
 }//end namespace xml
+
+/// Specialization of sptr_utils::build_sptr for xmlTextReader
+template<>
+xml::reader_sptr
+sptr_utils::build_sptr<xmlTextReader>(xmlTextReader *p);
+
+/// Specialization of build_str for xmlChar.
+template<>
+xml::xml_char_sptr sptr_utils::build_sptr<xmlChar>(xmlChar *p);
+
 }//end namespace abigail
 #endif //__ABG_LIBXML_UTILS_H__
diff --git a/include/abg-sptr-utils.h b/include/abg-sptr-utils.h
index 9737fe5f..2a12707b 100644
--- a/include/abg-sptr-utils.h
+++ b/include/abg-sptr-utils.h
@@ -26,7 +26,7 @@
 #define __ABG_SPTR_UTILS_H__
 
 #include <regex.h>
-#include <libxml/xmlreader.h>
+
 #include "abg-cxx-compat.h"
 
 namespace abigail
@@ -63,21 +63,6 @@ template<class T>
 shared_ptr<T>
 build_sptr();
 
-/// A convenience typedef for a shared pointer of xmlTextReader.
-typedef shared_ptr<xmlTextReader> reader_sptr;
-
-/// Specialization of sptr_utils::build_sptr for xmlTextReader
-template<>
-reader_sptr
-build_sptr<xmlTextReader>(xmlTextReader *p);
-
-/// A convenience typedef for a shared pointer of xmlChar.
-typedef shared_ptr<xmlChar> xml_char_sptr;
-
-/// Specialization of build_str for xmlChar.
-template<>
-xml_char_sptr build_sptr<xmlChar>(xmlChar *p);
-
 /// A deleter for shared pointers that ... doesn't delete the object
 /// managed by the shared pointer.
 struct noop_deleter
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH 03/21] Simplify generation of symbol whitelist regex.
  2020-04-23 15:44 [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
  2020-04-23 15:44 ` [PATCH 01/21] Move regex definitions to own files Giuliano Procida
  2020-04-23 15:44 ` [PATCH 02/21] Move libxml bits out of abg-sptr-utils.h Giuliano Procida
@ 2020-04-23 15:44 ` Giuliano Procida
  2020-04-23 15:44 ` [PATCH 04/21] Escape names used in symbol whitelisting regex Giuliano Procida
                   ` (19 subsequent siblings)
  22 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-23 15:44 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

The code to build the symbol whitelist regex uses things like seekp
and tellp to generate regexes like "^foo$|^bar$".

This patch simplifies the code, for further enhancement, resulting in
generated regexes like "^(foo|bar)$".

There should be no change in behaviour, unless whitelisted symbol
names contain special regex characters.

	* include/abg-regex.h (generate_from_strings): Declare new
	function to build a regex from some strings, representing a
	membership test.
	* src/abg-regex.cc (generate_from_strings): Implement new
	function to build a regex from some strings, representing a
	membership test, in a straightfoward fashion.
	* src/abg-tools-utils.cc
	(gen_suppr_spec_from_kernel_abi_whitelists): Replace
	regex-building code with a call to generate_from_strings.
	* tests/test-kmi-whitelist.cc: Update regexes in test.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 include/abg-regex.h         |  6 ++++++
 src/abg-regex.cc            | 28 ++++++++++++++++++++++++++++
 src/abg-tools-utils.cc      | 10 +++-------
 tests/test-kmi-whitelist.cc | 10 +++++-----
 4 files changed, 42 insertions(+), 12 deletions(-)

diff --git a/include/abg-regex.h b/include/abg-regex.h
index 84c386a9..2f638ef2 100644
--- a/include/abg-regex.h
+++ b/include/abg-regex.h
@@ -27,6 +27,9 @@
 
 #include <regex.h>
 
+#include <string>
+#include <vector>
+
 #include "abg-cxx-compat.h"
 #include "abg-sptr-utils.h"
 
@@ -55,6 +58,9 @@ struct regex_t_deleter
   }
 };//end struct regex_deleter
 
+std::string
+generate_from_strings(const std::vector<std::string>& strs);
+
 }// end namespace regex
 
 /// Specialization of sptr_utils::build_sptr for regex_t.
diff --git a/src/abg-regex.cc b/src/abg-regex.cc
index 13f5841d..79a89033 100644
--- a/src/abg-regex.cc
+++ b/src/abg-regex.cc
@@ -23,6 +23,7 @@
 /// Some specialization for shared pointer utility templates.
 ///
 
+#include <sstream>
 #include "abg-sptr-utils.h"
 #include "abg-regex.h"
 
@@ -52,4 +53,31 @@ regex::regex_t_sptr
 sptr_utils::build_sptr<regex_t>()
 {return sptr_utils::build_sptr(new regex_t);}
 
+namespace regex
+{
+
+/// Generate a regex pattern equivalent to testing set membership.
+///
+/// A string will match the resulting pattern regex, if and only if it
+/// was present in the vector.
+///
+/// @param strs a vector of strings
+///
+/// @return a regex pattern
+std::string
+generate_from_strings(const std::vector<std::string>& strs)
+{
+  if (strs.empty())
+    return "^_^";
+  std::ostringstream os;
+  std::vector<std::string>::const_iterator i = strs.begin();
+  os << "^(" << *i++;
+  while (i != strs.end())
+    os << "|" << *i++;
+  os << ")$";
+  return os.str();
+}
+
+}//end namespace regex
+
 }//end namespace abigail
diff --git a/src/abg-tools-utils.cc b/src/abg-tools-utils.cc
index a06e8615..11486a21 100644
--- a/src/abg-tools-utils.cc
+++ b/src/abg-tools-utils.cc
@@ -61,6 +61,8 @@
 #include "abg-dwarf-reader.h"
 #include "abg-internal.h"
 #include "abg-cxx-compat.h"
+#include "abg-regex.h"
+
 // <headers defining libabigail's API go under here>
 ABG_BEGIN_EXPORT_DECLARATIONS
 
@@ -2002,13 +2004,7 @@ gen_suppr_spec_from_kernel_abi_whitelists
 
       // Build a regular expression representing the union of all
       // the function and variable names expressed in the white list.
-      std::stringstream regex_ss;
-      regex_ss << "^";
-      std::copy(whitelisted_names.begin(), whitelisted_names.end(),
-		std::ostream_iterator<std::string>(regex_ss, "$|^"));
-      regex_ss.seekp(0, std::ios::end);
-      const std::string& regex =
-	  regex_ss.str().substr(0, static_cast<size_t>(regex_ss.tellp()) - 2);
+      const std::string regex = regex::generate_from_strings(whitelisted_names);
 
       // Build a suppression specification which *keeps* functions
       // whose ELF symbols match the regular expression contained
diff --git a/tests/test-kmi-whitelist.cc b/tests/test-kmi-whitelist.cc
index 2aa0f463..bcc5adee 100644
--- a/tests/test-kmi-whitelist.cc
+++ b/tests/test-kmi-whitelist.cc
@@ -96,7 +96,7 @@ TEST_CASE("WhitelistWithASingleEntry", "[whitelists]")
   suppressions_type suppr
       = gen_suppr_spec_from_kernel_abi_whitelists(abi_whitelist_paths);
   REQUIRE(!suppr.empty());
-  test_suppressions_are_consistent(suppr, "^test_symbol$");
+  test_suppressions_are_consistent(suppr, "^(test_symbol)$");
 }
 
 TEST_CASE("WhitelistWithADuplicateEntry", "[whitelists]")
@@ -106,7 +106,7 @@ TEST_CASE("WhitelistWithADuplicateEntry", "[whitelists]")
   suppressions_type suppr
       = gen_suppr_spec_from_kernel_abi_whitelists(abi_whitelist_paths);
   REQUIRE(!suppr.empty());
-  test_suppressions_are_consistent(suppr, "^test_symbol$");
+  test_suppressions_are_consistent(suppr, "^(test_symbol)$");
 }
 
 TEST_CASE("TwoWhitelists", "[whitelists]")
@@ -118,7 +118,7 @@ TEST_CASE("TwoWhitelists", "[whitelists]")
       gen_suppr_spec_from_kernel_abi_whitelists(abi_whitelist_paths);
   REQUIRE(!suppr.empty());
   test_suppressions_are_consistent(suppr,
-				   "^test_another_symbol$|^test_symbol$");
+				   "^(test_another_symbol|test_symbol)$");
 }
 
 TEST_CASE("TwoWhitelistsWithDuplicates", "[whitelists]")
@@ -130,7 +130,7 @@ TEST_CASE("TwoWhitelistsWithDuplicates", "[whitelists]")
       = gen_suppr_spec_from_kernel_abi_whitelists(abi_whitelist_paths);
   REQUIRE(!suppr.empty());
   test_suppressions_are_consistent(suppr,
-				   "^test_another_symbol$|^test_symbol$");
+				   "^(test_another_symbol|test_symbol)$");
 }
 
 TEST_CASE("WhitelistWithTwoSections", "[whitelists]")
@@ -140,5 +140,5 @@ TEST_CASE("WhitelistWithTwoSections", "[whitelists]")
   suppressions_type suppr
       = gen_suppr_spec_from_kernel_abi_whitelists(abi_whitelist_paths);
   REQUIRE(!suppr.empty());
-  test_suppressions_are_consistent(suppr, "^test_symbol1$|^test_symbol2$");
+  test_suppressions_are_consistent(suppr, "^(test_symbol1|test_symbol2)$");
 }
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH 04/21] Escape names used in symbol whitelisting regex.
  2020-04-23 15:44 [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
                   ` (2 preceding siblings ...)
  2020-04-23 15:44 ` [PATCH 03/21] Simplify generation of symbol whitelist regex Giuliano Procida
@ 2020-04-23 15:44 ` Giuliano Procida
  2020-04-23 15:44 ` [PATCH 05/21] abg-suppression.cc: More uniform variable naming Giuliano Procida
                   ` (18 subsequent siblings)
  22 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-23 15:44 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

There is the theoretical possibility that symbols may contain special
regex characters like '.' and '$'. This patch ensures all such
characters in symbol names are escaped before they are added to the
whitelisting regex.

	* include/regex.h (escape): New string reference holder
	class. (operator<<): Declaration of std::ostream,
	regex::escape overload.
	* include/regex.cc (operator<<): New std::ostream,
	regex::escape overload that outputs regex-escaped strings.
	* src/abg-tools-utils.cc
	(gen_suppr_spec_from_kernel_abi_whitelists): Make sure any
	special regex characters in symbol names are escaped.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 include/abg-regex.h | 10 ++++++++++
 src/abg-regex.cc    | 27 +++++++++++++++++++++++++--
 2 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/include/abg-regex.h b/include/abg-regex.h
index 2f638ef2..59976794 100644
--- a/include/abg-regex.h
+++ b/include/abg-regex.h
@@ -58,6 +58,16 @@ struct regex_t_deleter
   }
 };//end struct regex_deleter
 
+/// A class to hold a reference to a string to regex escape.
+struct escape
+{
+  escape(const std::string& str) : ref(str) { }
+  const std::string& ref;
+};
+
+std::ostream&
+operator<<(std::ostream& os, const escape& esc);
+
 std::string
 generate_from_strings(const std::vector<std::string>& strs);
 
diff --git a/src/abg-regex.cc b/src/abg-regex.cc
index 79a89033..90e4d144 100644
--- a/src/abg-regex.cc
+++ b/src/abg-regex.cc
@@ -24,6 +24,7 @@
 ///
 
 #include <sstream>
+#include <ostream>
 #include "abg-sptr-utils.h"
 #include "abg-regex.h"
 
@@ -56,6 +57,28 @@ sptr_utils::build_sptr<regex_t>()
 namespace regex
 {
 
+/// Escape regex special charaters in input string.
+///
+/// @param os the output stream being written to.
+///
+/// @param esc the regex_escape object holding a reference to the string
+/// needing to be escaped.
+///
+/// @return the output stream.
+std::ostream&
+operator<<(std::ostream& os, const escape& esc)
+{
+  static const std::string specials = "^.[$()|*+?{\\";
+  const std::string str = esc.ref;
+  for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
+    {
+      if (specials.find(*i) != std::string::npos)
+        os << '\\';
+      os << *i;
+    }
+  return os;
+}
+
 /// Generate a regex pattern equivalent to testing set membership.
 ///
 /// A string will match the resulting pattern regex, if and only if it
@@ -71,9 +94,9 @@ generate_from_strings(const std::vector<std::string>& strs)
     return "^_^";
   std::ostringstream os;
   std::vector<std::string>::const_iterator i = strs.begin();
-  os << "^(" << *i++;
+  os << "^(" << escape(*i++);
   while (i != strs.end())
-    os << "|" << *i++;
+    os << "|" << escape(*i++);
   os << ")$";
   return os.str();
 }
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH 05/21] abg-suppression.cc: More uniform variable naming.
  2020-04-23 15:44 [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
                   ` (3 preceding siblings ...)
  2020-04-23 15:44 ` [PATCH 04/21] Escape names used in symbol whitelisting regex Giuliano Procida
@ 2020-04-23 15:44 ` Giuliano Procida
  2020-04-23 15:44 ` [PATCH 06/21] diff suppression: Fix handling of change kinds Giuliano Procida
                   ` (17 subsequent siblings)
  22 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-23 15:44 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

In abg-suppression.cc most of the read_foo functions populate and
return a single variable "result". Others vary a little from this,
having variables "nil" or "suppr".

This patch makes all the functions use a single variable "result".
This will make the next patches a bit simpler.

There are no behavioural changes.

	* src/abg-suppression.cc (read_type_suppression): Rename "nil"
	variable to "result" and reset it instead of introducing
	"suppr" later on. (read_function_suppression): Rename "nil"
	variable to "result" and reset it instead of introducing
	"result" later on.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-suppression.cc | 64 +++++++++++++++++++++---------------------
 1 file changed, 32 insertions(+), 32 deletions(-)

diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index f26c9208..2fbbd61b 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -1547,10 +1547,10 @@ read_suppression_reach_kind(const string& input)
 static type_suppression_sptr
 read_type_suppression(const ini::config::section& section)
 {
-  type_suppression_sptr nil;
+  type_suppression_sptr result;
 
   if (section.get_name() != "suppress_type")
-    return nil;
+    return result;
 
   ini::simple_property_sptr drop_artifact =
     is_simple_property(section.find_property("drop_artifact"));
@@ -1674,7 +1674,7 @@ read_type_suppression(const ini::config::section& section)
 	       type_suppression::insertion_range::create_fn_call_expr_boundary(ini::read_function_call_expr(ins_point)))
 	begin = expr;
       else
-	return nil;
+	return result;
 
       end = type_suppression::insertion_range::create_integer_boundary(-1);
       type_suppression::insertion_range_sptr insert_range
@@ -1717,7 +1717,7 @@ read_type_suppression(const ini::config::section& section)
 		   type_suppression::insertion_range::create_fn_call_expr_boundary(ini::read_function_call_expr(str)))
 	    begin = expr;
 	  else
-	    return nil;
+	    return result;
 
 	  str = val->get_content()[1];
 	  if (str == "end")
@@ -1730,7 +1730,7 @@ read_type_suppression(const ini::config::section& section)
 		   type_suppression::insertion_range::create_fn_call_expr_boundary(ini::read_function_call_expr(str)))
 	    end = expr;
 	  else
-	    return nil;
+	    return result;
 
 	  type_suppression::insertion_range_sptr insert_range
 	    (new type_suppression::insertion_range(begin, end));
@@ -1741,7 +1741,7 @@ read_type_suppression(const ini::config::section& section)
 	// the 'has_data_member_inserted_between' property has a wrong
 	// value type, so let's discard the endire [suppress_type]
 	// section.
-	return nil;
+	return result;
     }
 
   // Support has_data_members_inserted_between
@@ -1792,7 +1792,7 @@ read_type_suppression(const ini::config::section& section)
 		   type_suppression::insertion_range::create_fn_call_expr_boundary(ini::read_function_call_expr(str)))
 	    begin = expr;
 	  else
-	    return nil;
+	    return result;
 
 	  str = list_value->get_content()[1];
 	  if (str == "end")
@@ -1805,7 +1805,7 @@ read_type_suppression(const ini::config::section& section)
 		   type_suppression::insertion_range::create_fn_call_expr_boundary(ini::read_function_call_expr(str)))
 	    end = expr;
 	  else
-	    return nil;
+	    return result;
 
 	  type_suppression::insertion_range_sptr insert_range
 	    (new type_suppression::insertion_range(begin, end));
@@ -1813,7 +1813,7 @@ read_type_suppression(const ini::config::section& section)
 	  consider_data_member_insertion = true;
 	}
       if (!is_well_formed)
-	return nil;
+	return result;
     }
 
   /// Support 'changed_enumerators = foo, bar, baz'
@@ -1851,59 +1851,58 @@ read_type_suppression(const ini::config::section& section)
       && !consider_type_kind
       && srcloc_not_regexp_str.empty()
       && srcloc_not_in.empty())
-    return nil;
+    return result;
+
+  result.reset(new type_suppression(label_str, name_regex_str, name_str));
 
-  type_suppression_sptr suppr(new type_suppression(label_str,
-						   name_regex_str,
-						   name_str));
   if (consider_type_kind)
     {
-      suppr->set_consider_type_kind(true);
-      suppr->set_type_kind(type_kind);
+      result->set_consider_type_kind(true);
+      result->set_type_kind(type_kind);
     }
 
   if (consider_reach_kind)
     {
-      suppr->set_consider_reach_kind(true);
-      suppr->set_reach_kind(reach_kind);
+      result->set_consider_reach_kind(true);
+      result->set_reach_kind(reach_kind);
     }
 
   if (consider_data_member_insertion)
-    suppr->set_data_member_insertion_ranges(insert_ranges);
+    result->set_data_member_insertion_ranges(insert_ranges);
 
   if (!name_not_regex_str.empty())
-    suppr->set_type_name_not_regex_str(name_not_regex_str);
+    result->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);
+    result->set_file_name_regex_str(file_name_regex_str);
 
   if (!file_name_not_regex_str.empty())
-    suppr->set_file_name_not_regex_str(file_name_not_regex_str);
+    result->set_file_name_not_regex_str(file_name_not_regex_str);
 
   if (!soname_regex_str.empty())
-    suppr->set_soname_regex_str(soname_regex_str);
+    result->set_soname_regex_str(soname_regex_str);
 
   if (!soname_not_regex_str.empty())
-    suppr->set_soname_not_regex_str(soname_not_regex_str);
+    result->set_soname_not_regex_str(soname_not_regex_str);
 
   if (!srcloc_not_in.empty())
-    suppr->set_source_locations_to_keep(srcloc_not_in);
+    result->set_source_locations_to_keep(srcloc_not_in);
 
   if (!srcloc_not_regexp_str.empty())
-    suppr->set_source_location_to_keep_regex_str(srcloc_not_regexp_str);
+    result->set_source_location_to_keep_regex_str(srcloc_not_regexp_str);
 
   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
       && ((!name_regex_str.empty()
 	   || !name_str.empty()
 	   || !srcloc_not_regexp_str.empty()
 	   || !srcloc_not_in.empty())))
-    suppr->set_drops_artifact_from_ir(true);
+    result->set_drops_artifact_from_ir(true);
 
-  if (suppr->get_type_kind() == type_suppression::ENUM_TYPE_KIND
+  if (result->get_type_kind() == type_suppression::ENUM_TYPE_KIND
       && !changed_enumerator_names.empty())
-    suppr->set_changed_enumerator_names(changed_enumerator_names);
+    result->set_changed_enumerator_names(changed_enumerator_names);
 
-  return suppr;
+  return result;
 }
 
 // <function_suppression stuff>
@@ -3158,10 +3157,10 @@ read_parameter_spec_from_string(const string& str)
 static function_suppression_sptr
 read_function_suppression(const ini::config::section& section)
 {
-  function_suppression_sptr nil;
+  function_suppression_sptr result;
 
   if (section.get_name() != "suppress_function")
-    return nil;
+    return result;
 
   ini::simple_property_sptr drop_artifact =
     is_simple_property(section.find_property("drop_artifact"));
@@ -3289,7 +3288,6 @@ read_function_suppression(const ini::config::section& section)
 	  parms.push_back(parm);
       }
 
-  function_suppression_sptr result;
   if (!label_str.empty()
       || !name.empty()
       || !name_regex_str.empty()
@@ -3306,6 +3304,7 @@ read_function_suppression(const ini::config::section& section)
       || !sym_version.empty()
       || !sym_ver_regex_str.empty()
       || !parms.empty())
+
     result.reset(new function_suppression(label_str, name,
 					  name_regex_str,
 					  return_type_name,
@@ -4343,6 +4342,7 @@ read_file_suppression(const ini::config::section& section)
       && soname_regex_str.empty()
       && soname_not_regex_str.empty())
     return result;
+
   result.reset(new file_suppression(label_str,
 				    file_name_regex_str,
 				    file_name_not_regex_str));
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH 06/21] diff suppression: Fix handling of change kinds.
  2020-04-23 15:44 [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
                   ` (4 preceding siblings ...)
  2020-04-23 15:44 ` [PATCH 05/21] abg-suppression.cc: More uniform variable naming Giuliano Procida
@ 2020-04-23 15:44 ` Giuliano Procida
  2020-04-23 15:44 ` [PATCH 07/21] Add POSIX regex wrapper functions Giuliano Procida
                   ` (16 subsequent siblings)
  22 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-23 15:44 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

When parsing suppression specifications, libabigail attempts to detect
and so ignore useless suppressions. This is an optimisation to avoid
the cost of testing against a suppression that will do nothing.

Unfortunately, with the way the parser currently works, these checks
have to be against an exhaustive list of fields that matter, rather
than by listing the fields that don't (label). They are fragile in the
face of changes that add new fields.

Two of the short-cut checks are in fact buggy, missing out the
change_kind field. One of the checks also risks a null pointer
dereference as it doesn't actually trigger a return from the function.

This patch eliminates (rather than fixing up) this short-cutting on
the grounds that it buys very litte and is a maintenance burden. In a
future version, it could be reinstated with logic that has global
knowledge of which fields are present and which fields have no
suppression semantics and perhaps emitting warning message to the user
if they have supplied a useless specification.

The patch also corrects 4 affected test cases to reflect that
suppression is actually happening (according to change_kind).

	* src/abg-suppression.cc (read_type_suppression): Remove
	short-circuiting of useless suppressions.
	(read_function_suppression): Ditto.
	(read_variable_suppression: Ditto.
	(read_file_suppression): Ditto.
	tests/data/test-diff-suppr/test15-suppr-added-fn-report-5.txt:
	Fix test - something is actually suppressed.
	* tests/data/test-diff-suppr/test16-suppr-removed-fn-report-5.txt:
	Ditto.
	* tests/data/test-diff-suppr/test17-suppr-added-var-report-5.txt:
	Ditto.
	* tests/data/test-diff-suppr/test18-suppr-removed-var-report-5.txt:
	Ditto.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-suppression.cc                        | 89 +++++--------------
 .../test15-suppr-added-fn-report-5.txt        |  6 +-
 .../test16-suppr-removed-fn-report-5.txt      | 15 +---
 .../test17-suppr-added-var-report-5.txt       | 15 +---
 .../test18-suppr-removed-var-report-5.txt     | 15 +---
 5 files changed, 25 insertions(+), 115 deletions(-)

diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 2fbbd61b..b600c88c 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -1840,19 +1840,6 @@ read_type_suppression(const ini::config::section& section)
 	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()
-      && 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()
-      && srcloc_not_in.empty())
-    return result;
-
   result.reset(new type_suppression(label_str, name_regex_str, name_str));
 
   if (consider_type_kind)
@@ -3288,32 +3275,16 @@ read_function_suppression(const ini::config::section& section)
 	  parms.push_back(parm);
       }
 
-  if (!label_str.empty()
-      || !name.empty()
-      || !name_regex_str.empty()
-      || !name_not_regex_str.empty()
-      || !file_name_regex_str.empty()
-      || !file_name_not_regex_str.empty()
-      || !soname_regex_str.empty()
-      || !soname_not_regex_str.empty()
-      || !return_type_name.empty()
-      || !return_type_regex_str.empty()
-      || !sym_name.empty()
-      || !sym_name_regex_str.empty()
-      || !sym_name_not_regex_str.empty()
-      || !sym_version.empty()
-      || !sym_ver_regex_str.empty()
-      || !parms.empty())
-
-    result.reset(new function_suppression(label_str, name,
-					  name_regex_str,
-					  return_type_name,
-					  return_type_regex_str,
-					  parms,
-					  sym_name,
-					  sym_name_regex_str,
-					  sym_version,
-					  sym_ver_regex_str));
+  result.reset(new function_suppression(label_str,
+					name,
+					name_regex_str,
+					return_type_name,
+					return_type_regex_str,
+					parms,
+					sym_name,
+					sym_name_regex_str,
+					sym_version,
+					sym_ver_regex_str));
 
   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
       && (!name.empty()
@@ -3324,11 +3295,11 @@ read_function_suppression(const ini::config::section& section)
 	  || !sym_name_not_regex_str.empty()))
     result->set_drops_artifact_from_ir(true);
 
-  if (result && !change_kind_str.empty())
+  if (!change_kind_str.empty())
     result->set_change_kind
       (function_suppression::parse_change_kind(change_kind_str));
 
-  if (result && !allow_other_aliases.empty())
+  if (!allow_other_aliases.empty())
     result->set_allow_other_aliases(allow_other_aliases == "yes"
 				    || allow_other_aliases == "true");
 
@@ -4157,27 +4128,15 @@ read_variable_suppression(const ini::config::section& section)
     ? type_name_regex_prop->get_value()->as_string()
      : "";
 
-  if (label_str.empty()
-      && name_str.empty()
-      && name_regex_str.empty()
-      && name_not_regex_str.empty()
-      && file_name_regex_str.empty()
-      && file_name_not_regex_str.empty()
-      && soname_regex_str.empty()
-      && soname_not_regex_str.empty()
-      && symbol_name.empty()
-      && symbol_name_regex_str.empty()
-      && symbol_name_not_regex_str.empty()
-      && symbol_version.empty()
-      && symbol_version_regex_str.empty()
-      && type_name_str.empty()
-      && type_name_regex_str.empty())
-    return result;
-
-  result.reset(new variable_suppression(label_str, name_str, name_regex_str,
-					symbol_name, symbol_name_regex_str,
-					symbol_version, symbol_version_regex_str,
-					type_name_str, type_name_regex_str));
+  result.reset(new variable_suppression(label_str,
+					name_str,
+					name_regex_str,
+					symbol_name,
+					symbol_name_regex_str,
+					symbol_version,
+					symbol_version_regex_str,
+					type_name_str,
+					type_name_regex_str));
 
   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
       && (!name_str.empty()
@@ -4337,12 +4296,6 @@ read_file_suppression(const ini::config::section& section)
     ? soname_not_regex_prop->get_value()->as_string()
     : "";
 
-  if (file_name_regex_str.empty()
-      && file_name_not_regex_str.empty()
-      && soname_regex_str.empty()
-      && soname_not_regex_str.empty())
-    return result;
-
   result.reset(new file_suppression(label_str,
 				    file_name_regex_str,
 				    file_name_not_regex_str));
diff --git a/tests/data/test-diff-suppr/test15-suppr-added-fn-report-5.txt b/tests/data/test-diff-suppr/test15-suppr-added-fn-report-5.txt
index 4eaba5b7..83dfe326 100644
--- a/tests/data/test-diff-suppr/test15-suppr-added-fn-report-5.txt
+++ b/tests/data/test-diff-suppr/test15-suppr-added-fn-report-5.txt
@@ -1,10 +1,6 @@
-Functions changes summary: 0 Removed, 1 Changed, 1 Added functions
+Functions changes summary: 0 Removed, 1 Changed, 0 Added (1 filtered out) functions
 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 
-1 Added function:
-
-  [A] 'function void bar()'    {_Z3barv}
-
 1 function with some indirect sub-type change:
 
   [C] 'function void bar(S&)' has some indirect sub-type changes:
diff --git a/tests/data/test-diff-suppr/test16-suppr-removed-fn-report-5.txt b/tests/data/test-diff-suppr/test16-suppr-removed-fn-report-5.txt
index b28fbd16..851f7728 100644
--- a/tests/data/test-diff-suppr/test16-suppr-removed-fn-report-5.txt
+++ b/tests/data/test-diff-suppr/test16-suppr-removed-fn-report-5.txt
@@ -1,16 +1,3 @@
-Functions changes summary: 1 Removed, 1 Changed, 0 Added functions
+Functions changes summary: 0 Removed (1 filtered out), 0 Changed (1 filtered out), 0 Added functions
 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 
-1 Removed function:
-
-  [D] 'function void bar()'    {_Z3barv}
-
-1 function with some indirect sub-type change:
-
-  [C] 'function void bar(S*)' has some indirect sub-type changes:
-    parameter 1 of type 'S*' has sub-type changes:
-      in pointed to type 'struct S':
-        type size changed from 32 to 64 (in bits)
-        1 data member insertion:
-          'unsigned int S::bar', at offset 32 (in bits)
-
diff --git a/tests/data/test-diff-suppr/test17-suppr-added-var-report-5.txt b/tests/data/test-diff-suppr/test17-suppr-added-var-report-5.txt
index 6965a151..f4e0aa29 100644
--- a/tests/data/test-diff-suppr/test17-suppr-added-var-report-5.txt
+++ b/tests/data/test-diff-suppr/test17-suppr-added-var-report-5.txt
@@ -1,16 +1,3 @@
 Functions changes summary: 0 Removed, 0 Changed, 0 Added function
-Variables changes summary: 0 Removed, 1 Changed, 1 Added variables
-
-1 Added variable:
-
-  [A] 'int var1'    {var1}
-
-1 Changed variable:
-
-  [C] 'S* var0' was changed:
-    type of variable changed:
-      in pointed to type 'struct S':
-        type size changed from 32 to 64 (in bits)
-        1 data member insertion:
-          'char S::m1', at offset 32 (in bits)
+Variables changes summary: 0 Removed, 0 Changed (1 filtered out), 0 Added (1 filtered out) variables
 
diff --git a/tests/data/test-diff-suppr/test18-suppr-removed-var-report-5.txt b/tests/data/test-diff-suppr/test18-suppr-removed-var-report-5.txt
index 3edf2bd1..ac380a4a 100644
--- a/tests/data/test-diff-suppr/test18-suppr-removed-var-report-5.txt
+++ b/tests/data/test-diff-suppr/test18-suppr-removed-var-report-5.txt
@@ -1,16 +1,3 @@
 Functions changes summary: 0 Removed, 0 Changed, 0 Added function
-Variables changes summary: 1 Removed, 1 Changed, 0 Added variables
-
-1 Removed variable:
-
-  [D] 'int var1'    {var1}
-
-1 Changed variable:
-
-  [C] 'S* var0' was changed:
-    type of variable changed:
-      in pointed to type 'struct S':
-        type size changed from 32 to 64 (in bits)
-        1 data member insertion:
-          'char S::m1', at offset 32 (in bits)
+Variables changes summary: 0 Removed (1 filtered out), 0 Changed (1 filtered out), 0 Added variables
 
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH 07/21] Add POSIX regex wrapper functions.
  2020-04-23 15:44 [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
                   ` (5 preceding siblings ...)
  2020-04-23 15:44 ` [PATCH 06/21] diff suppression: Fix handling of change kinds Giuliano Procida
@ 2020-04-23 15:44 ` Giuliano Procida
  2020-04-23 18:07   ` [PATCH v2 " Giuliano Procida
  2020-04-23 15:44 ` [PATCH 08/21] Use regex::compile wrapper instead of regcomp Giuliano Procida
                   ` (15 subsequent siblings)
  22 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-04-23 15:44 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

libabigail code uses the POSIX regex library consistently:

    - compile std::string to regex, with the flag REG_EXTENDED
    - store regex using a shared pointer wrapper
    - check match of regex against std::string

All the C string / std::string logic and so on is repeated at every
call site. This patch introduces wrapper functions to take care of
this logic.

There are no behavioural changes.

	* include/abg-regex.h (compile): Declare new function.
	(match): Declare new function.
	* src/abg-regex.cc (compile): Add new function wrapping
	regcomp. (match): Add new function wrapping regexec.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 include/abg-regex.h |  4 ++++
 src/abg-regex.cc    | 28 ++++++++++++++++++++++++++++
 2 files changed, 32 insertions(+)

diff --git a/include/abg-regex.h b/include/abg-regex.h
index 59976794..4a56292a 100644
--- a/include/abg-regex.h
+++ b/include/abg-regex.h
@@ -71,6 +71,10 @@ operator<<(std::ostream& os, const escape& esc);
 std::string
 generate_from_strings(const std::vector<std::string>& strs);
 
+regex_t_sptr compile(const std::string& str);
+
+bool match(const regex_t_sptr& r, const std::string& str);
+
 }// end namespace regex
 
 /// Specialization of sptr_utils::build_sptr for regex_t.
diff --git a/src/abg-regex.cc b/src/abg-regex.cc
index 90e4d144..e4466bf4 100644
--- a/src/abg-regex.cc
+++ b/src/abg-regex.cc
@@ -101,6 +101,34 @@ generate_from_strings(const std::vector<std::string>& strs)
   return os.str();
 }
 
+/// Compile a regex from a string.
+///
+/// The result is held in a shared pointer. This will be null if regex
+/// compilation fails.
+///
+/// @param str the string representation of the regex.
+///
+/// @return shared pointer holder of a compiled regex object.
+regex_t_sptr compile(const std::string& str)
+{
+  regex_t_sptr r = sptr_utils::build_sptr(new regex_t);
+  if (regcomp(r.get(), str.c_str(), REG_EXTENDED))
+    r.reset();
+  return r;
+}
+
+/// See if a string matches a regex.
+///
+/// @param r a shared pointer holder of a compiled regex object.
+///
+/// @param str a string.
+///
+/// @return whether there was a match.
+bool match(const regex_t_sptr& r, const std::string& str)
+{
+  return !regexec(r.get(), str.c_str(), 0, NULL, 0);
+}
+
 }//end namespace regex
 
 }//end namespace abigail
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH 08/21] Use regex::compile wrapper instead of regcomp.
  2020-04-23 15:44 [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
                   ` (6 preceding siblings ...)
  2020-04-23 15:44 ` [PATCH 07/21] Add POSIX regex wrapper functions Giuliano Procida
@ 2020-04-23 15:44 ` Giuliano Procida
  2020-04-23 15:44 ` [PATCH 09/21] Use regex::match wrapper instead of regexec Giuliano Procida
                   ` (14 subsequent siblings)
  22 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-23 15:44 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

This patch eliminates all calls to regcomp except that by
regex::compile itself.

	* src/abg-corpus-priv.h: Mechanically substitute use of
	regcomp with regex::compile wrapper.
	* src/abg-suppression-priv.h: Ditto.

There are no behavioural changes.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-corpus-priv.h      |  16 +--
 src/abg-suppression-priv.h | 198 ++++++-------------------------------
 2 files changed, 38 insertions(+), 176 deletions(-)

diff --git a/src/abg-corpus-priv.h b/src/abg-corpus-priv.h
index e65f7c8f..544fac54 100644
--- a/src/abg-corpus-priv.h
+++ b/src/abg-corpus-priv.h
@@ -123,8 +123,8 @@ public:
 	     i != fns_suppress_regexps_.end();
 	     ++i)
 	  {
-	    regex_t_sptr r = sptr_utils::build_sptr(new regex_t);
-	    if (regcomp(r.get(), i->c_str(), REG_EXTENDED) == 0)
+	    regex_t_sptr r = regex::compile(*i);
+	    if (r)
 	      compiled_fns_suppress_regexp_.push_back(r);
 	  }
       }
@@ -145,8 +145,8 @@ public:
 	     i != fns_keep_regexps_.end();
 	     ++i)
 	  {
-	    regex_t_sptr r = sptr_utils::build_sptr(new regex_t);
-	    if (regcomp(r.get(), i->c_str(), REG_EXTENDED) == 0)
+	    regex_t_sptr r = regex::compile(*i);
+	    if (r)
 	      compiled_fns_keep_regexps_.push_back(r);
 	  }
       }
@@ -167,8 +167,8 @@ public:
 	     i != vars_suppress_regexps_.end();
 	     ++i)
 	  {
-	    regex_t_sptr r = sptr_utils::build_sptr(new regex_t);
-	    if (regcomp(r.get(), i->c_str(), REG_EXTENDED) == 0)
+	    regex_t_sptr r = regex::compile(*i);
+	    if (r)
 	      compiled_vars_suppress_regexp_.push_back(r);
 	  }
       }
@@ -189,8 +189,8 @@ public:
 	     i != vars_keep_regexps_.end();
 	     ++i)
 	  {
-	    regex_t_sptr r = sptr_utils::build_sptr(new regex_t);
-	    if (regcomp(r.get(), i->c_str(), REG_EXTENDED) == 0)
+	    regex_t_sptr r = regex::compile(*i);
+	    if (r)
 	      compiled_vars_keep_regexps_.push_back(r);
 	  }
       }
diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
index c37ceff6..4959cdbb 100644
--- a/src/abg-suppression-priv.h
+++ b/src/abg-suppression-priv.h
@@ -91,17 +91,8 @@ public:
   const regex::regex_t_sptr&
   get_file_name_regex() const
   {
-    if (!file_name_regex_)
-      {
-	if (!file_name_regex_str_.empty())
-	  {
-	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	    if (regcomp(r.get(),
-			file_name_regex_str_.c_str(),
-			REG_EXTENDED) == 0)
-	      file_name_regex_ = r;
-	  }
-      }
+    if (!file_name_regex_ && !file_name_regex_str_.empty())
+      file_name_regex_ = regex::compile(file_name_regex_str_);
     return file_name_regex_;
   }
 
@@ -116,17 +107,8 @@ public:
   const regex::regex_t_sptr&
   get_file_name_not_regex() const
   {
-    if (!file_name_not_regex_)
-      {
-	if (!file_name_not_regex_str_.empty())
-	  {
-	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	    if (regcomp(r.get(),
-			file_name_not_regex_str_.c_str(),
-			REG_EXTENDED) == 0)
-	      file_name_not_regex_ = r;
-	  }
-      }
+    if (!file_name_not_regex_ && !file_name_not_regex_str_.empty())
+      file_name_not_regex_ = regex::compile(file_name_not_regex_str_);
     return file_name_not_regex_;
   }
 
@@ -141,17 +123,8 @@ public:
   const regex::regex_t_sptr&
   get_soname_regex() const
   {
-    if (!soname_regex_)
-      {
-	if (!soname_regex_str_.empty())
-	  {
-	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	    if (regcomp(r.get(),
-			soname_regex_str_.c_str(),
-			REG_EXTENDED) == 0)
-	      soname_regex_ = r;
-	  }
-      }
+    if (!soname_regex_ && !soname_regex_str_.empty())
+      soname_regex_ = regex::compile(soname_regex_str_);
     return soname_regex_;
   }
 
@@ -166,17 +139,8 @@ public:
   const regex::regex_t_sptr&
   get_soname_not_regex() const
   {
-    if (!soname_not_regex_)
-      {
-	if (!soname_not_regex_str_.empty())
-	  {
-	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	    if (regcomp(r.get(),
-			soname_not_regex_str_.c_str(),
-			REG_EXTENDED) == 0)
-	      soname_not_regex_ = r;
-	  }
-      }
+    if (!soname_not_regex_ && !soname_not_regex_str_.empty())
+      soname_not_regex_ = regex::compile(soname_not_regex_str_);
     return soname_not_regex_;
   }
 
@@ -282,13 +246,7 @@ class function_suppression::parameter_spec::priv
   get_type_name_regex() const
   {
     if (!type_name_regex_ && !type_name_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    type_name_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  type_name_regex_ = r;
-      }
+      type_name_regex_ = regex::compile(type_name_regex_str_);
     return type_name_regex_;
   }
 }; // end class function_suppression::parameter_spec::priv
@@ -361,13 +319,7 @@ struct function_suppression::priv
   get_name_regex() const
   {
     if (!name_regex_ && !name_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    name_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  name_regex_ = r;
-      }
+      name_regex_ = regex::compile(name_regex_str_);
     return name_regex_;
   }
 
@@ -384,13 +336,7 @@ struct function_suppression::priv
   get_name_not_regex() const
   {
     if (!name_not_regex_ && !name_not_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    name_not_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  name_not_regex_ = r;
-      }
+      name_not_regex_ = regex::compile(name_not_regex_str_);
     return name_not_regex_;
   }
 
@@ -407,13 +353,7 @@ struct function_suppression::priv
   get_return_type_regex() const
   {
     if (!return_type_regex_ && !return_type_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    return_type_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  return_type_regex_ = r;
-      }
+      return_type_regex_ = regex::compile(return_type_regex_str_);
     return return_type_regex_;
   }
 
@@ -430,13 +370,7 @@ struct function_suppression::priv
   get_symbol_name_regex() const
   {
     if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    symbol_name_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  symbol_name_regex_ = r;
-      }
+      symbol_name_regex_ = regex::compile(symbol_name_regex_str_);
     return symbol_name_regex_;
   }
 
@@ -453,13 +387,7 @@ struct function_suppression::priv
   get_symbol_name_not_regex() const
   {
     if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    symbol_name_not_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  symbol_name_not_regex_ = r;
-      }
+      symbol_name_not_regex_ = regex::compile(symbol_name_not_regex_str_);
     return symbol_name_not_regex_;
   }
 
@@ -475,14 +403,8 @@ struct function_suppression::priv
   const regex::regex_t_sptr
   get_symbol_version_regex() const
   {
-    if (!symbol_version_regex_ && ! symbol_version_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    symbol_version_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  symbol_version_regex_ = r;
-      }
+    if (!symbol_version_regex_ && !symbol_version_regex_str_.empty())
+      symbol_version_regex_ = regex::compile(symbol_version_regex_str_);
     return symbol_version_regex_;
   }
 }; // end class function_suppression::priv
@@ -609,13 +531,7 @@ struct variable_suppression::priv
   get_name_regex() const
   {
     if (!name_regex_ && !name_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    name_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  name_regex_ = r;
-      }
+      name_regex_ = regex::compile(name_regex_str_);
     return name_regex_;
   }
 
@@ -632,13 +548,7 @@ struct variable_suppression::priv
   get_name_not_regex() const
   {
     if (!name_not_regex_ && !name_not_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    name_not_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  name_not_regex_ = r;
-      }
+      name_not_regex_ = regex::compile(name_not_regex_str_);
     return name_not_regex_;
   }
 
@@ -655,13 +565,7 @@ struct variable_suppression::priv
   get_symbol_name_regex() const
   {
     if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    symbol_name_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  symbol_name_regex_ = r;
-      }
+      symbol_name_regex_ = regex::compile(symbol_name_regex_str_);
     return symbol_name_regex_;
   }
 
@@ -678,12 +582,7 @@ struct variable_suppression::priv
   get_symbol_name_not_regex() const
   {
     if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(), symbol_name_not_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  symbol_name_not_regex_ = r;
-      }
+      symbol_name_not_regex_ = regex::compile(symbol_name_not_regex_str_);
     return symbol_name_not_regex_;
   }
 
@@ -700,13 +599,7 @@ struct variable_suppression::priv
   get_symbol_version_regex()  const
   {
     if (!symbol_version_regex_ && !symbol_version_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    symbol_version_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  symbol_version_regex_ = r;
-      }
+      symbol_version_regex_ = regex::compile(symbol_version_regex_str_);
     return symbol_version_regex_;
   }
 
@@ -723,13 +616,7 @@ struct variable_suppression::priv
   get_type_name_regex() const
   {
     if (!type_name_regex_ && !type_name_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    type_name_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  type_name_regex_ = r;
-      }
+      type_name_regex_ = regex::compile(type_name_regex_str_);
     return type_name_regex_;
   }
 };// end class variable_supppression::priv
@@ -809,17 +696,8 @@ public:
   const regex::regex_t_sptr
   get_type_name_regex() const
   {
-    if (!type_name_regex_)
-      {
-	if (!type_name_regex_str_.empty())
-	  {
-	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	    if (regcomp(r.get(),
-			type_name_regex_str_.c_str(),
-			REG_EXTENDED) == 0)
-	      type_name_regex_ = r;
-	  }
-      }
+    if (!type_name_regex_ && !type_name_regex_str_.empty())
+      type_name_regex_ = regex::compile(type_name_regex_str_);
     return type_name_regex_;
   }
 
@@ -841,17 +719,8 @@ public:
   const regex::regex_t_sptr
   get_type_name_not_regex() const
   {
-    if (!type_name_not_regex_)
-      {
-	if (!type_name_not_regex_str_.empty())
-	  {
-	    regex::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;
-	  }
-      }
+    if (!type_name_not_regex_ && !type_name_not_regex_str_.empty())
+      type_name_not_regex_ = regex::compile(type_name_not_regex_str_);
     return type_name_not_regex_;
   }
 
@@ -886,17 +755,10 @@ public:
   const regex::regex_t_sptr
   get_source_location_to_keep_regex() const
   {
-    if (!source_location_to_keep_regex_)
-      {
-	if (!source_location_to_keep_regex_str_.empty())
-	  {
-	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	    if (regcomp(r.get(),
-			source_location_to_keep_regex_str_.c_str(),
-			REG_EXTENDED) == 0)
-	      source_location_to_keep_regex_ = r;
-	  }
-      }
+    if (!source_location_to_keep_regex_
+	&& !source_location_to_keep_regex_str_.empty())
+      source_location_to_keep_regex_ =
+	  regex::compile(source_location_to_keep_regex_str_);
     return source_location_to_keep_regex_;
   }
 
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH 09/21] Use regex::match wrapper instead of regexec.
  2020-04-23 15:44 [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
                   ` (7 preceding siblings ...)
  2020-04-23 15:44 ` [PATCH 08/21] Use regex::compile wrapper instead of regcomp Giuliano Procida
@ 2020-04-23 15:44 ` Giuliano Procida
  2020-04-23 18:02   ` [PATCH v2 " Giuliano Procida
  2020-04-23 15:44 ` [PATCH 10/21] Refactor read_parameter_spec_from_string logic Giuliano Procida
                   ` (13 subsequent siblings)
  22 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-04-23 15:44 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

This patch eliminates all calls to regexec except that by regex::match
itself.

There are no behavioural changes.

	* src/abg-corpus-priv.h: Mechanically substitute use of
	regexec with regex::match wrapper.
	* src/abg-suppression-priv.h: Ditto.
	* src/abg-suppression.cc: Ditto.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-corpus-priv.h      |   8 +--
 src/abg-suppression-priv.h |  10 ++--
 src/abg-suppression.cc     | 119 +++++++++++--------------------------
 3 files changed, 44 insertions(+), 93 deletions(-)

diff --git a/src/abg-corpus-priv.h b/src/abg-corpus-priv.h
index 544fac54..2618e2d0 100644
--- a/src/abg-corpus-priv.h
+++ b/src/abg-corpus-priv.h
@@ -521,7 +521,7 @@ public:
 	   compiled_regex_fns_suppress().begin();
 	 i != compiled_regex_fns_suppress().end();
 	 ++i)
-      if (regexec(i->get(), frep.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(*i, frep))
 	{
 	  keep = false;
 	  break;
@@ -554,7 +554,7 @@ public:
 	     compiled_regex_fns_keep().begin();
 	   i != compiled_regex_fns_keep().end();
 	   ++i)
-	if (regexec(i->get(), frep.c_str(), 0, NULL, 0) == 0)
+	if (regex::match(*i, frep))
 	  {
 	    keep = true;
 	    break;
@@ -628,7 +628,7 @@ public:
 	   compiled_regex_vars_suppress().begin();
 	 i != compiled_regex_vars_suppress().end();
 	 ++i)
-      if (regexec(i->get(), frep.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(*i, frep))
 	{
 	  keep = false;
 	  break;
@@ -662,7 +662,7 @@ public:
 	       compiled_regex_vars_keep().begin();
 	     i != compiled_regex_vars_keep().end();
 	     ++i)
-	  if (regexec(i->get(), frep.c_str(), 0, NULL, 0) == 0)
+	  if (regex::match(*i, frep))
 	    {
 	      keep = true;
 	      break;
diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
index 4959cdbb..8043ebd9 100644
--- a/src/abg-suppression-priv.h
+++ b/src/abg-suppression-priv.h
@@ -160,14 +160,14 @@ public:
     if (regex::regex_t_sptr regexp = get_soname_regex())
       {
 	has_regexp = true;
-	if (regexec(regexp.get(), soname.c_str(), 0, NULL, 0) != 0)
+	if (!regex::match(regexp, soname))
 	  return false;
       }
 
     if (regex::regex_t_sptr regexp = get_soname_not_regex())
       {
 	has_regexp = true;
-	if (regexec(regexp.get(), soname.c_str(), 0, NULL, 0) == 0)
+	if (regex::match(regexp, soname))
 	  return false;
       }
 
@@ -195,16 +195,14 @@ public:
     if (regex::regex_t_sptr regexp = get_file_name_regex())
       {
 	has_regexp = true;
-	if (regexec(regexp.get(), binary_name.c_str(),
-	  0, NULL, 0) != 0)
+	if (!regex::match(regexp, binary_name))
 	  return false;
       }
 
     if (regex::regex_t_sptr regexp = get_file_name_not_regex())
       {
 	has_regexp = true;
-	if (regexec(regexp.get(), binary_name.c_str(),
-	  0, NULL, 0) == 0)
+	if (regex::match(regexp, binary_name))
 	  return false;
       }
 
diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index b600c88c..afedf6c7 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -994,18 +994,14 @@ suppression_matches_type_name(const type_suppression&	s,
 	  if (const 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)
+	      if (!regex::match(type_name_regex, type_name))
 		return false;
 	    }
 
 	  if (const 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)
+	      if (regex::match(type_name_not_regex, type_name))
 		return false;
 	    }
 	}
@@ -1052,7 +1048,7 @@ suppression_matches_type_location(const type_suppression&	s,
       loc.expand(loc_path, loc_line, loc_column);
 
       if (regex_t_sptr regexp = s.priv_->get_source_location_to_keep_regex())
-	if (regexec(regexp.get(), loc_path.c_str(), 0, NULL, 0) == 0)
+	if (regex::match(regexp, loc_path))
 	  return false;
 
       tools_utils::base_name(loc_path, loc_path_base);
@@ -2489,9 +2485,7 @@ function_suppression::suppresses_function(const function_decl* fn,
   const regex_t_sptr name_regex = priv_->get_name_regex();
   if (name_regex)
     {
-      if (regexec(name_regex.get(),
-		  fname.c_str(),
-		  0, NULL, 0) != 0)
+      if (!regex::match(name_regex, fname))
 	return false;
 
       if (get_allow_other_aliases()
@@ -2512,9 +2506,7 @@ function_suppression::suppresses_function(const function_decl* fn,
 	      for (elf_symbol_sptr a = sym->get_next_alias();
 		   a && !a->is_main_symbol();
 		   a = a->get_next_alias())
-		if (regexec(name_regex.get(),
-			    a->get_name().c_str(),
-			    0, NULL, 0) != 0)
+		if (!regex::match(name_regex, a->get_name()))
 		  return false;
 	    }
 	}
@@ -2524,9 +2516,7 @@ function_suppression::suppresses_function(const function_decl* fn,
   const regex_t_sptr name_not_regex = priv_->get_name_not_regex();
   if (name_not_regex)
     {
-      if (regexec(name_not_regex.get(),
-		  fname.c_str(),
-		  0, NULL, 0) == 0)
+      if (regex::match(name_not_regex, fname))
 	return false;
 
       if (get_allow_other_aliases()
@@ -2547,9 +2537,7 @@ function_suppression::suppresses_function(const function_decl* fn,
 	      for (elf_symbol_sptr a = sym->get_next_alias();
 		   a && !a->is_main_symbol();
 		   a = a->get_next_alias())
-		if (regexec(name_regex.get(),
-			    a->get_name().c_str(),
-			    0, NULL, 0) == 0)
+		if (regex::match(name_regex, a->get_name()))
 		  return false;
 	    }
 	}
@@ -2573,9 +2561,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     {
       const regex_t_sptr return_type_regex = priv_->get_return_type_regex();
       if (return_type_regex
-	  && (regexec(return_type_regex.get(),
-		      fn_return_type_name.c_str(),
-		      0, NULL, 0) != 0))
+	  && !regex::match(return_type_regex, fn_return_type_name))
 	return false;
     }
 
@@ -2612,18 +2598,13 @@ function_suppression::suppresses_function(const function_decl* fn,
   else if (sym)
     {
       const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
-      if (symbol_name_regex
-	  && (regexec(symbol_name_regex.get(),
-		      fn_sym_name.c_str(),
-		      0, NULL, 0) != 0))
+      if (symbol_name_regex && !regex::match(symbol_name_regex, fn_sym_name))
 	return false;
 
       const regex_t_sptr symbol_name_not_regex =
 	priv_->get_symbol_name_not_regex();
       if (symbol_name_not_regex
-	  && (regexec(symbol_name_not_regex.get(),
-		      fn_sym_name.c_str(),
-		      0, NULL, 0) == 0))
+	  && regex::match(symbol_name_not_regex, fn_sym_name))
 	return false;
 
       if (get_allow_other_aliases())
@@ -2638,15 +2619,11 @@ function_suppression::suppresses_function(const function_decl* fn,
 		   a = a->get_next_alias())
 		{
 		  if (symbol_name_regex
-		      && (regexec(symbol_name_regex.get(),
-				  a->get_name().c_str(),
-				  0, NULL, 0) != 0))
+		      && !regex::match(symbol_name_regex, a->get_name()))
 		    return false;
 
 		  if (symbol_name_not_regex
-		      && (regexec(symbol_name_not_regex.get(),
-				  a->get_name().c_str(),
-				  0, NULL, 0) == 0))
+		      && regex::match(symbol_name_not_regex, a->get_name()))
 		    return false;
 		}
 	    }
@@ -2665,9 +2642,7 @@ function_suppression::suppresses_function(const function_decl* fn,
       const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
       if (symbol_version_regex
-	  && (regexec(symbol_version_regex.get(),
-		      fn_sym_version.c_str(),
-		      0, NULL, 0) != 0))
+	  && !regex::match(symbol_version_regex, fn_sym_version))
 	return false;
     }
 
@@ -2708,9 +2683,8 @@ function_suppression::suppresses_function(const function_decl* fn,
 		(*p)->priv_->get_type_name_regex();
 	      if (parm_type_name_regex)
 		{
-		  if ((regexec(parm_type_name_regex.get(),
-			       fn_parm_type_qualified_name.c_str(),
-			       0, NULL, 0) != 0))
+		  if (!regex::match(parm_type_name_regex,
+				    fn_parm_type_qualified_name))
 		    return false;
 		}
 	    }
@@ -2798,10 +2772,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
   else if (!get_symbol_name_regex_str().empty())
     {
       const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
-      if (symbol_name_regex
-	  && (regexec(symbol_name_regex.get(),
-		      sym_name.c_str(),
-		      0, NULL, 0) != 0))
+      if (symbol_name_regex && !regex::match(symbol_name_regex, sym_name))
 	return false;
     }
   else
@@ -2818,9 +2789,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
       const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
       if (symbol_version_regex
-	  && (regexec(symbol_version_regex.get(),
-		      sym_version.c_str(),
-		      0, NULL, 0) != 0))
+	  && !regex::match(symbol_version_regex, sym_version))
 	return false;
     }
   else
@@ -2912,12 +2881,12 @@ suppression_matches_function_name(const suppr::function_suppression& s,
 {
   if (regex_t_sptr regexp = s.priv_->get_name_regex())
     {
-      if (regexec(regexp.get(), fn_name.c_str(), 0, NULL, 0) != 0)
+      if (!regex::match(regexp, fn_name))
 	return false;
     }
   else if (regex_t_sptr regexp = s.priv_->get_name_not_regex())
     {
-      if (regexec(regexp.get(), fn_name.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(regexp, fn_name))
 	return false;
     }
   else if (s.priv_->name_.empty())
@@ -2948,12 +2917,12 @@ suppression_matches_function_sym_name(const suppr::function_suppression& s,
 {
   if (regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
     {
-      if (regexec(regexp.get(), fn_linkage_name.c_str(), 0, NULL, 0) != 0)
+      if (!regex::match(regexp, fn_linkage_name))
 	return false;
     }
   else if (regex_t_sptr regexp = s.priv_->get_symbol_name_not_regex())
     {
-      if (regexec(regexp.get(), fn_linkage_name.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(regexp, fn_linkage_name))
 	return false;
     }
   else if (s.priv_->symbol_name_.empty())
@@ -2981,12 +2950,12 @@ suppression_matches_variable_name(const suppr::variable_suppression& s,
 {
   if (regex_t_sptr regexp = s.priv_->get_name_regex())
     {
-      if (regexec(regexp.get(), var_name.c_str(), 0, NULL, 0) != 0)
+      if (!regex::match(regexp, var_name))
 	return false;
     }
   else if (regex_t_sptr regexp = s.priv_->get_name_not_regex())
     {
-      if (regexec(regexp.get(), var_name.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(regexp, var_name))
 	return false;
     }
   else if (s.priv_->name_.empty())
@@ -3015,13 +2984,13 @@ suppression_matches_variable_sym_name(const suppr::variable_suppression& s,
 {
   if (regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
     {
-      if (regexec(regexp.get(), var_linkage_name.c_str(), 0, NULL, 0) != 0)
+      if (!regex::match(regexp, var_linkage_name))
 	return false;
     }
   else if (regex_t_sptr regexp =
 	   s.priv_->get_symbol_name_not_regex())
     {
-      if (regexec(regexp.get(), var_linkage_name.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(regexp, var_linkage_name))
 	return false;
     }
   else if (s.priv_->symbol_name_.empty())
@@ -3050,7 +3019,7 @@ suppression_matches_type(const suppr::type_suppression& s,
 {
   if (regex_t_sptr regexp = s.priv_->get_type_name_regex())
     {
-      if (regexec(regexp.get(), type_name.c_str(), 0, NULL, 0) != 0)
+      if (!regex::match(regexp, type_name))
 	return false;
     }
   else if (!s.get_type_name().empty())
@@ -3748,15 +3717,11 @@ variable_suppression::suppresses_variable(const var_decl* var,
       if (get_name().empty())
 	{
 	  const regex_t_sptr name_regex = priv_->get_name_regex();
-	  if (name_regex
-	      && (regexec(name_regex.get(), var_name.c_str(),
-			  0, NULL, 0) != 0))
+	  if (name_regex && !regex::match(name_regex, var_name))
 	    return false;
 
 	  const regex_t_sptr name_not_regex = priv_->get_name_not_regex();
-	  if (name_not_regex
-	      && (regexec(name_not_regex.get(), var_name.c_str(),
-			  0, NULL, 0) == 0))
+	  if (name_not_regex && regex::match(name_not_regex, var_name))
 	    return false;
 	}
     }
@@ -3772,16 +3737,12 @@ variable_suppression::suppresses_variable(const var_decl* var,
   else
     {
       const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
-      if (sym_name_regex
-	  && (regexec(sym_name_regex.get(), var_sym_name.c_str(),
-		      0, NULL, 0) != 0))
+      if (sym_name_regex && !regex::match(sym_name_regex, var_sym_name))
 	return false;
 
       const regex_t_sptr sym_name_not_regex =
 	priv_->get_symbol_name_not_regex();
-      if (sym_name_not_regex
-	  && (regexec(sym_name_not_regex.get(), var_sym_name.c_str(),
-		      0, NULL, 0) == 0))
+      if (sym_name_not_regex && regex::match(sym_name_not_regex, var_sym_name))
 	return false;
     }
 
@@ -3798,9 +3759,7 @@ variable_suppression::suppresses_variable(const var_decl* var,
       const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
       if (symbol_version_regex
-	  && (regexec(symbol_version_regex.get(),
-		      var_sym_version.c_str(),
-		      0, NULL, 0) != 0))
+	  && !regex::match(symbol_version_regex, var_sym_version))
 	return false;
     }
 
@@ -3818,9 +3777,7 @@ variable_suppression::suppresses_variable(const var_decl* var,
       if (get_type_name().empty())
 	{
 	  const regex_t_sptr type_name_regex = priv_->get_type_name_regex();
-	  if (type_name_regex
-	      && (regexec(type_name_regex.get(), var_type_name.c_str(),
-			  0, NULL, 0) != 0))
+	  if (type_name_regex && !regex::match(type_name_regex, var_type_name))
 	    return false;
 	}
     }
@@ -3911,9 +3868,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
   else if (!get_symbol_name_regex_str().empty())
     {
       const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
-      if (sym_name_regex
-	  && (regexec(sym_name_regex.get(), sym_name.c_str(),
-		      0, NULL, 0) != 0))
+      if (sym_name_regex && !regex::match(sym_name_regex, sym_name))
 	return false;
     }
   else
@@ -3931,9 +3886,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
       const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
       if (symbol_version_regex
-	  && (regexec(symbol_version_regex.get(),
-		      sym_version.c_str(),
-		      0, NULL, 0) != 0))
+	  && !regex::match(symbol_version_regex, sym_version))
 	return false;
     }
   else
@@ -4229,14 +4182,14 @@ file_suppression::suppresses_file(const string& file_path)
   if (regex_t_sptr regexp = suppression_base::priv_->get_file_name_regex())
     {
       has_regexp = true;
-      if (regexec(regexp.get(), fname.c_str(), 0, NULL, 0) != 0)
+      if (!regex::match(regexp, fname))
 	return false;
     }
 
   if (regex_t_sptr regexp = suppression_base::priv_->get_file_name_not_regex())
     {
       has_regexp = true;
-      if (regexec(regexp.get(), fname.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(regexp, fname))
 	return false;
     }
 
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH 10/21] Refactor read_parameter_spec_from_string logic.
  2020-04-23 15:44 [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
                   ` (8 preceding siblings ...)
  2020-04-23 15:44 ` [PATCH 09/21] Use regex::match wrapper instead of regexec Giuliano Procida
@ 2020-04-23 15:44 ` Giuliano Procida
  2020-04-23 15:44 ` [PATCH 11/21] Compile suppression regexes earlier Giuliano Procida
                   ` (12 subsequent siblings)
  22 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-23 15:44 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

This function extracts either a string or a regex from the same input.
This patch simplifies the string vs regex conditional logic, in order
to make following patches simpler.

There are no behavioural changes.

	* src/abg-suppression.cc (read_parameter_spec_from_string):
	Use separate string and regex variables to simplify the
	creation of returned parameter specification.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-suppression.cc | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index afedf6c7..1407eef3 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -3090,13 +3090,15 @@ read_parameter_spec_from_string(const string& str)
 
   if (!index_str.empty() || !type_name.empty())
     {
-      function_suppression::parameter_spec* p;
+      std::string type_name_regex;
       if (is_regex)
-	p = new function_suppression::parameter_spec(atoi(index_str.c_str()),
-						     "", type_name);
-      else
-	p = new function_suppression::parameter_spec(atoi(index_str.c_str()),
-						     type_name, "");
+	{
+	  type_name_regex = type_name;
+	  type_name.clear();
+	}
+      function_suppression::parameter_spec* p =
+	new function_suppression::parameter_spec(atoi(index_str.c_str()),
+						 type_name, type_name_regex);
       result.reset(p);
     }
 
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH 11/21] Compile suppression regexes earlier.
  2020-04-23 15:44 [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
                   ` (9 preceding siblings ...)
  2020-04-23 15:44 ` [PATCH 10/21] Refactor read_parameter_spec_from_string logic Giuliano Procida
@ 2020-04-23 15:44 ` Giuliano Procida
  2020-04-23 15:44 ` [PATCH 12/21] Reduce direct access to suppression priv_ members Giuliano Procida
                   ` (11 subsequent siblings)
  22 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-23 15:44 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

Regexes are used in suppression specifications for various things.
They are currently compiled on first use, rather than on construction
of the specifications.

This patches changes the suppression specification types to hold
compiled regexes directly which is a significant simplification and is
a prerequisite for early error reporting.

There are no behavioural changes.

	* include/abg-suppression.h (suppression_base): In
	constructor, take regex arguments as regex_t_sptr. Replace all
	set_*_regex_str and get_*_regex_str methods with set_*_regex
	and get_*_regex methods.
	(type_suppression): In constructor, take regex arguments as
	regex_t_sptr. Replace all set_*_regex_str and get_*_regex_str
	methods with set_*_regex and get_*_regex methods.
	(function_suppression): In constructor, take regex arguments
	as regex_t_sptr. Replace all set_*_regex_str and
	get_*_regex_str methods with set_*_regex and get_*_regex
	methods.
	(function_suppression::parameter_spec): In constructor, take
	regex arguments as regex_t_sptr. Replace all set_*_regex_str and
	get_*_regex_str methods with set_*_regex and get_*_regex
	methods.
	(variable_suppression): In constructor, take regex arguments
	as regex_t_sptr. Replace all set_*_regex_str and get_*_regex_str
	methods with set_*_regex and get_*_regex methods.
	(file_suppression): In constructor, take regex arguments
	as regex_t_sptr.
	* src/abg-suppression-priv.h (suppression_base::priv): Drop
	all *_regex_str_ members. Drop mutable qualifier on
	all *_regex_ members. In constructor, take regexes instead of
	strings for regex arguments. Update all get_*_regex methods to
	remove regex compilation and update comments.
	(function_suppression::parameter_spec::priv): Drop
	all *_regex_str_ members. Drop mutable qualifier on
	all *_regex_ members. In constructor, take regexes instead of
	strings for regex arguments. Update get_*_regex methods to
	remove regex compilation and update comments.
	(function_suppression::priv): Drop all *_regex_str_ members.
	Drop mutable qualifier on all *_regex_ members. In constructor,
	take regexes instead of strings for regex arguments. Update
	all get_*_regex methods to remove regex compilation and
	update comments.
	(variable_suppression::priv): Drop all *_regex_str_ members.
	Drop mutable qualifier on all *_regex_ members. In
	constructor, take regexes instead of strings for regex
	arguments. Update all get_*_regex methods to remove
	regex compilation and update comments.
	(type_suppression::priv): Drop all *_regex_str_ members.
	Drop mutable qualifier on all *_regex_ members. In constructor,
	take regexes instead of strings for regex arguments. Update
	all get_*_regex methods to remove regex compilation and
	update comments. Drop set_type_name_regex_str and
	get_type_name_regex_str methods.
	* src/abg-suppression.cc (suppression_base): In constructor,
	take regexes instead of strings for regex arguments. Replace
	all set_*_regex_str and get_*_regex_str methods with
	set_*_regex and get_*_regex methods. Update
	has_file_name_related_property and has_soname_related_property
	methods.
	(type_suppression): In constructor, take regexes instead of
	strings for regex arguments. Replace all set_*_regex_str and
	get_*_regex_str methods with set_*_regex and get_*_regex
	methods. Update has_file_name_related_property and
	has_soname_related_property methods.
	(read_type_suppression): Compile regexes instead of keeping
	them as strings. Pass them to type_suppression constructor and
	setters.
	(function_suppression::parameter_spec): In constructor, take
	regexes instead of strings for regex arguments. Replace all
	set_*_regex_str and get_*_regex_str methods with set_*_regex and
	get_*_regex methods.
	(function_suppression): In constructor, take regexes instead
	of strings for regex arguments. Replace all set_*_regex_str
	and get_*_regex_str methods with set_*_regex and get_*_regex
	methods. Update suppresses_function_symbol method.
	(read_parameter_spec_from_string): Change type of
	type_name_regex from string to regex and compile when needed.
	(read_function_suppression): Compile regexes instead of
	keeping them as strings. Pass them to function_suppression
	constructor and setters.
	(variable_suppression): In constructor, take regexes instead
	of strings for regex arguments. Replace all set_*_regex_str
	and get_*_regex_str methods with set_*_regex and get_*_regex
	methods.
	(file_suppression): In constructor, take regexes instead of
	strings for regex arguments. Replace all set_*_regex_str and
	get_*_regex_str methods with set_*_regex and get_*_regex
	methods.
	* src/abg-tools-utils.cc (handle_file_entry): Compile and
	check regex for /usr/include.
	(gen_suppr_spec_from_kernel_abi_whitelists):
	Compile and check whitelisting regex.
	* tests/test-kmi-whitelist.cc (random_symbols) Add array of
	symbols. (test_suppressions_are_consistent): Rework to test by
	matching regexes against symbols, now that uncompiled regex
	strings are no longer available.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 include/abg-suppression.h   | 165 +++++-----
 src/abg-suppression-priv.h  | 357 +++++---------------
 src/abg-suppression.cc      | 628 +++++++++++++++++++-----------------
 src/abg-tools-utils.cc      |  17 +-
 tests/test-kmi-whitelist.cc |  60 +++-
 5 files changed, 552 insertions(+), 675 deletions(-)

diff --git a/include/abg-suppression.h b/include/abg-suppression.h
index 4f1fb417..1869cbe5 100644
--- a/include/abg-suppression.h
+++ b/include/abg-suppression.h
@@ -26,6 +26,7 @@
 #include "abg-cxx-compat.h"
 #include "abg-ini.h"
 #include "abg-comparison.h"
+#include "abg-regex.h"
 
 namespace abigail
 {
@@ -64,8 +65,8 @@ public:
   suppression_base(const string& label);
 
   suppression_base(const string& label,
-		   const string& file_name_regex_str,
-		   const string& file_name_not_regex_str);
+		   const regex::regex_t_sptr& file_name_regex,
+		   const regex::regex_t_sptr& file_name_not_regex);
 
   bool
   get_drops_artifact_from_ir() const;
@@ -86,31 +87,31 @@ public:
   set_label(const string&);
 
   void
-  set_file_name_regex_str(const string& regexp);
+  set_file_name_regex(const regex::regex_t_sptr& regexp);
 
-  const string&
-  get_file_name_regex_str() const;
+  const regex::regex_t_sptr&
+  get_file_name_regex() const;
 
   void
-  set_file_name_not_regex_str(const string& regexp);
+  set_file_name_not_regex(const regex::regex_t_sptr& regexp);
 
-  const string&
-  get_file_name_not_regex_str() const;
+  const regex::regex_t_sptr&
+  get_file_name_not_regex() const;
 
   bool
   has_file_name_related_property() const;
 
   void
-  set_soname_regex_str(const string& regexp);
+  set_soname_regex(const regex::regex_t_sptr& regexp);
 
-  const string&
-  get_soname_regex_str() const;
+  const regex::regex_t_sptr&
+  get_soname_regex() const;
 
   void
-  set_soname_not_regex_str(const string& regexp);
+  set_soname_not_regex(const regex::regex_t_sptr& regexp);
 
-  const string&
-  get_soname_not_regex_str() const;
+  const regex::regex_t_sptr&
+  get_soname_not_regex() const;
 
   bool
   has_soname_related_property() const;
@@ -204,22 +205,22 @@ public:
   typedef vector<insertion_range_sptr> insertion_ranges;
 
   type_suppression(const string& label,
-		   const string& type_name_regexp,
+		   const regex::regex_t_sptr& type_name_regexp,
 		   const string& type_name);
 
   virtual ~type_suppression();
 
   void
-  set_type_name_regex_str(const string& name_regex_str);
+  set_type_name_regex(const regex::regex_t_sptr& name_regex);
 
-  const string&
-  get_type_name_regex_str() const;
+  const regex::regex_t_sptr&
+  get_type_name_regex() const;
 
   void
-  set_type_name_not_regex_str(const string& name_regex_str);
+  set_type_name_not_regex(const regex::regex_t_sptr& name_regex);
 
-  const string&
-  get_type_name_not_regex_str() const;
+  const regex::regex_t_sptr&
+  get_type_name_not_regex() const;
 
   void
   set_type_name(const string& name);
@@ -269,11 +270,11 @@ public:
   void
   set_source_locations_to_keep(const unordered_set<string>&);
 
-  const string&
-  get_source_location_to_keep_regex_str() const;
+  const regex::regex_t_sptr&
+  get_source_location_to_keep_regex() const;
 
   void
-  set_source_location_to_keep_regex_str(const string&);
+  set_source_location_to_keep_regex(const regex::regex_t_sptr&);
 
   const vector<string>&
   get_changed_enumerator_names() const;
@@ -460,16 +461,16 @@ public:
 
   function_suppression();
 
-  function_suppression(const string&		label,
-		       const string&		name,
-		       const string&		name_regex,
-		       const string&		return_type_name,
-		       const string&		return_type_regex,
-		       parameter_specs_type&	parm_specs,
-		       const string&		symbol_name,
-		       const string&		symbol_name_regex,
-		       const string&		symbol_version,
-		       const string&		symbol_version_regex_str);
+  function_suppression(const string&			label,
+		       const string&			name,
+		       const regex::regex_t_sptr&	name_regex,
+		       const string&			return_type_name,
+		       const regex::regex_t_sptr&	return_type_regex,
+		       parameter_specs_type&		parm_specs,
+		       const string&			symbol_name,
+		       const regex::regex_t_sptr&	symbol_name_regex,
+		       const string&			symbol_version,
+		       const regex::regex_t_sptr&	symbol_version_regex);
 
   virtual ~function_suppression();
 
@@ -488,17 +489,17 @@ public:
   void
   set_name(const string&);
 
-  const string&
-  get_name_regex_str() const;
+  const regex::regex_t_sptr&
+  get_name_regex() const;
 
   void
-  set_name_regex_str(const string&);
+  set_name_regex(const regex::regex_t_sptr&);
 
-  const string&
-  get_name_not_regex_str() const;
+  const regex::regex_t_sptr&
+  get_name_not_regex() const;
 
   void
-  set_name_not_regex_str(const string&);
+  set_name_not_regex(const regex::regex_t_sptr&);
 
   const string&
   get_return_type_name() const;
@@ -506,11 +507,11 @@ public:
   void
   set_return_type_name(const string&);
 
-  const string&
-  get_return_type_regex_str() const;
+  const regex::regex_t_sptr&
+  get_return_type_regex() const;
 
   void
-  set_return_type_regex_str(const string& r);
+  set_return_type_regex(const regex::regex_t_sptr& r);
 
   const parameter_specs_type&
   get_parameter_specs() const;
@@ -527,17 +528,17 @@ public:
   void
   set_symbol_name(const string& n);
 
-  const string&
-  get_symbol_name_regex_str() const;
+  const regex::regex_t_sptr&
+  get_symbol_name_regex() const;
 
   void
-  set_symbol_name_regex_str(const string&);
+  set_symbol_name_regex(const regex::regex_t_sptr&);
 
-  const string&
-  get_symbol_name_not_regex_str() const;
+  const regex::regex_t_sptr&
+  get_symbol_name_not_regex() const;
 
   void
-  set_symbol_name_not_regex_str(const string&);
+  set_symbol_name_not_regex(const regex::regex_t_sptr&);
 
   const string&
   get_symbol_version() const;
@@ -545,11 +546,11 @@ public:
   void
   set_symbol_version(const string&);
 
-  const string&
-  get_symbol_version_regex_str() const;
+  const regex::regex_t_sptr&
+  get_symbol_version_regex() const;
 
   void
-  set_symbol_version_regex_str(const string&);
+  set_symbol_version_regex(const regex::regex_t_sptr&);
 
   bool
   get_allow_other_aliases() const;
@@ -609,7 +610,7 @@ class function_suppression::parameter_spec
 public:
   parameter_spec(size_t index,
 		 const string& type_name,
-		 const string& type_name_regex);
+		 const regex::regex_t_sptr& type_name_regex);
 
   size_t
   get_index() const;
@@ -623,11 +624,11 @@ public:
   void
   set_parameter_type_name(const string&);
 
-  const string&
-  get_parameter_type_name_regex_str() const;
+  const regex::regex_t_sptr&
+  get_parameter_type_name_regex() const;
 
   void
-  set_parameter_type_name_regex_str(const string&);
+  set_parameter_type_name_regex(const regex::regex_t_sptr&);
 };// end class function_suppression::parameter_spec
 
 class variable_suppression;
@@ -679,13 +680,17 @@ public:
 
   variable_suppression(const string& label = "",
 		       const string& name = "",
-		       const string& name_regex_str = "",
+		       const regex::regex_t_sptr& name_regex =
+			 regex::regex_t_sptr(),
 		       const string& symbol_name = "",
-		       const string& symbol_name_regex_str = "",
+		       const regex::regex_t_sptr& symbol_name_regex =
+			 regex::regex_t_sptr(),
 		       const string& symbol_version = "",
-		       const string& symbol_version_regex_str = "",
+		       const regex::regex_t_sptr& symbol_version_regex =
+			 regex::regex_t_sptr(),
 		       const string& type_name = "",
-		       const string& type_name_regex_str = "");
+		       const regex::regex_t_sptr& type_name_regex =
+			 regex::regex_t_sptr());
 
   virtual ~variable_suppression();
 
@@ -704,17 +709,17 @@ public:
   void
   set_name(const string&);
 
-  const string&
-  get_name_regex_str() const;
+  const regex::regex_t_sptr&
+  get_name_regex() const;
 
   void
-  set_name_regex_str(const string&);
+  set_name_regex(const regex::regex_t_sptr&);
 
-  const string&
-  get_name_not_regex_str() const;
+  const regex::regex_t_sptr&
+  get_name_not_regex() const;
 
   void
-  set_name_not_regex_str(const string&);
+  set_name_not_regex(const regex::regex_t_sptr&);
 
   const string&
   get_symbol_name() const;
@@ -722,17 +727,17 @@ public:
   void
   set_symbol_name(const string&);
 
-  const string&
-  get_symbol_name_regex_str() const;
+  const regex::regex_t_sptr&
+  get_symbol_name_regex() const;
 
   void
-  set_symbol_name_regex_str(const string&);
+  set_symbol_name_regex(const regex::regex_t_sptr&);
 
-  const string&
-  get_symbol_name_not_regex_str() const;
+  const regex::regex_t_sptr&
+  get_symbol_name_not_regex() const;
 
   void
-  set_symbol_name_not_regex_str(const string&);
+  set_symbol_name_not_regex(const regex::regex_t_sptr&);
 
   const string&
   get_symbol_version() const;
@@ -740,11 +745,11 @@ public:
   void
   set_symbol_version(const string&);
 
-  const string&
-  get_symbol_version_regex_str() const;
+  const regex::regex_t_sptr&
+  get_symbol_version_regex() const;
 
   void
-  set_symbol_version_regex_str(const string&);
+  set_symbol_version_regex(const regex::regex_t_sptr&);
 
   const string&
   get_type_name() const;
@@ -752,11 +757,11 @@ public:
   void
   set_type_name(const string&);
 
-  const string&
-  get_type_name_regex_str() const;
+  const regex::regex_t_sptr&
+  get_type_name_regex() const;
 
   void
-  set_type_name_regex_str(const string&);
+  set_type_name_regex(const regex::regex_t_sptr&);
 
   bool
   suppresses_diff(const diff* d) const;
@@ -816,8 +821,8 @@ class file_suppression: public suppression_base
 public:
 
   file_suppression(const string& label,
-		   const string& file_name_regex,
-		   const string& file_name_not_regex);
+		   const regex::regex_t_sptr& file_name_regex,
+		   const regex::regex_t_sptr& file_name_not_regex);
 
   virtual bool
   suppresses_diff(const diff* diff) const;
diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
index 8043ebd9..263052d4 100644
--- a/src/abg-suppression-priv.h
+++ b/src/abg-suppression-priv.h
@@ -47,14 +47,10 @@ class suppression_base::priv
   bool					is_artificial_;
   bool					drops_artifact_;
   string				label_;
-  string				file_name_regex_str_;
-  mutable regex::regex_t_sptr		file_name_regex_;
-  string				file_name_not_regex_str_;
-  mutable regex::regex_t_sptr		file_name_not_regex_;
-  string				soname_regex_str_;
-  mutable regex::regex_t_sptr		soname_regex_;
-  string				soname_not_regex_str_;
-  mutable regex::regex_t_sptr		soname_not_regex_;
+  regex::regex_t_sptr			file_name_regex_;
+  regex::regex_t_sptr			file_name_not_regex_;
+  regex::regex_t_sptr			soname_regex_;
+  regex::regex_t_sptr			soname_not_regex_;
 
 public:
   priv()
@@ -69,78 +65,46 @@ public:
   {}
 
   priv(const string& label,
-       const string& file_name_regex_str,
-       const string& file_name_not_regex_str)
+       const regex::regex_t_sptr& file_name_regex,
+       const regex::regex_t_sptr& file_name_not_regex)
     : is_artificial_(),
       drops_artifact_(),
       label_(label),
-      file_name_regex_str_(file_name_regex_str),
-      file_name_not_regex_str_(file_name_not_regex_str)
+      file_name_regex_(file_name_regex),
+      file_name_not_regex_(file_name_not_regex)
   {}
 
   friend class suppression_base;
 
-  /// Get the regular expression object associated to the 'file_name_regex'
-  /// property of @ref suppression_base.
-  ///
-  /// If the regular expression object is not created, this method
-  /// creates it and returns it.
-  ///
-  /// If the 'file_name_regex' property of @ref suppression_base is
-  /// empty then this method returns nil.
+  /// Get the regular expression object associated to the
+  /// 'file_name_regex' property of @ref suppression_base.
   const regex::regex_t_sptr&
   get_file_name_regex() const
   {
-    if (!file_name_regex_ && !file_name_regex_str_.empty())
-      file_name_regex_ = regex::compile(file_name_regex_str_);
     return file_name_regex_;
   }
 
   /// Get the regular expression object associated to the
   /// 'file_name_not_regex' property of @ref suppression_base.
-  ///
-  /// If the regular expression object is not created, this method
-  /// creates it and returns it.
-  ///
-  /// If the 'file_name_not_regex' property of @ref suppression_base
-  /// is empty then this method returns nil.
   const regex::regex_t_sptr&
   get_file_name_not_regex() const
   {
-    if (!file_name_not_regex_ && !file_name_not_regex_str_.empty())
-      file_name_not_regex_ = regex::compile(file_name_not_regex_str_);
     return file_name_not_regex_;
   }
 
-  /// Get the regular expression object associated to the
-  /// 'soname_regex' property of @ref suppression_base.
-  ///
-  /// If the regular expression object is not created, this method
-  /// creates it and returns it.
-  ///
-  /// If the 'soname_regex' property of @ref suppression_base is empty
-  /// then this method returns nil.
+  /// Get the regular expression object associated to the 'soname_regex'
+  /// property of @ref suppression_base.
   const regex::regex_t_sptr&
   get_soname_regex() const
   {
-    if (!soname_regex_ && !soname_regex_str_.empty())
-      soname_regex_ = regex::compile(soname_regex_str_);
     return soname_regex_;
   }
 
   /// Get the regular expression object associated to the
   /// 'soname_not_regex' property of @ref suppression_base.
-  ///
-  /// If the regular expression object is not created, this method
-  /// creates it and returns it.
-  ///
-  /// If the 'soname_not_regex' property of @ref suppression_base is
-  /// empty then this method returns nil.
   const regex::regex_t_sptr&
   get_soname_not_regex() const
   {
-    if (!soname_not_regex_ && !soname_not_regex_str_.empty())
-      soname_not_regex_ = regex::compile(soname_not_regex_str_);
     return soname_not_regex_;
   }
 
@@ -225,8 +189,7 @@ class function_suppression::parameter_spec::priv
 
   size_t				index_;
   string				type_name_;
-  string				type_name_regex_str_;
-  mutable regex::regex_t_sptr		type_name_regex_;
+  regex::regex_t_sptr			type_name_regex_;
 
   priv()
     : index_()
@@ -236,15 +199,16 @@ class function_suppression::parameter_spec::priv
     : index_(i), type_name_(tn)
   {}
 
-  priv(size_t i, const string& tn, const string& tn_regex)
-    : index_(i), type_name_(tn), type_name_regex_str_(tn_regex)
+  priv(size_t i, const string& tn, const regex::regex_t_sptr& tn_regex)
+    : index_(i), type_name_(tn), type_name_regex_(tn_regex)
   {}
 
+  /// Get the regular expression object associated to the
+  /// 'type_name_regex' property of @ref
+  /// function_suppression::parameter_spec.
   const regex::regex_t_sptr
   get_type_name_regex() const
   {
-    if (!type_name_regex_ && !type_name_regex_str_.empty())
-      type_name_regex_ = regex::compile(type_name_regex_str_);
     return type_name_regex_;
   }
 }; // end class function_suppression::parameter_spec::priv
@@ -258,22 +222,16 @@ struct function_suppression::priv
 
   change_kind				change_kind_;
   string				name_;
-  string				name_regex_str_;
-  mutable regex::regex_t_sptr		name_regex_;
-  string				name_not_regex_str_;
-  mutable regex::regex_t_sptr		name_not_regex_;
+  regex::regex_t_sptr			name_regex_;
+  regex::regex_t_sptr			name_not_regex_;
   string				return_type_name_;
-  string				return_type_regex_str_;
-  mutable regex::regex_t_sptr		return_type_regex_;
+  regex::regex_t_sptr			return_type_regex_;
   parameter_specs_type			parm_specs_;
   string				symbol_name_;
-  string				symbol_name_regex_str_;
-  mutable regex::regex_t_sptr		symbol_name_regex_;
-  string				symbol_name_not_regex_str_;
-  mutable regex::regex_t_sptr		symbol_name_not_regex_;
+  regex::regex_t_sptr			symbol_name_regex_;
+  regex::regex_t_sptr			symbol_name_not_regex_;
   string				symbol_version_;
-  string				symbol_version_regex_str_;
-  mutable regex::regex_t_sptr		symbol_version_regex_;
+  regex::regex_t_sptr			symbol_version_regex_;
   bool					allow_other_aliases_;
 
   priv():
@@ -282,127 +240,72 @@ struct function_suppression::priv
   {}
 
   priv(const string&			name,
-       const string&			name_regex_str,
+       const regex::regex_t_sptr&	name_regex,
        const string&			return_type_name,
-       const string&			return_type_regex_str,
+       const regex::regex_t_sptr&	return_type_regex,
        const parameter_specs_type&	parm_specs,
        const string&			symbol_name,
-       const string&			symbol_name_regex_str,
+       const regex::regex_t_sptr&	symbol_name_regex,
        const string&			symbol_version,
-       const string&			symbol_version_regex_str)
+       const regex::regex_t_sptr&	symbol_version_regex)
     : change_kind_(ALL_CHANGE_KIND),
       name_(name),
-      name_regex_str_(name_regex_str),
+      name_regex_(name_regex),
       return_type_name_(return_type_name),
-      return_type_regex_str_(return_type_regex_str),
+      return_type_regex_(return_type_regex),
       parm_specs_(parm_specs),
       symbol_name_(symbol_name),
-      symbol_name_regex_str_(symbol_name_regex_str),
+      symbol_name_regex_(symbol_name_regex),
       symbol_version_(symbol_version),
-      symbol_version_regex_str_(symbol_version_regex_str),
+      symbol_version_regex_(symbol_version_regex),
       allow_other_aliases_(true)
   {}
 
-
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// function_suppression::priv::name_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// function_suppression::priv::name_regex_str_..
+  /// Get the regular expression object associated to the 'name_regex'
+  /// property of @ref function_suppression.
   const regex::regex_t_sptr
   get_name_regex() const
   {
-    if (!name_regex_ && !name_regex_str_.empty())
-      name_regex_ = regex::compile(name_regex_str_);
     return name_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// function_suppression::priv::name_not_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// function_suppression::priv::name_not_regex_str_..
+  /// Get the regular expression object associated to the
+  /// 'name_not_regex' property of @ref function_suppression.
   const regex::regex_t_sptr
   get_name_not_regex() const
   {
-    if (!name_not_regex_ && !name_not_regex_str_.empty())
-      name_not_regex_ = regex::compile(name_not_regex_str_);
     return name_not_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// function_suppression::priv::return_type_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// function_suppression::priv::return_type_regex_str_.
+  /// Get the regular expression object associated to the
+  /// 'return_type_regex' property of @ref function_suppression.
   const regex::regex_t_sptr
   get_return_type_regex() const
   {
-    if (!return_type_regex_ && !return_type_regex_str_.empty())
-      return_type_regex_ = regex::compile(return_type_regex_str_);
     return return_type_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// function_suppression::priv::symbol_name_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// function_suppression::priv::symbol_name_regex_str_.
+  /// Get the regular expression object associated to the
+  /// 'symbol_name_regex' property of @ref function_suppression.
   const regex::regex_t_sptr
   get_symbol_name_regex() const
   {
-    if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
-      symbol_name_regex_ = regex::compile(symbol_name_regex_str_);
     return symbol_name_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// function_suppression::priv::symbol_name_not_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// function_suppression::priv::symbol_name_not_regex_str_.
+  /// Get the regular expression object associated to the
+  /// 'symbol_name_not_regex' property of @ref function_suppression.
   const regex::regex_t_sptr
   get_symbol_name_not_regex() const
   {
-    if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
-      symbol_name_not_regex_ = regex::compile(symbol_name_not_regex_str_);
     return symbol_name_not_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// function_suppression::priv::symbol_version_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// function_suppression::priv::symbol_version_regex_str_.
+  /// Get the regular expression object associated to the
+  /// 'symbol_version_regex' property of @ref function_suppression.
   const regex::regex_t_sptr
   get_symbol_version_regex() const
   {
-    if (!symbol_version_regex_ && !symbol_version_regex_str_.empty())
-      symbol_version_regex_ = regex::compile(symbol_version_regex_str_);
     return symbol_version_regex_;
   }
 }; // end class function_suppression::priv
@@ -481,140 +384,80 @@ struct variable_suppression::priv
 
   change_kind				change_kind_;
   string				name_;
-  string				name_regex_str_;
-  mutable regex::regex_t_sptr		name_regex_;
-  string				name_not_regex_str_;
-  mutable regex::regex_t_sptr		name_not_regex_;
+  regex::regex_t_sptr			name_regex_;
+  regex::regex_t_sptr			name_not_regex_;
   string				symbol_name_;
-  string				symbol_name_regex_str_;
-  mutable regex::regex_t_sptr		symbol_name_regex_;
-  string				symbol_name_not_regex_str_;
-  mutable regex::regex_t_sptr		symbol_name_not_regex_;
+  regex::regex_t_sptr			symbol_name_regex_;
+  regex::regex_t_sptr			symbol_name_not_regex_;
   string				symbol_version_;
-  string				symbol_version_regex_str_;
-  mutable regex::regex_t_sptr		symbol_version_regex_;
+  regex::regex_t_sptr			symbol_version_regex_;
   string				type_name_;
-  string				type_name_regex_str_;
-  mutable regex::regex_t_sptr		type_name_regex_;
+  regex::regex_t_sptr			type_name_regex_;
 
   priv(const string& name,
-       const string& name_regex_str,
+       const regex::regex_t_sptr& name_regex,
        const string& symbol_name,
-       const string& symbol_name_regex_str,
+       const regex::regex_t_sptr& symbol_name_regex,
        const string& symbol_version,
-       const string& symbol_version_regex_str,
+       const regex::regex_t_sptr& symbol_version_regex,
        const string& type_name,
-       const string& type_name_regex_str)
+       const regex::regex_t_sptr& type_name_regex)
     : change_kind_(ALL_CHANGE_KIND),
       name_(name),
-      name_regex_str_(name_regex_str),
+      name_regex_(name_regex),
       symbol_name_(symbol_name),
-      symbol_name_regex_str_(symbol_name_regex_str),
+      symbol_name_regex_(symbol_name_regex),
       symbol_version_(symbol_version),
-      symbol_version_regex_str_(symbol_version_regex_str),
+      symbol_version_regex_(symbol_version_regex),
       type_name_(type_name),
-      type_name_regex_str_(type_name_regex_str)
+      type_name_regex_(type_name_regex)
   {}
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// variable_suppression::priv::name_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// variable_suppression::priv::name_regex_str_.
+  /// Get the regular expression object associated to the 'name_regex'
+  /// property of @ref variable_suppression.
   const regex::regex_t_sptr
   get_name_regex() const
   {
-    if (!name_regex_ && !name_regex_str_.empty())
-      name_regex_ = regex::compile(name_regex_str_);
     return name_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// variable_suppression::priv::name_not_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// variable_suppression::priv::name_not_regex_str_..
+  /// Get the regular expression object associated to the
+  /// 'name_not_regex' property of @ref variable_suppression.
   const regex::regex_t_sptr
   get_name_not_regex() const
   {
-    if (!name_not_regex_ && !name_not_regex_str_.empty())
-      name_not_regex_ = regex::compile(name_not_regex_str_);
     return name_not_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// variable_suppression::priv::symbol_name_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// variable_suppression::priv::symbol_name_regex_str_.
+  /// Get the regular expression object associated to the
+  /// 'symbol_name_regex' property of @ref variable_suppression.
   const regex::regex_t_sptr
   get_symbol_name_regex() const
   {
-    if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
-      symbol_name_regex_ = regex::compile(symbol_name_regex_str_);
     return symbol_name_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// variable_suppression::priv::symbol_name_not_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// variable_suppression::priv::symbol_name_not_regex_str_.
+  /// Get the regular expression object associated to the
+  /// 'symbol_name_not_regex' property of @ref variable_suppression.
   const regex::regex_t_sptr
   get_symbol_name_not_regex() const
   {
-    if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
-      symbol_name_not_regex_ = regex::compile(symbol_name_not_regex_str_);
     return symbol_name_not_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// variable_suppression::priv::symbol_version_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// variable_suppression::priv::symbol_version_regex_str_.
+  /// Get the regular expression object associated to the
+  /// 'symbol_version_regex' property of @ref variable_suppression.
   const regex::regex_t_sptr
   get_symbol_version_regex()  const
   {
-    if (!symbol_version_regex_ && !symbol_version_regex_str_.empty())
-      symbol_version_regex_ = regex::compile(symbol_version_regex_str_);
     return symbol_version_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// variable_suppression::priv::type_name_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// variable_suppression::priv::type_name_regex_str_.
+  /// Get the regular expression object associated to the
+  /// 'type_name_regex' property of @ref variable_suppression.
   const regex::regex_t_sptr
   get_type_name_regex() const
   {
-    if (!type_name_regex_ && !type_name_regex_str_.empty())
-      type_name_regex_ = regex::compile(type_name_regex_str_);
     return type_name_regex_;
   }
 };// end class variable_supppression::priv
@@ -651,31 +494,28 @@ variable_is_suppressed(const ReadContextType&	ctxt,
 /// The private data for @ref type_suppression.
 class type_suppression::priv
 {
-  string				type_name_regex_str_;
-  mutable regex::regex_t_sptr		type_name_regex_;
+  regex::regex_t_sptr			type_name_regex_;
   string				type_name_;
-  string				type_name_not_regex_str_;
-  mutable regex::regex_t_sptr		type_name_not_regex_;
+  regex::regex_t_sptr			type_name_not_regex_;
   bool					consider_type_kind_;
   type_suppression::type_kind		type_kind_;
   bool					consider_reach_kind_;
   type_suppression::reach_kind		reach_kind_;
   type_suppression::insertion_ranges	insertion_ranges_;
   unordered_set<string>			source_locations_to_keep_;
-  string				source_location_to_keep_regex_str_;
-  mutable regex::regex_t_sptr		source_location_to_keep_regex_;
+  regex::regex_t_sptr			source_location_to_keep_regex_;
   mutable vector<string>		changed_enumerator_names_;
 
   priv();
 
 public:
-  priv(const string&			type_name_regexp,
+  priv(const regex::regex_t_sptr&	type_name_regexp,
        const string&			type_name,
        bool				consider_type_kind,
        type_suppression::type_kind	type_kind,
        bool				consider_reach_kind,
        type_suppression::reach_kind	reach_kind)
-    : type_name_regex_str_(type_name_regexp),
+    : type_name_regex_(type_name_regexp),
       type_name_(type_name),
       consider_type_kind_(consider_type_kind),
       type_kind_(type_kind),
@@ -683,19 +523,11 @@ public:
       reach_kind_(reach_kind)
   {}
 
-  /// Get the regular expression object associated to the 'type_name_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_regex' property of @ref type_suppression is
-  /// empty then this method returns nil.
+  /// Get the regular expression object associated to the
+  /// 'type_name_regex' property of @ref type_suppression.
   const regex::regex_t_sptr
   get_type_name_regex() const
   {
-    if (!type_name_regex_ && !type_name_regex_str_.empty())
-      type_name_regex_ = regex::compile(type_name_regex_str_);
     return type_name_regex_;
   }
 
@@ -708,17 +540,9 @@ public:
 
   /// 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 regex::regex_t_sptr
   get_type_name_not_regex() const
   {
-    if (!type_name_not_regex_ && !type_name_not_regex_str_.empty())
-      type_name_not_regex_ = regex::compile(type_name_not_regex_str_);
     return type_name_not_regex_;
   }
 
@@ -729,34 +553,11 @@ public:
   set_type_name_not_regex(regex::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.
+  /// Get the regular expression object associated to the
+  /// 'source_location_to_keep_regex' property of @ref type_suppression.
   const regex::regex_t_sptr
   get_source_location_to_keep_regex() const
   {
-    if (!source_location_to_keep_regex_
-	&& !source_location_to_keep_regex_str_.empty())
-      source_location_to_keep_regex_ =
-	  regex::compile(source_location_to_keep_regex_str_);
     return source_location_to_keep_regex_;
   }
 
diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 1407eef3..5082536d 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -66,17 +66,17 @@ suppression_base::suppression_base(const string& label)
 /// @param a label for the suppression.  This represents just a
 /// comment.
 ///
-/// @param file_name_regex_str the regular expression that denotes the
+/// @param file_name_regex the regular expression that denotes the
 /// file name to match.
 ///
-/// @param file_name_not_regex_str the regular expression that denotes
+/// @param file_name_not_regex the regular expression that denotes
 /// the file name to *NOT* match.
 suppression_base::suppression_base(const string& label,
-				   const string& file_name_regex_str,
-				   const string& file_name_not_regex_str)
+				   const regex_t_sptr& file_name_regex,
+				   const regex_t_sptr& file_name_not_regex)
   : priv_(new priv(label,
-		   file_name_regex_str,
-		   file_name_not_regex_str))
+		   file_name_regex,
+		   file_name_not_regex))
 {
 }
 
@@ -144,8 +144,8 @@ suppression_base::set_label(const string& label)
 ///
 /// @param regexp the new regular expression string.
 void
-suppression_base::set_file_name_regex_str(const string& regexp)
-{priv_->file_name_regex_str_ = regexp;}
+suppression_base::set_file_name_regex(const regex_t_sptr& regexp)
+{priv_->file_name_regex_ = regexp;}
 
 /// Getter for the "file_name_regex" property of the current instance
 /// of @ref suppression_base.
@@ -155,9 +155,9 @@ suppression_base::set_file_name_regex_str(const string& regexp)
 /// suppression should apply to.
 ///
 /// @return the regular expression string.
-const string&
-suppression_base::get_file_name_regex_str() const
-{return priv_->file_name_regex_str_;}
+const regex_t_sptr&
+suppression_base::get_file_name_regex() const
+{return priv_->file_name_regex_;}
 
 /// Setter for the "file_name_not_regex" property of the current
 /// instance of @ref suppression_base.
@@ -169,8 +169,8 @@ suppression_base::get_file_name_regex_str() const
 ///
 /// @param regexp the new regular expression string.
 void
-suppression_base::set_file_name_not_regex_str(const string& regexp)
-{priv_->file_name_not_regex_str_ = regexp;}
+suppression_base::set_file_name_not_regex(const regex_t_sptr& regexp)
+{priv_->file_name_not_regex_ = regexp;}
 
 /// Getter for the "file_name_not_regex" property of the current
 /// instance of @ref suppression_base.
@@ -181,9 +181,9 @@ suppression_base::set_file_name_not_regex_str(const string& regexp)
 /// property.
 ///
 /// @return the regular expression string.
-const string&
-suppression_base::get_file_name_not_regex_str() const
-{return priv_->file_name_not_regex_str_;}
+const regex_t_sptr&
+suppression_base::get_file_name_not_regex() const
+{return priv_->file_name_not_regex_;}
 
 /// Test if the current suppression has a property related to file
 /// name.
@@ -193,35 +193,34 @@ suppression_base::get_file_name_not_regex_str() const
 bool
 suppression_base::has_file_name_related_property() const
 {
-  return (!(get_file_name_regex_str().empty()
-	    && get_file_name_not_regex_str().empty()));
+  return get_file_name_regex() || get_file_name_not_regex();
 }
 
-/// Setter of the "soname_regex_str property of the current instance
+/// Setter of the "soname_regex" property of the current instance
 /// of @ref suppression_base.
 ///
-/// The "soname_regex_str" is a regular expression string that
+/// The "soname_regex" is a regular expression string that
 /// designates the soname of the shared library that contains the ABI
 /// artifacts this suppression should apply to.
 ///
 /// @param regexp the new regular expression string.
 void
-suppression_base::set_soname_regex_str(const string& regexp)
-{priv_->soname_regex_str_ = regexp;}
+suppression_base::set_soname_regex(const regex_t_sptr& regexp)
+{priv_->soname_regex_ = regexp;}
 
-/// Getter of the "soname_regex_str property of the current instance
+/// Getter of the "soname_regex" property of the current instance
 /// of @ref suppression_base.
 ///
-/// The "soname_regex_str" is a regular expression string that
+/// The "soname_regex" is a regular expression string that
 /// designates the soname of the shared library that contains the ABI
 /// artifacts this suppression should apply to.
 ///
 /// @return the regular expression string.
-const string&
-suppression_base::get_soname_regex_str() const
-{return priv_->soname_regex_str_;}
+const regex_t_sptr&
+suppression_base::get_soname_regex() const
+{return priv_->soname_regex_;}
 
-/// Setter of the "soname_not_regex_str property of the current
+/// Setter of the "soname_not_regex" property of the current
 /// instance of @ref suppression_base.
 ///
 /// The current suppression specification should apply to ABI
@@ -231,10 +230,10 @@ suppression_base::get_soname_regex_str() const
 ///
 /// @param regexp the new regular expression string.
 void
-suppression_base::set_soname_not_regex_str(const string& regexp)
-{priv_->soname_not_regex_str_ = regexp;}
+suppression_base::set_soname_not_regex(const regex_t_sptr& regexp)
+{priv_->soname_not_regex_ = regexp;}
 
-/// Getter of the "soname_not_regex_str property of the current
+/// Getter of the "soname_not_regex" property of the current
 /// instance of @ref suppression_base.
 ///
 /// The current suppression specification should apply to ABI
@@ -243,9 +242,9 @@ suppression_base::set_soname_not_regex_str(const string& regexp)
 /// property.
 ///
 /// @return the regular expression string.
-const string&
-suppression_base::get_soname_not_regex_str() const
-{return priv_->soname_not_regex_str_;}
+const regex_t_sptr&
+suppression_base::get_soname_not_regex() const
+{return priv_->soname_not_regex_;}
 
 /// Test if the current suppression has a property related to SONAMEs.
 ///
@@ -254,8 +253,7 @@ suppression_base::get_soname_not_regex_str() const
 bool
 suppression_base::has_soname_related_property() const
 {
-  return (!(get_soname_regex_str().empty()
-	    && get_soname_not_regex_str().empty()));
+  return get_soname_regex() || get_soname_not_regex();
 }
 
 /// Check if the SONAMEs of the two binaries being compared match the
@@ -408,7 +406,7 @@ read_suppressions(const string& file_path,
 /// should not necessarily be populated.  It usually is either one or
 /// the other that the user wants.
 type_suppression::type_suppression(const string& label,
-				   const string& type_name_regexp,
+				   const regex_t_sptr& type_name_regexp,
 				   const string& type_name)
   : suppression_base(label),
     priv_(new priv(type_name_regexp,
@@ -428,10 +426,10 @@ type_suppression::~type_suppression()
 /// This sets a regular expression that specifies the family of types
 /// about which diff reports should be suppressed.
 ///
-/// @param name_regex_str the new regular expression to set.
+/// @param name_regex the new regular expression to set.
 void
-type_suppression::set_type_name_regex_str(const string& name_regex_str)
-{priv_->type_name_regex_str_ = name_regex_str;}
+type_suppression::set_type_name_regex(const regex_t_sptr& name_regex)
+{priv_->type_name_regex_ = name_regex;}
 
 /// Getter for the "type_name_regex" property of the type suppression
 /// specification.
@@ -440,11 +438,11 @@ type_suppression::set_type_name_regex_str(const string& name_regex_str)
 /// of types about which diff reports should be suppressed.
 ///
 /// @return the regular expression string.
-const string&
-type_suppression::get_type_name_regex_str() const
-{return priv_->type_name_regex_str_;}
+const regex_t_sptr&
+type_suppression::get_type_name_regex() const
+{return priv_->type_name_regex_;}
 
-/// Setter for the "type_name_not_regex_str" property of the type
+/// Setter for the "type_name_not_regex" property of the type
 /// suppression specification.
 ///
 /// This returns a regular expression string that specifies the family
@@ -452,19 +450,19 @@ type_suppression::get_type_name_regex_str() const
 ///
 /// @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);}
+type_suppression::set_type_name_not_regex(const regex_t_sptr& r)
+{priv_->set_type_name_not_regex(r);}
 
-/// Getter for the "type_name_not_regex_str" property of the type
+/// Getter for the "type_name_not_regex" 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();}
+const regex_t_sptr&
+type_suppression::get_type_name_not_regex() const
+{return priv_->type_name_not_regex_;}
 
 /// Setter for the name of the type about which diff reports should be
 /// suppressed.
@@ -616,17 +614,17 @@ type_suppression::set_source_locations_to_keep
 /// location paths of types that should not be suppressed.
 ///
 /// @return the regular expression string.
-const string&
-type_suppression::get_source_location_to_keep_regex_str() const
-{return priv_->source_location_to_keep_regex_str_;}
+const regex_t_sptr&
+type_suppression::get_source_location_to_keep_regex() const
+{return priv_->source_location_to_keep_regex_;}
 
 /// Setter of the regular expression string that designates the source
 /// location paths of types that should not be suppressed.
 ///
 /// @param r the new regular expression.
 void
-type_suppression::set_source_location_to_keep_regex_str(const string& r)
-{priv_->source_location_to_keep_regex_str_ = r;}
+type_suppression::set_source_location_to_keep_regex(const regex_t_sptr& r)
+{priv_->source_location_to_keep_regex_ = 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
@@ -1563,39 +1561,43 @@ read_type_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr file_name_regex_prop =
     is_simple_property(section.find_property("file_name_regexp"));
-  string file_name_regex_str =
-    file_name_regex_prop ? file_name_regex_prop->get_value()->as_string() : "";
+  regex_t_sptr file_name_regex;
+  if (file_name_regex_prop)
+    file_name_regex =
+      regex::compile(file_name_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr file_name_not_regex_prop =
     is_simple_property(section.find_property("file_name_not_regexp"));
-  string file_name_not_regex_str =
-    file_name_not_regex_prop
-    ? file_name_not_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr file_name_not_regex;
+  if (file_name_not_regex_prop)
+    file_name_not_regex =
+      regex::compile(file_name_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr soname_regex_prop =
     is_simple_property(section.find_property("soname_regexp"));
-  string soname_regex_str =
-    soname_regex_prop ? soname_regex_prop->get_value()->as_string() : "";
+  regex_t_sptr soname_regex;
+  if (soname_regex_prop)
+    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr soname_not_regex_prop =
     is_simple_property(section.find_property("soname_not_regexp"));
-  string soname_not_regex_str =
-    soname_not_regex_prop
-    ? soname_not_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr soname_not_regex;
+  if (soname_not_regex_prop)
+    soname_not_regex =
+      regex::compile(soname_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr name_regex_prop =
     is_simple_property(section.find_property("name_regexp"));
-  string name_regex_str = name_regex_prop
-    ? name_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr name_regex;
+  if (name_regex_prop)
+    name_regex = regex::compile(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()
-    : "";
+  regex_t_sptr name_not_regex;
+  if (name_not_regex_prop)
+    name_not_regex =
+      regex::compile(name_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr name_prop =
     is_simple_property(section.find_property("name"));
@@ -1627,9 +1629,10 @@ read_type_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr srcloc_not_regexp_prop =
     is_simple_property(section.find_property("source_location_not_regexp"));
-  string srcloc_not_regexp_str;
+  regex_t_sptr srcloc_not_regex;
   if (srcloc_not_regexp_prop)
-    srcloc_not_regexp_str = srcloc_not_regexp_prop->get_value()->as_string();
+    srcloc_not_regex =
+      regex::compile(srcloc_not_regexp_prop->get_value()->as_string());
 
   bool consider_type_kind = false;
   type_suppression::type_kind type_kind = type_suppression::UNKNOWN_TYPE_KIND;
@@ -1836,7 +1839,7 @@ read_type_suppression(const ini::config::section& section)
 	changed_enumerator_names.push_back(p->get_value()->as_string());
     }
 
-  result.reset(new type_suppression(label_str, name_regex_str, name_str));
+  result.reset(new type_suppression(label_str, name_regex, name_str));
 
   if (consider_type_kind)
     {
@@ -1853,31 +1856,31 @@ read_type_suppression(const ini::config::section& section)
   if (consider_data_member_insertion)
     result->set_data_member_insertion_ranges(insert_ranges);
 
-  if (!name_not_regex_str.empty())
-    result->set_type_name_not_regex_str(name_not_regex_str);
+  if (name_not_regex)
+    result->set_type_name_not_regex(name_not_regex);
 
-  if (!file_name_regex_str.empty())
-    result->set_file_name_regex_str(file_name_regex_str);
+  if (file_name_regex)
+    result->set_file_name_regex(file_name_regex);
 
-  if (!file_name_not_regex_str.empty())
-    result->set_file_name_not_regex_str(file_name_not_regex_str);
+  if (file_name_not_regex)
+    result->set_file_name_not_regex(file_name_not_regex);
 
-  if (!soname_regex_str.empty())
-    result->set_soname_regex_str(soname_regex_str);
+  if (soname_regex)
+    result->set_soname_regex(soname_regex);
 
-  if (!soname_not_regex_str.empty())
-    result->set_soname_not_regex_str(soname_not_regex_str);
+  if (soname_not_regex)
+    result->set_soname_not_regex(soname_not_regex);
 
   if (!srcloc_not_in.empty())
     result->set_source_locations_to_keep(srcloc_not_in);
 
-  if (!srcloc_not_regexp_str.empty())
-    result->set_source_location_to_keep_regex_str(srcloc_not_regexp_str);
+  if (srcloc_not_regex)
+    result->set_source_location_to_keep_regex(srcloc_not_regex);
 
   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
-      && ((!name_regex_str.empty()
+      && ((name_regex
 	   || !name_str.empty()
-	   || !srcloc_not_regexp_str.empty()
+	   || srcloc_not_regex
 	   || !srcloc_not_in.empty())))
     result->set_drops_artifact_from_ir(true);
 
@@ -1903,7 +1906,7 @@ read_type_suppression(const ini::config::section& section)
 /// account only if the parameter @p tn is empty.
 function_suppression::parameter_spec::parameter_spec(size_t i,
 						     const string& tn,
-						     const string& tn_regex)
+						     const regex_t_sptr& tn_regex)
   : priv_(new priv(i, tn, tn_regex))
 {}
 
@@ -1948,9 +1951,9 @@ function_suppression::parameter_spec::set_parameter_type_name(const string& tn)
 /// empty.
 ///
 /// @return the regular expression or the parameter type name.
-const string&
-function_suppression::parameter_spec::get_parameter_type_name_regex_str() const
-{return priv_->type_name_regex_str_;}
+const regex_t_sptr&
+function_suppression::parameter_spec::get_parameter_type_name_regex() const
+{return priv_->type_name_regex_;}
 
 /// Setter for the regular expression that defines a set of type names
 /// for the parameter designated by this specification.
@@ -1960,12 +1963,12 @@ function_suppression::parameter_spec::get_parameter_type_name_regex_str() const
 /// function_suppression::parameter_spec::get_parameter_type_name() is
 /// empty.
 ///
-/// @param type_name_regex_str the new type name regular expression to
+/// @param type_name_regex the new type name regular expression to
 /// set.
 void
-function_suppression::parameter_spec::set_parameter_type_name_regex_str
-(const string& type_name_regex_str)
-{priv_->type_name_regex_str_ = type_name_regex_str;}
+function_suppression::parameter_spec::set_parameter_type_name_regex
+(const regex_t_sptr& type_name_regex)
+{priv_->type_name_regex_ = type_name_regex;}
 
 /// Default constructor for the @ref function_suppression type.
 ///
@@ -2033,14 +2036,14 @@ function_suppression::function_suppression()
 /// case it's ignored at evaluation time.
 function_suppression::function_suppression(const string&		label,
 					   const string&		name,
-					   const string&		nr,
+					   const regex_t_sptr&		nr,
 					   const string&		ret_tn,
-					   const string&		ret_tr,
+					   const regex_t_sptr&		ret_tr,
 					   parameter_specs_type&	ps,
 					   const string&		sym_n,
-					   const string&		sym_nr,
+					   const regex_t_sptr&		sym_nr,
 					   const string&		sym_v,
-					   const string&		sym_vr)
+					   const regex_t_sptr&		sym_vr)
   : suppression_base(label),
     priv_(new priv(name, nr, ret_tn, ret_tr, ps,
 		   sym_n, sym_nr, sym_v, sym_vr))
@@ -2108,9 +2111,9 @@ function_suppression::set_name(const string& n)
 ///
 /// @return the regular expression for the possible names of the
 /// function(s).
-const string&
-function_suppression::get_name_regex_str() const
-{return priv_->name_regex_str_;}
+const regex_t_sptr&
+function_suppression::get_name_regex() const
+{return priv_->name_regex_;}
 
 /// Setter for a regular expression for a family of names of functions
 /// the user wants the current specification to designate.
@@ -2118,8 +2121,8 @@ function_suppression::get_name_regex_str() const
 /// @param r the new the regular expression for the possible names of
 /// the function(s).
 void
-function_suppression::set_name_regex_str(const string& r)
-{priv_->name_regex_str_ = r;}
+function_suppression::set_name_regex(const regex_t_sptr& r)
+{priv_->name_regex_ = r;}
 
 /// Getter for a regular expression of a family of names of functions
 /// the user wants the current specification to designate the negation
@@ -2127,9 +2130,9 @@ function_suppression::set_name_regex_str(const string& r)
 ///
 /// @return the regular expression for the possible names of the
 /// function(s).
-const string&
-function_suppression::get_name_not_regex_str() const
-{return priv_->name_not_regex_str_;}
+const regex_t_sptr&
+function_suppression::get_name_not_regex() const
+{return priv_->name_not_regex_;}
 
 /// Setter for a regular expression for a family of names of functions
 /// the user wants the current specification to designate the negation
@@ -2138,8 +2141,8 @@ function_suppression::get_name_not_regex_str() const
 /// @param r the new the regular expression for the possible names of
 /// the function(s).
 void
-function_suppression::set_name_not_regex_str(const string& r)
-{priv_->name_not_regex_str_ = r;}
+function_suppression::set_name_not_regex(const regex_t_sptr& r)
+{priv_->name_not_regex_ = r;}
 
 /// Getter for the name of the return type of the function the user
 /// wants this specification to designate.  This property might be
@@ -2171,9 +2174,9 @@ function_suppression::set_return_type_name(const string& tr)
 ///
 /// @return the regular expression for the possible names of the
 /// return types of the function(s).
-const string&
-function_suppression::get_return_type_regex_str() const
-{return priv_->return_type_regex_str_;}
+const regex_t_sptr&
+function_suppression::get_return_type_regex() const
+{return priv_->return_type_regex_;}
 
 /// Setter for a regular expression for a family of return type names
 /// for functions the user wants the current specification to
@@ -2188,8 +2191,8 @@ function_suppression::get_return_type_regex_str() const
 /// @param r the new regular expression for the possible names of the
 /// return types of the function(s) to set.
 void
-function_suppression::set_return_type_regex_str(const string& r)
-{priv_->return_type_regex_str_ = r;}
+function_suppression::set_return_type_regex(const regex_t_sptr& r)
+{priv_->return_type_regex_ = r;}
 
 /// Getter for a vector of parameter specifications to specify
 /// properties of the parameters of the functions the user wants this
@@ -2257,9 +2260,9 @@ function_suppression::set_symbol_name(const string& n)
 ///
 /// @return the regular expression for a family of names of symbols of
 /// functions to designate.
-const string&
-function_suppression::get_symbol_name_regex_str() const
-{return priv_->symbol_name_regex_str_;}
+const regex_t_sptr&
+function_suppression::get_symbol_name_regex() const
+{return priv_->symbol_name_regex_;}
 
 /// Setter for a regular expression for a family of names of symbols
 /// of functions the user wants this specification to designate.
@@ -2274,8 +2277,8 @@ function_suppression::get_symbol_name_regex_str() const
 /// @param r the new regular expression for a family of names of
 /// symbols of functions to set.
 void
-function_suppression::set_symbol_name_regex_str(const string& r)
-{priv_->symbol_name_regex_str_ = r;}
+function_suppression::set_symbol_name_regex(const regex_t_sptr& r)
+{priv_->symbol_name_regex_ = r;}
 
 /// Getter for a regular expression for a family of names of symbols
 /// of functions the user wants this specification to designate.
@@ -2292,9 +2295,9 @@ function_suppression::set_symbol_name_regex_str(const string& r)
 ///
 /// @return the regular expression string for a family of names of
 /// symbols that is to be *NOT* suppressed by this suppression specification.
-const string&
-function_suppression::get_symbol_name_not_regex_str() const
-{return priv_->symbol_name_not_regex_str_;}
+const regex_t_sptr&
+function_suppression::get_symbol_name_not_regex() const
+{return priv_->symbol_name_not_regex_;}
 
 /// Setter for a regular expression for a family of names of symbols
 /// of functions the user wants this specification to designate.
@@ -2313,8 +2316,8 @@ function_suppression::get_symbol_name_not_regex_str() const
 /// symbols that is to be *NOT* suppressed by this suppression
 /// specification.
 void
-function_suppression::set_symbol_name_not_regex_str(const string& r)
-{priv_->symbol_name_not_regex_str_ = r;}
+function_suppression::set_symbol_name_not_regex(const regex_t_sptr& r)
+{priv_->symbol_name_not_regex_ = r;}
 
 /// Getter for the name of the version of the symbol of the function
 /// the user wants this specification to designate.
@@ -2349,9 +2352,9 @@ function_suppression::set_symbol_version(const string& v)
 ///
 /// @return the regular expression for the versions of symbols of
 /// functions to designate.
-const string&
-function_suppression::get_symbol_version_regex_str() const
-{return priv_->symbol_version_regex_str_;}
+const regex_t_sptr&
+function_suppression::get_symbol_version_regex() const
+{return priv_->symbol_version_regex_;}
 
 /// Setter for a regular expression for a family of versions of
 /// symbols of functions the user wants the current specification to
@@ -2365,8 +2368,8 @@ function_suppression::get_symbol_version_regex_str() const
 /// @param the new regular expression for the versions of symbols of
 /// functions to designate.
 void
-function_suppression::set_symbol_version_regex_str(const string& r)
-{priv_->symbol_version_regex_str_ = r;}
+function_suppression::set_symbol_version_regex(const regex_t_sptr& r)
+{priv_->symbol_version_regex_ = r;}
 
 /// Getter for the "allow_other_aliases" property of the function
 /// suppression specification.
@@ -2769,7 +2772,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
       if (sym_name != get_symbol_name())
 	return false;
     }
-  else if (!get_symbol_name_regex_str().empty())
+  else if (get_symbol_name_regex())
     {
       const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
       if (symbol_name_regex && !regex::match(symbol_name_regex, sym_name))
@@ -2784,7 +2787,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
       if (sym_version != get_symbol_version())
 	return false;
     }
-  else if (!get_symbol_version_regex_str().empty())
+  else if (get_symbol_version_regex())
     {
       const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
@@ -3090,10 +3093,10 @@ read_parameter_spec_from_string(const string& str)
 
   if (!index_str.empty() || !type_name.empty())
     {
-      std::string type_name_regex;
+      regex_t_sptr type_name_regex;
       if (is_regex)
 	{
-	  type_name_regex = type_name;
+	  type_name_regex = regex::compile(type_name);
 	  type_name.clear();
 	}
       function_suppression::parameter_spec* p =
@@ -3143,27 +3146,30 @@ read_function_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr file_name_regex_prop =
     is_simple_property(section.find_property("file_name_regexp"));
-  string file_name_regex_str =
-    file_name_regex_prop ? file_name_regex_prop->get_value()->as_string() : "";
+  regex_t_sptr file_name_regex;
+  if (file_name_regex_prop)
+    file_name_regex =
+      regex::compile(file_name_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr file_name_not_regex_prop =
     is_simple_property(section.find_property("file_name_not_regexp"));
-  string file_name_not_regex_str =
-    file_name_not_regex_prop
-    ? file_name_not_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr file_name_not_regex;
+  if (file_name_not_regex_prop)
+    file_name_not_regex =
+      regex::compile(file_name_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr soname_regex_prop =
     is_simple_property(section.find_property("soname_regexp"));
-  string soname_regex_str =
-    soname_regex_prop ? soname_regex_prop->get_value()->as_string() : "";
+  regex_t_sptr soname_regex;
+  if (soname_regex_prop)
+    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr soname_not_regex_prop =
     is_simple_property(section.find_property("soname_not_regexp"));
-  string soname_not_regex_str =
-    soname_not_regex_prop
-    ? soname_not_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr soname_not_regex;
+  if (soname_not_regex_prop)
+    soname_not_regex =
+      regex::compile(soname_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr name_prop =
     is_simple_property(section.find_property("name"));
@@ -3173,15 +3179,16 @@ read_function_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr name_regex_prop =
     is_simple_property(section.find_property("name_regexp"));
-  string name_regex_str = name_regex_prop
-    ? name_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr name_regex;
+  if (name_regex_prop)
+    name_regex = regex::compile(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()
-    : "";
+  regex_t_sptr name_not_regex;
+  if (name_not_regex_prop)
+    name_not_regex =
+      regex::compile(name_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr return_type_name_prop =
     is_simple_property(section.find_property("return_type_name"));
@@ -3191,9 +3198,10 @@ read_function_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr return_type_regex_prop =
     is_simple_property(section.find_property("return_type_regexp"));
-  string return_type_regex_str = return_type_regex_prop
-    ? return_type_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr return_type_regex;
+  if (return_type_regex_prop)
+    return_type_regex =
+      regex::compile(return_type_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr sym_name_prop =
     is_simple_property(section.find_property("symbol_name"));
@@ -3203,15 +3211,17 @@ read_function_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr sym_name_regex_prop =
     is_simple_property(section.find_property("symbol_name_regexp"));
-  string sym_name_regex_str = sym_name_regex_prop
-    ? sym_name_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr sym_name_regex;
+  if (sym_name_regex_prop)
+    sym_name_regex =
+      regex::compile(sym_name_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr sym_name_not_regex_prop =
     is_simple_property(section.find_property("symbol_name_not_regexp"));
-  string sym_name_not_regex_str = sym_name_not_regex_prop
-    ? sym_name_not_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr sym_name_not_regex;
+  if (sym_name_not_regex_prop)
+    sym_name_not_regex =
+      regex::compile(sym_name_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr sym_ver_prop =
     is_simple_property(section.find_property("symbol_version"));
@@ -3221,9 +3231,10 @@ read_function_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr sym_ver_regex_prop =
     is_simple_property(section.find_property("symbol_version_regexp"));
-  string sym_ver_regex_str = sym_ver_regex_prop
-    ? sym_ver_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr sym_ver_regex;
+  if (sym_ver_regex_prop)
+    sym_ver_regex =
+      regex::compile(sym_ver_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr allow_other_aliases_prop =
     is_simple_property(section.find_property("allow_other_aliases"));
@@ -3248,22 +3259,22 @@ read_function_suppression(const ini::config::section& section)
 
   result.reset(new function_suppression(label_str,
 					name,
-					name_regex_str,
+					name_regex,
 					return_type_name,
-					return_type_regex_str,
+					return_type_regex,
 					parms,
 					sym_name,
-					sym_name_regex_str,
+					sym_name_regex,
 					sym_version,
-					sym_ver_regex_str));
+					sym_ver_regex));
 
   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
       && (!name.empty()
-	  || !name_regex_str.empty()
-	  || !name_not_regex_str.empty()
+	  || name_regex
+	  || name_not_regex
 	  || !sym_name.empty()
-	  || !sym_name_regex_str.empty()
-	  || !sym_name_not_regex_str.empty()))
+	  || sym_name_regex
+	  || sym_name_not_regex))
     result->set_drops_artifact_from_ir(true);
 
   if (!change_kind_str.empty())
@@ -3274,23 +3285,23 @@ read_function_suppression(const ini::config::section& section)
     result->set_allow_other_aliases(allow_other_aliases == "yes"
 				    || allow_other_aliases == "true");
 
-  if (!name_not_regex_str.empty())
-    result->set_name_not_regex_str(name_not_regex_str);
+  if (name_not_regex)
+    result->set_name_not_regex(name_not_regex);
 
-  if (!sym_name_not_regex_str.empty())
-    result->set_symbol_name_not_regex_str(sym_name_not_regex_str);
+  if (sym_name_not_regex)
+    result->set_symbol_name_not_regex(sym_name_not_regex);
 
-  if (!file_name_regex_str.empty())
-    result->set_file_name_regex_str(file_name_regex_str);
+  if (file_name_regex)
+    result->set_file_name_regex(file_name_regex);
 
-  if (!file_name_not_regex_str.empty())
-    result->set_file_name_not_regex_str(file_name_not_regex_str);
+  if (file_name_not_regex)
+    result->set_file_name_not_regex(file_name_not_regex);
 
-  if (!soname_regex_str.empty())
-    result->set_soname_regex_str(soname_regex_str);
+  if (soname_regex)
+    result->set_soname_regex(soname_regex);
 
-  if (!soname_not_regex_str.empty())
-    result->set_soname_not_regex_str(soname_not_regex_str);
+  if (soname_not_regex)
+    result->set_soname_not_regex(soname_not_regex);
 
   return result;
 }
@@ -3310,7 +3321,7 @@ read_function_suppression(const ini::config::section& section)
 /// specification to designate.  This parameter might be empty, in
 /// which case it's ignored at evaluation time.
 ///
-/// @param name_regex_str if @p name is empty, this parameter is a
+/// @param name_regex if @p name is empty, this parameter is a
 /// regular expression for a family of names of variables the user
 /// wants the current specification to designate.  If @p name is not
 /// empty, then this parameter is ignored at evaluation time.  This
@@ -3344,7 +3355,7 @@ read_function_suppression(const ini::config::section& section)
 /// wants the current specification to designate.  This parameter
 /// might be empty, in which case it's ignored at evaluation time.
 ///
-/// @param type_name_regex_str if @p type_name is empty, then this
+/// @param type_name_regex if @p type_name is empty, then this
 /// parameter is a regular expression for a family of type names of
 /// variables the user wants the current specification to designate.
 /// If @p type_name is not empty, then this parameter is ignored at
@@ -3352,18 +3363,18 @@ read_function_suppression(const ini::config::section& section)
 /// ignored at evaluation time.
 variable_suppression::variable_suppression(const string& label,
 					   const string& name,
-					   const string& name_regex_str,
+					   const regex_t_sptr& name_regex,
 					   const string& symbol_name,
-					   const string& symbol_name_regex_str,
+					   const regex_t_sptr& symbol_name_regex,
 					   const string& symbol_version,
-					   const string& symbol_version_regex,
+					   const regex_t_sptr& symbol_version_regex,
 					   const string& type_name,
-					   const string& type_name_regex_str)
+					   const regex_t_sptr& type_name_regex)
   : suppression_base(label),
-    priv_(new priv(name, name_regex_str,
-		   symbol_name, symbol_name_regex_str,
+    priv_(new priv(name, name_regex,
+		   symbol_name, symbol_name_regex,
 		   symbol_version, symbol_version_regex,
-		   type_name, type_name_regex_str))
+		   type_name, type_name_regex))
 {}
 
 /// Virtual destructor for the @erf variable_suppression type.
@@ -3433,9 +3444,9 @@ variable_suppression::set_name(const string& n)
 /// which case it's ignored at evaluation time.
 ///
 /// @return the regular expression for the variable name.
-const string&
-variable_suppression::get_name_regex_str() const
-{return priv_->name_regex_str_;}
+const regex_t_sptr&
+variable_suppression::get_name_regex() const
+{return priv_->name_regex_;}
 
 /// Setter for the regular expression for a family of names of
 /// variables the user wants the current specification to designate.
@@ -3446,22 +3457,22 @@ variable_suppression::get_name_regex_str() const
 ///
 /// @param r the new regular expression for the variable name.
 void
-variable_suppression::set_name_regex_str(const string& r)
-{priv_->name_regex_str_ = r;}
+variable_suppression::set_name_regex(const regex_t_sptr& r)
+{priv_->name_regex_ = r;}
 
 /// Getter for the "name_not_regexp" property of the specification.
 ///
 /// @return the value of the "name_not_regexp" property.
-const string&
-variable_suppression::get_name_not_regex_str() const
-{return priv_->name_not_regex_str_;}
+const regex_t_sptr&
+variable_suppression::get_name_not_regex() const
+{return priv_->name_not_regex_;}
 
 /// Setter for the "name_not_regexp" property of the specification.
 ///
 /// @param r the new value of the "name_not_regexp" property.
 void
-variable_suppression::set_name_not_regex_str(const string& r)
-{priv_->name_not_regex_str_ = r;}
+variable_suppression::set_name_not_regex(const regex_t_sptr& r)
+{priv_->name_not_regex_ = r;}
 
 /// Getter for the name of the symbol of the variable the user wants
 /// the current specification to designate.
@@ -3494,9 +3505,9 @@ variable_suppression::set_symbol_name(const string& n)
 /// empty.
 ///
 /// @return the regular expression for a symbol name of the variable.
-const string&
-variable_suppression::get_symbol_name_regex_str() const
-{return priv_->symbol_name_regex_str_;}
+const regex_t_sptr&
+variable_suppression::get_symbol_name_regex() const
+{return priv_->symbol_name_regex_;}
 
 /// Setter of the regular expression for a family of symbol names of
 /// the variables this specification is about to designate.
@@ -3508,8 +3519,8 @@ variable_suppression::get_symbol_name_regex_str() const
 ///
 /// @param r the regular expression for a symbol name of the variable.
 void
-variable_suppression::set_symbol_name_regex_str(const string& r)
-{priv_->symbol_name_regex_str_ = r;}
+variable_suppression::set_symbol_name_regex(const regex_t_sptr& r)
+{priv_->symbol_name_regex_ = r;}
 
 /// Getter for a regular expression for a family of names of symbols
 /// of variables the user wants this specification to designate.
@@ -3526,9 +3537,9 @@ variable_suppression::set_symbol_name_regex_str(const string& r)
 ///
 /// @return the regular expression string for a family of names of
 /// symbols that is to be *NOT* suppressed by this suppression specification.
-const string&
-variable_suppression::get_symbol_name_not_regex_str() const
-{return priv_->symbol_name_not_regex_str_;}
+const regex_t_sptr&
+variable_suppression::get_symbol_name_not_regex() const
+{return priv_->symbol_name_not_regex_;}
 
 /// Setter for a regular expression for a family of names of symbols
 /// of variables the user wants this specification to designate.
@@ -3547,8 +3558,8 @@ variable_suppression::get_symbol_name_not_regex_str() const
 /// symbols that is to be *NOT* suppressed by this suppression
 /// specification.
 void
-variable_suppression::set_symbol_name_not_regex_str(const string& r)
-{priv_->symbol_name_not_regex_str_ = r;}
+variable_suppression::set_symbol_name_not_regex(const regex_t_sptr& r)
+{priv_->symbol_name_not_regex_ = r;}
 
 /// Getter for the version of the symbol of the variable the user
 /// wants the current specification to designate.  This property might
@@ -3576,9 +3587,9 @@ variable_suppression::set_symbol_version(const string& v)
 ///
 /// @return the regular expression of the symbol version of the
 /// variable.
-const string&
-variable_suppression::get_symbol_version_regex_str() const
-{return priv_->symbol_version_regex_str_;}
+const regex_t_sptr&
+variable_suppression::get_symbol_version_regex() const
+{return priv_->symbol_version_regex_;}
 
 /// Setter of the regular expression for a family of versions of
 /// symbol for the variables the user wants the current specification
@@ -3589,8 +3600,8 @@ variable_suppression::get_symbol_version_regex_str() const
 /// @param v the new regular expression of the symbol version of the
 /// variable.
 void
-variable_suppression::set_symbol_version_regex_str(const string& r)
-{priv_->symbol_version_regex_str_ = r;}
+variable_suppression::set_symbol_version_regex(const regex_t_sptr& r)
+{priv_->symbol_version_regex_ = r;}
 
 /// Getter for the name of the type of the variable the user wants the
 /// current specification to designate.
@@ -3623,9 +3634,9 @@ variable_suppression::set_type_name(const string& n)
 /// empty, in which case it's ignored at evaluation time.
 ///
 /// @return the regular expression of the variable type name.
-const string&
-variable_suppression::get_type_name_regex_str() const
-{return priv_->type_name_regex_str_;}
+const regex_t_sptr&
+variable_suppression::get_type_name_regex() const
+{return priv_->type_name_regex_;}
 
 /// Setter for the regular expression for a family of type names of
 /// variables the user wants the current specification to designate.
@@ -3637,8 +3648,8 @@ variable_suppression::get_type_name_regex_str() const
 ///
 /// @param r the regular expression of the variable type name.
 void
-variable_suppression::set_type_name_regex_str(const string& r)
-{priv_->type_name_regex_str_ = r;}
+variable_suppression::set_type_name_regex(const regex_t_sptr& r)
+{priv_->type_name_regex_ = r;}
 
 /// Evaluate this suppression specification on a given diff node and
 /// say if the diff node should be suppressed or not.
@@ -3867,7 +3878,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
       if (get_symbol_name() != sym_name)
 	return false;
     }
-  else if (!get_symbol_name_regex_str().empty())
+  else if (get_symbol_name_regex())
     {
       const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
       if (sym_name_regex && !regex::match(sym_name_regex, sym_name))
@@ -3883,7 +3894,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
       if (get_symbol_version() != sym_version)
 	return false;
     }
-  else if (!get_symbol_version_regex_str().empty())
+  else if (get_symbol_version_regex())
     {
       const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
@@ -4001,27 +4012,30 @@ read_variable_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr file_name_regex_prop =
     is_simple_property(section.find_property("file_name_regexp"));
-  string file_name_regex_str =
-    file_name_regex_prop ? file_name_regex_prop->get_value()->as_string() : "";
+  regex_t_sptr file_name_regex;
+  if (file_name_regex_prop)
+    file_name_regex =
+      regex::compile(file_name_regex_prop->get_value()->as_string());
 
  ini::simple_property_sptr file_name_not_regex_prop =
-    is_simple_property(section.find_property("file_name_not_regexp"));
-  string file_name_not_regex_str =
-    file_name_not_regex_prop
-    ? file_name_not_regex_prop->get_value()->as_string()
-    : "";
+  is_simple_property(section.find_property("file_name_not_regexp"));
+ regex_t_sptr file_name_not_regex;
+ if (file_name_not_regex_prop)
+   file_name_not_regex =
+     regex::compile(file_name_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr soname_regex_prop =
     is_simple_property(section.find_property("soname_regexp"));
-  string soname_regex_str =
-    soname_regex_prop ? soname_regex_prop->get_value()->as_string() : "";
+  regex_t_sptr soname_regex;
+  if (soname_regex_prop)
+    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr soname_not_regex_prop =
     is_simple_property(section.find_property("soname_not_regexp"));
-  string soname_not_regex_str =
-    soname_not_regex_prop
-    ? soname_not_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr soname_not_regex;
+  if (soname_not_regex_prop)
+    soname_not_regex =
+      regex::compile(soname_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr name_prop =
     is_simple_property(section.find_property("name"));
@@ -4031,15 +4045,16 @@ read_variable_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr name_regex_prop =
     is_simple_property(section.find_property("name_regexp"));
-  string name_regex_str = (name_regex_prop
-			   ? name_regex_prop->get_value()->as_string()
-			   : "");
+  regex_t_sptr name_regex;
+  if (name_regex_prop)
+    name_regex = regex::compile(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()
-    : "";
+  regex_t_sptr name_not_regex;
+  if (name_not_regex_prop)
+    name_not_regex =
+      regex::compile(name_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr sym_name_prop =
     is_simple_property(section.find_property("symbol_name"));
@@ -4049,15 +4064,17 @@ read_variable_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr sym_name_regex_prop =
     is_simple_property(section.find_property("symbol_name_regexp"));
-  string symbol_name_regex_str = sym_name_regex_prop
-    ? sym_name_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr symbol_name_regex;
+  if (sym_name_regex_prop)
+    symbol_name_regex =
+      regex::compile(sym_name_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr sym_name_not_regex_prop =
     is_simple_property(section.find_property("symbol_name_not_regexp"));
-  string symbol_name_not_regex_str = sym_name_not_regex_prop
-    ? sym_name_not_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr symbol_name_not_regex;
+  if (sym_name_not_regex_prop)
+    symbol_name_not_regex =
+      regex::compile(sym_name_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr sym_version_prop =
     is_simple_property(section.find_property("symbol_version"));
@@ -4067,9 +4084,10 @@ read_variable_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr sym_version_regex_prop =
     is_simple_property(section.find_property("symbol_version_regexp"));
-  string symbol_version_regex_str = sym_version_regex_prop
-    ? sym_version_regex_prop->get_value()->as_string()
-     : "";
+  regex_t_sptr symbol_version_regex;
+  if (sym_version_regex_prop)
+    symbol_version_regex =
+      regex::compile(sym_version_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr type_name_prop =
     is_simple_property(section.find_property("type_name"));
@@ -4079,50 +4097,51 @@ read_variable_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr type_name_regex_prop =
     is_simple_property(section.find_property("type_name_regexp"));
-  string type_name_regex_str = type_name_regex_prop
-    ? type_name_regex_prop->get_value()->as_string()
-     : "";
+  regex_t_sptr type_name_regex;
+  if (type_name_regex_prop)
+    type_name_regex =
+      regex::compile(type_name_regex_prop->get_value()->as_string());
 
   result.reset(new variable_suppression(label_str,
 					name_str,
-					name_regex_str,
+					name_regex,
 					symbol_name,
-					symbol_name_regex_str,
+					symbol_name_regex,
 					symbol_version,
-					symbol_version_regex_str,
+					symbol_version_regex,
 					type_name_str,
-					type_name_regex_str));
+					type_name_regex));
 
   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
       && (!name_str.empty()
-	  || !name_regex_str.empty()
-	  || !name_not_regex_str.empty()
+	  || name_regex
+	  || name_not_regex
 	  || !symbol_name.empty()
-	  || !symbol_name_regex_str.empty()
-	  || !symbol_name_not_regex_str.empty()))
+	  || symbol_name_regex
+	  || symbol_name_not_regex))
     result->set_drops_artifact_from_ir(true);
 
-  if (!name_not_regex_str.empty())
-    result->set_name_not_regex_str(name_not_regex_str);
+  if (name_not_regex)
+    result->set_name_not_regex(name_not_regex);
 
-  if (!symbol_name_not_regex_str.empty())
-    result->set_symbol_name_not_regex_str(symbol_name_not_regex_str);
+  if (symbol_name_not_regex)
+    result->set_symbol_name_not_regex(symbol_name_not_regex);
 
   if (result && !change_kind_str.empty())
     result->set_change_kind
       (variable_suppression::parse_change_kind(change_kind_str));
 
-  if (!file_name_regex_str.empty())
-    result->set_file_name_regex_str(file_name_regex_str);
+  if (file_name_regex)
+    result->set_file_name_regex(file_name_regex);
 
-  if (!file_name_not_regex_str.empty())
-    result->set_file_name_not_regex_str(file_name_not_regex_str);
+  if (file_name_not_regex)
+    result->set_file_name_not_regex(file_name_not_regex);
 
-  if (!soname_regex_str.empty())
-    result->set_soname_regex_str(soname_regex_str);
+  if (soname_regex)
+    result->set_soname_regex(soname_regex);
 
-  if (!soname_not_regex_str.empty())
-    result->set_soname_not_regex_str(soname_not_regex_str);
+  if (soname_not_regex)
+    result->set_soname_not_regex(soname_not_regex);
 
   return result;
 }
@@ -4135,21 +4154,21 @@ read_variable_suppression(const ini::config::section& section)
 ///
 /// @param label the label of the suppression directive.
 ///
-/// @param fname_regex_str the regular expression string that
+/// @param fname_regex the regular expression string that
 /// designates the file name that instances of @ref file_suppression
 /// should match.
 ///
-/// @param fname_not_regex_str the regular expression string that
+/// @param fname_not_regex the regular expression string that
 /// designates the file name that instances of @ref file_suppression
 /// shoult *NOT* match.  In other words, this file_suppression should
 /// be activated if its file name does not match the regular
-/// expression @p fname_not_regex_str.
+/// expression @p fname_not_regex.
 file_suppression::file_suppression(const string& label,
-				   const string& fname_regex_str,
-				   const string& fname_not_regex_str)
+				   const regex_t_sptr& fname_regex,
+				   const regex_t_sptr& fname_not_regex)
   : suppression_base(label,
-		     fname_regex_str,
-		     fname_not_regex_str)
+		     fname_regex,
+		     fname_not_regex)
 {}
 
 /// Test if instances of this @ref file_suppression suppresses a
@@ -4229,41 +4248,44 @@ read_file_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr file_name_regex_prop =
     is_simple_property(section.find_property("file_name_regexp"));
-  string file_name_regex_str =
-    file_name_regex_prop ? file_name_regex_prop->get_value()->as_string() : "";
+  regex_t_sptr file_name_regex;
+  if (file_name_regex_prop)
+    file_name_regex =
+      regex::compile(file_name_regex_prop->get_value()->as_string());
 
  ini::simple_property_sptr file_name_not_regex_prop =
     is_simple_property(section.find_property("file_name_not_regexp"));
-  string file_name_not_regex_str =
-    file_name_not_regex_prop
-    ? file_name_not_regex_prop->get_value()->as_string()
-    : "";
+ regex_t_sptr file_name_not_regex;
+ if (file_name_not_regex_prop)
+   file_name_not_regex =
+     regex::compile(file_name_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr soname_regex_prop =
     is_simple_property(section.find_property("soname_regexp"));
-  string soname_regex_str =
-    soname_regex_prop ? soname_regex_prop->get_value()->as_string() : "";
+  regex_t_sptr soname_regex;
+  if (soname_regex_prop)
+    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr soname_not_regex_prop =
     is_simple_property(section.find_property("soname_not_regexp"));
-  string soname_not_regex_str =
-    soname_not_regex_prop
-    ? soname_not_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr soname_not_regex;
+  if (soname_not_regex_prop)
+    soname_not_regex =
+      regex::compile(soname_not_regex_prop->get_value()->as_string());
 
   result.reset(new file_suppression(label_str,
-				    file_name_regex_str,
-				    file_name_not_regex_str));
+				    file_name_regex,
+				    file_name_not_regex));
 
-  if (!soname_regex_str.empty())
+  if (soname_regex)
     {
-      result->set_soname_regex_str(soname_regex_str);
+      result->set_soname_regex(soname_regex);
       result->set_drops_artifact_from_ir(true);
     }
 
-  if (!soname_not_regex_str.empty())
+  if (soname_not_regex)
     {
-      result->set_soname_not_regex_str(soname_not_regex_str);
+      result->set_soname_not_regex(soname_not_regex);
       result->set_drops_artifact_from_ir(true);
     }
 
diff --git a/src/abg-tools-utils.cc b/src/abg-tools-utils.cc
index 11486a21..fe0de750 100644
--- a/src/abg-tools-utils.cc
+++ b/src/abg-tools-utils.cc
@@ -1810,13 +1810,15 @@ handle_file_entry(const string& file_path,
 {
   if (!suppr)
     {
-      suppr.reset(new type_suppression(get_private_types_suppr_spec_label(),
-				       /*type_name_regexp=*/"",
-				       /*type_name=*/""));
+      suppr.reset(
+	new type_suppression(get_private_types_suppr_spec_label(),
+			     /*type_name_regexp=*/regex::regex_t_sptr(),
+			     /*type_name=*/""));
 
       // Types that are defined in system headers are usually
       // OK to be considered as public types.
-      suppr->set_source_location_to_keep_regex_str("^/usr/include/");
+      regex::regex_t_sptr headers_regex = regex::compile("^/usr/include/");
+      suppr->set_source_location_to_keep_regex(headers_regex);
       suppr->set_is_artificial(true);
     }
 
@@ -2004,7 +2006,8 @@ gen_suppr_spec_from_kernel_abi_whitelists
 
       // Build a regular expression representing the union of all
       // the function and variable names expressed in the white list.
-      const std::string regex = regex::generate_from_strings(whitelisted_names);
+      regex::regex_t_sptr regex =
+	regex::compile(regex::generate_from_strings(whitelisted_names));
 
       // Build a suppression specification which *keeps* functions
       // whose ELF symbols match the regular expression contained
@@ -2013,7 +2016,7 @@ gen_suppr_spec_from_kernel_abi_whitelists
       // match this regexp.
       function_suppression_sptr fn_suppr(new function_suppression);
       fn_suppr->set_label("whitelist");
-      fn_suppr->set_symbol_name_not_regex_str(regex);
+      fn_suppr->set_symbol_name_not_regex(regex);
       fn_suppr->set_drops_artifact_from_ir(true);
       result.push_back(fn_suppr);
 
@@ -2024,7 +2027,7 @@ gen_suppr_spec_from_kernel_abi_whitelists
       // match this regexp.
       variable_suppression_sptr var_suppr(new variable_suppression);
       var_suppr->set_label("whitelist");
-      var_suppr->set_symbol_name_not_regex_str(regex);
+      var_suppr->set_symbol_name_not_regex(regex);
       var_suppr->set_drops_artifact_from_ir(true);
       result.push_back(var_suppr);
     }
diff --git a/tests/test-kmi-whitelist.cc b/tests/test-kmi-whitelist.cc
index bcc5adee..16cc1861 100644
--- a/tests/test-kmi-whitelist.cc
+++ b/tests/test-kmi-whitelist.cc
@@ -29,10 +29,14 @@
 #include "lib/catch.hpp"
 
 #include "abg-fwd.h"
-#include "abg-suppression.h"
+#include "abg-regex.h"
 #include "abg-tools-utils.h"
+#include "abg-suppression.h"
 #include "test-utils.h"
 
+using abigail::regex::regex_t_sptr;
+using abigail::regex::compile;
+using abigail::regex::match;
 using abigail::tools_utils::gen_suppr_spec_from_kernel_abi_whitelists;
 using abigail::suppr::suppression_sptr;
 using abigail::suppr::suppressions_type;
@@ -57,9 +61,30 @@ const static std::string whitelist_with_duplicate_entry
     = std::string(abigail::tests::get_src_dir())
       + "/tests/data/test-kmi-whitelist/whitelist-with-duplicate-entry";
 
+// These are strings, not regexes, we cannot exhaustively check all
+// strings, but we can do some sampling and match sure we haven't got
+// the regex logic completely wrong.
+static const char* const random_symbols[] =
+{
+  "",
+  ".*",
+  "^$",
+  "test_symbol",
+  "test-symbol",
+  "test symbol",
+  "Test Symbol",
+  "est_symbo",
+  ".*test_symbol.*",
+  "test_symbol ",
+  " test_symbol",
+  " test_symbol ",
+  "test_another_symbol",
+  "$test_another_symbol",
+};
+
 void
 test_suppressions_are_consistent(const suppressions_type& suppr,
-			    const std::string&	     expr)
+				 const std::string&	  expr)
 {
   REQUIRE(suppr.size() == 2);
 
@@ -74,11 +99,32 @@ test_suppressions_are_consistent(const suppressions_type& suppr,
   // same mode
   REQUIRE(left->get_drops_artifact_from_ir()
 	  == right->get_drops_artifact_from_ir());
-  // same regex
-  REQUIRE(left->get_symbol_name_not_regex_str()
-     == right->get_symbol_name_not_regex_str());
-  // regex as expected
-  REQUIRE(left->get_symbol_name_not_regex_str() == expr);
+
+  // these parts of the symbol name matching should be absent
+  REQUIRE(left->get_symbol_name().empty());
+  REQUIRE(!left->get_symbol_name_regex());
+  REQUIRE(right->get_symbol_name().empty());
+  REQUIRE(!right->get_symbol_name_regex());
+
+  regex_t_sptr left_regex = left->get_symbol_name_not_regex();
+  regex_t_sptr right_regex = right->get_symbol_name_not_regex();
+  regex_t_sptr check_regex = compile(expr);
+
+  // all regexes present (compiled)
+  REQUIRE(left_regex);
+  REQUIRE(right_regex);
+  REQUIRE(check_regex);
+
+  // all regexes match or do not match a random symbol
+  for (size_t i = 0; i < sizeof(random_symbols)/sizeof(random_symbols[0]); ++i)
+    {
+      const std::string symbol(random_symbols[i]);
+      bool left_matches = match(left_regex, symbol);
+      bool right_matches = match(right_regex, symbol);
+      bool check_matches = match(check_regex, symbol);
+      REQUIRE(left_matches == right_matches);
+      REQUIRE(left_matches == check_matches);
+    }
 }
 
 TEST_CASE("NoWhitelists", "[whitelists]")
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH 12/21] Reduce direct access to suppression priv_ members.
  2020-04-23 15:44 [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
                   ` (10 preceding siblings ...)
  2020-04-23 15:44 ` [PATCH 11/21] Compile suppression regexes earlier Giuliano Procida
@ 2020-04-23 15:44 ` Giuliano Procida
  2020-04-23 15:44 ` [PATCH 13/21] Move match methods from priv to suppression_base Giuliano Procida
                   ` (10 subsequent siblings)
  22 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-23 15:44 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

Most suppression type functionality is available on the types
themselves via methods, particularly now that there are getters
for all the regex members.

This patch eliminates lots of accesses via priv_ members.

There are no behavioural changes.

	* src/abg-suppression.cc (sonames_of_binaries_match): Use
	suppression_matches_soname helper function.
	(suppression_matches_type_name): Use type_suppression regex getters.
	(suppression_matches_type_location): Use type_suppression
	regex getters.
	(function::suppression::suppresses_function): Use own regex
	getters.
	(function::suppression::suppresses_function_symbol): Use own
	regex getters.
	(suppression_matches_function_name): Use function_suppression
	regex and name getters.
	(suppression_matches_function_sym_name): Use function_suppression
	regex and symbol name getters.
	(suppression_matches_variable_name): Use variable__suppression
	regex and name getters.
	(suppression_matches_variable_sym_name): Use variable_suppression
	regex and symbol name getters.
	(suppression_matches_type): Use type_suppression
	regex getter.
	(variable_suppression::suppresses_variable): Use own regex
	getters.
	(variable_suppression::suppresses_variable_symbol): Use own
	regex getters.
	(type_suppression::suppresses_file): Use own regex getters.
	(suppression_matches_soname_or_filename): Indentation fix, en
	passant.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-suppression.cc | 107 +++++++++++++++++++----------------------
 1 file changed, 50 insertions(+), 57 deletions(-)

diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 5082536d..f6710b71 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -279,8 +279,8 @@ sonames_of_binaries_match(const suppression_base& suppr,
   if (!suppr.has_soname_related_property())
     return false;
 
-  if (!suppr.priv_->matches_soname(first_soname)
-      && !suppr.priv_->matches_soname(second_soname))
+  if (!suppression_matches_soname(first_soname, suppr)
+      && !suppression_matches_soname(second_soname, suppr))
     return false;
 
   return true;
@@ -973,8 +973,8 @@ suppression_matches_type_name(const type_suppression&	s,
 			      const string&		type_name)
 {
   if (!s.get_type_name().empty()
-      || s.priv_->get_type_name_regex()
-      || s.priv_->get_type_name_not_regex())
+      || s.get_type_name_regex()
+      || s.get_type_name_not_regex())
     {
       // Check if there is an exact type name match.
       if (!s.get_type_name().empty())
@@ -990,14 +990,14 @@ suppression_matches_type_name(const type_suppression&	s,
 	  // the regular expression of the type name, then this
 	  // suppression doesn't apply.
 	  if (const regex_t_sptr& type_name_regex =
-	      s.priv_->get_type_name_regex())
+	      s.get_type_name_regex())
 	    {
 	      if (!regex::match(type_name_regex, type_name))
 		return false;
 	    }
 
 	  if (const regex_t_sptr type_name_not_regex =
-	      s.priv_->get_type_name_not_regex())
+	      s.get_type_name_not_regex())
 	    {
 	      if (regex::match(type_name_not_regex, type_name))
 		return false;
@@ -1045,7 +1045,7 @@ suppression_matches_type_location(const type_suppression&	s,
       unsigned loc_line = 0, loc_column = 0;
       loc.expand(loc_path, loc_line, loc_column);
 
-      if (regex_t_sptr regexp = s.priv_->get_source_location_to_keep_regex())
+      if (regex_t_sptr regexp = s.get_source_location_to_keep_regex())
 	if (regex::match(regexp, loc_path))
 	  return false;
 
@@ -1060,7 +1060,7 @@ suppression_matches_type_location(const type_suppression&	s,
   else
     {
       if (!s.get_source_locations_to_keep().empty()
-	  || s.priv_->get_source_location_to_keep_regex())
+	  || s.get_source_location_to_keep_regex())
 	// The user provided a "source_location_not_regexp" or
 	// a "source_location_not_in" property that was not
 	// triggered.  This means the current type suppression
@@ -1111,7 +1111,7 @@ suppression_matches_type_location(const type_suppression&	s,
 	    }
 	}
       if (!s.get_source_locations_to_keep().empty()
-	  || s.priv_->get_source_location_to_keep_regex())
+	  || s.get_source_location_to_keep_regex())
 	// The user provided a "source_location_not_regexp" or
 	// a "source_location_not_in" property that was not
 	// triggered.  This means the current type suppression
@@ -2485,7 +2485,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
 
   // check if the "name_regexp" property matches.
-  const regex_t_sptr name_regex = priv_->get_name_regex();
+  const regex_t_sptr name_regex = get_name_regex();
   if (name_regex)
     {
       if (!regex::match(name_regex, fname))
@@ -2516,7 +2516,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
 
   // check if the "name_not_regexp" property matches.
-  const regex_t_sptr name_not_regex = priv_->get_name_not_regex();
+  const regex_t_sptr name_not_regex = get_name_not_regex();
   if (name_not_regex)
     {
       if (regex::match(name_not_regex, fname))
@@ -2562,7 +2562,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
   else
     {
-      const regex_t_sptr return_type_regex = priv_->get_return_type_regex();
+      const regex_t_sptr return_type_regex = get_return_type_regex();
       if (return_type_regex
 	  && !regex::match(return_type_regex, fn_return_type_name))
 	return false;
@@ -2600,12 +2600,11 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
   else if (sym)
     {
-      const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
+      const regex_t_sptr symbol_name_regex = get_symbol_name_regex();
       if (symbol_name_regex && !regex::match(symbol_name_regex, fn_sym_name))
 	return false;
 
-      const regex_t_sptr symbol_name_not_regex =
-	priv_->get_symbol_name_not_regex();
+      const regex_t_sptr symbol_name_not_regex = get_symbol_name_not_regex();
       if (symbol_name_not_regex
 	  && regex::match(symbol_name_not_regex, fn_sym_name))
 	return false;
@@ -2642,8 +2641,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
   else if (sym)
     {
-      const regex_t_sptr symbol_version_regex =
-	priv_->get_symbol_version_regex();
+      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
       if (symbol_version_regex
 	  && !regex::match(symbol_version_regex, fn_sym_version))
 	return false;
@@ -2683,7 +2681,7 @@ function_suppression::suppresses_function(const function_decl* fn,
 	  else
 	    {
 	      const regex_t_sptr parm_type_name_regex =
-		(*p)->priv_->get_type_name_regex();
+		(*p)->get_parameter_type_name_regex();
 	      if (parm_type_name_regex)
 		{
 		  if (!regex::match(parm_type_name_regex,
@@ -2774,7 +2772,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
     }
   else if (get_symbol_name_regex())
     {
-      const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
+      const regex_t_sptr symbol_name_regex = get_symbol_name_regex();
       if (symbol_name_regex && !regex::match(symbol_name_regex, sym_name))
 	return false;
     }
@@ -2789,8 +2787,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
     }
   else if (get_symbol_version_regex())
     {
-      const regex_t_sptr symbol_version_regex =
-	priv_->get_symbol_version_regex();
+      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
       if (symbol_version_regex
 	  && !regex::match(symbol_version_regex, sym_version))
 	return false;
@@ -2882,21 +2879,21 @@ bool
 suppression_matches_function_name(const suppr::function_suppression& s,
 				  const string& fn_name)
 {
-  if (regex_t_sptr regexp = s.priv_->get_name_regex())
+  if (regex_t_sptr regexp = s.get_name_regex())
     {
       if (!regex::match(regexp, fn_name))
 	return false;
     }
-  else if (regex_t_sptr regexp = s.priv_->get_name_not_regex())
+  else if (regex_t_sptr regexp = s.get_name_not_regex())
     {
       if (regex::match(regexp, fn_name))
 	return false;
     }
-  else if (s.priv_->name_.empty())
+  else if (s.get_name().empty())
     return false;
-  else // if (!s.priv_->name_.empty())
+  else // if (!s.get_name().empty())
     {
-      if (s.priv_->name_ != fn_name)
+      if (s.get_name() != fn_name)
 	return false;
     }
 
@@ -2918,21 +2915,21 @@ bool
 suppression_matches_function_sym_name(const suppr::function_suppression& s,
 				      const string& fn_linkage_name)
 {
-  if (regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
+  if (regex_t_sptr regexp = s.get_symbol_name_regex())
     {
       if (!regex::match(regexp, fn_linkage_name))
 	return false;
     }
-  else if (regex_t_sptr regexp = s.priv_->get_symbol_name_not_regex())
+  else if (regex_t_sptr regexp = s.get_symbol_name_not_regex())
     {
       if (regex::match(regexp, fn_linkage_name))
 	return false;
     }
-  else if (s.priv_->symbol_name_.empty())
+  else if (s.get_symbol_name().empty())
     return false;
-  else // if (!s.priv_->symbol_name_.empty())
+  else // if (!s.get_symbol_name().empty())
     {
-      if (s.priv_->symbol_name_ != fn_linkage_name)
+      if (s.get_symbol_name() != fn_linkage_name)
 	return false;
     }
 
@@ -2951,21 +2948,21 @@ bool
 suppression_matches_variable_name(const suppr::variable_suppression& s,
 				  const string& var_name)
 {
-  if (regex_t_sptr regexp = s.priv_->get_name_regex())
+  if (regex_t_sptr regexp = s.get_name_regex())
     {
       if (!regex::match(regexp, var_name))
 	return false;
     }
-  else if (regex_t_sptr regexp = s.priv_->get_name_not_regex())
+  else if (regex_t_sptr regexp = s.get_name_not_regex())
     {
       if (regex::match(regexp, var_name))
 	return false;
     }
-  else if (s.priv_->name_.empty())
+  else if (s.get_name().empty())
     return false;
-  else // if (!s.priv_->name_.empty())
+  else // if (!s.get_name().empty())
     {
-      if (s.priv_->name_ != var_name)
+      if (s.get_name() != var_name)
 	return false;
     }
 
@@ -2985,22 +2982,21 @@ bool
 suppression_matches_variable_sym_name(const suppr::variable_suppression& s,
 				      const string& var_linkage_name)
 {
-  if (regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
+  if (regex_t_sptr regexp = s.get_symbol_name_regex())
     {
       if (!regex::match(regexp, var_linkage_name))
 	return false;
     }
-  else if (regex_t_sptr regexp =
-	   s.priv_->get_symbol_name_not_regex())
+  else if (regex_t_sptr regexp = s.get_symbol_name_not_regex())
     {
       if (regex::match(regexp, var_linkage_name))
 	return false;
     }
-  else if (s.priv_->symbol_name_.empty())
+  else if (s.get_symbol_name().empty())
     return false;
-  else // if (!s.priv_->symbol_name_.empty())
+  else // if (!s.get_symbol_name().empty())
     {
-      if (s.priv_->symbol_name_ != var_linkage_name)
+      if (s.get_symbol_name() != var_linkage_name)
 	return false;
     }
 
@@ -3020,7 +3016,7 @@ bool
 suppression_matches_type(const suppr::type_suppression& s,
 			 const string& type_name)
 {
-  if (regex_t_sptr regexp = s.priv_->get_type_name_regex())
+  if (regex_t_sptr regexp = s.get_type_name_regex())
     {
       if (!regex::match(regexp, type_name))
 	return false;
@@ -3729,11 +3725,11 @@ variable_suppression::suppresses_variable(const var_decl* var,
       // "name_regex" and "name_not_regex" properties match
       if (get_name().empty())
 	{
-	  const regex_t_sptr name_regex = priv_->get_name_regex();
+	  const regex_t_sptr name_regex = get_name_regex();
 	  if (name_regex && !regex::match(name_regex, var_name))
 	    return false;
 
-	  const regex_t_sptr name_not_regex = priv_->get_name_not_regex();
+	  const regex_t_sptr name_not_regex = get_name_not_regex();
 	  if (name_not_regex && regex::match(name_not_regex, var_name))
 	    return false;
 	}
@@ -3749,12 +3745,11 @@ variable_suppression::suppresses_variable(const var_decl* var,
     }
   else
     {
-      const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
+      const regex_t_sptr sym_name_regex = get_symbol_name_regex();
       if (sym_name_regex && !regex::match(sym_name_regex, var_sym_name))
 	return false;
 
-      const regex_t_sptr sym_name_not_regex =
-	priv_->get_symbol_name_not_regex();
+      const regex_t_sptr sym_name_not_regex = get_symbol_name_not_regex();
       if (sym_name_not_regex && regex::match(sym_name_not_regex, var_sym_name))
 	return false;
     }
@@ -3769,8 +3764,7 @@ variable_suppression::suppresses_variable(const var_decl* var,
     }
   else
     {
-      const regex_t_sptr symbol_version_regex =
-	priv_->get_symbol_version_regex();
+      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
       if (symbol_version_regex
 	  && !regex::match(symbol_version_regex, var_sym_version))
 	return false;
@@ -3789,7 +3783,7 @@ variable_suppression::suppresses_variable(const var_decl* var,
     {
       if (get_type_name().empty())
 	{
-	  const regex_t_sptr type_name_regex = priv_->get_type_name_regex();
+	  const regex_t_sptr type_name_regex = get_type_name_regex();
 	  if (type_name_regex && !regex::match(type_name_regex, var_type_name))
 	    return false;
 	}
@@ -3880,7 +3874,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
     }
   else if (get_symbol_name_regex())
     {
-      const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
+      const regex_t_sptr sym_name_regex = get_symbol_name_regex();
       if (sym_name_regex && !regex::match(sym_name_regex, sym_name))
 	return false;
     }
@@ -3896,8 +3890,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
     }
   else if (get_symbol_version_regex())
     {
-      const regex_t_sptr symbol_version_regex =
-	priv_->get_symbol_version_regex();
+      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
       if (symbol_version_regex
 	  && !regex::match(symbol_version_regex, sym_version))
 	return false;
@@ -4200,14 +4193,14 @@ file_suppression::suppresses_file(const string& file_path)
 
   bool has_regexp = false;
 
-  if (regex_t_sptr regexp = suppression_base::priv_->get_file_name_regex())
+  if (regex_t_sptr regexp = get_file_name_regex())
     {
       has_regexp = true;
       if (!regex::match(regexp, fname))
 	return false;
     }
 
-  if (regex_t_sptr regexp = suppression_base::priv_->get_file_name_not_regex())
+  if (regex_t_sptr regexp = get_file_name_not_regex())
     {
       has_regexp = true;
       if (regex::match(regexp, fname))
@@ -4361,7 +4354,7 @@ suppression_matches_soname_or_filename(const string& soname,
 				       const suppression_base& suppr)
 {
   return (suppression_matches_soname(soname, suppr)
-	 || suppr.priv_->matches_binary_name(filename));
+	  || suppr.priv_->matches_binary_name(filename));
 }
 
 /// @return the name of the artificial private type suppression
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH 13/21] Move match methods from priv to suppression_base.
  2020-04-23 15:44 [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
                   ` (11 preceding siblings ...)
  2020-04-23 15:44 ` [PATCH 12/21] Reduce direct access to suppression priv_ members Giuliano Procida
@ 2020-04-23 15:44 ` Giuliano Procida
  2020-04-23 15:44 ` [PATCH 14/21] Remove suppression types' priv class methods Giuliano Procida
                   ` (9 subsequent siblings)
  22 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-23 15:44 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

The suppression_base::priv methods matches_soname and
matches_binary_name do not require special access to the priv class
and can be moved to the main suppression_base class and use its
getters.

This is a step towards simplifying the suppression type priv classes
to the point they are simple data containers.

There are no behavioural changes.

	* include/abg-suppression.h
	(suppression_base::matches_soname): Add	declaration.
	(suppression_base::matches_binary_name): Add declaration.
	(suppression_base): Remove friend declarations of
	suppression_matches_soname and
	suppression_matches_soname_or_filename.
	* src/abg-dwarf-reader.cc (suppression_can_match): Call
	matches_soname and matches_binary_name on suppression values
	directly.
	* src/abg-reader.cc (suppression_can_match): Call
	matches_soname and matches_binary_name on suppression values
	directly.
	* src/abg-suppression-priv.h
	(suppression_base::priv::matches_soname): Remove method.
	(suppression_base::priv::matches_binary_name): Remove method.
	* src/abg-suppression.cc
	(suppression_base::matches_soname): Add definition.
	(suppression_base::matches_binary_name): Add definition.
	(names_of_binaries_match): Call matches_binary_name on
	suppression values directly. (suppression_matches_soname):
	Call matches_soname on suppression values directly.
	(suppression_matches_soname_or_filename): Call
	matches_binary_name on suppression values directly.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 include/abg-suppression.h  | 15 +++-----
 src/abg-dwarf-reader.cc    |  4 +-
 src/abg-reader.cc          |  4 +-
 src/abg-suppression-priv.h | 71 +----------------------------------
 src/abg-suppression.cc     | 76 ++++++++++++++++++++++++++++++++++++--
 5 files changed, 83 insertions(+), 87 deletions(-)

diff --git a/include/abg-suppression.h b/include/abg-suppression.h
index 1869cbe5..02e77ea9 100644
--- a/include/abg-suppression.h
+++ b/include/abg-suppression.h
@@ -116,19 +116,16 @@ public:
   bool
   has_soname_related_property() const;
 
+  bool
+  matches_soname(const string& soname) const;
+
+  bool
+  matches_binary_name(const string& binary_name) const;
+
   virtual bool
   suppresses_diff(const diff*) const = 0;
 
   virtual ~suppression_base();
-
-  friend bool
-  suppression_matches_soname(const string& soname,
-			     const suppression_base& suppr);
-
-  friend bool
-  suppression_matches_soname_or_filename(const string& soname,
-					 const string& filename,
-					 const suppression_base& suppr);
 }; // end class suppression_base
 
 void
diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
index 850281ad..c9e6f918 100644
--- a/src/abg-dwarf-reader.cc
+++ b/src/abg-dwarf-reader.cc
@@ -7723,14 +7723,14 @@ public:
   bool
   suppression_can_match(const suppr::suppression_base& s) const
   {
-    if (!s.priv_->matches_soname(dt_soname()))
+    if (!s.matches_soname(dt_soname()))
       if (s.has_soname_related_property())
 	// The suppression has some SONAME related properties, but
 	// none of them match the SONAME of the current binary.  So
 	// the suppression cannot match the current binary.
 	return false;
 
-    if (!s.priv_->matches_binary_name(elf_path()))
+    if (!s.matches_binary_name(elf_path()))
       if (s.has_file_name_related_property())
 	// The suppression has some file_name related properties, but
 	// none of them match the file name of the current binary.  So
diff --git a/src/abg-reader.cc b/src/abg-reader.cc
index dcaa27e1..5e0b97e0 100644
--- a/src/abg-reader.cc
+++ b/src/abg-reader.cc
@@ -999,14 +999,14 @@ public:
   {
     corpus_sptr corp = get_corpus();
 
-    if (!s.priv_->matches_soname(corp->get_soname()))
+    if (!s.matches_soname(corp->get_soname()))
       if (s.has_soname_related_property())
 	// The suppression has some SONAME related properties, but
 	// none of them match the SONAME of the current binary.  So
 	// the suppression cannot match the current binary.
 	return false;
 
-    if (!s.priv_->matches_binary_name(corp->get_path()))
+    if (!s.matches_binary_name(corp->get_path()))
       if (s.has_file_name_related_property())
 	// The suppression has some file_name related properties, but
 	// none of them match the file name of the current binary.  So
diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
index 263052d4..5c06d5d0 100644
--- a/src/abg-suppression-priv.h
+++ b/src/abg-suppression-priv.h
@@ -107,76 +107,7 @@ public:
   {
     return soname_not_regex_;
   }
-
-  /// Test if the current suppression matches a given SONAME.
-  ///
-  /// @param soname the SONAME to consider.
-  ///
-  /// @return true iff the suppression matches the SONAME denoted by
-  /// @p soname.
-  ///
-  /// Note that if the suppression contains no property that is
-  /// related to SONAMEs, the function returns false.
-  bool
-  matches_soname(const string& soname) const
-  {
-    bool has_regexp = false;
-    if (regex::regex_t_sptr regexp = get_soname_regex())
-      {
-	has_regexp = true;
-	if (!regex::match(regexp, soname))
-	  return false;
-      }
-
-    if (regex::regex_t_sptr regexp = get_soname_not_regex())
-      {
-	has_regexp = true;
-	if (regex::match(regexp, soname))
-	  return false;
-      }
-
-      if (!has_regexp)
-	return false;
-
-    return true;
-  }
-
-  /// Test if the current suppression matches the full file path to a
-  /// given binary.
-  ///
-  /// @param binary_name the full path to the binary.
-  ///
-  /// @return true iff the suppression matches the path denoted by @p
-  /// binary_name.
-  ///
-  /// Note that if the suppression contains no property that is
-  /// related to file name, the function returns false.
-  bool
-  matches_binary_name(const string& binary_name) const
-  {
-    bool has_regexp = false;
-
-    if (regex::regex_t_sptr regexp = get_file_name_regex())
-      {
-	has_regexp = true;
-	if (!regex::match(regexp, binary_name))
-	  return false;
-      }
-
-    if (regex::regex_t_sptr regexp = get_file_name_not_regex())
-      {
-	has_regexp = true;
-	if (regex::match(regexp, binary_name))
-	  return false;
-      }
-
-    if (!has_regexp)
-      return false;
-
-    return true;
-  }
-
-}; // end clas suppression_base::priv
+}; // end class suppression_base::priv
 
 // </suppression_base stuff>
 
diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index f6710b71..02c3e98a 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -256,6 +256,74 @@ suppression_base::has_soname_related_property() const
   return get_soname_regex() || get_soname_not_regex();
 }
 
+/// Test if the current suppression matches a given SONAME.
+///
+/// @param soname the SONAME to consider.
+///
+/// @return true iff the suppression matches the SONAME denoted by
+/// @p soname.
+///
+/// Note that if the suppression contains no property that is
+/// related to SONAMEs, the function returns false.
+bool
+suppression_base::matches_soname(const string& soname) const
+{
+  bool has_regexp = false;
+  if (regex::regex_t_sptr regexp = get_soname_regex())
+    {
+      has_regexp = true;
+      if (!regex::match(regexp, soname))
+        return false;
+    }
+
+  if (regex::regex_t_sptr regexp = get_soname_not_regex())
+    {
+      has_regexp = true;
+      if (regex::match(regexp, soname))
+        return false;
+    }
+
+    if (!has_regexp)
+      return false;
+
+  return true;
+}
+
+/// Test if the current suppression matches the full file path to a
+/// given binary.
+///
+/// @param binary_name the full path to the binary.
+///
+/// @return true iff the suppression matches the path denoted by @p
+/// binary_name.
+///
+/// Note that if the suppression contains no property that is
+/// related to file name, the function returns false.
+bool
+suppression_base::matches_binary_name(const string& binary_name) const
+{
+  bool has_regexp = false;
+
+  if (regex::regex_t_sptr regexp = get_file_name_regex())
+    {
+      has_regexp = true;
+      if (!regex::match(regexp, binary_name))
+        return false;
+    }
+
+  if (regex::regex_t_sptr regexp = get_file_name_not_regex())
+    {
+      has_regexp = true;
+      if (regex::match(regexp, binary_name))
+        return false;
+    }
+
+  if (!has_regexp)
+    return false;
+
+  return true;
+}
+
 /// Check if the SONAMEs of the two binaries being compared match the
 /// content of the properties "soname_regexp" and "soname_not_regexp"
 /// of the current suppression specification.
@@ -309,8 +377,8 @@ names_of_binaries_match(const suppression_base& suppr,
   if (!suppr.has_file_name_related_property())
     return false;
 
-  if (!suppr.priv_->matches_binary_name(first_binary_path)
-      && !suppr.priv_->matches_binary_name(second_binary_path))
+  if (!suppr.matches_binary_name(first_binary_path)
+      && !suppr.matches_binary_name(second_binary_path))
     return false;
 
   return true;
@@ -4334,7 +4402,7 @@ bool
 suppression_matches_soname(const string& soname,
 			   const suppression_base& suppr)
 {
-  return suppr.priv_->matches_soname(soname);
+  return suppr.matches_soname(soname);
 }
 
 /// Test if a given SONAME or file name is matched by a given
@@ -4354,7 +4422,7 @@ suppression_matches_soname_or_filename(const string& soname,
 				       const suppression_base& suppr)
 {
   return (suppression_matches_soname(soname, suppr)
-	  || suppr.priv_->matches_binary_name(filename));
+	  || suppr.matches_binary_name(filename));
 }
 
 /// @return the name of the artificial private type suppression
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH 14/21] Remove suppression types' priv class methods.
  2020-04-23 15:44 [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
                   ` (12 preceding siblings ...)
  2020-04-23 15:44 ` [PATCH 13/21] Move match methods from priv to suppression_base Giuliano Procida
@ 2020-04-23 15:44 ` Giuliano Procida
  2020-04-23 15:44 ` [PATCH 15/21] abg-suppression.cc: More consistent regex matching Giuliano Procida
                   ` (8 subsequent siblings)
  22 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-23 15:44 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

The type_suppression::set_type_name_not_regex method is the only
remaining user of all the various suppression_type::priv member
functions. This is easily remedied and all the remaining priv member
functions (regex getters and setters) can be dropped.

This patches leaves all the various suppression priv types as simple
data containers (modulo their constructors).

There are no behavioural changes.

	* src/abg-suppression-priv.h (suppression_base::priv): Drop
	all regex getter methods.
	(function_suppression::parameter_spec::priv): Drop all regex
	getter methods.
	(function_suppression::priv): Drop all regex getter methods.
	(variable_suppression::priv): Drop all regex getter methods.
	(type_suppression::priv): Drop all regex getter and setter
	methods.
	* src/abg-suppression.cc (set_type_name_not_regex): Access
	priv_->type_name_not_regex_ directly.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-suppression-priv.h | 182 -------------------------------------
 src/abg-suppression.cc     |   2 +-
 2 files changed, 1 insertion(+), 183 deletions(-)

diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
index 5c06d5d0..78f11e2f 100644
--- a/src/abg-suppression-priv.h
+++ b/src/abg-suppression-priv.h
@@ -75,38 +75,6 @@ public:
   {}
 
   friend class suppression_base;
-
-  /// Get the regular expression object associated to the
-  /// 'file_name_regex' property of @ref suppression_base.
-  const regex::regex_t_sptr&
-  get_file_name_regex() const
-  {
-    return file_name_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'file_name_not_regex' property of @ref suppression_base.
-  const regex::regex_t_sptr&
-  get_file_name_not_regex() const
-  {
-    return file_name_not_regex_;
-  }
-
-  /// Get the regular expression object associated to the 'soname_regex'
-  /// property of @ref suppression_base.
-  const regex::regex_t_sptr&
-  get_soname_regex() const
-  {
-    return soname_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'soname_not_regex' property of @ref suppression_base.
-  const regex::regex_t_sptr&
-  get_soname_not_regex() const
-  {
-    return soname_not_regex_;
-  }
 }; // end class suppression_base::priv
 
 // </suppression_base stuff>
@@ -133,15 +101,6 @@ class function_suppression::parameter_spec::priv
   priv(size_t i, const string& tn, const regex::regex_t_sptr& tn_regex)
     : index_(i), type_name_(tn), type_name_regex_(tn_regex)
   {}
-
-  /// Get the regular expression object associated to the
-  /// 'type_name_regex' property of @ref
-  /// function_suppression::parameter_spec.
-  const regex::regex_t_sptr
-  get_type_name_regex() const
-  {
-    return type_name_regex_;
-  }
 }; // end class function_suppression::parameter_spec::priv
 
 
@@ -191,54 +150,6 @@ struct function_suppression::priv
       symbol_version_regex_(symbol_version_regex),
       allow_other_aliases_(true)
   {}
-
-  /// Get the regular expression object associated to the 'name_regex'
-  /// property of @ref function_suppression.
-  const regex::regex_t_sptr
-  get_name_regex() const
-  {
-    return name_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'name_not_regex' property of @ref function_suppression.
-  const regex::regex_t_sptr
-  get_name_not_regex() const
-  {
-    return name_not_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'return_type_regex' property of @ref function_suppression.
-  const regex::regex_t_sptr
-  get_return_type_regex() const
-  {
-    return return_type_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'symbol_name_regex' property of @ref function_suppression.
-  const regex::regex_t_sptr
-  get_symbol_name_regex() const
-  {
-    return symbol_name_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'symbol_name_not_regex' property of @ref function_suppression.
-  const regex::regex_t_sptr
-  get_symbol_name_not_regex() const
-  {
-    return symbol_name_not_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'symbol_version_regex' property of @ref function_suppression.
-  const regex::regex_t_sptr
-  get_symbol_version_regex() const
-  {
-    return symbol_version_regex_;
-  }
 }; // end class function_suppression::priv
 
 bool
@@ -343,54 +254,6 @@ struct variable_suppression::priv
       type_name_(type_name),
       type_name_regex_(type_name_regex)
   {}
-
-  /// Get the regular expression object associated to the 'name_regex'
-  /// property of @ref variable_suppression.
-  const regex::regex_t_sptr
-  get_name_regex() const
-  {
-    return name_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'name_not_regex' property of @ref variable_suppression.
-  const regex::regex_t_sptr
-  get_name_not_regex() const
-  {
-    return name_not_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'symbol_name_regex' property of @ref variable_suppression.
-  const regex::regex_t_sptr
-  get_symbol_name_regex() const
-  {
-    return symbol_name_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'symbol_name_not_regex' property of @ref variable_suppression.
-  const regex::regex_t_sptr
-  get_symbol_name_not_regex() const
-  {
-    return symbol_name_not_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'symbol_version_regex' property of @ref variable_suppression.
-  const regex::regex_t_sptr
-  get_symbol_version_regex()  const
-  {
-    return symbol_version_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'type_name_regex' property of @ref variable_suppression.
-  const regex::regex_t_sptr
-  get_type_name_regex() const
-  {
-    return type_name_regex_;
-  }
 };// end class variable_supppression::priv
 
 template <typename ReadContextType>
@@ -454,51 +317,6 @@ public:
       reach_kind_(reach_kind)
   {}
 
-  /// Get the regular expression object associated to the
-  /// 'type_name_regex' property of @ref type_suppression.
-  const regex::regex_t_sptr
-  get_type_name_regex() const
-  {
-    return type_name_regex_;
-  }
-
-  /// Setter for the type_name_regex object.
-  ///
-  /// @param r the new type_name_regex object.
-  void
-  set_type_name_regex(regex::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.
-  const regex::regex_t_sptr
-  get_type_name_not_regex() const
-  {
-    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(regex::regex_t_sptr r)
-  {type_name_not_regex_ = r;}
-
-  /// Get the regular expression object associated to the
-  /// 'source_location_to_keep_regex' property of @ref type_suppression.
-  const regex::regex_t_sptr
-  get_source_location_to_keep_regex() const
-  {
-    return source_location_to_keep_regex_;
-  }
-
-  /// Setter for the source_location_to_keep_regex object.
-  ///
-  /// @param r the new regex object.
-  void
-  set_source_location_to_keep_regex(regex::regex_t_sptr r)
-  {source_location_to_keep_regex_ = r;}
-
   friend class type_suppression;
 }; // class type_suppression::priv
 
diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 02c3e98a..33bccbb6 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -519,7 +519,7 @@ type_suppression::get_type_name_regex() const
 /// @param r the new regexp string.
 void
 type_suppression::set_type_name_not_regex(const regex_t_sptr& r)
-{priv_->set_type_name_not_regex(r);}
+{priv_->type_name_not_regex_ = r;}
 
 /// Getter for the "type_name_not_regex" property of the type
 /// suppression specification.
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH 15/21] abg-suppression.cc: More consistent regex matching.
  2020-04-23 15:44 [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
                   ` (13 preceding siblings ...)
  2020-04-23 15:44 ` [PATCH 14/21] Remove suppression types' priv class methods Giuliano Procida
@ 2020-04-23 15:44 ` Giuliano Procida
  2020-04-23 15:44 ` [PATCH 16/21] abg-tools-utils.cc: Assert generated regexes OK Giuliano Procida
                   ` (7 subsequent siblings)
  22 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-23 15:44 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

Following previous patches, various minor inconsistencies in the
suppression regex matching code were more readily apparent.

- regex_t_sptr values are fetched both by reference and by
  value (which has a reference count mutation cost)
- there's a mixture of code styles for testing regex presence
    - regex = ...; if (regex && ...)
    - if (regex = ...) if (...)
  the latter has the advantage that the variable has a smaller scope
  and can be given a shorter name
- in some cases there are redundant tests (always true due to previous
  conditional logic)

This patch ensures all shared pointers to compiled regexes are fetched
by const reference and that the code uses the nested if style of
presence checking where possible. It simplifies some logic where
there's redundancy.

There are no behavioural changes. There may be performance
improvements.

	* src/abg-suppression.cc (suppression_matches_type_name): Get
	regexes by const reference.
	(suppression_matches_type_location): Get regexes by const
	reference. (function_suppression::suppresses_function): Get
	regexes by const reference; use nested if checks; simplify
	logic around symbol version checks.
	(function_suppression::suppresses_function_symbol): Get
	regexes by const reference; use nested if checks; remove
	redundant regex presence checks.
	(suppression_matches_function_name): Get regexes by const
	reference. (suppression_matches_function_sym_name): Get
	regexes by const reference.
	(suppression_matches_variable_name): Get regexes by const
	reference. (suppression_matches_variable_sym_name): Get
	regexes by const reference. (suppression_matches_type): Get
	regexes by const reference.
	(variable_suppression::suppresses_variable): Get regexes by
	const reference; use nested if checks; remove redundant
	type_name empty check.
	(variable_suppression::suppresses_variable_symbol): Get
	regexes by const reference; use nested if checks.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-suppression.cc | 167 +++++++++++++++++++----------------------
 1 file changed, 76 insertions(+), 91 deletions(-)

diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 33bccbb6..fa382e02 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -1057,15 +1057,14 @@ 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.
-	  if (const regex_t_sptr& type_name_regex =
-	      s.get_type_name_regex())
+	  if (const regex_t_sptr& type_name_regex = s.get_type_name_regex())
 	    {
 	      if (!regex::match(type_name_regex, type_name))
 		return false;
 	    }
 
-	  if (const regex_t_sptr type_name_not_regex =
-	      s.get_type_name_not_regex())
+	  if (const regex_t_sptr& type_name_not_regex =
+		s.get_type_name_not_regex())
 	    {
 	      if (regex::match(type_name_not_regex, type_name))
 		return false;
@@ -1113,7 +1112,7 @@ suppression_matches_type_location(const type_suppression&	s,
       unsigned loc_line = 0, loc_column = 0;
       loc.expand(loc_path, loc_line, loc_column);
 
-      if (regex_t_sptr regexp = s.get_source_location_to_keep_regex())
+      if (const regex_t_sptr& regexp = s.get_source_location_to_keep_regex())
 	if (regex::match(regexp, loc_path))
 	  return false;
 
@@ -2553,7 +2552,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
 
   // check if the "name_regexp" property matches.
-  const regex_t_sptr name_regex = get_name_regex();
+  const regex_t_sptr& name_regex = get_name_regex();
   if (name_regex)
     {
       if (!regex::match(name_regex, fname))
@@ -2584,7 +2583,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
 
   // check if the "name_not_regexp" property matches.
-  const regex_t_sptr name_not_regex = get_name_not_regex();
+  const regex_t_sptr& name_not_regex = get_name_not_regex();
   if (name_not_regex)
     {
       if (regex::match(name_not_regex, fname))
@@ -2628,11 +2627,9 @@ function_suppression::suppresses_function(const function_decl* fn,
       if (fn_return_type_name != get_return_type_name())
 	return false;
     }
-  else
+  else if (const regex_t_sptr& regex = get_return_type_regex())
     {
-      const regex_t_sptr return_type_regex = get_return_type_regex();
-      if (return_type_regex
-	  && !regex::match(return_type_regex, fn_return_type_name))
+      if (!regex::match(regex, fn_return_type_name))
 	return false;
     }
 
@@ -2668,14 +2665,15 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
   else if (sym)
     {
-      const regex_t_sptr symbol_name_regex = get_symbol_name_regex();
-      if (symbol_name_regex && !regex::match(symbol_name_regex, fn_sym_name))
-	return false;
+      const regex_t_sptr& symbol_name_regex = get_symbol_name_regex();
+      const regex_t_sptr& symbol_name_not_regex = get_symbol_name_not_regex();
 
-      const regex_t_sptr symbol_name_not_regex = get_symbol_name_not_regex();
-      if (symbol_name_not_regex
-	  && regex::match(symbol_name_not_regex, fn_sym_name))
-	return false;
+      if (symbol_name_regex)
+	if (!regex::match(symbol_name_regex, fn_sym_name))
+	  return false;
+      if (symbol_name_not_regex)
+	if (regex::match(symbol_name_not_regex, fn_sym_name))
+	  return false;
 
       if (get_allow_other_aliases())
 	{
@@ -2688,13 +2686,13 @@ function_suppression::suppresses_function(const function_decl* fn,
 		   a && !a->is_main_symbol();
 		   a = a->get_next_alias())
 		{
-		  if (symbol_name_regex
-		      && !regex::match(symbol_name_regex, a->get_name()))
-		    return false;
-
-		  if (symbol_name_not_regex
-		      && regex::match(symbol_name_not_regex, a->get_name()))
-		    return false;
+		  const std::string& alias_name = a->get_name();
+		  if (symbol_name_regex)
+		    if (!regex::match(symbol_name_regex, alias_name))
+		      return false;
+		  if (symbol_name_not_regex)
+		    if (regex::match(symbol_name_not_regex, alias_name))
+		      return false;
 		}
 	    }
 	}
@@ -2702,17 +2700,19 @@ function_suppression::suppresses_function(const function_decl* fn,
 
   // Check if the "symbol_version" and "symbol_version_regexp"
   // properties match.
-  if (sym && !get_symbol_version().empty())
-    {
-      if (fn_sym_version != get_symbol_version())
-	return false;
-    }
-  else if (sym)
+  if (sym)
     {
-      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
-      if (symbol_version_regex
-	  && !regex::match(symbol_version_regex, fn_sym_version))
-	return false;
+      if (!get_symbol_version().empty())
+	{
+	  if (fn_sym_version != get_symbol_version())
+	    return false;
+	}
+      else
+	{
+	  if (const regex_t_sptr& regex = get_symbol_version_regex())
+	    if (!regex::match(regex, fn_sym_version))
+	      return false;
+	}
     }
 
   // Check the 'parameter' property.
@@ -2746,16 +2746,11 @@ function_suppression::suppresses_function(const function_decl* fn,
 	      if (tn != fn_parm_type_qualified_name)
 		return false;
 	    }
-	  else
+	  else if (const regex_t_sptr& regex =
+		     (*p)->get_parameter_type_name_regex())
 	    {
-	      const regex_t_sptr parm_type_name_regex =
-		(*p)->get_parameter_type_name_regex();
-	      if (parm_type_name_regex)
-		{
-		  if (!regex::match(parm_type_name_regex,
-				    fn_parm_type_qualified_name))
-		    return false;
-		}
+	      if (!regex::match(regex, fn_parm_type_qualified_name))
+		return false;
 	    }
 	}
     }
@@ -2838,10 +2833,9 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
       if (sym_name != get_symbol_name())
 	return false;
     }
-  else if (get_symbol_name_regex())
+  else if (const regex_t_sptr& regex = get_symbol_name_regex())
     {
-      const regex_t_sptr symbol_name_regex = get_symbol_name_regex();
-      if (symbol_name_regex && !regex::match(symbol_name_regex, sym_name))
+      if (!regex::match(regex, sym_name))
 	return false;
     }
   else
@@ -2853,11 +2847,9 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
       if (sym_version != get_symbol_version())
 	return false;
     }
-  else if (get_symbol_version_regex())
+  else if (const regex_t_sptr& regex = get_symbol_version_regex())
     {
-      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
-      if (symbol_version_regex
-	  && !regex::match(symbol_version_regex, sym_version))
+      if (!regex::match(regex, sym_version))
 	return false;
     }
   else
@@ -2947,12 +2939,12 @@ bool
 suppression_matches_function_name(const suppr::function_suppression& s,
 				  const string& fn_name)
 {
-  if (regex_t_sptr regexp = s.get_name_regex())
+  if (const regex_t_sptr& regexp = s.get_name_regex())
     {
       if (!regex::match(regexp, fn_name))
 	return false;
     }
-  else if (regex_t_sptr regexp = s.get_name_not_regex())
+  else if (const regex_t_sptr& regexp = s.get_name_not_regex())
     {
       if (regex::match(regexp, fn_name))
 	return false;
@@ -2983,12 +2975,12 @@ bool
 suppression_matches_function_sym_name(const suppr::function_suppression& s,
 				      const string& fn_linkage_name)
 {
-  if (regex_t_sptr regexp = s.get_symbol_name_regex())
+  if (const regex_t_sptr& regexp = s.get_symbol_name_regex())
     {
       if (!regex::match(regexp, fn_linkage_name))
 	return false;
     }
-  else if (regex_t_sptr regexp = s.get_symbol_name_not_regex())
+  else if (const regex_t_sptr& regexp = s.get_symbol_name_not_regex())
     {
       if (regex::match(regexp, fn_linkage_name))
 	return false;
@@ -3016,12 +3008,12 @@ bool
 suppression_matches_variable_name(const suppr::variable_suppression& s,
 				  const string& var_name)
 {
-  if (regex_t_sptr regexp = s.get_name_regex())
+  if (const regex_t_sptr& regexp = s.get_name_regex())
     {
       if (!regex::match(regexp, var_name))
 	return false;
     }
-  else if (regex_t_sptr regexp = s.get_name_not_regex())
+  else if (const regex_t_sptr& regexp = s.get_name_not_regex())
     {
       if (regex::match(regexp, var_name))
 	return false;
@@ -3050,12 +3042,12 @@ bool
 suppression_matches_variable_sym_name(const suppr::variable_suppression& s,
 				      const string& var_linkage_name)
 {
-  if (regex_t_sptr regexp = s.get_symbol_name_regex())
+  if (const regex_t_sptr& regexp = s.get_symbol_name_regex())
     {
       if (!regex::match(regexp, var_linkage_name))
 	return false;
     }
-  else if (regex_t_sptr regexp = s.get_symbol_name_not_regex())
+  else if (const regex_t_sptr& regexp = s.get_symbol_name_not_regex())
     {
       if (regex::match(regexp, var_linkage_name))
 	return false;
@@ -3084,7 +3076,7 @@ bool
 suppression_matches_type(const suppr::type_suppression& s,
 			 const string& type_name)
 {
-  if (regex_t_sptr regexp = s.get_type_name_regex())
+  if (const regex_t_sptr& regexp = s.get_type_name_regex())
     {
       if (!regex::match(regexp, type_name))
 	return false;
@@ -3793,13 +3785,13 @@ variable_suppression::suppresses_variable(const var_decl* var,
       // "name_regex" and "name_not_regex" properties match
       if (get_name().empty())
 	{
-	  const regex_t_sptr name_regex = get_name_regex();
-	  if (name_regex && !regex::match(name_regex, var_name))
-	    return false;
+	  if (const regex_t_sptr& regex = get_name_regex())
+	    if (!regex::match(regex, var_name))
+	      return false;
 
-	  const regex_t_sptr name_not_regex = get_name_not_regex();
-	  if (name_not_regex && regex::match(name_not_regex, var_name))
-	    return false;
+	  if (const regex_t_sptr& regex = get_name_not_regex())
+	    if (regex::match(regex, var_name))
+	      return false;
 	}
     }
 
@@ -3813,13 +3805,13 @@ variable_suppression::suppresses_variable(const var_decl* var,
     }
   else
     {
-      const regex_t_sptr sym_name_regex = get_symbol_name_regex();
-      if (sym_name_regex && !regex::match(sym_name_regex, var_sym_name))
-	return false;
+      if (const regex_t_sptr& regex = get_symbol_name_regex())
+	if (!regex::match(regex, var_sym_name))
+	  return false;
 
-      const regex_t_sptr sym_name_not_regex = get_symbol_name_not_regex();
-      if (sym_name_not_regex && regex::match(sym_name_not_regex, var_sym_name))
-	return false;
+      if (const regex_t_sptr& regex = get_symbol_name_not_regex())
+	if (regex::match(regex, var_sym_name))
+	  return false;
     }
 
   // Check for symbol_version and symbol_version_regexp property match
@@ -3832,10 +3824,9 @@ variable_suppression::suppresses_variable(const var_decl* var,
     }
   else
     {
-      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
-      if (symbol_version_regex
-	  && !regex::match(symbol_version_regex, var_sym_version))
-	return false;
+      if (const regex_t_sptr& regex = get_symbol_version_regex())
+	if (!regex::match(regex, var_sym_version))
+	  return false;
     }
 
   // Check for the "type_name" and type_name_regex properties match.
@@ -3849,12 +3840,9 @@ variable_suppression::suppresses_variable(const var_decl* var,
     }
   else
     {
-      if (get_type_name().empty())
-	{
-	  const regex_t_sptr type_name_regex = get_type_name_regex();
-	  if (type_name_regex && !regex::match(type_name_regex, var_type_name))
-	    return false;
-	}
+      if (const regex_t_sptr& regex = get_type_name_regex())
+	if (!regex::match(regex, var_type_name))
+	  return false;
     }
 
   return true;
@@ -3940,10 +3928,9 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
       if (get_symbol_name() != sym_name)
 	return false;
     }
-  else if (get_symbol_name_regex())
+  else if (const regex_t_sptr& regex = get_symbol_name_regex())
     {
-      const regex_t_sptr sym_name_regex = get_symbol_name_regex();
-      if (sym_name_regex && !regex::match(sym_name_regex, sym_name))
+      if (!regex::match(regex, sym_name))
 	return false;
     }
   else
@@ -3956,11 +3943,9 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
       if (get_symbol_version() != sym_version)
 	return false;
     }
-  else if (get_symbol_version_regex())
+  else if (const regex_t_sptr& regex = get_symbol_version_regex())
     {
-      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
-      if (symbol_version_regex
-	  && !regex::match(symbol_version_regex, sym_version))
+      if (!regex::match(regex, sym_version))
 	return false;
     }
   else
@@ -4261,14 +4246,14 @@ file_suppression::suppresses_file(const string& file_path)
 
   bool has_regexp = false;
 
-  if (regex_t_sptr regexp = get_file_name_regex())
+  if (const regex_t_sptr& regexp = get_file_name_regex())
     {
       has_regexp = true;
       if (!regex::match(regexp, fname))
 	return false;
     }
 
-  if (regex_t_sptr regexp = get_file_name_not_regex())
+  if (const regex_t_sptr& regexp = get_file_name_not_regex())
     {
       has_regexp = true;
       if (regex::match(regexp, fname))
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH 16/21] abg-tools-utils.cc: Assert generated regexes OK.
  2020-04-23 15:44 [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
                   ` (14 preceding siblings ...)
  2020-04-23 15:44 ` [PATCH 15/21] abg-suppression.cc: More consistent regex matching Giuliano Procida
@ 2020-04-23 15:44 ` Giuliano Procida
  2020-04-23 15:44 ` [PATCH 17/21] Refactor suppression property string parsing Giuliano Procida
                   ` (6 subsequent siblings)
  22 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-23 15:44 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

There are a couple of places where regexes are generated interally.
Assert they compile OK.

This is just paranoia. There should be no behavioural changes.

	* src/abg-tools-utils.cc (handle_file_entry): Assert
	internally-generated regex compiles.
	(gen_suppr_spec_from_kernel_abi_whitelists): Assert
	internally-generated regex compiles.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-tools-utils.cc | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/abg-tools-utils.cc b/src/abg-tools-utils.cc
index fe0de750..3af9fc49 100644
--- a/src/abg-tools-utils.cc
+++ b/src/abg-tools-utils.cc
@@ -1818,6 +1818,7 @@ handle_file_entry(const string& file_path,
       // Types that are defined in system headers are usually
       // OK to be considered as public types.
       regex::regex_t_sptr headers_regex = regex::compile("^/usr/include/");
+      ABG_ASSERT(headers_regex);
       suppr->set_source_location_to_keep_regex(headers_regex);
       suppr->set_is_artificial(true);
     }
@@ -2008,6 +2009,7 @@ gen_suppr_spec_from_kernel_abi_whitelists
       // the function and variable names expressed in the white list.
       regex::regex_t_sptr regex =
 	regex::compile(regex::generate_from_strings(whitelisted_names));
+      ABG_ASSERT(regex);
 
       // Build a suppression specification which *keeps* functions
       // whose ELF symbols match the regular expression contained
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH 17/21] Refactor suppression property string parsing.
  2020-04-23 15:44 [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
                   ` (15 preceding siblings ...)
  2020-04-23 15:44 ` [PATCH 16/21] abg-tools-utils.cc: Assert generated regexes OK Giuliano Procida
@ 2020-04-23 15:44 ` Giuliano Procida
  2020-04-23 15:44 ` [PATCH 18/21] Refactor suppression property regex parsing Giuliano Procida
                   ` (5 subsequent siblings)
  22 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-23 15:44 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

This patch introduces a helper function to look up a key in an ini
configuration section and get a string value. All string look-ups now
use this.

There are no behavioural changes.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-suppression.cc | 198 ++++++++++++++++-------------------------
 1 file changed, 78 insertions(+), 120 deletions(-)

diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index fa382e02..13431eef 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -1598,6 +1598,31 @@ read_suppression_reach_kind(const string& input)
     return type_suppression::DIRECT_REACH_KIND;
 }
 
+/// Maybe fetch a property to a string.
+///
+/// Attempt to find a simple property in an ini section and copy it
+/// to a string
+///
+/// @param section the ini section to look in
+///
+/// @param prop the property name
+///
+/// @param str the string to compile into
+///
+/// @return whether the property was found
+static bool
+maybe_get_string_prop(const ini::config::section& section,
+                      const std::string& name,
+                      std::string& str)
+{
+  ini::simple_property_sptr prop =
+    is_simple_property(section.find_property(name));
+  if (!prop)
+    return false;
+  str = prop->get_value()->as_string();
+  return true;
+}
+
 /// Read a type suppression from an instance of ini::config::section
 /// and build a @ref type_suppression as a result.
 ///
@@ -1613,18 +1638,12 @@ read_type_suppression(const ini::config::section& section)
   if (section.get_name() != "suppress_type")
     return result;
 
-  ini::simple_property_sptr drop_artifact =
-    is_simple_property(section.find_property("drop_artifact"));
-  if (!drop_artifact)
-    drop_artifact = is_simple_property(section.find_property("drop"));
-
-  string drop_artifact_str = drop_artifact
-    ? drop_artifact->get_value()->as_string()
-    : "";
+  string drop_artifact_str;
+  maybe_get_string_prop(section, "drop_artifact", drop_artifact_str)
+    || maybe_get_string_prop(section, "drop", drop_artifact_str);
 
-  ini::simple_property_sptr label =
-    is_simple_property(section.find_property("label"));
-  string label_str = label ? label->get_value()->as_string() : "";
+  string label_str;
+  maybe_get_string_prop(section, "label", label_str);
 
   ini::simple_property_sptr file_name_regex_prop =
     is_simple_property(section.find_property("file_name_regexp"));
@@ -1666,11 +1685,8 @@ read_type_suppression(const ini::config::section& section)
     name_not_regex =
       regex::compile(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
-    ? name_prop->get_value()->as_string()
-    : "";
+  string name_str;
+  maybe_get_string_prop(section, "name", name_str);
 
   ini::property_sptr srcloc_not_in_prop =
     section.find_property("source_location_not_in");
@@ -1701,25 +1717,19 @@ read_type_suppression(const ini::config::section& section)
     srcloc_not_regex =
       regex::compile(srcloc_not_regexp_prop->get_value()->as_string());
 
-  bool consider_type_kind = false;
-  type_suppression::type_kind type_kind = type_suppression::UNKNOWN_TYPE_KIND;
-  if (ini::simple_property_sptr type_kind_prop =
-      is_simple_property(section.find_property("type_kind")))
-    {
-      consider_type_kind = true;
-      type_kind =
-	read_type_kind_string(type_kind_prop->get_value()->as_string());
-    }
+  std::string type_kind_str;
+  bool consider_type_kind =
+    maybe_get_string_prop(section, "type_kind", type_kind_str);
+  type_suppression::type_kind type_kind = consider_type_kind
+    ? read_type_kind_string(type_kind_str)
+    : type_suppression::UNKNOWN_TYPE_KIND;
 
-  bool consider_reach_kind = false;
-  type_suppression::reach_kind reach_kind = type_suppression::DIRECT_REACH_KIND;
-  if (ini::simple_property_sptr reach_kind_prop =
-      is_simple_property(section.find_property("accessed_through")))
-    {
-      consider_reach_kind = true;
-      reach_kind =
-	read_suppression_reach_kind(reach_kind_prop->get_value()->as_string());
-    }
+  std::string reach_kind_str;
+  bool consider_reach_kind =
+      maybe_get_string_prop(section, "accessed_through", reach_kind_str);
+  type_suppression::reach_kind reach_kind = consider_reach_kind
+    ? read_suppression_reach_kind(reach_kind_str)
+    : type_suppression::DIRECT_REACH_KIND;
 
   // Support has_data_member_inserted_at
   vector<type_suppression::insertion_range_sptr> insert_ranges;
@@ -3179,26 +3189,15 @@ read_function_suppression(const ini::config::section& section)
   if (section.get_name() != "suppress_function")
     return result;
 
-  ini::simple_property_sptr drop_artifact =
-    is_simple_property(section.find_property("drop_artifact"));
-  if (!drop_artifact)
-    drop_artifact = is_simple_property(section.find_property("drop"));
-
-  string drop_artifact_str = drop_artifact
-    ? drop_artifact->get_value()->as_string()
-    : "";
+  string drop_artifact_str;
+  maybe_get_string_prop(section, "drop_artifact", drop_artifact_str)
+    || maybe_get_string_prop(section, "drop", drop_artifact_str);
 
-  ini::simple_property_sptr change_kind_prop =
-    is_simple_property(section.find_property("change_kind"));
-  string change_kind_str = change_kind_prop
-    ? change_kind_prop->get_value()->as_string()
-    : "";
+  string change_kind_str;
+  maybe_get_string_prop(section, "change_kind", change_kind_str);
 
-  ini::simple_property_sptr label_prop =
-    is_simple_property(section.find_property("label"));
-  string label_str = label_prop
-    ? label_prop->get_value()->as_string()
-    : "";
+  string label_str;
+  maybe_get_string_prop(section, "label", label_str);
 
   ini::simple_property_sptr file_name_regex_prop =
     is_simple_property(section.find_property("file_name_regexp"));
@@ -3227,11 +3226,8 @@ read_function_suppression(const ini::config::section& section)
     soname_not_regex =
       regex::compile(soname_not_regex_prop->get_value()->as_string());
 
-  ini::simple_property_sptr name_prop =
-    is_simple_property(section.find_property("name"));
-  string name = name_prop
-    ? name_prop->get_value()->as_string()
-    : "";
+  string name;
+  maybe_get_string_prop(section, "name", name);
 
   ini::simple_property_sptr name_regex_prop =
     is_simple_property(section.find_property("name_regexp"));
@@ -3246,11 +3242,8 @@ read_function_suppression(const ini::config::section& section)
     name_not_regex =
       regex::compile(name_not_regex_prop->get_value()->as_string());
 
-  ini::simple_property_sptr return_type_name_prop =
-    is_simple_property(section.find_property("return_type_name"));
-  string return_type_name = return_type_name_prop
-    ? return_type_name_prop->get_value()->as_string()
-    : "";
+  string return_type_name;
+  maybe_get_string_prop(section, "return_type_name", return_type_name);
 
   ini::simple_property_sptr return_type_regex_prop =
     is_simple_property(section.find_property("return_type_regexp"));
@@ -3259,11 +3252,8 @@ read_function_suppression(const ini::config::section& section)
     return_type_regex =
       regex::compile(return_type_regex_prop->get_value()->as_string());
 
-  ini::simple_property_sptr sym_name_prop =
-    is_simple_property(section.find_property("symbol_name"));
-  string sym_name = sym_name_prop
-    ? sym_name_prop->get_value()->as_string()
-    : "";
+  string sym_name;
+  maybe_get_string_prop(section, "symbol_name", sym_name);
 
   ini::simple_property_sptr sym_name_regex_prop =
     is_simple_property(section.find_property("symbol_name_regexp"));
@@ -3279,11 +3269,8 @@ read_function_suppression(const ini::config::section& section)
     sym_name_not_regex =
       regex::compile(sym_name_not_regex_prop->get_value()->as_string());
 
-  ini::simple_property_sptr sym_ver_prop =
-    is_simple_property(section.find_property("symbol_version"));
-  string sym_version = sym_ver_prop
-    ? sym_ver_prop->get_value()->as_string()
-    : "";
+  string sym_version;
+  maybe_get_string_prop(section, "symbol_version", sym_version);
 
   ini::simple_property_sptr sym_ver_regex_prop =
     is_simple_property(section.find_property("symbol_version_regexp"));
@@ -3292,11 +3279,8 @@ read_function_suppression(const ini::config::section& section)
     sym_ver_regex =
       regex::compile(sym_ver_regex_prop->get_value()->as_string());
 
-  ini::simple_property_sptr allow_other_aliases_prop =
-    is_simple_property(section.find_property("allow_other_aliases"));
-  string allow_other_aliases = allow_other_aliases_prop
-    ? allow_other_aliases_prop->get_value()->as_string()
-    : "";
+  string allow_other_aliases;
+  maybe_get_string_prop(section, "allow_other_aliases", allow_other_aliases);
 
   function_suppression::parameter_spec_sptr parm;
   function_suppression::parameter_specs_type parms;
@@ -4035,26 +4019,15 @@ read_variable_suppression(const ini::config::section& section)
   if (section.get_name() != "suppress_variable")
     return result;
 
-  ini::simple_property_sptr drop_artifact =
-    is_simple_property(section.find_property("drop_artifact"));
-  if (!drop_artifact)
-    drop_artifact = is_simple_property(section.find_property("drop"));
-
-  string drop_artifact_str = drop_artifact
-    ? drop_artifact->get_value()->as_string()
-    : "";
+  string drop_artifact_str;
+  maybe_get_string_prop(section, "drop_artifact", drop_artifact_str)
+    || maybe_get_string_prop(section, "drop", drop_artifact_str);
 
-  ini::simple_property_sptr change_kind_prop =
-    is_simple_property(section.find_property("change_kind"));
-  string change_kind_str = change_kind_prop
-    ? change_kind_prop->get_value()->as_string()
-    : "";
+  string change_kind_str;
+  maybe_get_string_prop(section, "change_kind", change_kind_str);
 
-  ini::simple_property_sptr label_prop =
-    is_simple_property(section.find_property("label"));
-  string label_str = (label_prop
-		      ? label_prop->get_value()->as_string()
-		      : "");
+  string label_str;
+  maybe_get_string_prop(section, "label", label_str);
 
   ini::simple_property_sptr file_name_regex_prop =
     is_simple_property(section.find_property("file_name_regexp"));
@@ -4083,11 +4056,8 @@ read_variable_suppression(const ini::config::section& section)
     soname_not_regex =
       regex::compile(soname_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
-		     ? name_prop->get_value()->as_string()
-		     : "");
+  string name_str;
+  maybe_get_string_prop(section, "name", name_str);
 
   ini::simple_property_sptr name_regex_prop =
     is_simple_property(section.find_property("name_regexp"));
@@ -4102,11 +4072,8 @@ read_variable_suppression(const ini::config::section& section)
     name_not_regex =
       regex::compile(name_not_regex_prop->get_value()->as_string());
 
-  ini::simple_property_sptr sym_name_prop =
-    is_simple_property(section.find_property("symbol_name"));
-  string symbol_name = (sym_name_prop
-			? sym_name_prop->get_value()->as_string()
-			: "");
+  string symbol_name;
+  maybe_get_string_prop(section, "symbol_name", symbol_name);
 
   ini::simple_property_sptr sym_name_regex_prop =
     is_simple_property(section.find_property("symbol_name_regexp"));
@@ -4122,11 +4089,8 @@ read_variable_suppression(const ini::config::section& section)
     symbol_name_not_regex =
       regex::compile(sym_name_not_regex_prop->get_value()->as_string());
 
-  ini::simple_property_sptr sym_version_prop =
-    is_simple_property(section.find_property("symbol_version"));
-  string symbol_version = sym_version_prop
-    ? sym_version_prop->get_value()->as_string()
-    : "";
+  string symbol_version;
+  maybe_get_string_prop(section, "symbol_version", symbol_version);
 
   ini::simple_property_sptr sym_version_regex_prop =
     is_simple_property(section.find_property("symbol_version_regexp"));
@@ -4135,11 +4099,8 @@ read_variable_suppression(const ini::config::section& section)
     symbol_version_regex =
       regex::compile(sym_version_regex_prop->get_value()->as_string());
 
-  ini::simple_property_sptr type_name_prop =
-    is_simple_property(section.find_property("type_name"));
-  string type_name_str = type_name_prop
-    ? type_name_prop->get_value()->as_string()
-    : "";
+  string type_name_str;
+  maybe_get_string_prop(section, "type_name", type_name_str);
 
   ini::simple_property_sptr type_name_regex_prop =
     is_simple_property(section.find_property("type_name_regexp"));
@@ -4286,11 +4247,8 @@ read_file_suppression(const ini::config::section& section)
   if (section.get_name() != "suppress_file")
     return result;
 
-  ini::simple_property_sptr label_prop =
-    is_simple_property(section.find_property("label"));
-  string label_str = (label_prop
-		      ? label_prop->get_value()->as_string()
-		      : "");
+  string label_str;
+  maybe_get_string_prop(section, "label", label_str);
 
   ini::simple_property_sptr file_name_regex_prop =
     is_simple_property(section.find_property("file_name_regexp"));
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH 18/21] Refactor suppression property regex parsing.
  2020-04-23 15:44 [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
                   ` (16 preceding siblings ...)
  2020-04-23 15:44 ` [PATCH 17/21] Refactor suppression property string parsing Giuliano Procida
@ 2020-04-23 15:44 ` Giuliano Procida
  2020-04-23 15:44 ` [PATCH 19/21] Warn if user-supplied regexes fail to compile Giuliano Procida
                   ` (4 subsequent siblings)
  22 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-23 15:44 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

This patch introduces a helper function to look up a key in an ini
configuration section and get a compiled regex value. All regex
look-ups now use this.

There are no behavioural changes.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-suppression.cc | 215 ++++++++++++-----------------------------
 1 file changed, 61 insertions(+), 154 deletions(-)

diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 13431eef..3db2b7b1 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -1623,6 +1623,30 @@ maybe_get_string_prop(const ini::config::section& section,
   return true;
 }
 
+/// Maybe compile a property to a regex.
+///
+/// Attempt to find a simple property in an ini section and compile it
+/// to a regex.
+///
+/// @param section the ini section to look in
+///
+/// @param prop the property name
+///
+/// @param r the regex to compile into
+///
+/// @return whether the property was found
+static bool
+maybe_get_regex_prop(const ini::config::section& section,
+                     const std::string& name,
+                     regex_t_sptr& regex)
+{
+  string str;
+  if (!maybe_get_string_prop(section, name, str))
+    return false;
+  regex = regex::compile(str);
+  return true;
+}
+
 /// Read a type suppression from an instance of ini::config::section
 /// and build a @ref type_suppression as a result.
 ///
@@ -1645,45 +1669,23 @@ read_type_suppression(const ini::config::section& section)
   string label_str;
   maybe_get_string_prop(section, "label", label_str);
 
-  ini::simple_property_sptr file_name_regex_prop =
-    is_simple_property(section.find_property("file_name_regexp"));
   regex_t_sptr file_name_regex;
-  if (file_name_regex_prop)
-    file_name_regex =
-      regex::compile(file_name_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "file_name_regexp", file_name_regex);
 
-  ini::simple_property_sptr file_name_not_regex_prop =
-    is_simple_property(section.find_property("file_name_not_regexp"));
   regex_t_sptr file_name_not_regex;
-  if (file_name_not_regex_prop)
-    file_name_not_regex =
-      regex::compile(file_name_not_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "file_name_not_regexp", file_name_not_regex);
 
-  ini::simple_property_sptr soname_regex_prop =
-    is_simple_property(section.find_property("soname_regexp"));
   regex_t_sptr soname_regex;
-  if (soname_regex_prop)
-    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "soname_regexp", soname_regex);
 
-  ini::simple_property_sptr soname_not_regex_prop =
-    is_simple_property(section.find_property("soname_not_regexp"));
   regex_t_sptr soname_not_regex;
-  if (soname_not_regex_prop)
-    soname_not_regex =
-      regex::compile(soname_not_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "soname_not_regexp", soname_not_regex);
 
-  ini::simple_property_sptr name_regex_prop =
-    is_simple_property(section.find_property("name_regexp"));
   regex_t_sptr name_regex;
-  if (name_regex_prop)
-    name_regex = regex::compile(name_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "name_regexp", name_regex);
 
-  ini::simple_property_sptr name_not_regex_prop =
-    is_simple_property(section.find_property("name_not_regexp"));
   regex_t_sptr name_not_regex;
-  if (name_not_regex_prop)
-    name_not_regex =
-      regex::compile(name_not_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "name_not_regexp", name_not_regex);
 
   string name_str;
   maybe_get_string_prop(section, "name", name_str);
@@ -1710,12 +1712,8 @@ read_type_suppression(const ini::config::section& section)
 	}
     }
 
-  ini::simple_property_sptr srcloc_not_regexp_prop =
-    is_simple_property(section.find_property("source_location_not_regexp"));
   regex_t_sptr srcloc_not_regex;
-  if (srcloc_not_regexp_prop)
-    srcloc_not_regex =
-      regex::compile(srcloc_not_regexp_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "source_location_not_regexp", srcloc_not_regex);
 
   std::string type_kind_str;
   bool consider_type_kind =
@@ -3199,85 +3197,47 @@ read_function_suppression(const ini::config::section& section)
   string label_str;
   maybe_get_string_prop(section, "label", label_str);
 
-  ini::simple_property_sptr file_name_regex_prop =
-    is_simple_property(section.find_property("file_name_regexp"));
   regex_t_sptr file_name_regex;
-  if (file_name_regex_prop)
-    file_name_regex =
-      regex::compile(file_name_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "file_name_regexp", file_name_regex);
 
-  ini::simple_property_sptr file_name_not_regex_prop =
-    is_simple_property(section.find_property("file_name_not_regexp"));
   regex_t_sptr file_name_not_regex;
-  if (file_name_not_regex_prop)
-    file_name_not_regex =
-      regex::compile(file_name_not_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "file_name_not_regexp", file_name_not_regex);
 
-  ini::simple_property_sptr soname_regex_prop =
-    is_simple_property(section.find_property("soname_regexp"));
   regex_t_sptr soname_regex;
-  if (soname_regex_prop)
-    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "soname_regexp", soname_regex);
 
-  ini::simple_property_sptr soname_not_regex_prop =
-    is_simple_property(section.find_property("soname_not_regexp"));
   regex_t_sptr soname_not_regex;
-  if (soname_not_regex_prop)
-    soname_not_regex =
-      regex::compile(soname_not_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "soname_not_regexp", soname_not_regex);
 
   string name;
   maybe_get_string_prop(section, "name", name);
 
-  ini::simple_property_sptr name_regex_prop =
-    is_simple_property(section.find_property("name_regexp"));
   regex_t_sptr name_regex;
-  if (name_regex_prop)
-    name_regex = regex::compile(name_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "name_regexp", name_regex);
 
-  ini::simple_property_sptr name_not_regex_prop =
-    is_simple_property(section.find_property("name_not_regexp"));
   regex_t_sptr name_not_regex;
-  if (name_not_regex_prop)
-    name_not_regex =
-      regex::compile(name_not_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "name_not_regexp", name_not_regex);
 
   string return_type_name;
   maybe_get_string_prop(section, "return_type_name", return_type_name);
 
-  ini::simple_property_sptr return_type_regex_prop =
-    is_simple_property(section.find_property("return_type_regexp"));
   regex_t_sptr return_type_regex;
-  if (return_type_regex_prop)
-    return_type_regex =
-      regex::compile(return_type_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "return_type_regexp", return_type_regex);
 
   string sym_name;
   maybe_get_string_prop(section, "symbol_name", sym_name);
 
-  ini::simple_property_sptr sym_name_regex_prop =
-    is_simple_property(section.find_property("symbol_name_regexp"));
   regex_t_sptr sym_name_regex;
-  if (sym_name_regex_prop)
-    sym_name_regex =
-      regex::compile(sym_name_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "symbol_name_regexp", sym_name_regex);
 
-  ini::simple_property_sptr sym_name_not_regex_prop =
-    is_simple_property(section.find_property("symbol_name_not_regexp"));
   regex_t_sptr sym_name_not_regex;
-  if (sym_name_not_regex_prop)
-    sym_name_not_regex =
-      regex::compile(sym_name_not_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "symbol_name_not_regexp", sym_name_not_regex);
 
   string sym_version;
   maybe_get_string_prop(section, "symbol_version", sym_version);
 
-  ini::simple_property_sptr sym_ver_regex_prop =
-    is_simple_property(section.find_property("symbol_version_regexp"));
   regex_t_sptr sym_ver_regex;
-  if (sym_ver_regex_prop)
-    sym_ver_regex =
-      regex::compile(sym_ver_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "symbol_version_regexp", sym_ver_regex);
 
   string allow_other_aliases;
   maybe_get_string_prop(section, "allow_other_aliases", allow_other_aliases);
@@ -4029,85 +3989,47 @@ read_variable_suppression(const ini::config::section& section)
   string label_str;
   maybe_get_string_prop(section, "label", label_str);
 
-  ini::simple_property_sptr file_name_regex_prop =
-    is_simple_property(section.find_property("file_name_regexp"));
   regex_t_sptr file_name_regex;
-  if (file_name_regex_prop)
-    file_name_regex =
-      regex::compile(file_name_regex_prop->get_value()->as_string());
-
- ini::simple_property_sptr file_name_not_regex_prop =
-  is_simple_property(section.find_property("file_name_not_regexp"));
- regex_t_sptr file_name_not_regex;
- if (file_name_not_regex_prop)
-   file_name_not_regex =
-     regex::compile(file_name_not_regex_prop->get_value()->as_string());
-
-  ini::simple_property_sptr soname_regex_prop =
-    is_simple_property(section.find_property("soname_regexp"));
+  maybe_get_regex_prop(section, "file_name_regexp", file_name_regex);
+
+  regex_t_sptr file_name_not_regex;
+  maybe_get_regex_prop(section, "file_name_not_regexp", file_name_not_regex);
+
   regex_t_sptr soname_regex;
-  if (soname_regex_prop)
-    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "soname_regexp", soname_regex);
 
-  ini::simple_property_sptr soname_not_regex_prop =
-    is_simple_property(section.find_property("soname_not_regexp"));
   regex_t_sptr soname_not_regex;
-  if (soname_not_regex_prop)
-    soname_not_regex =
-      regex::compile(soname_not_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "soname_not_regexp", soname_not_regex);
 
   string name_str;
   maybe_get_string_prop(section, "name", name_str);
 
-  ini::simple_property_sptr name_regex_prop =
-    is_simple_property(section.find_property("name_regexp"));
   regex_t_sptr name_regex;
-  if (name_regex_prop)
-    name_regex = regex::compile(name_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "name_regexp", name_regex);
 
-  ini::simple_property_sptr name_not_regex_prop =
-    is_simple_property(section.find_property("name_not_regexp"));
   regex_t_sptr name_not_regex;
-  if (name_not_regex_prop)
-    name_not_regex =
-      regex::compile(name_not_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "name_not_regexp", name_not_regex);
 
   string symbol_name;
   maybe_get_string_prop(section, "symbol_name", symbol_name);
 
-  ini::simple_property_sptr sym_name_regex_prop =
-    is_simple_property(section.find_property("symbol_name_regexp"));
   regex_t_sptr symbol_name_regex;
-  if (sym_name_regex_prop)
-    symbol_name_regex =
-      regex::compile(sym_name_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "symbol_name_regexp", symbol_name_regex);
 
-  ini::simple_property_sptr sym_name_not_regex_prop =
-    is_simple_property(section.find_property("symbol_name_not_regexp"));
   regex_t_sptr symbol_name_not_regex;
-  if (sym_name_not_regex_prop)
-    symbol_name_not_regex =
-      regex::compile(sym_name_not_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "symbol_name_not_regexp", symbol_name_not_regex);
 
   string symbol_version;
   maybe_get_string_prop(section, "symbol_version", symbol_version);
 
-  ini::simple_property_sptr sym_version_regex_prop =
-    is_simple_property(section.find_property("symbol_version_regexp"));
   regex_t_sptr symbol_version_regex;
-  if (sym_version_regex_prop)
-    symbol_version_regex =
-      regex::compile(sym_version_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "symbol_version_regexp", symbol_version_regex);
 
   string type_name_str;
   maybe_get_string_prop(section, "type_name", type_name_str);
 
-  ini::simple_property_sptr type_name_regex_prop =
-    is_simple_property(section.find_property("type_name_regexp"));
   regex_t_sptr type_name_regex;
-  if (type_name_regex_prop)
-    type_name_regex =
-      regex::compile(type_name_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "type_name_regexp", type_name_regex);
 
   result.reset(new variable_suppression(label_str,
 					name_str,
@@ -4250,32 +4172,17 @@ read_file_suppression(const ini::config::section& section)
   string label_str;
   maybe_get_string_prop(section, "label", label_str);
 
-  ini::simple_property_sptr file_name_regex_prop =
-    is_simple_property(section.find_property("file_name_regexp"));
   regex_t_sptr file_name_regex;
-  if (file_name_regex_prop)
-    file_name_regex =
-      regex::compile(file_name_regex_prop->get_value()->as_string());
-
- ini::simple_property_sptr file_name_not_regex_prop =
-    is_simple_property(section.find_property("file_name_not_regexp"));
- regex_t_sptr file_name_not_regex;
- if (file_name_not_regex_prop)
-   file_name_not_regex =
-     regex::compile(file_name_not_regex_prop->get_value()->as_string());
-
-  ini::simple_property_sptr soname_regex_prop =
-    is_simple_property(section.find_property("soname_regexp"));
+  maybe_get_regex_prop(section, "file_name_regexp", file_name_regex);
+
+  regex_t_sptr file_name_not_regex;
+  maybe_get_regex_prop(section, "file_name_not_regexp", file_name_not_regex);
+
   regex_t_sptr soname_regex;
-  if (soname_regex_prop)
-    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "soname_regexp", soname_regex);
 
-  ini::simple_property_sptr soname_not_regex_prop =
-    is_simple_property(section.find_property("soname_not_regexp"));
   regex_t_sptr soname_not_regex;
-  if (soname_not_regex_prop)
-    soname_not_regex =
-      regex::compile(soname_not_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "soname_not_regexp", soname_not_regex);
 
   result.reset(new file_suppression(label_str,
 				    file_name_regex,
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH 19/21] Warn if user-supplied regexes fail to compile.
  2020-04-23 15:44 [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
                   ` (17 preceding siblings ...)
  2020-04-23 15:44 ` [PATCH 18/21] Refactor suppression property regex parsing Giuliano Procida
@ 2020-04-23 15:44 ` Giuliano Procida
  2020-04-23 18:04   ` [PATCH v2 " Giuliano Procida
  2020-04-23 15:44 ` [PATCH 20/21] Default construct suppression types Giuliano Procida
                   ` (3 subsequent siblings)
  22 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-04-23 15:44 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

There are not many calls to regex::compile in the code base. Two of
these pass internally-generated regexes and are followed by assertions
that the regexes compile.

The remaining cases deal with user-supplied regexes. If these fail to
compile they are currently silently ignored.

This patch makes sure failures now result in warning messages on
stderr, but otherwise does not change program behaviour.

	* src/abg-corpus-priv.h
	(corpus::exported_decls_builder::priv::compiled_regex_fns_suppress):
	Emit a warning message if regex::compile fails.
	(corpus::exported_decls_builder::priv::compiled_regex_fns_keep):
	Ditto.
	(corpus::exported_decls_builder::priv::compiled_regex_vars_suppress):
	Ditto.
	(corpus::exported_decls_builder::priv::compiled_regex_vars_keep):
	Ditto.
	* src/abg-suppression.cc (maybe_get_string_prop): Ditto.
	(read_parameter_spec_from_string): Ditto.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-corpus-priv.h  | 8 ++++++++
 src/abg-suppression.cc | 4 ++++
 2 files changed, 12 insertions(+)

diff --git a/src/abg-corpus-priv.h b/src/abg-corpus-priv.h
index 2618e2d0..cae2dfb0 100644
--- a/src/abg-corpus-priv.h
+++ b/src/abg-corpus-priv.h
@@ -126,6 +126,8 @@ public:
 	    regex_t_sptr r = regex::compile(*i);
 	    if (r)
 	      compiled_fns_suppress_regexp_.push_back(r);
+	    else
+	      std::cerr << "warning: bad regex '" << *i << "'\n";
 	  }
       }
     return compiled_fns_suppress_regexp_;
@@ -148,6 +150,8 @@ public:
 	    regex_t_sptr r = regex::compile(*i);
 	    if (r)
 	      compiled_fns_keep_regexps_.push_back(r);
+	    else
+	      std::cerr << "warning: bad regex '" << *i << "'\n";
 	  }
       }
     return compiled_fns_keep_regexps_;
@@ -170,6 +174,8 @@ public:
 	    regex_t_sptr r = regex::compile(*i);
 	    if (r)
 	      compiled_vars_suppress_regexp_.push_back(r);
+	    else
+	      std::cerr << "warning: bad regex '" << *i << "'\n";
 	  }
       }
     return compiled_vars_suppress_regexp_;
@@ -192,6 +198,8 @@ public:
 	    regex_t_sptr r = regex::compile(*i);
 	    if (r)
 	      compiled_vars_keep_regexps_.push_back(r);
+	    else
+	      std::cerr << "warning: bad regex '" << *i << "'\n";
 	  }
       }
     return compiled_vars_keep_regexps_;
diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 3db2b7b1..8632d028 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -1644,6 +1644,8 @@ maybe_get_regex_prop(const ini::config::section& section,
   if (!maybe_get_string_prop(section, name, str))
     return false;
   regex = regex::compile(str);
+  if (!regex)
+    std::cerr << "warning: bad regex '" << str << "'\n";
   return true;
 }
 
@@ -3161,6 +3163,8 @@ read_parameter_spec_from_string(const string& str)
       if (is_regex)
 	{
 	  type_name_regex = regex::compile(type_name);
+	  if (!type_name_regex)
+	    std::cerr << "warning: bad regex '" << type_name << "'\n";
 	  type_name.clear();
 	}
       function_suppression::parameter_spec* p =
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH 20/21] Default construct suppression types.
  2020-04-23 15:44 [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
                   ` (18 preceding siblings ...)
  2020-04-23 15:44 ` [PATCH 19/21] Warn if user-supplied regexes fail to compile Giuliano Procida
@ 2020-04-23 15:44 ` Giuliano Procida
  2020-04-23 15:44 ` [PATCH 21/21] Remove unused suppression type priv constructors Giuliano Procida
                   ` (2 subsequent siblings)
  22 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-23 15:44 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

The current constructors for the various suppression types are not a
good match for their current uses. Given that every member is
effectively optional, default constructing these to a default
unpopulated state makes the code simpler.

There are no behavioural changes.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 include/abg-suppression.h  |  48 +------
 src/abg-suppression-priv.h |  28 ++--
 src/abg-suppression.cc     | 255 +++++++------------------------------
 src/abg-tools-utils.cc     |   7 +-
 4 files changed, 58 insertions(+), 280 deletions(-)

diff --git a/include/abg-suppression.h b/include/abg-suppression.h
index 02e77ea9..4c987a79 100644
--- a/include/abg-suppression.h
+++ b/include/abg-suppression.h
@@ -56,17 +56,10 @@ class suppression_base
   class priv;
   typedef shared_ptr<priv> priv_sptr;
 
-  // Forbid default constructor
-  suppression_base();
-
 public:
   priv_sptr priv_;
 
-  suppression_base(const string& label);
-
-  suppression_base(const string& label,
-		   const regex::regex_t_sptr& file_name_regex,
-		   const regex::regex_t_sptr& file_name_not_regex);
+  suppression_base();
 
   bool
   get_drops_artifact_from_ir() const;
@@ -153,9 +146,6 @@ class type_suppression : public suppression_base
   class priv;
   typedef shared_ptr<priv> priv_sptr;
 
-  // Forbid this;
-  type_suppression();
-
 public:
 
   priv_sptr priv_;
@@ -201,9 +191,7 @@ public:
   /// A convenience typedef for a vector of @ref insertion_range_sptr.
   typedef vector<insertion_range_sptr> insertion_ranges;
 
-  type_suppression(const string& label,
-		   const regex::regex_t_sptr& type_name_regexp,
-		   const string& type_name);
+  type_suppression();
 
   virtual ~type_suppression();
 
@@ -458,17 +446,6 @@ public:
 
   function_suppression();
 
-  function_suppression(const string&			label,
-		       const string&			name,
-		       const regex::regex_t_sptr&	name_regex,
-		       const string&			return_type_name,
-		       const regex::regex_t_sptr&	return_type_regex,
-		       parameter_specs_type&		parm_specs,
-		       const string&			symbol_name,
-		       const regex::regex_t_sptr&	symbol_name_regex,
-		       const string&			symbol_version,
-		       const regex::regex_t_sptr&	symbol_version_regex);
-
   virtual ~function_suppression();
 
   static change_kind
@@ -675,19 +652,7 @@ public:
 
   priv_sptr priv_;
 
-  variable_suppression(const string& label = "",
-		       const string& name = "",
-		       const regex::regex_t_sptr& name_regex =
-			 regex::regex_t_sptr(),
-		       const string& symbol_name = "",
-		       const regex::regex_t_sptr& symbol_name_regex =
-			 regex::regex_t_sptr(),
-		       const string& symbol_version = "",
-		       const regex::regex_t_sptr& symbol_version_regex =
-			 regex::regex_t_sptr(),
-		       const string& type_name = "",
-		       const regex::regex_t_sptr& type_name_regex =
-			 regex::regex_t_sptr());
+  variable_suppression();
 
   virtual ~variable_suppression();
 
@@ -812,14 +777,9 @@ class file_suppression: public suppression_base
 
   priv_sptr priv_;
 
-  // Forbid this
-  file_suppression();
-
 public:
 
-  file_suppression(const string& label,
-		   const regex::regex_t_sptr& file_name_regex,
-		   const regex::regex_t_sptr& file_name_not_regex);
+  file_suppression();
 
   virtual bool
   suppresses_diff(const diff* diff) const;
diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
index 78f11e2f..7f98fb08 100644
--- a/src/abg-suppression-priv.h
+++ b/src/abg-suppression-priv.h
@@ -236,23 +236,8 @@ struct variable_suppression::priv
   string				type_name_;
   regex::regex_t_sptr			type_name_regex_;
 
-  priv(const string& name,
-       const regex::regex_t_sptr& name_regex,
-       const string& symbol_name,
-       const regex::regex_t_sptr& symbol_name_regex,
-       const string& symbol_version,
-       const regex::regex_t_sptr& symbol_version_regex,
-       const string& type_name,
-       const regex::regex_t_sptr& type_name_regex)
-    : change_kind_(ALL_CHANGE_KIND),
-      name_(name),
-      name_regex_(name_regex),
-      symbol_name_(symbol_name),
-      symbol_name_regex_(symbol_name_regex),
-      symbol_version_(symbol_version),
-      symbol_version_regex_(symbol_version_regex),
-      type_name_(type_name),
-      type_name_regex_(type_name_regex)
+  priv()
+    : change_kind_(ALL_CHANGE_KIND)
   {}
 };// end class variable_supppression::priv
 
@@ -300,9 +285,14 @@ class type_suppression::priv
   regex::regex_t_sptr			source_location_to_keep_regex_;
   mutable vector<string>		changed_enumerator_names_;
 
-  priv();
-
 public:
+  priv()
+    : consider_type_kind_(false),
+      type_kind_(CLASS_TYPE_KIND),
+      consider_reach_kind_(false),
+      reach_kind_(DIRECT_REACH_KIND)
+  {}
+
   priv(const regex::regex_t_sptr&	type_name_regexp,
        const string&			type_name,
        bool				consider_type_kind,
diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 8632d028..31a70e77 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -53,33 +53,11 @@ using regex::regex_t_sptr;
 
 // <suppression_base stuff>
 
-/// Constructor for @ref suppression_base
-///
-/// @param a label for the suppression.  This represents just a
-/// comment.
-suppression_base::suppression_base(const string& label)
-  : priv_(new priv(label))
+/// Default constructor for @ref suppression_base
+suppression_base::suppression_base()
+  : priv_(new priv())
 {}
 
-/// Constructor for @ref suppression_base
-///
-/// @param a label for the suppression.  This represents just a
-/// comment.
-///
-/// @param file_name_regex the regular expression that denotes the
-/// file name to match.
-///
-/// @param file_name_not_regex the regular expression that denotes
-/// the file name to *NOT* match.
-suppression_base::suppression_base(const string& label,
-				   const regex_t_sptr& file_name_regex,
-				   const regex_t_sptr& file_name_not_regex)
-  : priv_(new priv(label,
-		   file_name_regex,
-		   file_name_not_regex))
-{
-}
-
 /// Tests if the current suppression specification is to avoid adding
 /// the matched ABI artifact to the internal representation or not.
 ///
@@ -473,16 +451,8 @@ read_suppressions(const string& file_path,
 /// Note that parameter @p type_name_regexp and @p type_name_regexp
 /// should not necessarily be populated.  It usually is either one or
 /// the other that the user wants.
-type_suppression::type_suppression(const string& label,
-				   const regex_t_sptr& type_name_regexp,
-				   const string& type_name)
-  : suppression_base(label),
-    priv_(new priv(type_name_regexp,
-		   type_name,
-		   /*consider_type_kind=*/false,
-		   /*type_kind=*/CLASS_TYPE_KIND,
-		   /*consider_reach_kind=*/false,
-		   /*reach_kind=*/DIRECT_REACH_KIND))
+type_suppression::type_suppression()
+  : suppression_base(), priv_(new priv)
 {}
 
 type_suppression::~type_suppression()
@@ -1916,7 +1886,10 @@ read_type_suppression(const ini::config::section& section)
 	changed_enumerator_names.push_back(p->get_value()->as_string());
     }
 
-  result.reset(new type_suppression(label_str, name_regex, name_str));
+  result.reset(new type_suppression());
+  result->set_label(label_str);
+  result->set_type_name_regex(name_regex);
+  result->set_type_name(name_str);
 
   if (consider_type_kind)
     {
@@ -2053,77 +2026,7 @@ function_suppression::parameter_spec::set_parameter_type_name_regex
 /// specified by using the various accessors of the @ref
 /// function_suppression type.
 function_suppression::function_suppression()
-  :  suppression_base(/*label=*/""), priv_(new priv)
-{}
-
-/// Constructor for the @ref function_suppression type.
-///
-/// @param label an informative text string that the evalution code
-/// might use to designate this function suppression specification in
-/// error messages.  This parameter might be empty, in which case it's
-/// ignored at evaluation time.
-///
-/// @param the name of the function the user wants the current
-/// specification to designate.  This parameter might be empty, in
-/// which case it's ignored at evaluation time.
-///
-/// @param nr if @p name is empty this parameter is a regular
-/// expression for a family of names of functions the user wants the
-/// current specification to designate.  If @p name is not empty, this
-/// parameter is ignored at specification evaluation time.  This
-/// parameter might be empty, in which case it's ignored at evaluation
-/// time.
-///
-/// @param ret_tn the name of the return type of the function the user
-/// wants this specification to designate.  This parameter might be
-/// empty, in which case it's ignored at evaluation time.
-///
-/// @param ret_tr if @p ret_tn is empty, then this is a regular
-/// expression for a family of return type names for functions the
-/// user wants the current specification to designate.  If @p ret_tn
-/// is not empty, then this parameter is ignored at specification
-/// evaluation time.  This parameter might be empty, in which case
-/// it's ignored at evaluation time.
-///
-/// @param ps a vector of parameter specifications to specify
-/// properties of the parameters of the functions the user wants this
-/// specification to designate.  This parameter might be empty, in
-/// which case it's ignored at evaluation time.
-///
-/// @param sym_n the name of symbol of the function the user wants
-/// this specification to designate.  This parameter might be empty,
-/// in which case it's ignored at evaluation time.
-///
-/// @param sym_nr if the parameter @p sym_n is empty, then this
-/// parameter is a regular expression for a family of names of symbols
-/// of functions the user wants this specification to designate.  If
-/// the parameter @p sym_n is not empty, then this parameter is
-/// ignored at specification evaluation time.  This parameter might be
-/// empty, in which case it's ignored at evaluation time.
-///
-/// @param sym_v the name of the version of the symbol of the function
-/// the user wants this specification to designate.  This parameter
-/// might be empty, in which case it's ignored at evaluation time.
-///
-/// @param sym_vr if the parameter @p sym_v is empty, then this
-/// parameter is a regular expression for a family of versions of
-/// symbols of functions the user wants the current specification to
-/// designate.  If the parameter @p sym_v is non empty, then this
-/// parameter is ignored.  This parameter might be empty, in which
-/// case it's ignored at evaluation time.
-function_suppression::function_suppression(const string&		label,
-					   const string&		name,
-					   const regex_t_sptr&		nr,
-					   const string&		ret_tn,
-					   const regex_t_sptr&		ret_tr,
-					   parameter_specs_type&	ps,
-					   const string&		sym_n,
-					   const regex_t_sptr&		sym_nr,
-					   const string&		sym_v,
-					   const regex_t_sptr&		sym_vr)
-  : suppression_base(label),
-    priv_(new priv(name, nr, ret_tn, ret_tr, ps,
-		   sym_n, sym_nr, sym_v, sym_vr))
+  : suppression_base(), priv_(new priv)
 {}
 
 function_suppression::~function_suppression()
@@ -3261,16 +3164,17 @@ read_function_suppression(const ini::config::section& section)
 	  parms.push_back(parm);
       }
 
-  result.reset(new function_suppression(label_str,
-					name,
-					name_regex,
-					return_type_name,
-					return_type_regex,
-					parms,
-					sym_name,
-					sym_name_regex,
-					sym_version,
-					sym_ver_regex));
+  result.reset(new function_suppression());
+  result->set_label(label_str);
+  result->set_name(name);
+  result->set_name_regex(name_regex);
+  result->set_return_type_name(return_type_name);
+  result->set_return_type_regex(return_type_regex);
+  result->set_parameter_specs(parms);
+  result->set_symbol_name(sym_name);
+  result->set_symbol_name_regex(sym_name_regex);
+  result->set_symbol_version(sym_version);
+  result->set_symbol_version_regex(sym_ver_regex);
 
   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
       && (!name.empty()
@@ -3314,71 +3218,13 @@ read_function_suppression(const ini::config::section& section)
 
 // <variable_suppression stuff>
 
-/// Constructor for the @ref variable_suppression type.
-///
-/// @param label an informative text string that the evalution code
-/// might use to designate this variable suppression specification in
-/// error messages.  This parameter might be empty, in which case it's
-/// ignored at evaluation time.
-///
-/// @param name the name of the variable the user wants the current
-/// specification to designate.  This parameter might be empty, in
-/// which case it's ignored at evaluation time.
-///
-/// @param name_regex if @p name is empty, this parameter is a
-/// regular expression for a family of names of variables the user
-/// wants the current specification to designate.  If @p name is not
-/// empty, then this parameter is ignored at evaluation time.  This
-/// parameter might be empty, in which case it's ignored at evaluation
-/// time.
-///
-/// @param symbol_name the name of the symbol of the variable the user
-/// wants the current specification to designate.  This parameter
-/// might be empty, in which case it's ignored at evaluation time.
-///
-/// @param symbol_name_str if @p symbol_name is empty, this parameter
-/// is a regular expression for a family of names of symbols of
-/// variables the user wants the current specification to designate.
-/// If @p symbol_name is not empty, then this parameter is ignored at
-/// evaluation time.  This parameter might be empty, in which case
-/// it's ignored at evaluation time.
-///
-/// @param symbol_version the version of the symbol of the variable
-/// the user wants the current specification to designate.  This
-/// parameter might be empty, in which case it's ignored at evaluation
-/// time.
-///
-/// @param symbol_version_regex if @p symbol_version is empty, then
-/// this parameter is a regular expression for a family of versions of
-/// symbol for the variables the user wants the current specification
-/// to designate.  If @p symbol_version is not empty, then this
-/// parameter is ignored at evaluation time.  This parameter might be
-/// empty, in which case it's ignored at evaluation time.
-///
-/// @param type_name the name of the type of the variable the user
-/// wants the current specification to designate.  This parameter
-/// might be empty, in which case it's ignored at evaluation time.
+/// Default constructor for the @ref variable_suppression type.
 ///
-/// @param type_name_regex if @p type_name is empty, then this
-/// parameter is a regular expression for a family of type names of
-/// variables the user wants the current specification to designate.
-/// If @p type_name is not empty, then this parameter is ignored at
-/// evluation time.  This parameter might be empty, in which case it's
-/// ignored at evaluation time.
-variable_suppression::variable_suppression(const string& label,
-					   const string& name,
-					   const regex_t_sptr& name_regex,
-					   const string& symbol_name,
-					   const regex_t_sptr& symbol_name_regex,
-					   const string& symbol_version,
-					   const regex_t_sptr& symbol_version_regex,
-					   const string& type_name,
-					   const regex_t_sptr& type_name_regex)
-  : suppression_base(label),
-    priv_(new priv(name, name_regex,
-		   symbol_name, symbol_name_regex,
-		   symbol_version, symbol_version_regex,
-		   type_name, type_name_regex))
+/// It defines no suppression for now.  Suppressions have to be
+/// specified by using the various accessors of the @ref
+/// variable_suppression type.
+variable_suppression::variable_suppression()
+  : suppression_base(), priv_(new priv)
 {}
 
 /// Virtual destructor for the @erf variable_suppression type.
@@ -4035,15 +3881,16 @@ read_variable_suppression(const ini::config::section& section)
   regex_t_sptr type_name_regex;
   maybe_get_regex_prop(section, "type_name_regexp", type_name_regex);
 
-  result.reset(new variable_suppression(label_str,
-					name_str,
-					name_regex,
-					symbol_name,
-					symbol_name_regex,
-					symbol_version,
-					symbol_version_regex,
-					type_name_str,
-					type_name_regex));
+  result.reset(new variable_suppression);
+  result->set_label(label_str);
+  result->set_name(name_str);
+  result->set_name_regex(name_regex);
+  result->set_symbol_name(symbol_name);
+  result->set_symbol_name_regex(symbol_name_regex);
+  result->set_symbol_version(symbol_version);
+  result->set_symbol_version_regex(symbol_version_regex);
+  result->set_type_name(type_name_str);
+  result->set_type_name_regex(type_name_regex);
 
   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
       && (!name_str.empty()
@@ -4083,25 +3930,8 @@ read_variable_suppression(const ini::config::section& section)
 
 // <file_suppression stuff>
 
-/// Constructor for the the @ref file_suppression type.
-///
-/// @param label the label of the suppression directive.
-///
-/// @param fname_regex the regular expression string that
-/// designates the file name that instances of @ref file_suppression
-/// should match.
-///
-/// @param fname_not_regex the regular expression string that
-/// designates the file name that instances of @ref file_suppression
-/// shoult *NOT* match.  In other words, this file_suppression should
-/// be activated if its file name does not match the regular
-/// expression @p fname_not_regex.
-file_suppression::file_suppression(const string& label,
-				   const regex_t_sptr& fname_regex,
-				   const regex_t_sptr& fname_not_regex)
-  : suppression_base(label,
-		     fname_regex,
-		     fname_not_regex)
+/// Default constructor for the the @ref file_suppression type.
+file_suppression::file_suppression()
 {}
 
 /// Test if instances of this @ref file_suppression suppresses a
@@ -4188,9 +4018,10 @@ read_file_suppression(const ini::config::section& section)
   regex_t_sptr soname_not_regex;
   maybe_get_regex_prop(section, "soname_not_regexp", soname_not_regex);
 
-  result.reset(new file_suppression(label_str,
-				    file_name_regex,
-				    file_name_not_regex));
+  result.reset(new file_suppression);
+  result->set_label(label_str);
+  result->set_file_name_regex(file_name_regex);
+  result->set_file_name_not_regex(file_name_not_regex);
 
   if (soname_regex)
     {
diff --git a/src/abg-tools-utils.cc b/src/abg-tools-utils.cc
index 3af9fc49..4cef400d 100644
--- a/src/abg-tools-utils.cc
+++ b/src/abg-tools-utils.cc
@@ -1810,11 +1810,8 @@ handle_file_entry(const string& file_path,
 {
   if (!suppr)
     {
-      suppr.reset(
-	new type_suppression(get_private_types_suppr_spec_label(),
-			     /*type_name_regexp=*/regex::regex_t_sptr(),
-			     /*type_name=*/""));
-
+      suppr.reset(new type_suppression());
+      suppr->set_label(get_private_types_suppr_spec_label());
       // Types that are defined in system headers are usually
       // OK to be considered as public types.
       regex::regex_t_sptr headers_regex = regex::compile("^/usr/include/");
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH 21/21] Remove unused suppression type priv constructors.
  2020-04-23 15:44 [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
                   ` (19 preceding siblings ...)
  2020-04-23 15:44 ` [PATCH 20/21] Default construct suppression types Giuliano Procida
@ 2020-04-23 15:44 ` Giuliano Procida
  2020-04-23 18:11 ` [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
  2020-04-24  9:21 ` [PATCH v3 00/21]Simplify " Giuliano Procida
  22 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-23 15:44 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

Following on from the previous commit, many constructors for the
various priv types are now unused. This patch drops them.

There are no behavioural changes.

	* src/abg-suppression-priv.h (suppression_base::priv) Drop all
	but default constructor.
	(function_suppression::parameter_spec::priv): Drop all but
	3-argument constructor. (function_suppression::priv): Drop all
	but default constructor. (type_suppression::priv): Drop all
	but default constructor.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-suppression-priv.h | 60 --------------------------------------
 1 file changed, 60 deletions(-)

diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
index 7f98fb08..97c163fe 100644
--- a/src/abg-suppression-priv.h
+++ b/src/abg-suppression-priv.h
@@ -58,22 +58,6 @@ public:
       drops_artifact_()
   {}
 
-  priv(const string& label)
-    : is_artificial_(),
-      drops_artifact_(),
-      label_(label)
-  {}
-
-  priv(const string& label,
-       const regex::regex_t_sptr& file_name_regex,
-       const regex::regex_t_sptr& file_name_not_regex)
-    : is_artificial_(),
-      drops_artifact_(),
-      label_(label),
-      file_name_regex_(file_name_regex),
-      file_name_not_regex_(file_name_not_regex)
-  {}
-
   friend class suppression_base;
 }; // end class suppression_base::priv
 
@@ -90,14 +74,6 @@ class function_suppression::parameter_spec::priv
   string				type_name_;
   regex::regex_t_sptr			type_name_regex_;
 
-  priv()
-    : index_()
-  {}
-
-  priv(size_t i, const string& tn)
-    : index_(i), type_name_(tn)
-  {}
-
   priv(size_t i, const string& tn, const regex::regex_t_sptr& tn_regex)
     : index_(i), type_name_(tn), type_name_regex_(tn_regex)
   {}
@@ -128,28 +104,6 @@ struct function_suppression::priv
     change_kind_(ALL_CHANGE_KIND),
     allow_other_aliases_(true)
   {}
-
-  priv(const string&			name,
-       const regex::regex_t_sptr&	name_regex,
-       const string&			return_type_name,
-       const regex::regex_t_sptr&	return_type_regex,
-       const parameter_specs_type&	parm_specs,
-       const string&			symbol_name,
-       const regex::regex_t_sptr&	symbol_name_regex,
-       const string&			symbol_version,
-       const regex::regex_t_sptr&	symbol_version_regex)
-    : change_kind_(ALL_CHANGE_KIND),
-      name_(name),
-      name_regex_(name_regex),
-      return_type_name_(return_type_name),
-      return_type_regex_(return_type_regex),
-      parm_specs_(parm_specs),
-      symbol_name_(symbol_name),
-      symbol_name_regex_(symbol_name_regex),
-      symbol_version_(symbol_version),
-      symbol_version_regex_(symbol_version_regex),
-      allow_other_aliases_(true)
-  {}
 }; // end class function_suppression::priv
 
 bool
@@ -293,20 +247,6 @@ public:
       reach_kind_(DIRECT_REACH_KIND)
   {}
 
-  priv(const regex::regex_t_sptr&	type_name_regexp,
-       const string&			type_name,
-       bool				consider_type_kind,
-       type_suppression::type_kind	type_kind,
-       bool				consider_reach_kind,
-       type_suppression::reach_kind	reach_kind)
-    : type_name_regex_(type_name_regexp),
-      type_name_(type_name),
-      consider_type_kind_(consider_type_kind),
-      type_kind_(type_kind),
-      consider_reach_kind_(consider_reach_kind),
-      reach_kind_(reach_kind)
-  {}
-
   friend class type_suppression;
 }; // class type_suppression::priv
 
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v2 09/21] Use regex::match wrapper instead of regexec.
  2020-04-23 15:44 ` [PATCH 09/21] Use regex::match wrapper instead of regexec Giuliano Procida
@ 2020-04-23 18:02   ` Giuliano Procida
  0 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-23 18:02 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

This patch eliminates all calls to regexec except that by regex::match
itself.

There are no behavioural changes.

	* src/abg-corpus-priv.h: Mechanically substitute use of
	regexec with regex::match wrapper.
	* src/abg-suppression-priv.h: Ditto.
	* src/abg-suppression.cc: Ditto.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-corpus-priv.h      |   8 +--
 src/abg-suppression-priv.h |  10 ++--
 src/abg-suppression.cc     | 119 +++++++++++--------------------------
 3 files changed, 44 insertions(+), 93 deletions(-)

diff --git a/src/abg-corpus-priv.h b/src/abg-corpus-priv.h
index 544fac54..2618e2d0 100644
--- a/src/abg-corpus-priv.h
+++ b/src/abg-corpus-priv.h
@@ -521,7 +521,7 @@ public:
 	   compiled_regex_fns_suppress().begin();
 	 i != compiled_regex_fns_suppress().end();
 	 ++i)
-      if (regexec(i->get(), frep.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(*i, frep))
 	{
 	  keep = false;
 	  break;
@@ -554,7 +554,7 @@ public:
 	     compiled_regex_fns_keep().begin();
 	   i != compiled_regex_fns_keep().end();
 	   ++i)
-	if (regexec(i->get(), frep.c_str(), 0, NULL, 0) == 0)
+	if (regex::match(*i, frep))
 	  {
 	    keep = true;
 	    break;
@@ -628,7 +628,7 @@ public:
 	   compiled_regex_vars_suppress().begin();
 	 i != compiled_regex_vars_suppress().end();
 	 ++i)
-      if (regexec(i->get(), frep.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(*i, frep))
 	{
 	  keep = false;
 	  break;
@@ -662,7 +662,7 @@ public:
 	       compiled_regex_vars_keep().begin();
 	     i != compiled_regex_vars_keep().end();
 	     ++i)
-	  if (regexec(i->get(), frep.c_str(), 0, NULL, 0) == 0)
+	  if (regex::match(*i, frep))
 	    {
 	      keep = true;
 	      break;
diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
index 4959cdbb..8043ebd9 100644
--- a/src/abg-suppression-priv.h
+++ b/src/abg-suppression-priv.h
@@ -160,14 +160,14 @@ public:
     if (regex::regex_t_sptr regexp = get_soname_regex())
       {
 	has_regexp = true;
-	if (regexec(regexp.get(), soname.c_str(), 0, NULL, 0) != 0)
+	if (!regex::match(regexp, soname))
 	  return false;
       }
 
     if (regex::regex_t_sptr regexp = get_soname_not_regex())
       {
 	has_regexp = true;
-	if (regexec(regexp.get(), soname.c_str(), 0, NULL, 0) == 0)
+	if (regex::match(regexp, soname))
 	  return false;
       }
 
@@ -195,16 +195,14 @@ public:
     if (regex::regex_t_sptr regexp = get_file_name_regex())
       {
 	has_regexp = true;
-	if (regexec(regexp.get(), binary_name.c_str(),
-	  0, NULL, 0) != 0)
+	if (!regex::match(regexp, binary_name))
 	  return false;
       }
 
     if (regex::regex_t_sptr regexp = get_file_name_not_regex())
       {
 	has_regexp = true;
-	if (regexec(regexp.get(), binary_name.c_str(),
-	  0, NULL, 0) == 0)
+	if (regex::match(regexp, binary_name))
 	  return false;
       }
 
diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index b600c88c..afedf6c7 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -994,18 +994,14 @@ suppression_matches_type_name(const type_suppression&	s,
 	  if (const 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)
+	      if (!regex::match(type_name_regex, type_name))
 		return false;
 	    }
 
 	  if (const 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)
+	      if (regex::match(type_name_not_regex, type_name))
 		return false;
 	    }
 	}
@@ -1052,7 +1048,7 @@ suppression_matches_type_location(const type_suppression&	s,
       loc.expand(loc_path, loc_line, loc_column);
 
       if (regex_t_sptr regexp = s.priv_->get_source_location_to_keep_regex())
-	if (regexec(regexp.get(), loc_path.c_str(), 0, NULL, 0) == 0)
+	if (regex::match(regexp, loc_path))
 	  return false;
 
       tools_utils::base_name(loc_path, loc_path_base);
@@ -2489,9 +2485,7 @@ function_suppression::suppresses_function(const function_decl* fn,
   const regex_t_sptr name_regex = priv_->get_name_regex();
   if (name_regex)
     {
-      if (regexec(name_regex.get(),
-		  fname.c_str(),
-		  0, NULL, 0) != 0)
+      if (!regex::match(name_regex, fname))
 	return false;
 
       if (get_allow_other_aliases()
@@ -2512,9 +2506,7 @@ function_suppression::suppresses_function(const function_decl* fn,
 	      for (elf_symbol_sptr a = sym->get_next_alias();
 		   a && !a->is_main_symbol();
 		   a = a->get_next_alias())
-		if (regexec(name_regex.get(),
-			    a->get_name().c_str(),
-			    0, NULL, 0) != 0)
+		if (!regex::match(name_regex, a->get_name()))
 		  return false;
 	    }
 	}
@@ -2524,9 +2516,7 @@ function_suppression::suppresses_function(const function_decl* fn,
   const regex_t_sptr name_not_regex = priv_->get_name_not_regex();
   if (name_not_regex)
     {
-      if (regexec(name_not_regex.get(),
-		  fname.c_str(),
-		  0, NULL, 0) == 0)
+      if (regex::match(name_not_regex, fname))
 	return false;
 
       if (get_allow_other_aliases()
@@ -2547,9 +2537,7 @@ function_suppression::suppresses_function(const function_decl* fn,
 	      for (elf_symbol_sptr a = sym->get_next_alias();
 		   a && !a->is_main_symbol();
 		   a = a->get_next_alias())
-		if (regexec(name_regex.get(),
-			    a->get_name().c_str(),
-			    0, NULL, 0) == 0)
+		if (regex::match(name_regex, a->get_name()))
 		  return false;
 	    }
 	}
@@ -2573,9 +2561,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     {
       const regex_t_sptr return_type_regex = priv_->get_return_type_regex();
       if (return_type_regex
-	  && (regexec(return_type_regex.get(),
-		      fn_return_type_name.c_str(),
-		      0, NULL, 0) != 0))
+	  && !regex::match(return_type_regex, fn_return_type_name))
 	return false;
     }
 
@@ -2612,18 +2598,13 @@ function_suppression::suppresses_function(const function_decl* fn,
   else if (sym)
     {
       const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
-      if (symbol_name_regex
-	  && (regexec(symbol_name_regex.get(),
-		      fn_sym_name.c_str(),
-		      0, NULL, 0) != 0))
+      if (symbol_name_regex && !regex::match(symbol_name_regex, fn_sym_name))
 	return false;
 
       const regex_t_sptr symbol_name_not_regex =
 	priv_->get_symbol_name_not_regex();
       if (symbol_name_not_regex
-	  && (regexec(symbol_name_not_regex.get(),
-		      fn_sym_name.c_str(),
-		      0, NULL, 0) == 0))
+	  && regex::match(symbol_name_not_regex, fn_sym_name))
 	return false;
 
       if (get_allow_other_aliases())
@@ -2638,15 +2619,11 @@ function_suppression::suppresses_function(const function_decl* fn,
 		   a = a->get_next_alias())
 		{
 		  if (symbol_name_regex
-		      && (regexec(symbol_name_regex.get(),
-				  a->get_name().c_str(),
-				  0, NULL, 0) != 0))
+		      && !regex::match(symbol_name_regex, a->get_name()))
 		    return false;
 
 		  if (symbol_name_not_regex
-		      && (regexec(symbol_name_not_regex.get(),
-				  a->get_name().c_str(),
-				  0, NULL, 0) == 0))
+		      && regex::match(symbol_name_not_regex, a->get_name()))
 		    return false;
 		}
 	    }
@@ -2665,9 +2642,7 @@ function_suppression::suppresses_function(const function_decl* fn,
       const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
       if (symbol_version_regex
-	  && (regexec(symbol_version_regex.get(),
-		      fn_sym_version.c_str(),
-		      0, NULL, 0) != 0))
+	  && !regex::match(symbol_version_regex, fn_sym_version))
 	return false;
     }
 
@@ -2708,9 +2683,8 @@ function_suppression::suppresses_function(const function_decl* fn,
 		(*p)->priv_->get_type_name_regex();
 	      if (parm_type_name_regex)
 		{
-		  if ((regexec(parm_type_name_regex.get(),
-			       fn_parm_type_qualified_name.c_str(),
-			       0, NULL, 0) != 0))
+		  if (!regex::match(parm_type_name_regex,
+				    fn_parm_type_qualified_name))
 		    return false;
 		}
 	    }
@@ -2798,10 +2772,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
   else if (!get_symbol_name_regex_str().empty())
     {
       const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
-      if (symbol_name_regex
-	  && (regexec(symbol_name_regex.get(),
-		      sym_name.c_str(),
-		      0, NULL, 0) != 0))
+      if (symbol_name_regex && !regex::match(symbol_name_regex, sym_name))
 	return false;
     }
   else
@@ -2818,9 +2789,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
       const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
       if (symbol_version_regex
-	  && (regexec(symbol_version_regex.get(),
-		      sym_version.c_str(),
-		      0, NULL, 0) != 0))
+	  && !regex::match(symbol_version_regex, sym_version))
 	return false;
     }
   else
@@ -2912,12 +2881,12 @@ suppression_matches_function_name(const suppr::function_suppression& s,
 {
   if (regex_t_sptr regexp = s.priv_->get_name_regex())
     {
-      if (regexec(regexp.get(), fn_name.c_str(), 0, NULL, 0) != 0)
+      if (!regex::match(regexp, fn_name))
 	return false;
     }
   else if (regex_t_sptr regexp = s.priv_->get_name_not_regex())
     {
-      if (regexec(regexp.get(), fn_name.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(regexp, fn_name))
 	return false;
     }
   else if (s.priv_->name_.empty())
@@ -2948,12 +2917,12 @@ suppression_matches_function_sym_name(const suppr::function_suppression& s,
 {
   if (regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
     {
-      if (regexec(regexp.get(), fn_linkage_name.c_str(), 0, NULL, 0) != 0)
+      if (!regex::match(regexp, fn_linkage_name))
 	return false;
     }
   else if (regex_t_sptr regexp = s.priv_->get_symbol_name_not_regex())
     {
-      if (regexec(regexp.get(), fn_linkage_name.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(regexp, fn_linkage_name))
 	return false;
     }
   else if (s.priv_->symbol_name_.empty())
@@ -2981,12 +2950,12 @@ suppression_matches_variable_name(const suppr::variable_suppression& s,
 {
   if (regex_t_sptr regexp = s.priv_->get_name_regex())
     {
-      if (regexec(regexp.get(), var_name.c_str(), 0, NULL, 0) != 0)
+      if (!regex::match(regexp, var_name))
 	return false;
     }
   else if (regex_t_sptr regexp = s.priv_->get_name_not_regex())
     {
-      if (regexec(regexp.get(), var_name.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(regexp, var_name))
 	return false;
     }
   else if (s.priv_->name_.empty())
@@ -3015,13 +2984,13 @@ suppression_matches_variable_sym_name(const suppr::variable_suppression& s,
 {
   if (regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
     {
-      if (regexec(regexp.get(), var_linkage_name.c_str(), 0, NULL, 0) != 0)
+      if (!regex::match(regexp, var_linkage_name))
 	return false;
     }
   else if (regex_t_sptr regexp =
 	   s.priv_->get_symbol_name_not_regex())
     {
-      if (regexec(regexp.get(), var_linkage_name.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(regexp, var_linkage_name))
 	return false;
     }
   else if (s.priv_->symbol_name_.empty())
@@ -3050,7 +3019,7 @@ suppression_matches_type(const suppr::type_suppression& s,
 {
   if (regex_t_sptr regexp = s.priv_->get_type_name_regex())
     {
-      if (regexec(regexp.get(), type_name.c_str(), 0, NULL, 0) != 0)
+      if (!regex::match(regexp, type_name))
 	return false;
     }
   else if (!s.get_type_name().empty())
@@ -3748,15 +3717,11 @@ variable_suppression::suppresses_variable(const var_decl* var,
       if (get_name().empty())
 	{
 	  const regex_t_sptr name_regex = priv_->get_name_regex();
-	  if (name_regex
-	      && (regexec(name_regex.get(), var_name.c_str(),
-			  0, NULL, 0) != 0))
+	  if (name_regex && !regex::match(name_regex, var_name))
 	    return false;
 
 	  const regex_t_sptr name_not_regex = priv_->get_name_not_regex();
-	  if (name_not_regex
-	      && (regexec(name_not_regex.get(), var_name.c_str(),
-			  0, NULL, 0) == 0))
+	  if (name_not_regex && regex::match(name_not_regex, var_name))
 	    return false;
 	}
     }
@@ -3772,16 +3737,12 @@ variable_suppression::suppresses_variable(const var_decl* var,
   else
     {
       const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
-      if (sym_name_regex
-	  && (regexec(sym_name_regex.get(), var_sym_name.c_str(),
-		      0, NULL, 0) != 0))
+      if (sym_name_regex && !regex::match(sym_name_regex, var_sym_name))
 	return false;
 
       const regex_t_sptr sym_name_not_regex =
 	priv_->get_symbol_name_not_regex();
-      if (sym_name_not_regex
-	  && (regexec(sym_name_not_regex.get(), var_sym_name.c_str(),
-		      0, NULL, 0) == 0))
+      if (sym_name_not_regex && regex::match(sym_name_not_regex, var_sym_name))
 	return false;
     }
 
@@ -3798,9 +3759,7 @@ variable_suppression::suppresses_variable(const var_decl* var,
       const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
       if (symbol_version_regex
-	  && (regexec(symbol_version_regex.get(),
-		      var_sym_version.c_str(),
-		      0, NULL, 0) != 0))
+	  && !regex::match(symbol_version_regex, var_sym_version))
 	return false;
     }
 
@@ -3818,9 +3777,7 @@ variable_suppression::suppresses_variable(const var_decl* var,
       if (get_type_name().empty())
 	{
 	  const regex_t_sptr type_name_regex = priv_->get_type_name_regex();
-	  if (type_name_regex
-	      && (regexec(type_name_regex.get(), var_type_name.c_str(),
-			  0, NULL, 0) != 0))
+	  if (type_name_regex && !regex::match(type_name_regex, var_type_name))
 	    return false;
 	}
     }
@@ -3911,9 +3868,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
   else if (!get_symbol_name_regex_str().empty())
     {
       const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
-      if (sym_name_regex
-	  && (regexec(sym_name_regex.get(), sym_name.c_str(),
-		      0, NULL, 0) != 0))
+      if (sym_name_regex && !regex::match(sym_name_regex, sym_name))
 	return false;
     }
   else
@@ -3931,9 +3886,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
       const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
       if (symbol_version_regex
-	  && (regexec(symbol_version_regex.get(),
-		      sym_version.c_str(),
-		      0, NULL, 0) != 0))
+	  && !regex::match(symbol_version_regex, sym_version))
 	return false;
     }
   else
@@ -4229,14 +4182,14 @@ file_suppression::suppresses_file(const string& file_path)
   if (regex_t_sptr regexp = suppression_base::priv_->get_file_name_regex())
     {
       has_regexp = true;
-      if (regexec(regexp.get(), fname.c_str(), 0, NULL, 0) != 0)
+      if (!regex::match(regexp, fname))
 	return false;
     }
 
   if (regex_t_sptr regexp = suppression_base::priv_->get_file_name_not_regex())
     {
       has_regexp = true;
-      if (regexec(regexp.get(), fname.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(regexp, fname))
 	return false;
     }
 
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v2 19/21] Warn if user-supplied regexes fail to compile.
  2020-04-23 15:44 ` [PATCH 19/21] Warn if user-supplied regexes fail to compile Giuliano Procida
@ 2020-04-23 18:04   ` Giuliano Procida
  0 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-23 18:04 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

There are not many calls to regex::compile in the code base. Two of
these pass internally-generated regexes and are followed by assertions
that the regexes compile.

The remaining cases deal with user-supplied regexes. If these fail to
compile they are currently silently ignored.

This patch makes sure failures now result in warning messages on
stderr, but otherwise does not change program behaviour.

	* src/abg-corpus-priv.h
	(corpus::exported_decls_builder::priv::compiled_regex_fns_suppress):
	Emit a warning message if regex::compile fails.
	(corpus::exported_decls_builder::priv::compiled_regex_fns_keep):
	Ditto.
	(corpus::exported_decls_builder::priv::compiled_regex_vars_suppress):
	Ditto.
	(corpus::exported_decls_builder::priv::compiled_regex_vars_keep):
	Ditto.
	* src/abg-suppression.cc (maybe_get_string_prop): Ditto.
	(read_parameter_spec_from_string): Ditto.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-corpus-priv.h  | 10 ++++++++++
 src/abg-suppression.cc |  4 ++++
 2 files changed, 14 insertions(+)

diff --git a/src/abg-corpus-priv.h b/src/abg-corpus-priv.h
index 2618e2d0..a06a1a23 100644
--- a/src/abg-corpus-priv.h
+++ b/src/abg-corpus-priv.h
@@ -29,6 +29,8 @@
 #ifndef __ABG_CORPUS_PRIV_H__
 #define __ABG_CORPUS_PRIV_H__
 
+#include <iostream>
+
 #include "abg-sptr-utils.h"
 #include "abg-regex.h"
 #include "abg-internal.h"
@@ -126,6 +128,8 @@ public:
 	    regex_t_sptr r = regex::compile(*i);
 	    if (r)
 	      compiled_fns_suppress_regexp_.push_back(r);
+	    else
+	      std::cerr << "warning: bad regex '" << *i << "'\n";
 	  }
       }
     return compiled_fns_suppress_regexp_;
@@ -148,6 +152,8 @@ public:
 	    regex_t_sptr r = regex::compile(*i);
 	    if (r)
 	      compiled_fns_keep_regexps_.push_back(r);
+	    else
+	      std::cerr << "warning: bad regex '" << *i << "'\n";
 	  }
       }
     return compiled_fns_keep_regexps_;
@@ -170,6 +176,8 @@ public:
 	    regex_t_sptr r = regex::compile(*i);
 	    if (r)
 	      compiled_vars_suppress_regexp_.push_back(r);
+	    else
+	      std::cerr << "warning: bad regex '" << *i << "'\n";
 	  }
       }
     return compiled_vars_suppress_regexp_;
@@ -192,6 +200,8 @@ public:
 	    regex_t_sptr r = regex::compile(*i);
 	    if (r)
 	      compiled_vars_keep_regexps_.push_back(r);
+	    else
+	      std::cerr << "warning: bad regex '" << *i << "'\n";
 	  }
       }
     return compiled_vars_keep_regexps_;
diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 3db2b7b1..8632d028 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -1644,6 +1644,8 @@ maybe_get_regex_prop(const ini::config::section& section,
   if (!maybe_get_string_prop(section, name, str))
     return false;
   regex = regex::compile(str);
+  if (!regex)
+    std::cerr << "warning: bad regex '" << str << "'\n";
   return true;
 }
 
@@ -3161,6 +3163,8 @@ read_parameter_spec_from_string(const string& str)
       if (is_regex)
 	{
 	  type_name_regex = regex::compile(type_name);
+	  if (!type_name_regex)
+	    std::cerr << "warning: bad regex '" << type_name << "'\n";
 	  type_name.clear();
 	}
       function_suppression::parameter_spec* p =
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v2 07/21] Add POSIX regex wrapper functions.
  2020-04-23 15:44 ` [PATCH 07/21] Add POSIX regex wrapper functions Giuliano Procida
@ 2020-04-23 18:07   ` Giuliano Procida
  0 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-23 18:07 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

libabigail code uses the POSIX regex library consistently:

    - compile std::string to regex, with the flag REG_EXTENDED
    - store regex using a shared pointer wrapper
    - check match of regex against std::string

All the C string / std::string logic and so on is repeated at every
call site. This patch introduces wrapper functions to take care of
this logic.

There are no behavioural changes.

	* include/abg-regex.h (compile): Declare new function.
	(match): Declare new function.
	* src/abg-regex.cc (compile): Add new function wrapping
	regcomp. (match): Add new function wrapping regexec.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 include/abg-regex.h |  6 ++++++
 src/abg-regex.cc    | 41 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git a/include/abg-regex.h b/include/abg-regex.h
index 59976794..c7951a8f 100644
--- a/include/abg-regex.h
+++ b/include/abg-regex.h
@@ -71,6 +71,12 @@ operator<<(std::ostream& os, const escape& esc);
 std::string
 generate_from_strings(const std::vector<std::string>& strs);
 
+regex_t_sptr
+compile(const std::string& str);
+
+bool
+match(const regex_t_sptr& r, const std::string& str);
+
 }// end namespace regex
 
 /// Specialization of sptr_utils::build_sptr for regex_t.
diff --git a/src/abg-regex.cc b/src/abg-regex.cc
index 90e4d144..7e5277e2 100644
--- a/src/abg-regex.cc
+++ b/src/abg-regex.cc
@@ -23,11 +23,22 @@
 /// Some specialization for shared pointer utility templates.
 ///
 
+#include "config.h"
+
 #include <sstream>
 #include <ostream>
+
+#include "abg-internal.h"
+
+// <headers defining libabigail's API go under here>
+ABG_BEGIN_EXPORT_DECLARATIONS
+
 #include "abg-sptr-utils.h"
 #include "abg-regex.h"
 
+ABG_END_EXPORT_DECLARATIONS
+// </headers defining libabigail's API>
+
 namespace abigail
 {
 
@@ -101,6 +112,36 @@ generate_from_strings(const std::vector<std::string>& strs)
   return os.str();
 }
 
+/// Compile a regex from a string.
+///
+/// The result is held in a shared pointer. This will be null if regex
+/// compilation fails.
+///
+/// @param str the string representation of the regex.
+///
+/// @return shared pointer holder of a compiled regex object.
+regex_t_sptr
+compile(const std::string& str)
+{
+  regex_t_sptr r = sptr_utils::build_sptr(new regex_t);
+  if (regcomp(r.get(), str.c_str(), REG_EXTENDED))
+    r.reset();
+  return r;
+}
+
+/// See if a string matches a regex.
+///
+/// @param r a shared pointer holder of a compiled regex object.
+///
+/// @param str a string.
+///
+/// @return whether there was a match.
+bool
+match(const regex_t_sptr& r, const std::string& str)
+{
+  return !regexec(r.get(), str.c_str(), 0, NULL, 0);
+}
+
 }//end namespace regex
 
 }//end namespace abigail
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH 00/21] Simplify regex and suppression parsing.
  2020-04-23 15:44 [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
                   ` (20 preceding siblings ...)
  2020-04-23 15:44 ` [PATCH 21/21] Remove unused suppression type priv constructors Giuliano Procida
@ 2020-04-23 18:11 ` Giuliano Procida
  2020-04-24  8:54   ` Giuliano Procida
  2020-04-24  9:21 ` [PATCH v3 00/21]Simplify " Giuliano Procida
  22 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-04-23 18:11 UTC (permalink / raw)
  To: libabigail; +Cc: Dodji Seketeli, kernel-team, Matthias Männich

There are some v2s.

0007 - fixed wrong style for function prototypes; added missing export
of regex.cc
0009 - ignore, no change
0019 - added missing #include <iostream>

Regards,
Giuliano.

On Thu, 23 Apr 2020 at 16:45, Giuliano Procida <gprocida@google.com> wrote:
>
> This patch series takes the suppression parsing very close to where it
> can be translated into a table-driven format. It is mostly a series of
> simplifications which are useful in their own right. I have tried to
> keep each commit doing exactly one thing, to make reviewing easier.
>
> These changes are not pure refactorings:
>
> Escape names used in symbol whitelisting regex.
> diff suppression: Fix handling of change kinds
> abg-tools-utils.cc: Assert generated regexes OK.
> Warn if user-supplied regexes fail to compile.
>
> The rest should be.
>
> Regards,
> Giuliano.
>
> Giuliano Procida (21):
>   Move regex definitions to own files.
>   Move libxml bits out of abg-sptr-utils.h.
>   Simplify generation of symbol whitelist regex.
>   Escape names used in symbol whitelisting regex.
>   abg-suppression.cc: More uniform variable naming.
>   diff suppression: Fix handling of change kinds.
>   Add POSIX regex wrapper functions.
>   Use regex::compile wrapper instead of regcomp.
>   Use regex::match wrapper instead of regexec.
>   Refactor read_parameter_spec_from_string logic.
>   Compile suppression regexes earlier.
>   Reduce direct access to suppression priv_ members.
>   Move match methods from priv to suppression_base.
>   Remove suppression types' priv class methods.
>   abg-suppression.cc: More consistent regex matching.
>   abg-tools-utils.cc: Assert generated regexes OK.
>   Refactor suppression property string parsing.
>   Refactor suppression property regex parsing.
>   Warn if user-supplied regexes fail to compile.
>   Default construct suppression types.
>   Remove unused suppression type priv constructors.
>
>  include/Makefile.am                           |    3 +-
>  include/abg-libxml-utils.h                    |   21 +-
>  src/abg-sptr-utils.cc => include/abg-regex.h  |   71 +-
>  include/abg-sptr-utils.h                      |   66 +-
>  include/abg-suppression.h                     |  182 +-
>  src/Makefile.am                               |    2 +-
>  src/abg-corpus-priv.h                         |   35 +-
>  src/abg-corpus.cc                             |    2 +-
>  src/abg-dwarf-reader.cc                       |    4 +-
>  src/abg-reader.cc                             |    4 +-
>  src/abg-regex.cc                              |  134 ++
>  src/abg-suppression-priv.h                    |  723 +-------
>  src/abg-suppression.cc                        | 1527 +++++++----------
>  src/abg-tools-utils.cc                        |   26 +-
>  .../test15-suppr-added-fn-report-5.txt        |    6 +-
>  .../test16-suppr-removed-fn-report-5.txt      |   15 +-
>  .../test17-suppr-added-var-report-5.txt       |   15 +-
>  .../test18-suppr-removed-var-report-5.txt     |   15 +-
>  tests/test-kmi-whitelist.cc                   |   70 +-
>  19 files changed, 1017 insertions(+), 1904 deletions(-)
>  rename src/abg-sptr-utils.cc => include/abg-regex.h (50%)
>  create mode 100644 src/abg-regex.cc
>
> --
> 2.26.1.301.g55bc3eb7cb9-goog
>

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH 00/21] Simplify regex and suppression parsing.
  2020-04-23 18:11 ` [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
@ 2020-04-24  8:54   ` Giuliano Procida
  0 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-24  8:54 UTC (permalink / raw)
  To: libabigail; +Cc: Dodji Seketeli, kernel-team, Matthias Männich

Hi.

I have a scattering of changes (comments, formatting, one significant
commit message change). I'm going to post a full v3 series.

Please ignore the earlier ones.

Sorry about this.

Giuliano.

On Thu, 23 Apr 2020 at 19:11, Giuliano Procida <gprocida@google.com> wrote:
>
> There are some v2s.
>
> 0007 - fixed wrong style for function prototypes; added missing export
> of regex.cc
> 0009 - ignore, no change
> 0019 - added missing #include <iostream>
>
> Regards,
> Giuliano.
>
> On Thu, 23 Apr 2020 at 16:45, Giuliano Procida <gprocida@google.com> wrote:
> >
> > This patch series takes the suppression parsing very close to where it
> > can be translated into a table-driven format. It is mostly a series of
> > simplifications which are useful in their own right. I have tried to
> > keep each commit doing exactly one thing, to make reviewing easier.
> >
> > These changes are not pure refactorings:
> >
> > Escape names used in symbol whitelisting regex.
> > diff suppression: Fix handling of change kinds
> > abg-tools-utils.cc: Assert generated regexes OK.
> > Warn if user-supplied regexes fail to compile.
> >
> > The rest should be.
> >
> > Regards,
> > Giuliano.
> >
> > Giuliano Procida (21):
> >   Move regex definitions to own files.
> >   Move libxml bits out of abg-sptr-utils.h.
> >   Simplify generation of symbol whitelist regex.
> >   Escape names used in symbol whitelisting regex.
> >   abg-suppression.cc: More uniform variable naming.
> >   diff suppression: Fix handling of change kinds.
> >   Add POSIX regex wrapper functions.
> >   Use regex::compile wrapper instead of regcomp.
> >   Use regex::match wrapper instead of regexec.
> >   Refactor read_parameter_spec_from_string logic.
> >   Compile suppression regexes earlier.
> >   Reduce direct access to suppression priv_ members.
> >   Move match methods from priv to suppression_base.
> >   Remove suppression types' priv class methods.
> >   abg-suppression.cc: More consistent regex matching.
> >   abg-tools-utils.cc: Assert generated regexes OK.
> >   Refactor suppression property string parsing.
> >   Refactor suppression property regex parsing.
> >   Warn if user-supplied regexes fail to compile.
> >   Default construct suppression types.
> >   Remove unused suppression type priv constructors.
> >
> >  include/Makefile.am                           |    3 +-
> >  include/abg-libxml-utils.h                    |   21 +-
> >  src/abg-sptr-utils.cc => include/abg-regex.h  |   71 +-
> >  include/abg-sptr-utils.h                      |   66 +-
> >  include/abg-suppression.h                     |  182 +-
> >  src/Makefile.am                               |    2 +-
> >  src/abg-corpus-priv.h                         |   35 +-
> >  src/abg-corpus.cc                             |    2 +-
> >  src/abg-dwarf-reader.cc                       |    4 +-
> >  src/abg-reader.cc                             |    4 +-
> >  src/abg-regex.cc                              |  134 ++
> >  src/abg-suppression-priv.h                    |  723 +-------
> >  src/abg-suppression.cc                        | 1527 +++++++----------
> >  src/abg-tools-utils.cc                        |   26 +-
> >  .../test15-suppr-added-fn-report-5.txt        |    6 +-
> >  .../test16-suppr-removed-fn-report-5.txt      |   15 +-
> >  .../test17-suppr-added-var-report-5.txt       |   15 +-
> >  .../test18-suppr-removed-var-report-5.txt     |   15 +-
> >  tests/test-kmi-whitelist.cc                   |   70 +-
> >  19 files changed, 1017 insertions(+), 1904 deletions(-)
> >  rename src/abg-sptr-utils.cc => include/abg-regex.h (50%)
> >  create mode 100644 src/abg-regex.cc
> >
> > --
> > 2.26.1.301.g55bc3eb7cb9-goog
> >

^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v3 00/21]Simplify regex and suppression parsing.
  2020-04-23 15:44 [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
                   ` (21 preceding siblings ...)
  2020-04-23 18:11 ` [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
@ 2020-04-24  9:21 ` Giuliano Procida
  2020-04-24  9:21   ` [PATCH v3 01/21] Move regex definitions to own files Giuliano Procida
                     ` (21 more replies)
  22 siblings, 22 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-24  9:21 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

This patch series takes the suppression parsing very close to where it
can be translated into a table-driven format. It is mostly a series of
simplifications which are useful in their own right. I have tried to
keep each commit doing exactly one thing, to make reviewing easier.

These changes are not pure refactorings:

Escape names used in symbol whitelisting regex.
diff suppression: Fix handling of change kinds
abg-tools-utils.cc: Assert generated regexes OK.
Warn if user-supplied regexes fail to compile.

The rest should be.

Regards,
Giuliano.

Giuliano Procida (21):
  Move regex definitions to own files.
  Move libxml bits out of abg-sptr-utils.h.
  Simplify generation of symbol whitelist regex.
  Escape names used in symbol whitelisting regex.
  abg-suppression.cc: More uniform variable naming.
  diff suppression: Fix handling of change kinds.
  Add POSIX regex wrapper functions.
  Use regex::compile wrapper instead of regcomp.
  Use regex::match wrapper instead of regexec.
  Refactor read_parameter_spec_from_string logic.
  Compile suppression regexes earlier.
  Reduce direct access to suppression priv_ members.
  Move match methods from priv to suppression_base.
  Remove suppression types' priv class methods.
  abg-suppression.cc: More consistent regex matching.
  abg-tools-utils.cc: Assert generated regexes OK.
  Refactor suppression property string parsing.
  Refactor suppression property regex parsing.
  Warn if user-supplied regexes fail to compile.
  Default construct suppression types.
  Remove unused suppression type priv constructors.

 include/Makefile.am                           |    3 +-
 include/abg-libxml-utils.h                    |   21 +-
 src/abg-sptr-utils.cc => include/abg-regex.h  |   73 +-
 include/abg-sptr-utils.h                      |   66 +-
 include/abg-suppression.h                     |  182 +-
 src/Makefile.am                               |    2 +-
 src/abg-corpus-priv.h                         |   37 +-
 src/abg-corpus.cc                             |    2 +-
 src/abg-dwarf-reader.cc                       |    4 +-
 src/abg-reader.cc                             |    4 +-
 src/abg-regex.cc                              |  147 ++
 src/abg-suppression-priv.h                    |  723 +-------
 src/abg-suppression.cc                        | 1608 +++++++----------
 src/abg-tools-utils.cc                        |   26 +-
 .../test15-suppr-added-fn-report-5.txt        |    6 +-
 .../test16-suppr-removed-fn-report-5.txt      |   15 +-
 .../test17-suppr-added-var-report-5.txt       |   15 +-
 .../test18-suppr-removed-var-report-5.txt     |   15 +-
 tests/test-kmi-whitelist.cc                   |   70 +-
 19 files changed, 1065 insertions(+), 1954 deletions(-)
 rename src/abg-sptr-utils.cc => include/abg-regex.h (51%)
 create mode 100644 src/abg-regex.cc

-- 
2.26.2.303.gf8c07b1a785-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v3 01/21] Move regex definitions to own files.
  2020-04-24  9:21 ` [PATCH v3 00/21]Simplify " Giuliano Procida
@ 2020-04-24  9:21   ` Giuliano Procida
  2020-04-27 10:52     ` Matthias Maennich
  2020-05-04  9:19     ` Dodji Seketeli
  2020-04-24  9:21   ` [PATCH v3 02/21] Move libxml bits out of abg-sptr-utils.h Giuliano Procida
                     ` (20 subsequent siblings)
  21 siblings, 2 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-24  9:21 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

As a prelude to adding wrapper and helper functions for regex
functionality, it makes sense to move the existing regex code (the
shared pointer type and its specialised deleter) to their own files.

This patch does this and also moves various entities into a new
namespace, abigail::regex. It removes the file abg-sptr-utils.cc which
only contained regex things.

There are no behavioural changes.

	* include/Makefile.am: Add abg-regex.h.
	* src/Makefile.am: Remove abg-sptr-utils.h, add abg-regex.cc
	* include/abg-sptr-utils.h (regex_t_sptr): Remove this
	typedef, from namespace abigail::sptr_utils.
	(regex_t_deleter): Remove this struct, from namespace
	abigail::sptr_utils. (build_sptr): Remove these template
	specialisations, in duplicate, for regex_t_sptr.
	* include/abg-regex.h: New file, introduces namespace
	abigail::regex. (regex_t_sptr): Add this typedef, to namespace
	abigail::regex. (regex_t_deleter): Add this struct, to
	namespace abigail::regex. (build_sptr): Add these template
	specialisations for regex_t_sptr
	* src/abg-sptr-utils.cc: Remove this file.
	* src/abg-regex.cc: Add new file with contents effectively
	the same as abg-sptr-utils.cc.
	* src/abg-corpus-priv.h: Update regex_t_sptr namespace
	qualification.
	* src/abg-corpus.cc: Ditto.
	* src/abg-suppression-priv.h: Ditto.
	* src/abg-suppression.cc: Ditto.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 include/Makefile.am                     |   3 +-
 include/abg-regex.h                     |  83 ++++++++++++++
 include/abg-sptr-utils.h                |  49 ---------
 src/Makefile.am                         |   2 +-
 src/abg-corpus-priv.h                   |   3 +-
 src/abg-corpus.cc                       |   2 +-
 src/{abg-sptr-utils.cc => abg-regex.cc} |  19 ++--
 src/abg-suppression-priv.h              | 137 ++++++++++++------------
 src/abg-suppression.cc                  |  73 ++++++-------
 9 files changed, 198 insertions(+), 173 deletions(-)
 create mode 100644 include/abg-regex.h
 rename src/{abg-sptr-utils.cc => abg-regex.cc} (84%)

diff --git a/include/Makefile.am b/include/Makefile.am
index ae97f674..b5475252 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -24,6 +24,7 @@ abg-cxx-compat.h	\
 abg-version.h		\
 abg-viz-common.h	\
 abg-viz-dot.h		\
-abg-viz-svg.h		
+abg-viz-svg.h		\
+abg-regex.h
 
 EXTRA_DIST = abg-version.h.in
diff --git a/include/abg-regex.h b/include/abg-regex.h
new file mode 100644
index 00000000..84c386a9
--- /dev/null
+++ b/include/abg-regex.h
@@ -0,0 +1,83 @@
+// -*- mode: C++ -*-
+//
+// Copyright (C) 2013-2020 Red Hat, Inc.
+//
+// This file is part of the GNU Application Binary Interface Generic
+// Analysis and Instrumentation Library (libabigail).  This library is
+// free software; you can redistribute it and/or modify it under the
+// terms of the GNU Lesser General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option) any
+// later version.
+
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Lesser Public License for more details.
+
+// You should have received a copy of the GNU Lesser General Public
+// License along with this program; see the file COPYING-LGPLV3.  If
+// not, see <http://www.gnu.org/licenses/>.
+
+/// @file
+///
+/// Wrappers around regex types and functions.
+
+#ifndef __ABG_REGEX_H__
+#define __ABG_REGEX_H__
+
+#include <regex.h>
+
+#include "abg-cxx-compat.h"
+#include "abg-sptr-utils.h"
+
+namespace abigail
+{
+
+/// Namespace for regex types and functions.
+namespace regex
+{
+
+/// A convenience typedef for a shared pointer of regex_t.
+typedef abg_compat::shared_ptr<regex_t> regex_t_sptr;
+
+/// A delete functor for a shared_ptr of regex_t.
+struct regex_t_deleter
+{
+  /// The operator called to de-allocate the pointer to regex_t
+  /// embedded in a shared_ptr<regex_t>
+  ///
+  /// @param r the pointer to regex_t to de-allocate.
+  void
+  operator()(::regex_t* r)
+  {
+    regfree(r);
+    delete r;
+  }
+};//end struct regex_deleter
+
+}// end namespace regex
+
+/// Specialization of sptr_utils::build_sptr for regex_t.
+///
+/// This is used to wrap a pointer to regex_t into a
+/// shared_ptr<regex_t>.
+///
+/// @param p the bare pointer to regex_t to wrap into a shared_ptr<regex_t>.
+///
+/// @return the shared_ptr<regex_t> that wraps @p p.
+template<>
+regex::regex_t_sptr
+sptr_utils::build_sptr<regex_t>(regex_t *p);
+
+/// Specialization of sptr_utils::build_sptr for regex_t.
+///
+/// This creates a pointer to regex_t and wraps it into a shared_ptr<regex_t>.
+///
+/// @return the shared_ptr<regex_t> wrapping the newly created regex_t*
+template<>
+regex::regex_t_sptr
+sptr_utils::build_sptr<regex_t>();
+
+}// end namespace abigail
+
+#endif //__ABG_REGEX_H__
diff --git a/include/abg-sptr-utils.h b/include/abg-sptr-utils.h
index 0adedbb3..9737fe5f 100644
--- a/include/abg-sptr-utils.h
+++ b/include/abg-sptr-utils.h
@@ -78,19 +78,6 @@ typedef shared_ptr<xmlChar> xml_char_sptr;
 template<>
 xml_char_sptr build_sptr<xmlChar>(xmlChar *p);
 
-/// A convenience typedef for a shared pointer of regex_t.
-typedef shared_ptr<regex_t> regex_t_sptr;
-
-/// Specialization of sptr_utils::build_sptr for regex_t.
-template<>
-regex_t_sptr
-build_sptr<regex_t>(regex_t *p);
-
-/// Specialization of sptr_utils::build_sptr for regex_t.
-template<>
-regex_t_sptr
-build_sptr<regex_t>();
-
 /// A deleter for shared pointers that ... doesn't delete the object
 /// managed by the shared pointer.
 struct noop_deleter
@@ -101,42 +88,6 @@ struct noop_deleter
   {}
 };
 
-/// A delete functor for a shared_ptr of regex_t.
-struct regex_t_deleter
-{
-  /// The operator called to de-allocate the pointer to regex_t
-  /// embedded in a shared_ptr<regex_t>
-  ///
-  /// @param r the pointer to regex_t to de-allocate.
-  void
-  operator()(::regex_t* r)
-  {
-    regfree(r);
-    delete r;
-  }
-};//end struct regex_deleter
-
-/// Specialization of sptr_utils::build_sptr for regex_t.
-///
-/// This is used to wrap a pointer to regex_t into a
-/// shared_ptr<regex_t>.
-///
-/// @param p the bare pointer to regex_t to wrap into a shared_ptr<regex_t>.
-///
-/// @return the shared_ptr<regex_t> that wraps @p p.
-template<>
-regex_t_sptr
-build_sptr<regex_t>(regex_t *p);
-
-/// Specialization of sptr_utils::build_sptr for regex_t.
-///
-/// This creates a pointer to regex_t and wraps it into a shared_ptr<regex_t>.
-///
-/// @return the shared_ptr<regex_t> wrapping the newly created regex_t*
-template<>
-regex_t_sptr
-build_sptr<regex_t>();
-
 }// end namespace sptr_utils
 }// end namespace abigail
 
diff --git a/src/Makefile.am b/src/Makefile.am
index fafab853..1153a5f8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -13,7 +13,6 @@ endif
 
 libabigail_la_SOURCES =			\
 abg-internal.h				\
-abg-sptr-utils.cc			\
 abg-traverse.cc				\
 abg-ir-priv.h				\
 abg-ir.cc				\
@@ -41,6 +40,7 @@ abg-workers.cc				\
 abg-tools-utils.cc			\
 abg-elf-helpers.h			\
 abg-elf-helpers.cc			\
+abg-regex.cc				\
 $(CXX11_SOURCES)
 
 libabigail_la_LIBADD = $(DEPS_LIBS)
diff --git a/src/abg-corpus-priv.h b/src/abg-corpus-priv.h
index 4cb2e43c..e65f7c8f 100644
--- a/src/abg-corpus-priv.h
+++ b/src/abg-corpus-priv.h
@@ -30,6 +30,7 @@
 #define __ABG_CORPUS_PRIV_H__
 
 #include "abg-sptr-utils.h"
+#include "abg-regex.h"
 #include "abg-internal.h"
 
 namespace abigail
@@ -42,7 +43,7 @@ namespace sptr_utils
 namespace ir
 {
 
-using sptr_utils::regex_t_sptr;
+using regex::regex_t_sptr;
 
 /// A convenience typedef for std::vector<regex_t_sptr>.
 typedef vector<regex_t_sptr> regex_t_sptrs_type;
diff --git a/src/abg-corpus.cc b/src/abg-corpus.cc
index 12f44fd1..2e9f304d 100644
--- a/src/abg-corpus.cc
+++ b/src/abg-corpus.cc
@@ -67,7 +67,7 @@ using zip_utils::open_archive;
 using zip_utils::open_file_in_archive;
 #endif // WITH_ZIP_ARCHIVE
 
-using sptr_utils::regex_t_sptr;
+using regex::regex_t_sptr;
 
 /// Constructor of @ref corpus::exported_decls_builder.
 ///
diff --git a/src/abg-sptr-utils.cc b/src/abg-regex.cc
similarity index 84%
rename from src/abg-sptr-utils.cc
rename to src/abg-regex.cc
index 2a6739a8..13f5841d 100644
--- a/src/abg-sptr-utils.cc
+++ b/src/abg-regex.cc
@@ -24,13 +24,11 @@
 ///
 
 #include "abg-sptr-utils.h"
+#include "abg-regex.h"
 
 namespace abigail
 {
 
-namespace sptr_utils
-{
-
 /// Specialization of sptr_utils::build_sptr for regex_t.
 ///
 /// This is used to wrap a pointer to regex_t into a
@@ -40,9 +38,9 @@ namespace sptr_utils
 ///
 /// @return the shared_ptr<regex_t> that wraps @p p.
 template<>
-regex_t_sptr
-build_sptr<regex_t>(regex_t *p)
-{return regex_t_sptr(p, regex_t_deleter());}
+regex::regex_t_sptr
+sptr_utils::build_sptr<regex_t>(regex_t *p)
+{return regex::regex_t_sptr(p, regex::regex_t_deleter());}
 
 /// Specialization of sptr_utils::build_sptr for regex_t.
 ///
@@ -50,9 +48,8 @@ build_sptr<regex_t>(regex_t *p)
 ///
 /// @return the shared_ptr<regex_t> wrapping the newly created regex_t*
 template<>
-regex_t_sptr
-build_sptr<regex_t>()
-{return build_sptr(new regex_t);}
+regex::regex_t_sptr
+sptr_utils::build_sptr<regex_t>()
+{return sptr_utils::build_sptr(new regex_t);}
 
-}
-}
+}//end namespace abigail
diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
index 1a9a7207..c37ceff6 100644
--- a/src/abg-suppression-priv.h
+++ b/src/abg-suppression-priv.h
@@ -31,6 +31,7 @@
 #include "abg-fwd.h"
 #include "abg-suppression.h"
 #include "abg-sptr-utils.h"
+#include "abg-regex.h"
 
 namespace abigail
 {
@@ -47,13 +48,13 @@ class suppression_base::priv
   bool					drops_artifact_;
   string				label_;
   string				file_name_regex_str_;
-  mutable sptr_utils::regex_t_sptr	file_name_regex_;
+  mutable regex::regex_t_sptr		file_name_regex_;
   string				file_name_not_regex_str_;
-  mutable sptr_utils::regex_t_sptr	file_name_not_regex_;
+  mutable regex::regex_t_sptr		file_name_not_regex_;
   string				soname_regex_str_;
-  mutable sptr_utils::regex_t_sptr	soname_regex_;
+  mutable regex::regex_t_sptr		soname_regex_;
   string				soname_not_regex_str_;
-  mutable sptr_utils::regex_t_sptr	soname_not_regex_;
+  mutable regex::regex_t_sptr		soname_not_regex_;
 
 public:
   priv()
@@ -87,14 +88,14 @@ public:
   ///
   /// If the 'file_name_regex' property of @ref suppression_base is
   /// empty then this method returns nil.
-  const sptr_utils::regex_t_sptr&
+  const regex::regex_t_sptr&
   get_file_name_regex() const
   {
     if (!file_name_regex_)
       {
 	if (!file_name_regex_str_.empty())
 	  {
-	    sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	    if (regcomp(r.get(),
 			file_name_regex_str_.c_str(),
 			REG_EXTENDED) == 0)
@@ -112,14 +113,14 @@ public:
   ///
   /// If the 'file_name_not_regex' property of @ref suppression_base
   /// is empty then this method returns nil.
-  const sptr_utils::regex_t_sptr&
+  const regex::regex_t_sptr&
   get_file_name_not_regex() const
   {
     if (!file_name_not_regex_)
       {
 	if (!file_name_not_regex_str_.empty())
 	  {
-	    sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	    if (regcomp(r.get(),
 			file_name_not_regex_str_.c_str(),
 			REG_EXTENDED) == 0)
@@ -137,14 +138,14 @@ public:
   ///
   /// If the 'soname_regex' property of @ref suppression_base is empty
   /// then this method returns nil.
-  const sptr_utils::regex_t_sptr&
+  const regex::regex_t_sptr&
   get_soname_regex() const
   {
     if (!soname_regex_)
       {
 	if (!soname_regex_str_.empty())
 	  {
-	    sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	    if (regcomp(r.get(),
 			soname_regex_str_.c_str(),
 			REG_EXTENDED) == 0)
@@ -162,14 +163,14 @@ public:
   ///
   /// If the 'soname_not_regex' property of @ref suppression_base is
   /// empty then this method returns nil.
-  const sptr_utils::regex_t_sptr&
+  const regex::regex_t_sptr&
   get_soname_not_regex() const
   {
     if (!soname_not_regex_)
       {
 	if (!soname_not_regex_str_.empty())
 	  {
-	    sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	    if (regcomp(r.get(),
 			soname_not_regex_str_.c_str(),
 			REG_EXTENDED) == 0)
@@ -192,14 +193,14 @@ public:
   matches_soname(const string& soname) const
   {
     bool has_regexp = false;
-    if (sptr_utils::regex_t_sptr regexp = get_soname_regex())
+    if (regex::regex_t_sptr regexp = get_soname_regex())
       {
 	has_regexp = true;
 	if (regexec(regexp.get(), soname.c_str(), 0, NULL, 0) != 0)
 	  return false;
       }
 
-    if (sptr_utils::regex_t_sptr regexp = get_soname_not_regex())
+    if (regex::regex_t_sptr regexp = get_soname_not_regex())
       {
 	has_regexp = true;
 	if (regexec(regexp.get(), soname.c_str(), 0, NULL, 0) == 0)
@@ -227,7 +228,7 @@ public:
   {
     bool has_regexp = false;
 
-    if (sptr_utils::regex_t_sptr regexp = get_file_name_regex())
+    if (regex::regex_t_sptr regexp = get_file_name_regex())
       {
 	has_regexp = true;
 	if (regexec(regexp.get(), binary_name.c_str(),
@@ -235,7 +236,7 @@ public:
 	  return false;
       }
 
-    if (sptr_utils::regex_t_sptr regexp = get_file_name_not_regex())
+    if (regex::regex_t_sptr regexp = get_file_name_not_regex())
       {
 	has_regexp = true;
 	if (regexec(regexp.get(), binary_name.c_str(),
@@ -263,7 +264,7 @@ class function_suppression::parameter_spec::priv
   size_t				index_;
   string				type_name_;
   string				type_name_regex_str_;
-  mutable sptr_utils::regex_t_sptr	type_name_regex_;
+  mutable regex::regex_t_sptr		type_name_regex_;
 
   priv()
     : index_()
@@ -277,12 +278,12 @@ class function_suppression::parameter_spec::priv
     : index_(i), type_name_(tn), type_name_regex_str_(tn_regex)
   {}
 
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_type_name_regex() const
   {
     if (!type_name_regex_ && !type_name_regex_str_.empty())
       {
-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	if (regcomp(r.get(),
 		    type_name_regex_str_.c_str(),
 		    REG_EXTENDED) == 0)
@@ -302,21 +303,21 @@ struct function_suppression::priv
   change_kind				change_kind_;
   string				name_;
   string				name_regex_str_;
-  mutable sptr_utils::regex_t_sptr	name_regex_;
+  mutable regex::regex_t_sptr		name_regex_;
   string				name_not_regex_str_;
-  mutable sptr_utils::regex_t_sptr	name_not_regex_;
+  mutable regex::regex_t_sptr		name_not_regex_;
   string				return_type_name_;
   string				return_type_regex_str_;
-  mutable sptr_utils::regex_t_sptr	return_type_regex_;
+  mutable regex::regex_t_sptr		return_type_regex_;
   parameter_specs_type			parm_specs_;
   string				symbol_name_;
   string				symbol_name_regex_str_;
-  mutable sptr_utils::regex_t_sptr	symbol_name_regex_;
+  mutable regex::regex_t_sptr		symbol_name_regex_;
   string				symbol_name_not_regex_str_;
-  mutable sptr_utils::regex_t_sptr	symbol_name_not_regex_;
+  mutable regex::regex_t_sptr		symbol_name_not_regex_;
   string				symbol_version_;
   string				symbol_version_regex_str_;
-  mutable sptr_utils::regex_t_sptr	symbol_version_regex_;
+  mutable regex::regex_t_sptr		symbol_version_regex_;
   bool					allow_other_aliases_;
 
   priv():
@@ -356,12 +357,12 @@ struct function_suppression::priv
   ///
   /// @return a pointer to the regular expression object of
   /// function_suppression::priv::name_regex_str_..
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_name_regex() const
   {
     if (!name_regex_ && !name_regex_str_.empty())
       {
-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	if (regcomp(r.get(),
 		    name_regex_str_.c_str(),
 		    REG_EXTENDED) == 0)
@@ -379,12 +380,12 @@ struct function_suppression::priv
   ///
   /// @return a pointer to the regular expression object of
   /// function_suppression::priv::name_not_regex_str_..
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_name_not_regex() const
   {
     if (!name_not_regex_ && !name_not_regex_str_.empty())
       {
-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	if (regcomp(r.get(),
 		    name_not_regex_str_.c_str(),
 		    REG_EXTENDED) == 0)
@@ -402,12 +403,12 @@ struct function_suppression::priv
   ///
   /// @return a pointer to the regular expression object of
   /// function_suppression::priv::return_type_regex_str_.
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_return_type_regex() const
   {
     if (!return_type_regex_ && !return_type_regex_str_.empty())
       {
-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	if (regcomp(r.get(),
 		    return_type_regex_str_.c_str(),
 		    REG_EXTENDED) == 0)
@@ -425,12 +426,12 @@ struct function_suppression::priv
   ///
   /// @return a pointer to the regular expression object of
   /// function_suppression::priv::symbol_name_regex_str_.
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_symbol_name_regex() const
   {
     if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
       {
-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	if (regcomp(r.get(),
 		    symbol_name_regex_str_.c_str(),
 		    REG_EXTENDED) == 0)
@@ -448,12 +449,12 @@ struct function_suppression::priv
   ///
   /// @return a pointer to the regular expression object of
   /// function_suppression::priv::symbol_name_not_regex_str_.
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_symbol_name_not_regex() const
   {
     if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
       {
-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	if (regcomp(r.get(),
 		    symbol_name_not_regex_str_.c_str(),
 		    REG_EXTENDED) == 0)
@@ -471,12 +472,12 @@ struct function_suppression::priv
   ///
   /// @return a pointer to the regular expression object of
   /// function_suppression::priv::symbol_version_regex_str_.
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_symbol_version_regex() const
   {
     if (!symbol_version_regex_ && ! symbol_version_regex_str_.empty())
       {
-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	if (regcomp(r.get(),
 		    symbol_version_regex_str_.c_str(),
 		    REG_EXTENDED) == 0)
@@ -561,20 +562,20 @@ struct variable_suppression::priv
   change_kind				change_kind_;
   string				name_;
   string				name_regex_str_;
-  mutable sptr_utils::regex_t_sptr	name_regex_;
+  mutable regex::regex_t_sptr		name_regex_;
   string				name_not_regex_str_;
-  mutable sptr_utils::regex_t_sptr	name_not_regex_;
+  mutable regex::regex_t_sptr		name_not_regex_;
   string				symbol_name_;
   string				symbol_name_regex_str_;
-  mutable sptr_utils::regex_t_sptr	symbol_name_regex_;
+  mutable regex::regex_t_sptr		symbol_name_regex_;
   string				symbol_name_not_regex_str_;
-  mutable sptr_utils::regex_t_sptr	symbol_name_not_regex_;
+  mutable regex::regex_t_sptr		symbol_name_not_regex_;
   string				symbol_version_;
   string				symbol_version_regex_str_;
-  mutable sptr_utils::regex_t_sptr	symbol_version_regex_;
+  mutable regex::regex_t_sptr		symbol_version_regex_;
   string				type_name_;
   string				type_name_regex_str_;
-  mutable sptr_utils::regex_t_sptr	type_name_regex_;
+  mutable regex::regex_t_sptr		type_name_regex_;
 
   priv(const string& name,
        const string& name_regex_str,
@@ -604,12 +605,12 @@ struct variable_suppression::priv
   ///
   /// @return a pointer to the regular expression object of
   /// variable_suppression::priv::name_regex_str_.
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_name_regex() const
   {
     if (!name_regex_ && !name_regex_str_.empty())
       {
-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	if (regcomp(r.get(),
 		    name_regex_str_.c_str(),
 		    REG_EXTENDED) == 0)
@@ -627,12 +628,12 @@ struct variable_suppression::priv
   ///
   /// @return a pointer to the regular expression object of
   /// variable_suppression::priv::name_not_regex_str_..
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_name_not_regex() const
   {
     if (!name_not_regex_ && !name_not_regex_str_.empty())
       {
-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	if (regcomp(r.get(),
 		    name_not_regex_str_.c_str(),
 		    REG_EXTENDED) == 0)
@@ -650,12 +651,12 @@ struct variable_suppression::priv
   ///
   /// @return a pointer to the regular expression object of
   /// variable_suppression::priv::symbol_name_regex_str_.
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_symbol_name_regex() const
   {
     if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
       {
-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	if (regcomp(r.get(),
 		    symbol_name_regex_str_.c_str(),
 		    REG_EXTENDED) == 0)
@@ -673,12 +674,12 @@ struct variable_suppression::priv
   ///
   /// @return a pointer to the regular expression object of
   /// variable_suppression::priv::symbol_name_not_regex_str_.
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_symbol_name_not_regex() const
   {
     if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
       {
-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	if (regcomp(r.get(), symbol_name_not_regex_str_.c_str(),
 		    REG_EXTENDED) == 0)
 	  symbol_name_not_regex_ = r;
@@ -695,12 +696,12 @@ struct variable_suppression::priv
   ///
   /// @return a pointer to the regular expression object of
   /// variable_suppression::priv::symbol_version_regex_str_.
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_symbol_version_regex()  const
   {
     if (!symbol_version_regex_ && !symbol_version_regex_str_.empty())
       {
-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	if (regcomp(r.get(),
 		    symbol_version_regex_str_.c_str(),
 		    REG_EXTENDED) == 0)
@@ -718,12 +719,12 @@ struct variable_suppression::priv
   ///
   /// @return a pointer to the regular expression object of
   /// variable_suppression::priv::type_name_regex_str_.
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_type_name_regex() const
   {
     if (!type_name_regex_ && !type_name_regex_str_.empty())
       {
-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	if (regcomp(r.get(),
 		    type_name_regex_str_.c_str(),
 		    REG_EXTENDED) == 0)
@@ -766,18 +767,18 @@ variable_is_suppressed(const ReadContextType&	ctxt,
 class type_suppression::priv
 {
   string				type_name_regex_str_;
-  mutable sptr_utils::regex_t_sptr	type_name_regex_;
+  mutable regex::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_;
+  mutable regex::regex_t_sptr		type_name_not_regex_;
   bool					consider_type_kind_;
   type_suppression::type_kind		type_kind_;
   bool					consider_reach_kind_;
   type_suppression::reach_kind		reach_kind_;
   type_suppression::insertion_ranges	insertion_ranges_;
-  unordered_set<string>		source_locations_to_keep_;
+  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 regex::regex_t_sptr		source_location_to_keep_regex_;
   mutable vector<string>		changed_enumerator_names_;
 
   priv();
@@ -805,14 +806,14 @@ public:
   ///
   /// If the 'type_name_regex' property of @ref type_suppression is
   /// empty then this method returns nil.
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_type_name_regex() const
   {
     if (!type_name_regex_)
       {
 	if (!type_name_regex_str_.empty())
 	  {
-	    sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	    if (regcomp(r.get(),
 			type_name_regex_str_.c_str(),
 			REG_EXTENDED) == 0)
@@ -826,7 +827,7 @@ public:
   ///
   /// @param r the new type_name_regex object.
   void
-  set_type_name_regex(sptr_utils::regex_t_sptr r)
+  set_type_name_regex(regex::regex_t_sptr r)
   {type_name_regex_ = r;}
 
   /// Get the regular expression object associated to the
@@ -837,14 +838,14 @@ public:
   ///
   /// If the 'type_name_not_regex' property of @ref type_suppression is
   /// empty then this method returns nil.
-  const sptr_utils::regex_t_sptr
+  const regex::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>();
+	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	    if (regcomp(r.get(),
 			type_name_not_regex_str_.c_str(),
 			REG_EXTENDED) == 0)
@@ -858,7 +859,7 @@ public:
   ///
   /// @param r the new type_name_not_regex object.
   void
-  set_type_name_not_regex(sptr_utils::regex_t_sptr r)
+  set_type_name_not_regex(regex::regex_t_sptr r)
   {type_name_not_regex_ = r;}
 
   /// Getter for the string that denotes the 'type_name_not_regex'
@@ -882,14 +883,14 @@ public:
   /// Getter for the source_location_to_keep_regex object.
   ///
   /// This function builds the regex if it's not yet built.
-  const sptr_utils::regex_t_sptr
+  const regex::regex_t_sptr
   get_source_location_to_keep_regex() const
   {
     if (!source_location_to_keep_regex_)
       {
 	if (!source_location_to_keep_regex_str_.empty())
 	  {
-	    sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
+	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
 	    if (regcomp(r.get(),
 			source_location_to_keep_regex_str_.c_str(),
 			REG_EXTENDED) == 0)
@@ -903,7 +904,7 @@ public:
   ///
   /// @param r the new regex object.
   void
-  set_source_location_to_keep_regex(sptr_utils::regex_t_sptr r)
+  set_source_location_to_keep_regex(regex::regex_t_sptr r)
   {source_location_to_keep_regex_ = r;}
 
   friend class type_suppression;
diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index d3ccb63c..f26c9208 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -49,6 +49,7 @@ namespace suppr
 {
 
 using abg_compat::dynamic_pointer_cast;
+using regex::regex_t_sptr;
 
 // <suppression_base stuff>
 
@@ -990,7 +991,7 @@ 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.
-	  if (const sptr_utils::regex_t_sptr& type_name_regex =
+	  if (const regex_t_sptr& type_name_regex =
 	      s.priv_->get_type_name_regex())
 	    {
 	      if (regexec(type_name_regex.get(),
@@ -999,7 +1000,7 @@ suppression_matches_type_name(const type_suppression&	s,
 		return false;
 	    }
 
-	  if (const sptr_utils::regex_t_sptr type_name_not_regex =
+	  if (const regex_t_sptr type_name_not_regex =
 	      s.priv_->get_type_name_not_regex())
 	    {
 	      if (regexec(type_name_not_regex.get(),
@@ -1050,8 +1051,7 @@ suppression_matches_type_location(const type_suppression&	s,
       unsigned loc_line = 0, loc_column = 0;
       loc.expand(loc_path, loc_line, loc_column);
 
-      if (sptr_utils::regex_t_sptr regexp =
-	  s.priv_->get_source_location_to_keep_regex())
+      if (regex_t_sptr regexp = s.priv_->get_source_location_to_keep_regex())
 	if (regexec(regexp.get(), loc_path.c_str(), 0, NULL, 0) == 0)
 	  return false;
 
@@ -2500,7 +2500,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
 
   // check if the "name_regexp" property matches.
-  const sptr_utils::regex_t_sptr name_regex = priv_->get_name_regex();
+  const regex_t_sptr name_regex = priv_->get_name_regex();
   if (name_regex)
     {
       if (regexec(name_regex.get(),
@@ -2535,7 +2535,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
 
   // check if the "name_not_regexp" property matches.
-  const sptr_utils::regex_t_sptr name_not_regex = priv_->get_name_not_regex();
+  const regex_t_sptr name_not_regex = priv_->get_name_not_regex();
   if (name_not_regex)
     {
       if (regexec(name_not_regex.get(),
@@ -2585,8 +2585,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
   else
     {
-      const sptr_utils::regex_t_sptr return_type_regex =
-	priv_->get_return_type_regex();
+      const regex_t_sptr return_type_regex = priv_->get_return_type_regex();
       if (return_type_regex
 	  && (regexec(return_type_regex.get(),
 		      fn_return_type_name.c_str(),
@@ -2626,15 +2625,14 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
   else if (sym)
     {
-      const sptr_utils::regex_t_sptr symbol_name_regex =
-	priv_->get_symbol_name_regex();
+      const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
       if (symbol_name_regex
 	  && (regexec(symbol_name_regex.get(),
 		      fn_sym_name.c_str(),
 		      0, NULL, 0) != 0))
 	return false;
 
-      const sptr_utils::regex_t_sptr symbol_name_not_regex =
+      const regex_t_sptr symbol_name_not_regex =
 	priv_->get_symbol_name_not_regex();
       if (symbol_name_not_regex
 	  && (regexec(symbol_name_not_regex.get(),
@@ -2678,7 +2676,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
   else if (sym)
     {
-      const sptr_utils::regex_t_sptr symbol_version_regex =
+      const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
       if (symbol_version_regex
 	  && (regexec(symbol_version_regex.get(),
@@ -2720,7 +2718,7 @@ function_suppression::suppresses_function(const function_decl* fn,
 	    }
 	  else
 	    {
-	      const sptr_utils::regex_t_sptr parm_type_name_regex =
+	      const regex_t_sptr parm_type_name_regex =
 		(*p)->priv_->get_type_name_regex();
 	      if (parm_type_name_regex)
 		{
@@ -2813,8 +2811,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
     }
   else if (!get_symbol_name_regex_str().empty())
     {
-      const sptr_utils::regex_t_sptr symbol_name_regex =
-	priv_->get_symbol_name_regex();
+      const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
       if (symbol_name_regex
 	  && (regexec(symbol_name_regex.get(),
 		      sym_name.c_str(),
@@ -2832,7 +2829,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
     }
   else if (!get_symbol_version_regex_str().empty())
     {
-      const sptr_utils::regex_t_sptr symbol_version_regex =
+      const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
       if (symbol_version_regex
 	  && (regexec(symbol_version_regex.get(),
@@ -2927,12 +2924,12 @@ bool
 suppression_matches_function_name(const suppr::function_suppression& s,
 				  const string& fn_name)
 {
-  if (sptr_utils::regex_t_sptr regexp = s.priv_->get_name_regex())
+  if (regex_t_sptr regexp = s.priv_->get_name_regex())
     {
       if (regexec(regexp.get(), fn_name.c_str(), 0, NULL, 0) != 0)
 	return false;
     }
-  else if (sptr_utils::regex_t_sptr regexp = s.priv_->get_name_not_regex())
+  else if (regex_t_sptr regexp = s.priv_->get_name_not_regex())
     {
       if (regexec(regexp.get(), fn_name.c_str(), 0, NULL, 0) == 0)
 	return false;
@@ -2963,12 +2960,12 @@ bool
 suppression_matches_function_sym_name(const suppr::function_suppression& s,
 				      const string& fn_linkage_name)
 {
-  if (sptr_utils::regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
+  if (regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
     {
       if (regexec(regexp.get(), fn_linkage_name.c_str(), 0, NULL, 0) != 0)
 	return false;
     }
-  else if (sptr_utils::regex_t_sptr regexp = s.priv_->get_symbol_name_not_regex())
+  else if (regex_t_sptr regexp = s.priv_->get_symbol_name_not_regex())
     {
       if (regexec(regexp.get(), fn_linkage_name.c_str(), 0, NULL, 0) == 0)
 	return false;
@@ -2996,12 +2993,12 @@ bool
 suppression_matches_variable_name(const suppr::variable_suppression& s,
 				  const string& var_name)
 {
-  if (sptr_utils::regex_t_sptr regexp = s.priv_->get_name_regex())
+  if (regex_t_sptr regexp = s.priv_->get_name_regex())
     {
       if (regexec(regexp.get(), var_name.c_str(), 0, NULL, 0) != 0)
 	return false;
     }
-  else if (sptr_utils::regex_t_sptr regexp = s.priv_->get_name_not_regex())
+  else if (regex_t_sptr regexp = s.priv_->get_name_not_regex())
     {
       if (regexec(regexp.get(), var_name.c_str(), 0, NULL, 0) == 0)
 	return false;
@@ -3030,12 +3027,12 @@ bool
 suppression_matches_variable_sym_name(const suppr::variable_suppression& s,
 				      const string& var_linkage_name)
 {
-  if (sptr_utils::regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
+  if (regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
     {
       if (regexec(regexp.get(), var_linkage_name.c_str(), 0, NULL, 0) != 0)
 	return false;
     }
-  else if (sptr_utils::regex_t_sptr regexp =
+  else if (regex_t_sptr regexp =
 	   s.priv_->get_symbol_name_not_regex())
     {
       if (regexec(regexp.get(), var_linkage_name.c_str(), 0, NULL, 0) == 0)
@@ -3065,7 +3062,7 @@ bool
 suppression_matches_type(const suppr::type_suppression& s,
 			 const string& type_name)
 {
-  if (sptr_utils::regex_t_sptr regexp = s.priv_->get_type_name_regex())
+  if (regex_t_sptr regexp = s.priv_->get_type_name_regex())
     {
       if (regexec(regexp.get(), type_name.c_str(), 0, NULL, 0) != 0)
 	return false;
@@ -3780,14 +3777,13 @@ variable_suppression::suppresses_variable(const var_decl* var,
       // "name_regex" and "name_not_regex" properties match
       if (get_name().empty())
 	{
-	  const sptr_utils::regex_t_sptr name_regex = priv_->get_name_regex();
+	  const regex_t_sptr name_regex = priv_->get_name_regex();
 	  if (name_regex
 	      && (regexec(name_regex.get(), var_name.c_str(),
 			  0, NULL, 0) != 0))
 	    return false;
 
-	  const sptr_utils::regex_t_sptr name_not_regex =
-	    priv_->get_name_not_regex();
+	  const regex_t_sptr name_not_regex = priv_->get_name_not_regex();
 	  if (name_not_regex
 	      && (regexec(name_not_regex.get(), var_name.c_str(),
 			  0, NULL, 0) == 0))
@@ -3805,14 +3801,13 @@ variable_suppression::suppresses_variable(const var_decl* var,
     }
   else
     {
-      const sptr_utils::regex_t_sptr sym_name_regex =
-	priv_->get_symbol_name_regex();
+      const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
       if (sym_name_regex
 	  && (regexec(sym_name_regex.get(), var_sym_name.c_str(),
 		      0, NULL, 0) != 0))
 	return false;
 
-      const sptr_utils::regex_t_sptr sym_name_not_regex =
+      const regex_t_sptr sym_name_not_regex =
 	priv_->get_symbol_name_not_regex();
       if (sym_name_not_regex
 	  && (regexec(sym_name_not_regex.get(), var_sym_name.c_str(),
@@ -3830,7 +3825,7 @@ variable_suppression::suppresses_variable(const var_decl* var,
     }
   else
     {
-      const sptr_utils::regex_t_sptr symbol_version_regex =
+      const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
       if (symbol_version_regex
 	  && (regexec(symbol_version_regex.get(),
@@ -3852,8 +3847,7 @@ variable_suppression::suppresses_variable(const var_decl* var,
     {
       if (get_type_name().empty())
 	{
-	  const sptr_utils::regex_t_sptr type_name_regex =
-	    priv_->get_type_name_regex();
+	  const regex_t_sptr type_name_regex = priv_->get_type_name_regex();
 	  if (type_name_regex
 	      && (regexec(type_name_regex.get(), var_type_name.c_str(),
 			  0, NULL, 0) != 0))
@@ -3946,8 +3940,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
     }
   else if (!get_symbol_name_regex_str().empty())
     {
-      const sptr_utils::regex_t_sptr sym_name_regex =
-	priv_->get_symbol_name_regex();
+      const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
       if (sym_name_regex
 	  && (regexec(sym_name_regex.get(), sym_name.c_str(),
 		      0, NULL, 0) != 0))
@@ -3965,7 +3958,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
     }
   else if (!get_symbol_version_regex_str().empty())
     {
-      const sptr_utils::regex_t_sptr symbol_version_regex =
+      const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
       if (symbol_version_regex
 	  && (regexec(symbol_version_regex.get(),
@@ -4275,16 +4268,14 @@ file_suppression::suppresses_file(const string& file_path)
 
   bool has_regexp = false;
 
-  if (sptr_utils::regex_t_sptr regexp =
-      suppression_base::priv_->get_file_name_regex())
+  if (regex_t_sptr regexp = suppression_base::priv_->get_file_name_regex())
     {
       has_regexp = true;
       if (regexec(regexp.get(), fname.c_str(), 0, NULL, 0) != 0)
 	return false;
     }
 
-  if (sptr_utils::regex_t_sptr regexp =
-      suppression_base::priv_->get_file_name_not_regex())
+  if (regex_t_sptr regexp = suppression_base::priv_->get_file_name_not_regex())
     {
       has_regexp = true;
       if (regexec(regexp.get(), fname.c_str(), 0, NULL, 0) == 0)
-- 
2.26.2.303.gf8c07b1a785-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v3 02/21] Move libxml bits out of abg-sptr-utils.h.
  2020-04-24  9:21 ` [PATCH v3 00/21]Simplify " Giuliano Procida
  2020-04-24  9:21   ` [PATCH v3 01/21] Move regex definitions to own files Giuliano Procida
@ 2020-04-24  9:21   ` Giuliano Procida
  2020-04-27 10:53     ` Matthias Maennich
                       ` (2 more replies)
  2020-04-24  9:21   ` [PATCH v3 03/21] Simplify generation of symbol whitelist regex Giuliano Procida
                     ` (19 subsequent siblings)
  21 siblings, 3 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-24  9:21 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

The header file abg-sptr-utils.h contains generic things relating to
shared pointers. It also contains shared pointer typedefs (in the
sptr_utils namespace) and template specialisations for XML types.

The last of these more naturally belong in abg-libxml-utils.h (and in
the xml namespace). This patch moves them.

There are no behavioural changes.

	* include/abg-sptr-utils.h: Remove reader_sptr and
	xml_char_sptr typedefs, from namespace
	sptr_utils. (build_sptr): Remove corresponding template
	function specialisations for these types.
	* include/abg-libxml-utils.h: Add reader_sptr and
	xml_char_sptr typedefs, to namespace xml. (build_sptr): Add
	corresponding template function specialisations for these
	types.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 include/abg-libxml-utils.h | 21 +++++++++++++++++++--
 include/abg-sptr-utils.h   | 17 +----------------
 2 files changed, 20 insertions(+), 18 deletions(-)

diff --git a/include/abg-libxml-utils.h b/include/abg-libxml-utils.h
index 6331bde5..1e46d950 100644
--- a/include/abg-libxml-utils.h
+++ b/include/abg-libxml-utils.h
@@ -23,7 +23,10 @@
 #ifndef __ABG_LIBXML_UTILS_H__
 #define __ABG_LIBXML_UTILS_H__
 
+#include <libxml/xmlreader.h>
+
 #include <istream>
+
 #include "abg-sptr-utils.h"
 #include "abg-cxx-compat.h"
 
@@ -36,8 +39,12 @@ namespace xml
 
 using sptr_utils::build_sptr;
 using abg_compat::shared_ptr;
-using sptr_utils::reader_sptr;
-using sptr_utils::xml_char_sptr;
+
+/// A convenience typedef for a shared pointer of xmlTextReader.
+typedef shared_ptr<xmlTextReader> reader_sptr;
+
+/// A convenience typedef for a shared pointer of xmlChar.
+typedef shared_ptr<xmlChar> xml_char_sptr;
 
 /// This functor is used to instantiate a shared_ptr for the
 /// xmlTextReader.
@@ -121,5 +128,15 @@ std::string
 unescape_xml_comment(const std::string& str);
 
 }//end namespace xml
+
+/// Specialization of sptr_utils::build_sptr for xmlTextReader
+template<>
+xml::reader_sptr
+sptr_utils::build_sptr<xmlTextReader>(xmlTextReader *p);
+
+/// Specialization of build_str for xmlChar.
+template<>
+xml::xml_char_sptr sptr_utils::build_sptr<xmlChar>(xmlChar *p);
+
 }//end namespace abigail
 #endif //__ABG_LIBXML_UTILS_H__
diff --git a/include/abg-sptr-utils.h b/include/abg-sptr-utils.h
index 9737fe5f..2a12707b 100644
--- a/include/abg-sptr-utils.h
+++ b/include/abg-sptr-utils.h
@@ -26,7 +26,7 @@
 #define __ABG_SPTR_UTILS_H__
 
 #include <regex.h>
-#include <libxml/xmlreader.h>
+
 #include "abg-cxx-compat.h"
 
 namespace abigail
@@ -63,21 +63,6 @@ template<class T>
 shared_ptr<T>
 build_sptr();
 
-/// A convenience typedef for a shared pointer of xmlTextReader.
-typedef shared_ptr<xmlTextReader> reader_sptr;
-
-/// Specialization of sptr_utils::build_sptr for xmlTextReader
-template<>
-reader_sptr
-build_sptr<xmlTextReader>(xmlTextReader *p);
-
-/// A convenience typedef for a shared pointer of xmlChar.
-typedef shared_ptr<xmlChar> xml_char_sptr;
-
-/// Specialization of build_str for xmlChar.
-template<>
-xml_char_sptr build_sptr<xmlChar>(xmlChar *p);
-
 /// A deleter for shared pointers that ... doesn't delete the object
 /// managed by the shared pointer.
 struct noop_deleter
-- 
2.26.2.303.gf8c07b1a785-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v3 03/21] Simplify generation of symbol whitelist regex.
  2020-04-24  9:21 ` [PATCH v3 00/21]Simplify " Giuliano Procida
  2020-04-24  9:21   ` [PATCH v3 01/21] Move regex definitions to own files Giuliano Procida
  2020-04-24  9:21   ` [PATCH v3 02/21] Move libxml bits out of abg-sptr-utils.h Giuliano Procida
@ 2020-04-24  9:21   ` Giuliano Procida
  2020-04-27 11:01     ` Matthias Maennich
  2020-05-04  9:20     ` Dodji Seketeli
  2020-04-24  9:21   ` [PATCH v3 04/21] Escape names used in symbol whitelisting regex Giuliano Procida
                     ` (18 subsequent siblings)
  21 siblings, 2 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-24  9:21 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

The code to build the symbol whitelist regex uses things like seekp
and tellp to generate regexes like "^foo$|^bar$".

This patch simplifies the code, for further enhancement, resulting in
generated regexes like "^(foo|bar)$".

There should be no change in behaviour, unless whitelisted symbol
names contain special regex characters.

	* include/abg-regex.h (generate_from_strings): Declare new
	function to build a regex from some strings, representing a
	membership test.
	* src/abg-regex.cc (generate_from_strings): Implement new
	function to build a regex from some strings, representing a
	membership test, in a straightfoward fashion.
	* src/abg-tools-utils.cc
	(gen_suppr_spec_from_kernel_abi_whitelists): Replace
	regex-building code with a call to generate_from_strings.
	* tests/test-kmi-whitelist.cc: Update regexes in test.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 include/abg-regex.h         |  6 ++++++
 src/abg-regex.cc            | 28 ++++++++++++++++++++++++++++
 src/abg-tools-utils.cc      | 10 +++-------
 tests/test-kmi-whitelist.cc | 10 +++++-----
 4 files changed, 42 insertions(+), 12 deletions(-)

diff --git a/include/abg-regex.h b/include/abg-regex.h
index 84c386a9..2f638ef2 100644
--- a/include/abg-regex.h
+++ b/include/abg-regex.h
@@ -27,6 +27,9 @@
 
 #include <regex.h>
 
+#include <string>
+#include <vector>
+
 #include "abg-cxx-compat.h"
 #include "abg-sptr-utils.h"
 
@@ -55,6 +58,9 @@ struct regex_t_deleter
   }
 };//end struct regex_deleter
 
+std::string
+generate_from_strings(const std::vector<std::string>& strs);
+
 }// end namespace regex
 
 /// Specialization of sptr_utils::build_sptr for regex_t.
diff --git a/src/abg-regex.cc b/src/abg-regex.cc
index 13f5841d..79a89033 100644
--- a/src/abg-regex.cc
+++ b/src/abg-regex.cc
@@ -23,6 +23,7 @@
 /// Some specialization for shared pointer utility templates.
 ///
 
+#include <sstream>
 #include "abg-sptr-utils.h"
 #include "abg-regex.h"
 
@@ -52,4 +53,31 @@ regex::regex_t_sptr
 sptr_utils::build_sptr<regex_t>()
 {return sptr_utils::build_sptr(new regex_t);}
 
+namespace regex
+{
+
+/// Generate a regex pattern equivalent to testing set membership.
+///
+/// A string will match the resulting pattern regex, if and only if it
+/// was present in the vector.
+///
+/// @param strs a vector of strings
+///
+/// @return a regex pattern
+std::string
+generate_from_strings(const std::vector<std::string>& strs)
+{
+  if (strs.empty())
+    return "^_^";
+  std::ostringstream os;
+  std::vector<std::string>::const_iterator i = strs.begin();
+  os << "^(" << *i++;
+  while (i != strs.end())
+    os << "|" << *i++;
+  os << ")$";
+  return os.str();
+}
+
+}//end namespace regex
+
 }//end namespace abigail
diff --git a/src/abg-tools-utils.cc b/src/abg-tools-utils.cc
index a06e8615..11486a21 100644
--- a/src/abg-tools-utils.cc
+++ b/src/abg-tools-utils.cc
@@ -61,6 +61,8 @@
 #include "abg-dwarf-reader.h"
 #include "abg-internal.h"
 #include "abg-cxx-compat.h"
+#include "abg-regex.h"
+
 // <headers defining libabigail's API go under here>
 ABG_BEGIN_EXPORT_DECLARATIONS
 
@@ -2002,13 +2004,7 @@ gen_suppr_spec_from_kernel_abi_whitelists
 
       // Build a regular expression representing the union of all
       // the function and variable names expressed in the white list.
-      std::stringstream regex_ss;
-      regex_ss << "^";
-      std::copy(whitelisted_names.begin(), whitelisted_names.end(),
-		std::ostream_iterator<std::string>(regex_ss, "$|^"));
-      regex_ss.seekp(0, std::ios::end);
-      const std::string& regex =
-	  regex_ss.str().substr(0, static_cast<size_t>(regex_ss.tellp()) - 2);
+      const std::string regex = regex::generate_from_strings(whitelisted_names);
 
       // Build a suppression specification which *keeps* functions
       // whose ELF symbols match the regular expression contained
diff --git a/tests/test-kmi-whitelist.cc b/tests/test-kmi-whitelist.cc
index 2aa0f463..bcc5adee 100644
--- a/tests/test-kmi-whitelist.cc
+++ b/tests/test-kmi-whitelist.cc
@@ -96,7 +96,7 @@ TEST_CASE("WhitelistWithASingleEntry", "[whitelists]")
   suppressions_type suppr
       = gen_suppr_spec_from_kernel_abi_whitelists(abi_whitelist_paths);
   REQUIRE(!suppr.empty());
-  test_suppressions_are_consistent(suppr, "^test_symbol$");
+  test_suppressions_are_consistent(suppr, "^(test_symbol)$");
 }
 
 TEST_CASE("WhitelistWithADuplicateEntry", "[whitelists]")
@@ -106,7 +106,7 @@ TEST_CASE("WhitelistWithADuplicateEntry", "[whitelists]")
   suppressions_type suppr
       = gen_suppr_spec_from_kernel_abi_whitelists(abi_whitelist_paths);
   REQUIRE(!suppr.empty());
-  test_suppressions_are_consistent(suppr, "^test_symbol$");
+  test_suppressions_are_consistent(suppr, "^(test_symbol)$");
 }
 
 TEST_CASE("TwoWhitelists", "[whitelists]")
@@ -118,7 +118,7 @@ TEST_CASE("TwoWhitelists", "[whitelists]")
       gen_suppr_spec_from_kernel_abi_whitelists(abi_whitelist_paths);
   REQUIRE(!suppr.empty());
   test_suppressions_are_consistent(suppr,
-				   "^test_another_symbol$|^test_symbol$");
+				   "^(test_another_symbol|test_symbol)$");
 }
 
 TEST_CASE("TwoWhitelistsWithDuplicates", "[whitelists]")
@@ -130,7 +130,7 @@ TEST_CASE("TwoWhitelistsWithDuplicates", "[whitelists]")
       = gen_suppr_spec_from_kernel_abi_whitelists(abi_whitelist_paths);
   REQUIRE(!suppr.empty());
   test_suppressions_are_consistent(suppr,
-				   "^test_another_symbol$|^test_symbol$");
+				   "^(test_another_symbol|test_symbol)$");
 }
 
 TEST_CASE("WhitelistWithTwoSections", "[whitelists]")
@@ -140,5 +140,5 @@ TEST_CASE("WhitelistWithTwoSections", "[whitelists]")
   suppressions_type suppr
       = gen_suppr_spec_from_kernel_abi_whitelists(abi_whitelist_paths);
   REQUIRE(!suppr.empty());
-  test_suppressions_are_consistent(suppr, "^test_symbol1$|^test_symbol2$");
+  test_suppressions_are_consistent(suppr, "^(test_symbol1|test_symbol2)$");
 }
-- 
2.26.2.303.gf8c07b1a785-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v3 04/21] Escape names used in symbol whitelisting regex.
  2020-04-24  9:21 ` [PATCH v3 00/21]Simplify " Giuliano Procida
                     ` (2 preceding siblings ...)
  2020-04-24  9:21   ` [PATCH v3 03/21] Simplify generation of symbol whitelist regex Giuliano Procida
@ 2020-04-24  9:21   ` Giuliano Procida
  2020-04-27 11:14     ` Matthias Maennich
  2020-04-24  9:21   ` [PATCH v3 05/21] abg-suppression.cc: More uniform variable naming Giuliano Procida
                     ` (17 subsequent siblings)
  21 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-04-24  9:21 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

There is the theoretical possibility that symbols may contain special
regex characters like '.' and '$'. This patch ensures all such
characters in symbol names are escaped before they are added to the
whitelisting regex.

	* include/regex.h (escape): New string reference holder
	class. (operator<<): Declaration of std::ostream,
	regex::escape overload.
	* include/regex.cc (operator<<): New std::ostream,
	regex::escape overload that outputs regex-escaped strings.
	* src/abg-tools-utils.cc
	(gen_suppr_spec_from_kernel_abi_whitelists): Make sure any
	special regex characters in symbol names are escaped.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 include/abg-regex.h | 10 ++++++++++
 src/abg-regex.cc    | 27 +++++++++++++++++++++++++--
 2 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/include/abg-regex.h b/include/abg-regex.h
index 2f638ef2..59976794 100644
--- a/include/abg-regex.h
+++ b/include/abg-regex.h
@@ -58,6 +58,16 @@ struct regex_t_deleter
   }
 };//end struct regex_deleter
 
+/// A class to hold a reference to a string to regex escape.
+struct escape
+{
+  escape(const std::string& str) : ref(str) { }
+  const std::string& ref;
+};
+
+std::ostream&
+operator<<(std::ostream& os, const escape& esc);
+
 std::string
 generate_from_strings(const std::vector<std::string>& strs);
 
diff --git a/src/abg-regex.cc b/src/abg-regex.cc
index 79a89033..90e4d144 100644
--- a/src/abg-regex.cc
+++ b/src/abg-regex.cc
@@ -24,6 +24,7 @@
 ///
 
 #include <sstream>
+#include <ostream>
 #include "abg-sptr-utils.h"
 #include "abg-regex.h"
 
@@ -56,6 +57,28 @@ sptr_utils::build_sptr<regex_t>()
 namespace regex
 {
 
+/// Escape regex special charaters in input string.
+///
+/// @param os the output stream being written to.
+///
+/// @param esc the regex_escape object holding a reference to the string
+/// needing to be escaped.
+///
+/// @return the output stream.
+std::ostream&
+operator<<(std::ostream& os, const escape& esc)
+{
+  static const std::string specials = "^.[$()|*+?{\\";
+  const std::string str = esc.ref;
+  for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
+    {
+      if (specials.find(*i) != std::string::npos)
+        os << '\\';
+      os << *i;
+    }
+  return os;
+}
+
 /// Generate a regex pattern equivalent to testing set membership.
 ///
 /// A string will match the resulting pattern regex, if and only if it
@@ -71,9 +94,9 @@ generate_from_strings(const std::vector<std::string>& strs)
     return "^_^";
   std::ostringstream os;
   std::vector<std::string>::const_iterator i = strs.begin();
-  os << "^(" << *i++;
+  os << "^(" << escape(*i++);
   while (i != strs.end())
-    os << "|" << *i++;
+    os << "|" << escape(*i++);
   os << ")$";
   return os.str();
 }
-- 
2.26.2.303.gf8c07b1a785-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v3 05/21] abg-suppression.cc: More uniform variable naming.
  2020-04-24  9:21 ` [PATCH v3 00/21]Simplify " Giuliano Procida
                     ` (3 preceding siblings ...)
  2020-04-24  9:21   ` [PATCH v3 04/21] Escape names used in symbol whitelisting regex Giuliano Procida
@ 2020-04-24  9:21   ` Giuliano Procida
  2020-04-27 11:17     ` Matthias Maennich
  2020-04-24  9:21   ` [PATCH v3 06/21] diff suppression: Fix handling of change kinds Giuliano Procida
                     ` (16 subsequent siblings)
  21 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-04-24  9:21 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

In abg-suppression.cc most of the read_foo functions populate and
return a single variable "result". Others vary a little from this,
having variables "nil" or "suppr".

This patch makes all the functions use a single variable "result".
This will make the next patches a bit simpler.

There are no behavioural changes.

	* src/abg-suppression.cc (read_type_suppression): Rename "nil"
	variable to "result" and reset it instead of introducing
	"suppr" later on. (read_function_suppression): Rename "nil"
	variable to "result" and reset it instead of introducing
	"result" later on.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-suppression.cc | 64 +++++++++++++++++++++---------------------
 1 file changed, 32 insertions(+), 32 deletions(-)

diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index f26c9208..2fbbd61b 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -1547,10 +1547,10 @@ read_suppression_reach_kind(const string& input)
 static type_suppression_sptr
 read_type_suppression(const ini::config::section& section)
 {
-  type_suppression_sptr nil;
+  type_suppression_sptr result;
 
   if (section.get_name() != "suppress_type")
-    return nil;
+    return result;
 
   ini::simple_property_sptr drop_artifact =
     is_simple_property(section.find_property("drop_artifact"));
@@ -1674,7 +1674,7 @@ read_type_suppression(const ini::config::section& section)
 	       type_suppression::insertion_range::create_fn_call_expr_boundary(ini::read_function_call_expr(ins_point)))
 	begin = expr;
       else
-	return nil;
+	return result;
 
       end = type_suppression::insertion_range::create_integer_boundary(-1);
       type_suppression::insertion_range_sptr insert_range
@@ -1717,7 +1717,7 @@ read_type_suppression(const ini::config::section& section)
 		   type_suppression::insertion_range::create_fn_call_expr_boundary(ini::read_function_call_expr(str)))
 	    begin = expr;
 	  else
-	    return nil;
+	    return result;
 
 	  str = val->get_content()[1];
 	  if (str == "end")
@@ -1730,7 +1730,7 @@ read_type_suppression(const ini::config::section& section)
 		   type_suppression::insertion_range::create_fn_call_expr_boundary(ini::read_function_call_expr(str)))
 	    end = expr;
 	  else
-	    return nil;
+	    return result;
 
 	  type_suppression::insertion_range_sptr insert_range
 	    (new type_suppression::insertion_range(begin, end));
@@ -1741,7 +1741,7 @@ read_type_suppression(const ini::config::section& section)
 	// the 'has_data_member_inserted_between' property has a wrong
 	// value type, so let's discard the endire [suppress_type]
 	// section.
-	return nil;
+	return result;
     }
 
   // Support has_data_members_inserted_between
@@ -1792,7 +1792,7 @@ read_type_suppression(const ini::config::section& section)
 		   type_suppression::insertion_range::create_fn_call_expr_boundary(ini::read_function_call_expr(str)))
 	    begin = expr;
 	  else
-	    return nil;
+	    return result;
 
 	  str = list_value->get_content()[1];
 	  if (str == "end")
@@ -1805,7 +1805,7 @@ read_type_suppression(const ini::config::section& section)
 		   type_suppression::insertion_range::create_fn_call_expr_boundary(ini::read_function_call_expr(str)))
 	    end = expr;
 	  else
-	    return nil;
+	    return result;
 
 	  type_suppression::insertion_range_sptr insert_range
 	    (new type_suppression::insertion_range(begin, end));
@@ -1813,7 +1813,7 @@ read_type_suppression(const ini::config::section& section)
 	  consider_data_member_insertion = true;
 	}
       if (!is_well_formed)
-	return nil;
+	return result;
     }
 
   /// Support 'changed_enumerators = foo, bar, baz'
@@ -1851,59 +1851,58 @@ read_type_suppression(const ini::config::section& section)
       && !consider_type_kind
       && srcloc_not_regexp_str.empty()
       && srcloc_not_in.empty())
-    return nil;
+    return result;
+
+  result.reset(new type_suppression(label_str, name_regex_str, name_str));
 
-  type_suppression_sptr suppr(new type_suppression(label_str,
-						   name_regex_str,
-						   name_str));
   if (consider_type_kind)
     {
-      suppr->set_consider_type_kind(true);
-      suppr->set_type_kind(type_kind);
+      result->set_consider_type_kind(true);
+      result->set_type_kind(type_kind);
     }
 
   if (consider_reach_kind)
     {
-      suppr->set_consider_reach_kind(true);
-      suppr->set_reach_kind(reach_kind);
+      result->set_consider_reach_kind(true);
+      result->set_reach_kind(reach_kind);
     }
 
   if (consider_data_member_insertion)
-    suppr->set_data_member_insertion_ranges(insert_ranges);
+    result->set_data_member_insertion_ranges(insert_ranges);
 
   if (!name_not_regex_str.empty())
-    suppr->set_type_name_not_regex_str(name_not_regex_str);
+    result->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);
+    result->set_file_name_regex_str(file_name_regex_str);
 
   if (!file_name_not_regex_str.empty())
-    suppr->set_file_name_not_regex_str(file_name_not_regex_str);
+    result->set_file_name_not_regex_str(file_name_not_regex_str);
 
   if (!soname_regex_str.empty())
-    suppr->set_soname_regex_str(soname_regex_str);
+    result->set_soname_regex_str(soname_regex_str);
 
   if (!soname_not_regex_str.empty())
-    suppr->set_soname_not_regex_str(soname_not_regex_str);
+    result->set_soname_not_regex_str(soname_not_regex_str);
 
   if (!srcloc_not_in.empty())
-    suppr->set_source_locations_to_keep(srcloc_not_in);
+    result->set_source_locations_to_keep(srcloc_not_in);
 
   if (!srcloc_not_regexp_str.empty())
-    suppr->set_source_location_to_keep_regex_str(srcloc_not_regexp_str);
+    result->set_source_location_to_keep_regex_str(srcloc_not_regexp_str);
 
   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
       && ((!name_regex_str.empty()
 	   || !name_str.empty()
 	   || !srcloc_not_regexp_str.empty()
 	   || !srcloc_not_in.empty())))
-    suppr->set_drops_artifact_from_ir(true);
+    result->set_drops_artifact_from_ir(true);
 
-  if (suppr->get_type_kind() == type_suppression::ENUM_TYPE_KIND
+  if (result->get_type_kind() == type_suppression::ENUM_TYPE_KIND
       && !changed_enumerator_names.empty())
-    suppr->set_changed_enumerator_names(changed_enumerator_names);
+    result->set_changed_enumerator_names(changed_enumerator_names);
 
-  return suppr;
+  return result;
 }
 
 // <function_suppression stuff>
@@ -3158,10 +3157,10 @@ read_parameter_spec_from_string(const string& str)
 static function_suppression_sptr
 read_function_suppression(const ini::config::section& section)
 {
-  function_suppression_sptr nil;
+  function_suppression_sptr result;
 
   if (section.get_name() != "suppress_function")
-    return nil;
+    return result;
 
   ini::simple_property_sptr drop_artifact =
     is_simple_property(section.find_property("drop_artifact"));
@@ -3289,7 +3288,6 @@ read_function_suppression(const ini::config::section& section)
 	  parms.push_back(parm);
       }
 
-  function_suppression_sptr result;
   if (!label_str.empty()
       || !name.empty()
       || !name_regex_str.empty()
@@ -3306,6 +3304,7 @@ read_function_suppression(const ini::config::section& section)
       || !sym_version.empty()
       || !sym_ver_regex_str.empty()
       || !parms.empty())
+
     result.reset(new function_suppression(label_str, name,
 					  name_regex_str,
 					  return_type_name,
@@ -4343,6 +4342,7 @@ read_file_suppression(const ini::config::section& section)
       && soname_regex_str.empty()
       && soname_not_regex_str.empty())
     return result;
+
   result.reset(new file_suppression(label_str,
 				    file_name_regex_str,
 				    file_name_not_regex_str));
-- 
2.26.2.303.gf8c07b1a785-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v3 06/21] diff suppression: Fix handling of change kinds.
  2020-04-24  9:21 ` [PATCH v3 00/21]Simplify " Giuliano Procida
                     ` (4 preceding siblings ...)
  2020-04-24  9:21   ` [PATCH v3 05/21] abg-suppression.cc: More uniform variable naming Giuliano Procida
@ 2020-04-24  9:21   ` Giuliano Procida
  2020-04-24  9:21   ` [PATCH v3 07/21] Add POSIX regex wrapper functions Giuliano Procida
                     ` (15 subsequent siblings)
  21 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-24  9:21 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

When parsing suppression specifications, libabigail attempts to detect
and ignore suppressions that are empty and so would match everything
in their category by default.

Unfortunately, with the way the parser currently works, these checks
have to be against an exhaustive list of fields that matter, rather
than by listing the fields that don't (like label). They are fragile
in the face of changes that add new fields.

Two of the short-cut checks are in fact buggy, missing out the
change_kind field. One of the checks also risks a null pointer
dereference as it doesn't actually trigger a return from the function.

This patch eliminates (rather than fixes up) this short-cutting on the
grounds that it is a maintenance burden and inconsistent behaviour.
Users should be able to do this:

[suppress_variable]
  label = Suppress all changes to variables

We could reinstate the logic when the code has global knowledge of
which fields are present and which have no suppression (restriction)
semantics, or perhaps just emit a warning message to the user if they
have supplied a completely empty (no label even) specification.

The patch also corrects 4 affected test cases to reflect that
suppression is actually happening (according to change_kind).

	* src/abg-suppression.cc (read_type_suppression): Remove
	short-circuiting of useless suppressions.
	(read_function_suppression): Ditto.
	(read_variable_suppression: Ditto.
	(read_file_suppression): Ditto.
	tests/data/test-diff-suppr/test15-suppr-added-fn-report-5.txt:
	Fix test - something is actually suppressed.
	* tests/data/test-diff-suppr/test16-suppr-removed-fn-report-5.txt:
	Ditto.
	* tests/data/test-diff-suppr/test17-suppr-added-var-report-5.txt:
	Ditto.
	* tests/data/test-diff-suppr/test18-suppr-removed-var-report-5.txt:
	Ditto.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-suppression.cc                        | 91 +++++--------------
 .../test15-suppr-added-fn-report-5.txt        |  6 +-
 .../test16-suppr-removed-fn-report-5.txt      | 15 +--
 .../test17-suppr-added-var-report-5.txt       | 15 +--
 .../test18-suppr-removed-var-report-5.txt     | 15 +--
 5 files changed, 26 insertions(+), 116 deletions(-)

diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 2fbbd61b..831a61ef 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -1840,19 +1840,6 @@ read_type_suppression(const ini::config::section& section)
 	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()
-      && 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()
-      && srcloc_not_in.empty())
-    return result;
-
   result.reset(new type_suppression(label_str, name_regex_str, name_str));
 
   if (consider_type_kind)
@@ -3288,32 +3275,16 @@ read_function_suppression(const ini::config::section& section)
 	  parms.push_back(parm);
       }
 
-  if (!label_str.empty()
-      || !name.empty()
-      || !name_regex_str.empty()
-      || !name_not_regex_str.empty()
-      || !file_name_regex_str.empty()
-      || !file_name_not_regex_str.empty()
-      || !soname_regex_str.empty()
-      || !soname_not_regex_str.empty()
-      || !return_type_name.empty()
-      || !return_type_regex_str.empty()
-      || !sym_name.empty()
-      || !sym_name_regex_str.empty()
-      || !sym_name_not_regex_str.empty()
-      || !sym_version.empty()
-      || !sym_ver_regex_str.empty()
-      || !parms.empty())
-
-    result.reset(new function_suppression(label_str, name,
-					  name_regex_str,
-					  return_type_name,
-					  return_type_regex_str,
-					  parms,
-					  sym_name,
-					  sym_name_regex_str,
-					  sym_version,
-					  sym_ver_regex_str));
+  result.reset(new function_suppression(label_str,
+					name,
+					name_regex_str,
+					return_type_name,
+					return_type_regex_str,
+					parms,
+					sym_name,
+					sym_name_regex_str,
+					sym_version,
+					sym_ver_regex_str));
 
   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
       && (!name.empty()
@@ -3324,11 +3295,11 @@ read_function_suppression(const ini::config::section& section)
 	  || !sym_name_not_regex_str.empty()))
     result->set_drops_artifact_from_ir(true);
 
-  if (result && !change_kind_str.empty())
+  if (!change_kind_str.empty())
     result->set_change_kind
       (function_suppression::parse_change_kind(change_kind_str));
 
-  if (result && !allow_other_aliases.empty())
+  if (!allow_other_aliases.empty())
     result->set_allow_other_aliases(allow_other_aliases == "yes"
 				    || allow_other_aliases == "true");
 
@@ -4157,27 +4128,15 @@ read_variable_suppression(const ini::config::section& section)
     ? type_name_regex_prop->get_value()->as_string()
      : "";
 
-  if (label_str.empty()
-      && name_str.empty()
-      && name_regex_str.empty()
-      && name_not_regex_str.empty()
-      && file_name_regex_str.empty()
-      && file_name_not_regex_str.empty()
-      && soname_regex_str.empty()
-      && soname_not_regex_str.empty()
-      && symbol_name.empty()
-      && symbol_name_regex_str.empty()
-      && symbol_name_not_regex_str.empty()
-      && symbol_version.empty()
-      && symbol_version_regex_str.empty()
-      && type_name_str.empty()
-      && type_name_regex_str.empty())
-    return result;
-
-  result.reset(new variable_suppression(label_str, name_str, name_regex_str,
-					symbol_name, symbol_name_regex_str,
-					symbol_version, symbol_version_regex_str,
-					type_name_str, type_name_regex_str));
+  result.reset(new variable_suppression(label_str,
+					name_str,
+					name_regex_str,
+					symbol_name,
+					symbol_name_regex_str,
+					symbol_version,
+					symbol_version_regex_str,
+					type_name_str,
+					type_name_regex_str));
 
   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
       && (!name_str.empty()
@@ -4194,7 +4153,7 @@ read_variable_suppression(const ini::config::section& section)
   if (!symbol_name_not_regex_str.empty())
     result->set_symbol_name_not_regex_str(symbol_name_not_regex_str);
 
-  if (result && !change_kind_str.empty())
+  if (!change_kind_str.empty())
     result->set_change_kind
       (variable_suppression::parse_change_kind(change_kind_str));
 
@@ -4337,12 +4296,6 @@ read_file_suppression(const ini::config::section& section)
     ? soname_not_regex_prop->get_value()->as_string()
     : "";
 
-  if (file_name_regex_str.empty()
-      && file_name_not_regex_str.empty()
-      && soname_regex_str.empty()
-      && soname_not_regex_str.empty())
-    return result;
-
   result.reset(new file_suppression(label_str,
 				    file_name_regex_str,
 				    file_name_not_regex_str));
diff --git a/tests/data/test-diff-suppr/test15-suppr-added-fn-report-5.txt b/tests/data/test-diff-suppr/test15-suppr-added-fn-report-5.txt
index 4eaba5b7..83dfe326 100644
--- a/tests/data/test-diff-suppr/test15-suppr-added-fn-report-5.txt
+++ b/tests/data/test-diff-suppr/test15-suppr-added-fn-report-5.txt
@@ -1,10 +1,6 @@
-Functions changes summary: 0 Removed, 1 Changed, 1 Added functions
+Functions changes summary: 0 Removed, 1 Changed, 0 Added (1 filtered out) functions
 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 
-1 Added function:
-
-  [A] 'function void bar()'    {_Z3barv}
-
 1 function with some indirect sub-type change:
 
   [C] 'function void bar(S&)' has some indirect sub-type changes:
diff --git a/tests/data/test-diff-suppr/test16-suppr-removed-fn-report-5.txt b/tests/data/test-diff-suppr/test16-suppr-removed-fn-report-5.txt
index b28fbd16..851f7728 100644
--- a/tests/data/test-diff-suppr/test16-suppr-removed-fn-report-5.txt
+++ b/tests/data/test-diff-suppr/test16-suppr-removed-fn-report-5.txt
@@ -1,16 +1,3 @@
-Functions changes summary: 1 Removed, 1 Changed, 0 Added functions
+Functions changes summary: 0 Removed (1 filtered out), 0 Changed (1 filtered out), 0 Added functions
 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 
-1 Removed function:
-
-  [D] 'function void bar()'    {_Z3barv}
-
-1 function with some indirect sub-type change:
-
-  [C] 'function void bar(S*)' has some indirect sub-type changes:
-    parameter 1 of type 'S*' has sub-type changes:
-      in pointed to type 'struct S':
-        type size changed from 32 to 64 (in bits)
-        1 data member insertion:
-          'unsigned int S::bar', at offset 32 (in bits)
-
diff --git a/tests/data/test-diff-suppr/test17-suppr-added-var-report-5.txt b/tests/data/test-diff-suppr/test17-suppr-added-var-report-5.txt
index 6965a151..f4e0aa29 100644
--- a/tests/data/test-diff-suppr/test17-suppr-added-var-report-5.txt
+++ b/tests/data/test-diff-suppr/test17-suppr-added-var-report-5.txt
@@ -1,16 +1,3 @@
 Functions changes summary: 0 Removed, 0 Changed, 0 Added function
-Variables changes summary: 0 Removed, 1 Changed, 1 Added variables
-
-1 Added variable:
-
-  [A] 'int var1'    {var1}
-
-1 Changed variable:
-
-  [C] 'S* var0' was changed:
-    type of variable changed:
-      in pointed to type 'struct S':
-        type size changed from 32 to 64 (in bits)
-        1 data member insertion:
-          'char S::m1', at offset 32 (in bits)
+Variables changes summary: 0 Removed, 0 Changed (1 filtered out), 0 Added (1 filtered out) variables
 
diff --git a/tests/data/test-diff-suppr/test18-suppr-removed-var-report-5.txt b/tests/data/test-diff-suppr/test18-suppr-removed-var-report-5.txt
index 3edf2bd1..ac380a4a 100644
--- a/tests/data/test-diff-suppr/test18-suppr-removed-var-report-5.txt
+++ b/tests/data/test-diff-suppr/test18-suppr-removed-var-report-5.txt
@@ -1,16 +1,3 @@
 Functions changes summary: 0 Removed, 0 Changed, 0 Added function
-Variables changes summary: 1 Removed, 1 Changed, 0 Added variables
-
-1 Removed variable:
-
-  [D] 'int var1'    {var1}
-
-1 Changed variable:
-
-  [C] 'S* var0' was changed:
-    type of variable changed:
-      in pointed to type 'struct S':
-        type size changed from 32 to 64 (in bits)
-        1 data member insertion:
-          'char S::m1', at offset 32 (in bits)
+Variables changes summary: 0 Removed (1 filtered out), 0 Changed (1 filtered out), 0 Added variables
 
-- 
2.26.2.303.gf8c07b1a785-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v3 07/21] Add POSIX regex wrapper functions.
  2020-04-24  9:21 ` [PATCH v3 00/21]Simplify " Giuliano Procida
                     ` (5 preceding siblings ...)
  2020-04-24  9:21   ` [PATCH v3 06/21] diff suppression: Fix handling of change kinds Giuliano Procida
@ 2020-04-24  9:21   ` Giuliano Procida
  2020-04-27 11:23     ` Matthias Maennich
  2020-04-24  9:21   ` [PATCH v3 08/21] Use regex::compile wrapper instead of regcomp Giuliano Procida
                     ` (14 subsequent siblings)
  21 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-04-24  9:21 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

libabigail code uses the POSIX regex library consistently:

    - compile std::string to regex, with the flag REG_EXTENDED
    - store regex using a shared pointer wrapper
    - check match of regex against std::string

All the C string / std::string logic and so on is repeated at every
call site. This patch introduces wrapper functions to take care of
this logic.

There are no behavioural changes.

	* include/abg-regex.h (compile): Declare new function.
	(match): Declare new function.
	* src/abg-regex.cc (compile): Add new function wrapping
	regcomp. (match): Add new function wrapping regexec.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 include/abg-regex.h |  6 ++++++
 src/abg-regex.cc    | 41 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git a/include/abg-regex.h b/include/abg-regex.h
index 59976794..c7951a8f 100644
--- a/include/abg-regex.h
+++ b/include/abg-regex.h
@@ -71,6 +71,12 @@ operator<<(std::ostream& os, const escape& esc);
 std::string
 generate_from_strings(const std::vector<std::string>& strs);
 
+regex_t_sptr
+compile(const std::string& str);
+
+bool
+match(const regex_t_sptr& r, const std::string& str);
+
 }// end namespace regex
 
 /// Specialization of sptr_utils::build_sptr for regex_t.
diff --git a/src/abg-regex.cc b/src/abg-regex.cc
index 90e4d144..7e5277e2 100644
--- a/src/abg-regex.cc
+++ b/src/abg-regex.cc
@@ -23,11 +23,22 @@
 /// Some specialization for shared pointer utility templates.
 ///
 
+#include "config.h"
+
 #include <sstream>
 #include <ostream>
+
+#include "abg-internal.h"
+
+// <headers defining libabigail's API go under here>
+ABG_BEGIN_EXPORT_DECLARATIONS
+
 #include "abg-sptr-utils.h"
 #include "abg-regex.h"
 
+ABG_END_EXPORT_DECLARATIONS
+// </headers defining libabigail's API>
+
 namespace abigail
 {
 
@@ -101,6 +112,36 @@ generate_from_strings(const std::vector<std::string>& strs)
   return os.str();
 }
 
+/// Compile a regex from a string.
+///
+/// The result is held in a shared pointer. This will be null if regex
+/// compilation fails.
+///
+/// @param str the string representation of the regex.
+///
+/// @return shared pointer holder of a compiled regex object.
+regex_t_sptr
+compile(const std::string& str)
+{
+  regex_t_sptr r = sptr_utils::build_sptr(new regex_t);
+  if (regcomp(r.get(), str.c_str(), REG_EXTENDED))
+    r.reset();
+  return r;
+}
+
+/// See if a string matches a regex.
+///
+/// @param r a shared pointer holder of a compiled regex object.
+///
+/// @param str a string.
+///
+/// @return whether there was a match.
+bool
+match(const regex_t_sptr& r, const std::string& str)
+{
+  return !regexec(r.get(), str.c_str(), 0, NULL, 0);
+}
+
 }//end namespace regex
 
 }//end namespace abigail
-- 
2.26.2.303.gf8c07b1a785-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v3 08/21] Use regex::compile wrapper instead of regcomp.
  2020-04-24  9:21 ` [PATCH v3 00/21]Simplify " Giuliano Procida
                     ` (6 preceding siblings ...)
  2020-04-24  9:21   ` [PATCH v3 07/21] Add POSIX regex wrapper functions Giuliano Procida
@ 2020-04-24  9:21   ` Giuliano Procida
  2020-04-27 11:34     ` Matthias Maennich
  2020-04-24  9:21   ` [PATCH v3 09/21] Use regex::match wrapper instead of regexec Giuliano Procida
                     ` (13 subsequent siblings)
  21 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-04-24  9:21 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

This patch eliminates all calls to regcomp except that by
regex::compile itself.

	* src/abg-corpus-priv.h: Mechanically substitute use of
	regcomp with regex::compile wrapper.
	* src/abg-suppression-priv.h: Ditto.

There are no behavioural changes.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-corpus-priv.h      |  16 +--
 src/abg-suppression-priv.h | 198 ++++++-------------------------------
 2 files changed, 38 insertions(+), 176 deletions(-)

diff --git a/src/abg-corpus-priv.h b/src/abg-corpus-priv.h
index e65f7c8f..544fac54 100644
--- a/src/abg-corpus-priv.h
+++ b/src/abg-corpus-priv.h
@@ -123,8 +123,8 @@ public:
 	     i != fns_suppress_regexps_.end();
 	     ++i)
 	  {
-	    regex_t_sptr r = sptr_utils::build_sptr(new regex_t);
-	    if (regcomp(r.get(), i->c_str(), REG_EXTENDED) == 0)
+	    regex_t_sptr r = regex::compile(*i);
+	    if (r)
 	      compiled_fns_suppress_regexp_.push_back(r);
 	  }
       }
@@ -145,8 +145,8 @@ public:
 	     i != fns_keep_regexps_.end();
 	     ++i)
 	  {
-	    regex_t_sptr r = sptr_utils::build_sptr(new regex_t);
-	    if (regcomp(r.get(), i->c_str(), REG_EXTENDED) == 0)
+	    regex_t_sptr r = regex::compile(*i);
+	    if (r)
 	      compiled_fns_keep_regexps_.push_back(r);
 	  }
       }
@@ -167,8 +167,8 @@ public:
 	     i != vars_suppress_regexps_.end();
 	     ++i)
 	  {
-	    regex_t_sptr r = sptr_utils::build_sptr(new regex_t);
-	    if (regcomp(r.get(), i->c_str(), REG_EXTENDED) == 0)
+	    regex_t_sptr r = regex::compile(*i);
+	    if (r)
 	      compiled_vars_suppress_regexp_.push_back(r);
 	  }
       }
@@ -189,8 +189,8 @@ public:
 	     i != vars_keep_regexps_.end();
 	     ++i)
 	  {
-	    regex_t_sptr r = sptr_utils::build_sptr(new regex_t);
-	    if (regcomp(r.get(), i->c_str(), REG_EXTENDED) == 0)
+	    regex_t_sptr r = regex::compile(*i);
+	    if (r)
 	      compiled_vars_keep_regexps_.push_back(r);
 	  }
       }
diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
index c37ceff6..4959cdbb 100644
--- a/src/abg-suppression-priv.h
+++ b/src/abg-suppression-priv.h
@@ -91,17 +91,8 @@ public:
   const regex::regex_t_sptr&
   get_file_name_regex() const
   {
-    if (!file_name_regex_)
-      {
-	if (!file_name_regex_str_.empty())
-	  {
-	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	    if (regcomp(r.get(),
-			file_name_regex_str_.c_str(),
-			REG_EXTENDED) == 0)
-	      file_name_regex_ = r;
-	  }
-      }
+    if (!file_name_regex_ && !file_name_regex_str_.empty())
+      file_name_regex_ = regex::compile(file_name_regex_str_);
     return file_name_regex_;
   }
 
@@ -116,17 +107,8 @@ public:
   const regex::regex_t_sptr&
   get_file_name_not_regex() const
   {
-    if (!file_name_not_regex_)
-      {
-	if (!file_name_not_regex_str_.empty())
-	  {
-	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	    if (regcomp(r.get(),
-			file_name_not_regex_str_.c_str(),
-			REG_EXTENDED) == 0)
-	      file_name_not_regex_ = r;
-	  }
-      }
+    if (!file_name_not_regex_ && !file_name_not_regex_str_.empty())
+      file_name_not_regex_ = regex::compile(file_name_not_regex_str_);
     return file_name_not_regex_;
   }
 
@@ -141,17 +123,8 @@ public:
   const regex::regex_t_sptr&
   get_soname_regex() const
   {
-    if (!soname_regex_)
-      {
-	if (!soname_regex_str_.empty())
-	  {
-	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	    if (regcomp(r.get(),
-			soname_regex_str_.c_str(),
-			REG_EXTENDED) == 0)
-	      soname_regex_ = r;
-	  }
-      }
+    if (!soname_regex_ && !soname_regex_str_.empty())
+      soname_regex_ = regex::compile(soname_regex_str_);
     return soname_regex_;
   }
 
@@ -166,17 +139,8 @@ public:
   const regex::regex_t_sptr&
   get_soname_not_regex() const
   {
-    if (!soname_not_regex_)
-      {
-	if (!soname_not_regex_str_.empty())
-	  {
-	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	    if (regcomp(r.get(),
-			soname_not_regex_str_.c_str(),
-			REG_EXTENDED) == 0)
-	      soname_not_regex_ = r;
-	  }
-      }
+    if (!soname_not_regex_ && !soname_not_regex_str_.empty())
+      soname_not_regex_ = regex::compile(soname_not_regex_str_);
     return soname_not_regex_;
   }
 
@@ -282,13 +246,7 @@ class function_suppression::parameter_spec::priv
   get_type_name_regex() const
   {
     if (!type_name_regex_ && !type_name_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    type_name_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  type_name_regex_ = r;
-      }
+      type_name_regex_ = regex::compile(type_name_regex_str_);
     return type_name_regex_;
   }
 }; // end class function_suppression::parameter_spec::priv
@@ -361,13 +319,7 @@ struct function_suppression::priv
   get_name_regex() const
   {
     if (!name_regex_ && !name_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    name_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  name_regex_ = r;
-      }
+      name_regex_ = regex::compile(name_regex_str_);
     return name_regex_;
   }
 
@@ -384,13 +336,7 @@ struct function_suppression::priv
   get_name_not_regex() const
   {
     if (!name_not_regex_ && !name_not_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    name_not_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  name_not_regex_ = r;
-      }
+      name_not_regex_ = regex::compile(name_not_regex_str_);
     return name_not_regex_;
   }
 
@@ -407,13 +353,7 @@ struct function_suppression::priv
   get_return_type_regex() const
   {
     if (!return_type_regex_ && !return_type_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    return_type_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  return_type_regex_ = r;
-      }
+      return_type_regex_ = regex::compile(return_type_regex_str_);
     return return_type_regex_;
   }
 
@@ -430,13 +370,7 @@ struct function_suppression::priv
   get_symbol_name_regex() const
   {
     if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    symbol_name_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  symbol_name_regex_ = r;
-      }
+      symbol_name_regex_ = regex::compile(symbol_name_regex_str_);
     return symbol_name_regex_;
   }
 
@@ -453,13 +387,7 @@ struct function_suppression::priv
   get_symbol_name_not_regex() const
   {
     if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    symbol_name_not_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  symbol_name_not_regex_ = r;
-      }
+      symbol_name_not_regex_ = regex::compile(symbol_name_not_regex_str_);
     return symbol_name_not_regex_;
   }
 
@@ -475,14 +403,8 @@ struct function_suppression::priv
   const regex::regex_t_sptr
   get_symbol_version_regex() const
   {
-    if (!symbol_version_regex_ && ! symbol_version_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    symbol_version_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  symbol_version_regex_ = r;
-      }
+    if (!symbol_version_regex_ && !symbol_version_regex_str_.empty())
+      symbol_version_regex_ = regex::compile(symbol_version_regex_str_);
     return symbol_version_regex_;
   }
 }; // end class function_suppression::priv
@@ -609,13 +531,7 @@ struct variable_suppression::priv
   get_name_regex() const
   {
     if (!name_regex_ && !name_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    name_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  name_regex_ = r;
-      }
+      name_regex_ = regex::compile(name_regex_str_);
     return name_regex_;
   }
 
@@ -632,13 +548,7 @@ struct variable_suppression::priv
   get_name_not_regex() const
   {
     if (!name_not_regex_ && !name_not_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    name_not_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  name_not_regex_ = r;
-      }
+      name_not_regex_ = regex::compile(name_not_regex_str_);
     return name_not_regex_;
   }
 
@@ -655,13 +565,7 @@ struct variable_suppression::priv
   get_symbol_name_regex() const
   {
     if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    symbol_name_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  symbol_name_regex_ = r;
-      }
+      symbol_name_regex_ = regex::compile(symbol_name_regex_str_);
     return symbol_name_regex_;
   }
 
@@ -678,12 +582,7 @@ struct variable_suppression::priv
   get_symbol_name_not_regex() const
   {
     if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(), symbol_name_not_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  symbol_name_not_regex_ = r;
-      }
+      symbol_name_not_regex_ = regex::compile(symbol_name_not_regex_str_);
     return symbol_name_not_regex_;
   }
 
@@ -700,13 +599,7 @@ struct variable_suppression::priv
   get_symbol_version_regex()  const
   {
     if (!symbol_version_regex_ && !symbol_version_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    symbol_version_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  symbol_version_regex_ = r;
-      }
+      symbol_version_regex_ = regex::compile(symbol_version_regex_str_);
     return symbol_version_regex_;
   }
 
@@ -723,13 +616,7 @@ struct variable_suppression::priv
   get_type_name_regex() const
   {
     if (!type_name_regex_ && !type_name_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    type_name_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  type_name_regex_ = r;
-      }
+      type_name_regex_ = regex::compile(type_name_regex_str_);
     return type_name_regex_;
   }
 };// end class variable_supppression::priv
@@ -809,17 +696,8 @@ public:
   const regex::regex_t_sptr
   get_type_name_regex() const
   {
-    if (!type_name_regex_)
-      {
-	if (!type_name_regex_str_.empty())
-	  {
-	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	    if (regcomp(r.get(),
-			type_name_regex_str_.c_str(),
-			REG_EXTENDED) == 0)
-	      type_name_regex_ = r;
-	  }
-      }
+    if (!type_name_regex_ && !type_name_regex_str_.empty())
+      type_name_regex_ = regex::compile(type_name_regex_str_);
     return type_name_regex_;
   }
 
@@ -841,17 +719,8 @@ public:
   const regex::regex_t_sptr
   get_type_name_not_regex() const
   {
-    if (!type_name_not_regex_)
-      {
-	if (!type_name_not_regex_str_.empty())
-	  {
-	    regex::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;
-	  }
-      }
+    if (!type_name_not_regex_ && !type_name_not_regex_str_.empty())
+      type_name_not_regex_ = regex::compile(type_name_not_regex_str_);
     return type_name_not_regex_;
   }
 
@@ -886,17 +755,10 @@ public:
   const regex::regex_t_sptr
   get_source_location_to_keep_regex() const
   {
-    if (!source_location_to_keep_regex_)
-      {
-	if (!source_location_to_keep_regex_str_.empty())
-	  {
-	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	    if (regcomp(r.get(),
-			source_location_to_keep_regex_str_.c_str(),
-			REG_EXTENDED) == 0)
-	      source_location_to_keep_regex_ = r;
-	  }
-      }
+    if (!source_location_to_keep_regex_
+	&& !source_location_to_keep_regex_str_.empty())
+      source_location_to_keep_regex_ =
+	  regex::compile(source_location_to_keep_regex_str_);
     return source_location_to_keep_regex_;
   }
 
-- 
2.26.2.303.gf8c07b1a785-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v3 09/21] Use regex::match wrapper instead of regexec.
  2020-04-24  9:21 ` [PATCH v3 00/21]Simplify " Giuliano Procida
                     ` (7 preceding siblings ...)
  2020-04-24  9:21   ` [PATCH v3 08/21] Use regex::compile wrapper instead of regcomp Giuliano Procida
@ 2020-04-24  9:21   ` Giuliano Procida
  2020-04-27 11:38     ` Matthias Maennich
  2020-04-24  9:21   ` [PATCH v3 10/21] Refactor read_parameter_spec_from_string logic Giuliano Procida
                     ` (12 subsequent siblings)
  21 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-04-24  9:21 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

This patch eliminates all calls to regexec except that by regex::match
itself.

There are no behavioural changes.

	* src/abg-corpus-priv.h: Mechanically substitute use of
	regexec with regex::match wrapper.
	* src/abg-suppression-priv.h: Ditto.
	* src/abg-suppression.cc: Ditto.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-corpus-priv.h      |   8 +--
 src/abg-suppression-priv.h |  10 ++--
 src/abg-suppression.cc     | 119 +++++++++++--------------------------
 3 files changed, 44 insertions(+), 93 deletions(-)

diff --git a/src/abg-corpus-priv.h b/src/abg-corpus-priv.h
index 544fac54..2618e2d0 100644
--- a/src/abg-corpus-priv.h
+++ b/src/abg-corpus-priv.h
@@ -521,7 +521,7 @@ public:
 	   compiled_regex_fns_suppress().begin();
 	 i != compiled_regex_fns_suppress().end();
 	 ++i)
-      if (regexec(i->get(), frep.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(*i, frep))
 	{
 	  keep = false;
 	  break;
@@ -554,7 +554,7 @@ public:
 	     compiled_regex_fns_keep().begin();
 	   i != compiled_regex_fns_keep().end();
 	   ++i)
-	if (regexec(i->get(), frep.c_str(), 0, NULL, 0) == 0)
+	if (regex::match(*i, frep))
 	  {
 	    keep = true;
 	    break;
@@ -628,7 +628,7 @@ public:
 	   compiled_regex_vars_suppress().begin();
 	 i != compiled_regex_vars_suppress().end();
 	 ++i)
-      if (regexec(i->get(), frep.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(*i, frep))
 	{
 	  keep = false;
 	  break;
@@ -662,7 +662,7 @@ public:
 	       compiled_regex_vars_keep().begin();
 	     i != compiled_regex_vars_keep().end();
 	     ++i)
-	  if (regexec(i->get(), frep.c_str(), 0, NULL, 0) == 0)
+	  if (regex::match(*i, frep))
 	    {
 	      keep = true;
 	      break;
diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
index 4959cdbb..8043ebd9 100644
--- a/src/abg-suppression-priv.h
+++ b/src/abg-suppression-priv.h
@@ -160,14 +160,14 @@ public:
     if (regex::regex_t_sptr regexp = get_soname_regex())
       {
 	has_regexp = true;
-	if (regexec(regexp.get(), soname.c_str(), 0, NULL, 0) != 0)
+	if (!regex::match(regexp, soname))
 	  return false;
       }
 
     if (regex::regex_t_sptr regexp = get_soname_not_regex())
       {
 	has_regexp = true;
-	if (regexec(regexp.get(), soname.c_str(), 0, NULL, 0) == 0)
+	if (regex::match(regexp, soname))
 	  return false;
       }
 
@@ -195,16 +195,14 @@ public:
     if (regex::regex_t_sptr regexp = get_file_name_regex())
       {
 	has_regexp = true;
-	if (regexec(regexp.get(), binary_name.c_str(),
-	  0, NULL, 0) != 0)
+	if (!regex::match(regexp, binary_name))
 	  return false;
       }
 
     if (regex::regex_t_sptr regexp = get_file_name_not_regex())
       {
 	has_regexp = true;
-	if (regexec(regexp.get(), binary_name.c_str(),
-	  0, NULL, 0) == 0)
+	if (regex::match(regexp, binary_name))
 	  return false;
       }
 
diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 831a61ef..73e422a3 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -994,18 +994,14 @@ suppression_matches_type_name(const type_suppression&	s,
 	  if (const 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)
+	      if (!regex::match(type_name_regex, type_name))
 		return false;
 	    }
 
 	  if (const 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)
+	      if (regex::match(type_name_not_regex, type_name))
 		return false;
 	    }
 	}
@@ -1052,7 +1048,7 @@ suppression_matches_type_location(const type_suppression&	s,
       loc.expand(loc_path, loc_line, loc_column);
 
       if (regex_t_sptr regexp = s.priv_->get_source_location_to_keep_regex())
-	if (regexec(regexp.get(), loc_path.c_str(), 0, NULL, 0) == 0)
+	if (regex::match(regexp, loc_path))
 	  return false;
 
       tools_utils::base_name(loc_path, loc_path_base);
@@ -2489,9 +2485,7 @@ function_suppression::suppresses_function(const function_decl* fn,
   const regex_t_sptr name_regex = priv_->get_name_regex();
   if (name_regex)
     {
-      if (regexec(name_regex.get(),
-		  fname.c_str(),
-		  0, NULL, 0) != 0)
+      if (!regex::match(name_regex, fname))
 	return false;
 
       if (get_allow_other_aliases()
@@ -2512,9 +2506,7 @@ function_suppression::suppresses_function(const function_decl* fn,
 	      for (elf_symbol_sptr a = sym->get_next_alias();
 		   a && !a->is_main_symbol();
 		   a = a->get_next_alias())
-		if (regexec(name_regex.get(),
-			    a->get_name().c_str(),
-			    0, NULL, 0) != 0)
+		if (!regex::match(name_regex, a->get_name()))
 		  return false;
 	    }
 	}
@@ -2524,9 +2516,7 @@ function_suppression::suppresses_function(const function_decl* fn,
   const regex_t_sptr name_not_regex = priv_->get_name_not_regex();
   if (name_not_regex)
     {
-      if (regexec(name_not_regex.get(),
-		  fname.c_str(),
-		  0, NULL, 0) == 0)
+      if (regex::match(name_not_regex, fname))
 	return false;
 
       if (get_allow_other_aliases()
@@ -2547,9 +2537,7 @@ function_suppression::suppresses_function(const function_decl* fn,
 	      for (elf_symbol_sptr a = sym->get_next_alias();
 		   a && !a->is_main_symbol();
 		   a = a->get_next_alias())
-		if (regexec(name_regex.get(),
-			    a->get_name().c_str(),
-			    0, NULL, 0) == 0)
+		if (regex::match(name_regex, a->get_name()))
 		  return false;
 	    }
 	}
@@ -2573,9 +2561,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     {
       const regex_t_sptr return_type_regex = priv_->get_return_type_regex();
       if (return_type_regex
-	  && (regexec(return_type_regex.get(),
-		      fn_return_type_name.c_str(),
-		      0, NULL, 0) != 0))
+	  && !regex::match(return_type_regex, fn_return_type_name))
 	return false;
     }
 
@@ -2612,18 +2598,13 @@ function_suppression::suppresses_function(const function_decl* fn,
   else if (sym)
     {
       const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
-      if (symbol_name_regex
-	  && (regexec(symbol_name_regex.get(),
-		      fn_sym_name.c_str(),
-		      0, NULL, 0) != 0))
+      if (symbol_name_regex && !regex::match(symbol_name_regex, fn_sym_name))
 	return false;
 
       const regex_t_sptr symbol_name_not_regex =
 	priv_->get_symbol_name_not_regex();
       if (symbol_name_not_regex
-	  && (regexec(symbol_name_not_regex.get(),
-		      fn_sym_name.c_str(),
-		      0, NULL, 0) == 0))
+	  && regex::match(symbol_name_not_regex, fn_sym_name))
 	return false;
 
       if (get_allow_other_aliases())
@@ -2638,15 +2619,11 @@ function_suppression::suppresses_function(const function_decl* fn,
 		   a = a->get_next_alias())
 		{
 		  if (symbol_name_regex
-		      && (regexec(symbol_name_regex.get(),
-				  a->get_name().c_str(),
-				  0, NULL, 0) != 0))
+		      && !regex::match(symbol_name_regex, a->get_name()))
 		    return false;
 
 		  if (symbol_name_not_regex
-		      && (regexec(symbol_name_not_regex.get(),
-				  a->get_name().c_str(),
-				  0, NULL, 0) == 0))
+		      && regex::match(symbol_name_not_regex, a->get_name()))
 		    return false;
 		}
 	    }
@@ -2665,9 +2642,7 @@ function_suppression::suppresses_function(const function_decl* fn,
       const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
       if (symbol_version_regex
-	  && (regexec(symbol_version_regex.get(),
-		      fn_sym_version.c_str(),
-		      0, NULL, 0) != 0))
+	  && !regex::match(symbol_version_regex, fn_sym_version))
 	return false;
     }
 
@@ -2708,9 +2683,8 @@ function_suppression::suppresses_function(const function_decl* fn,
 		(*p)->priv_->get_type_name_regex();
 	      if (parm_type_name_regex)
 		{
-		  if ((regexec(parm_type_name_regex.get(),
-			       fn_parm_type_qualified_name.c_str(),
-			       0, NULL, 0) != 0))
+		  if (!regex::match(parm_type_name_regex,
+				    fn_parm_type_qualified_name))
 		    return false;
 		}
 	    }
@@ -2798,10 +2772,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
   else if (!get_symbol_name_regex_str().empty())
     {
       const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
-      if (symbol_name_regex
-	  && (regexec(symbol_name_regex.get(),
-		      sym_name.c_str(),
-		      0, NULL, 0) != 0))
+      if (symbol_name_regex && !regex::match(symbol_name_regex, sym_name))
 	return false;
     }
   else
@@ -2818,9 +2789,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
       const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
       if (symbol_version_regex
-	  && (regexec(symbol_version_regex.get(),
-		      sym_version.c_str(),
-		      0, NULL, 0) != 0))
+	  && !regex::match(symbol_version_regex, sym_version))
 	return false;
     }
   else
@@ -2912,12 +2881,12 @@ suppression_matches_function_name(const suppr::function_suppression& s,
 {
   if (regex_t_sptr regexp = s.priv_->get_name_regex())
     {
-      if (regexec(regexp.get(), fn_name.c_str(), 0, NULL, 0) != 0)
+      if (!regex::match(regexp, fn_name))
 	return false;
     }
   else if (regex_t_sptr regexp = s.priv_->get_name_not_regex())
     {
-      if (regexec(regexp.get(), fn_name.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(regexp, fn_name))
 	return false;
     }
   else if (s.priv_->name_.empty())
@@ -2948,12 +2917,12 @@ suppression_matches_function_sym_name(const suppr::function_suppression& s,
 {
   if (regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
     {
-      if (regexec(regexp.get(), fn_linkage_name.c_str(), 0, NULL, 0) != 0)
+      if (!regex::match(regexp, fn_linkage_name))
 	return false;
     }
   else if (regex_t_sptr regexp = s.priv_->get_symbol_name_not_regex())
     {
-      if (regexec(regexp.get(), fn_linkage_name.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(regexp, fn_linkage_name))
 	return false;
     }
   else if (s.priv_->symbol_name_.empty())
@@ -2981,12 +2950,12 @@ suppression_matches_variable_name(const suppr::variable_suppression& s,
 {
   if (regex_t_sptr regexp = s.priv_->get_name_regex())
     {
-      if (regexec(regexp.get(), var_name.c_str(), 0, NULL, 0) != 0)
+      if (!regex::match(regexp, var_name))
 	return false;
     }
   else if (regex_t_sptr regexp = s.priv_->get_name_not_regex())
     {
-      if (regexec(regexp.get(), var_name.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(regexp, var_name))
 	return false;
     }
   else if (s.priv_->name_.empty())
@@ -3015,13 +2984,13 @@ suppression_matches_variable_sym_name(const suppr::variable_suppression& s,
 {
   if (regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
     {
-      if (regexec(regexp.get(), var_linkage_name.c_str(), 0, NULL, 0) != 0)
+      if (!regex::match(regexp, var_linkage_name))
 	return false;
     }
   else if (regex_t_sptr regexp =
 	   s.priv_->get_symbol_name_not_regex())
     {
-      if (regexec(regexp.get(), var_linkage_name.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(regexp, var_linkage_name))
 	return false;
     }
   else if (s.priv_->symbol_name_.empty())
@@ -3050,7 +3019,7 @@ suppression_matches_type(const suppr::type_suppression& s,
 {
   if (regex_t_sptr regexp = s.priv_->get_type_name_regex())
     {
-      if (regexec(regexp.get(), type_name.c_str(), 0, NULL, 0) != 0)
+      if (!regex::match(regexp, type_name))
 	return false;
     }
   else if (!s.get_type_name().empty())
@@ -3748,15 +3717,11 @@ variable_suppression::suppresses_variable(const var_decl* var,
       if (get_name().empty())
 	{
 	  const regex_t_sptr name_regex = priv_->get_name_regex();
-	  if (name_regex
-	      && (regexec(name_regex.get(), var_name.c_str(),
-			  0, NULL, 0) != 0))
+	  if (name_regex && !regex::match(name_regex, var_name))
 	    return false;
 
 	  const regex_t_sptr name_not_regex = priv_->get_name_not_regex();
-	  if (name_not_regex
-	      && (regexec(name_not_regex.get(), var_name.c_str(),
-			  0, NULL, 0) == 0))
+	  if (name_not_regex && regex::match(name_not_regex, var_name))
 	    return false;
 	}
     }
@@ -3772,16 +3737,12 @@ variable_suppression::suppresses_variable(const var_decl* var,
   else
     {
       const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
-      if (sym_name_regex
-	  && (regexec(sym_name_regex.get(), var_sym_name.c_str(),
-		      0, NULL, 0) != 0))
+      if (sym_name_regex && !regex::match(sym_name_regex, var_sym_name))
 	return false;
 
       const regex_t_sptr sym_name_not_regex =
 	priv_->get_symbol_name_not_regex();
-      if (sym_name_not_regex
-	  && (regexec(sym_name_not_regex.get(), var_sym_name.c_str(),
-		      0, NULL, 0) == 0))
+      if (sym_name_not_regex && regex::match(sym_name_not_regex, var_sym_name))
 	return false;
     }
 
@@ -3798,9 +3759,7 @@ variable_suppression::suppresses_variable(const var_decl* var,
       const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
       if (symbol_version_regex
-	  && (regexec(symbol_version_regex.get(),
-		      var_sym_version.c_str(),
-		      0, NULL, 0) != 0))
+	  && !regex::match(symbol_version_regex, var_sym_version))
 	return false;
     }
 
@@ -3818,9 +3777,7 @@ variable_suppression::suppresses_variable(const var_decl* var,
       if (get_type_name().empty())
 	{
 	  const regex_t_sptr type_name_regex = priv_->get_type_name_regex();
-	  if (type_name_regex
-	      && (regexec(type_name_regex.get(), var_type_name.c_str(),
-			  0, NULL, 0) != 0))
+	  if (type_name_regex && !regex::match(type_name_regex, var_type_name))
 	    return false;
 	}
     }
@@ -3911,9 +3868,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
   else if (!get_symbol_name_regex_str().empty())
     {
       const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
-      if (sym_name_regex
-	  && (regexec(sym_name_regex.get(), sym_name.c_str(),
-		      0, NULL, 0) != 0))
+      if (sym_name_regex && !regex::match(sym_name_regex, sym_name))
 	return false;
     }
   else
@@ -3931,9 +3886,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
       const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
       if (symbol_version_regex
-	  && (regexec(symbol_version_regex.get(),
-		      sym_version.c_str(),
-		      0, NULL, 0) != 0))
+	  && !regex::match(symbol_version_regex, sym_version))
 	return false;
     }
   else
@@ -4229,14 +4182,14 @@ file_suppression::suppresses_file(const string& file_path)
   if (regex_t_sptr regexp = suppression_base::priv_->get_file_name_regex())
     {
       has_regexp = true;
-      if (regexec(regexp.get(), fname.c_str(), 0, NULL, 0) != 0)
+      if (!regex::match(regexp, fname))
 	return false;
     }
 
   if (regex_t_sptr regexp = suppression_base::priv_->get_file_name_not_regex())
     {
       has_regexp = true;
-      if (regexec(regexp.get(), fname.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(regexp, fname))
 	return false;
     }
 
-- 
2.26.2.303.gf8c07b1a785-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v3 10/21] Refactor read_parameter_spec_from_string logic.
  2020-04-24  9:21 ` [PATCH v3 00/21]Simplify " Giuliano Procida
                     ` (8 preceding siblings ...)
  2020-04-24  9:21   ` [PATCH v3 09/21] Use regex::match wrapper instead of regexec Giuliano Procida
@ 2020-04-24  9:21   ` Giuliano Procida
  2020-04-24  9:21   ` [PATCH v3 11/21] Compile suppression regexes earlier Giuliano Procida
                     ` (11 subsequent siblings)
  21 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-24  9:21 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

This function extracts either a string or a regex from the same input.
This patch simplifies the string vs regex conditional logic, in order
to make following patches simpler.

There are no behavioural changes.

	* src/abg-suppression.cc (read_parameter_spec_from_string):
	Use separate string and regex variables to simplify the
	creation of returned parameter specification.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-suppression.cc | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 73e422a3..c389ed02 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -3090,13 +3090,15 @@ read_parameter_spec_from_string(const string& str)
 
   if (!index_str.empty() || !type_name.empty())
     {
-      function_suppression::parameter_spec* p;
+      std::string type_name_regex;
       if (is_regex)
-	p = new function_suppression::parameter_spec(atoi(index_str.c_str()),
-						     "", type_name);
-      else
-	p = new function_suppression::parameter_spec(atoi(index_str.c_str()),
-						     type_name, "");
+	{
+	  type_name_regex = type_name;
+	  type_name.clear();
+	}
+      function_suppression::parameter_spec* p =
+	new function_suppression::parameter_spec(atoi(index_str.c_str()),
+						 type_name, type_name_regex);
       result.reset(p);
     }
 
-- 
2.26.2.303.gf8c07b1a785-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v3 11/21] Compile suppression regexes earlier.
  2020-04-24  9:21 ` [PATCH v3 00/21]Simplify " Giuliano Procida
                     ` (9 preceding siblings ...)
  2020-04-24  9:21   ` [PATCH v3 10/21] Refactor read_parameter_spec_from_string logic Giuliano Procida
@ 2020-04-24  9:21   ` Giuliano Procida
  2020-04-24  9:21   ` [PATCH v3 12/21] Reduce direct access to suppression priv_ members Giuliano Procida
                     ` (10 subsequent siblings)
  21 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-24  9:21 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

Regexes are used in suppression specifications for various things.
They are currently compiled on first use, rather than on construction
of the specifications.

This patches changes the suppression specification types to hold
compiled regexes directly which is a significant simplification and is
a prerequisite for early error reporting.

There are no behavioural changes.

	* include/abg-suppression.h (suppression_base): In
	constructor, take regex arguments as regex_t_sptr. Replace all
	set_*_regex_str and get_*_regex_str methods with set_*_regex
	and get_*_regex methods.
	(type_suppression): In constructor, take regex arguments as
	regex_t_sptr. Replace all set_*_regex_str and get_*_regex_str
	methods with set_*_regex and get_*_regex methods.
	(function_suppression): In constructor, take regex arguments
	as regex_t_sptr. Replace all set_*_regex_str and
	get_*_regex_str methods with set_*_regex and get_*_regex
	methods.
	(function_suppression::parameter_spec): In constructor, take
	regex arguments as regex_t_sptr. Replace all set_*_regex_str and
	get_*_regex_str methods with set_*_regex and get_*_regex
	methods.
	(variable_suppression): In constructor, take regex arguments
	as regex_t_sptr. Replace all set_*_regex_str and get_*_regex_str
	methods with set_*_regex and get_*_regex methods.
	(file_suppression): In constructor, take regex arguments
	as regex_t_sptr.
	* src/abg-suppression-priv.h (suppression_base::priv): Drop
	all *_regex_str_ members. Drop mutable qualifier on
	all *_regex_ members. In constructor, take regexes instead of
	strings for regex arguments. Update all get_*_regex methods to
	remove regex compilation and update comments.
	(function_suppression::parameter_spec::priv): Drop
	all *_regex_str_ members. Drop mutable qualifier on
	all *_regex_ members. In constructor, take regexes instead of
	strings for regex arguments. Update get_*_regex methods to
	remove regex compilation and update comments.
	(function_suppression::priv): Drop all *_regex_str_ members.
	Drop mutable qualifier on all *_regex_ members. In constructor,
	take regexes instead of strings for regex arguments. Update
	all get_*_regex methods to remove regex compilation and
	update comments.
	(variable_suppression::priv): Drop all *_regex_str_ members.
	Drop mutable qualifier on all *_regex_ members. In
	constructor, take regexes instead of strings for regex
	arguments. Update all get_*_regex methods to remove
	regex compilation and update comments.
	(type_suppression::priv): Drop all *_regex_str_ members.
	Drop mutable qualifier on all *_regex_ members. In constructor,
	take regexes instead of strings for regex arguments. Update
	all get_*_regex methods to remove regex compilation and
	update comments. Drop set_type_name_regex_str and
	get_type_name_regex_str methods.
	* src/abg-suppression.cc (suppression_base): In constructor,
	take regexes instead of strings for regex arguments. Replace
	all set_*_regex_str and get_*_regex_str methods with
	set_*_regex and get_*_regex methods. Update
	has_file_name_related_property and has_soname_related_property
	methods.
	(type_suppression): In constructor, take regexes instead of
	strings for regex arguments. Replace all set_*_regex_str and
	get_*_regex_str methods with set_*_regex and get_*_regex
	methods. Update has_file_name_related_property and
	has_soname_related_property methods.
	(read_type_suppression): Compile regexes instead of keeping
	them as strings. Pass them to type_suppression constructor and
	setters.
	(function_suppression::parameter_spec): In constructor, take
	regexes instead of strings for regex arguments. Replace all
	set_*_regex_str and get_*_regex_str methods with set_*_regex and
	get_*_regex methods.
	(function_suppression): In constructor, take regexes instead
	of strings for regex arguments. Replace all set_*_regex_str
	and get_*_regex_str methods with set_*_regex and get_*_regex
	methods. Update suppresses_function_symbol method.
	(read_parameter_spec_from_string): Change type of
	type_name_regex from string to regex and compile when needed.
	(read_function_suppression): Compile regexes instead of
	keeping them as strings. Pass them to function_suppression
	constructor and setters.
	(variable_suppression): In constructor, take regexes instead
	of strings for regex arguments. Replace all set_*_regex_str
	and get_*_regex_str methods with set_*_regex and get_*_regex
	methods.
	(file_suppression): In constructor, take regexes instead of
	strings for regex arguments. Replace all set_*_regex_str and
	get_*_regex_str methods with set_*_regex and get_*_regex
	methods.
	* src/abg-tools-utils.cc (handle_file_entry): Compile and
	check regex for /usr/include.
	(gen_suppr_spec_from_kernel_abi_whitelists):
	Compile and check whitelisting regex.
	* tests/test-kmi-whitelist.cc (random_symbols) Add array of
	symbols. (test_suppressions_are_consistent): Rework to test by
	matching regexes against symbols, now that uncompiled regex
	strings are no longer available.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 include/abg-suppression.h   | 165 ++++-----
 src/abg-suppression-priv.h  | 357 ++++---------------
 src/abg-suppression.cc      | 694 ++++++++++++++++++------------------
 src/abg-tools-utils.cc      |  17 +-
 tests/test-kmi-whitelist.cc |  60 +++-
 5 files changed, 583 insertions(+), 710 deletions(-)

diff --git a/include/abg-suppression.h b/include/abg-suppression.h
index 4f1fb417..1869cbe5 100644
--- a/include/abg-suppression.h
+++ b/include/abg-suppression.h
@@ -26,6 +26,7 @@
 #include "abg-cxx-compat.h"
 #include "abg-ini.h"
 #include "abg-comparison.h"
+#include "abg-regex.h"
 
 namespace abigail
 {
@@ -64,8 +65,8 @@ public:
   suppression_base(const string& label);
 
   suppression_base(const string& label,
-		   const string& file_name_regex_str,
-		   const string& file_name_not_regex_str);
+		   const regex::regex_t_sptr& file_name_regex,
+		   const regex::regex_t_sptr& file_name_not_regex);
 
   bool
   get_drops_artifact_from_ir() const;
@@ -86,31 +87,31 @@ public:
   set_label(const string&);
 
   void
-  set_file_name_regex_str(const string& regexp);
+  set_file_name_regex(const regex::regex_t_sptr& regexp);
 
-  const string&
-  get_file_name_regex_str() const;
+  const regex::regex_t_sptr&
+  get_file_name_regex() const;
 
   void
-  set_file_name_not_regex_str(const string& regexp);
+  set_file_name_not_regex(const regex::regex_t_sptr& regexp);
 
-  const string&
-  get_file_name_not_regex_str() const;
+  const regex::regex_t_sptr&
+  get_file_name_not_regex() const;
 
   bool
   has_file_name_related_property() const;
 
   void
-  set_soname_regex_str(const string& regexp);
+  set_soname_regex(const regex::regex_t_sptr& regexp);
 
-  const string&
-  get_soname_regex_str() const;
+  const regex::regex_t_sptr&
+  get_soname_regex() const;
 
   void
-  set_soname_not_regex_str(const string& regexp);
+  set_soname_not_regex(const regex::regex_t_sptr& regexp);
 
-  const string&
-  get_soname_not_regex_str() const;
+  const regex::regex_t_sptr&
+  get_soname_not_regex() const;
 
   bool
   has_soname_related_property() const;
@@ -204,22 +205,22 @@ public:
   typedef vector<insertion_range_sptr> insertion_ranges;
 
   type_suppression(const string& label,
-		   const string& type_name_regexp,
+		   const regex::regex_t_sptr& type_name_regexp,
 		   const string& type_name);
 
   virtual ~type_suppression();
 
   void
-  set_type_name_regex_str(const string& name_regex_str);
+  set_type_name_regex(const regex::regex_t_sptr& name_regex);
 
-  const string&
-  get_type_name_regex_str() const;
+  const regex::regex_t_sptr&
+  get_type_name_regex() const;
 
   void
-  set_type_name_not_regex_str(const string& name_regex_str);
+  set_type_name_not_regex(const regex::regex_t_sptr& name_regex);
 
-  const string&
-  get_type_name_not_regex_str() const;
+  const regex::regex_t_sptr&
+  get_type_name_not_regex() const;
 
   void
   set_type_name(const string& name);
@@ -269,11 +270,11 @@ public:
   void
   set_source_locations_to_keep(const unordered_set<string>&);
 
-  const string&
-  get_source_location_to_keep_regex_str() const;
+  const regex::regex_t_sptr&
+  get_source_location_to_keep_regex() const;
 
   void
-  set_source_location_to_keep_regex_str(const string&);
+  set_source_location_to_keep_regex(const regex::regex_t_sptr&);
 
   const vector<string>&
   get_changed_enumerator_names() const;
@@ -460,16 +461,16 @@ public:
 
   function_suppression();
 
-  function_suppression(const string&		label,
-		       const string&		name,
-		       const string&		name_regex,
-		       const string&		return_type_name,
-		       const string&		return_type_regex,
-		       parameter_specs_type&	parm_specs,
-		       const string&		symbol_name,
-		       const string&		symbol_name_regex,
-		       const string&		symbol_version,
-		       const string&		symbol_version_regex_str);
+  function_suppression(const string&			label,
+		       const string&			name,
+		       const regex::regex_t_sptr&	name_regex,
+		       const string&			return_type_name,
+		       const regex::regex_t_sptr&	return_type_regex,
+		       parameter_specs_type&		parm_specs,
+		       const string&			symbol_name,
+		       const regex::regex_t_sptr&	symbol_name_regex,
+		       const string&			symbol_version,
+		       const regex::regex_t_sptr&	symbol_version_regex);
 
   virtual ~function_suppression();
 
@@ -488,17 +489,17 @@ public:
   void
   set_name(const string&);
 
-  const string&
-  get_name_regex_str() const;
+  const regex::regex_t_sptr&
+  get_name_regex() const;
 
   void
-  set_name_regex_str(const string&);
+  set_name_regex(const regex::regex_t_sptr&);
 
-  const string&
-  get_name_not_regex_str() const;
+  const regex::regex_t_sptr&
+  get_name_not_regex() const;
 
   void
-  set_name_not_regex_str(const string&);
+  set_name_not_regex(const regex::regex_t_sptr&);
 
   const string&
   get_return_type_name() const;
@@ -506,11 +507,11 @@ public:
   void
   set_return_type_name(const string&);
 
-  const string&
-  get_return_type_regex_str() const;
+  const regex::regex_t_sptr&
+  get_return_type_regex() const;
 
   void
-  set_return_type_regex_str(const string& r);
+  set_return_type_regex(const regex::regex_t_sptr& r);
 
   const parameter_specs_type&
   get_parameter_specs() const;
@@ -527,17 +528,17 @@ public:
   void
   set_symbol_name(const string& n);
 
-  const string&
-  get_symbol_name_regex_str() const;
+  const regex::regex_t_sptr&
+  get_symbol_name_regex() const;
 
   void
-  set_symbol_name_regex_str(const string&);
+  set_symbol_name_regex(const regex::regex_t_sptr&);
 
-  const string&
-  get_symbol_name_not_regex_str() const;
+  const regex::regex_t_sptr&
+  get_symbol_name_not_regex() const;
 
   void
-  set_symbol_name_not_regex_str(const string&);
+  set_symbol_name_not_regex(const regex::regex_t_sptr&);
 
   const string&
   get_symbol_version() const;
@@ -545,11 +546,11 @@ public:
   void
   set_symbol_version(const string&);
 
-  const string&
-  get_symbol_version_regex_str() const;
+  const regex::regex_t_sptr&
+  get_symbol_version_regex() const;
 
   void
-  set_symbol_version_regex_str(const string&);
+  set_symbol_version_regex(const regex::regex_t_sptr&);
 
   bool
   get_allow_other_aliases() const;
@@ -609,7 +610,7 @@ class function_suppression::parameter_spec
 public:
   parameter_spec(size_t index,
 		 const string& type_name,
-		 const string& type_name_regex);
+		 const regex::regex_t_sptr& type_name_regex);
 
   size_t
   get_index() const;
@@ -623,11 +624,11 @@ public:
   void
   set_parameter_type_name(const string&);
 
-  const string&
-  get_parameter_type_name_regex_str() const;
+  const regex::regex_t_sptr&
+  get_parameter_type_name_regex() const;
 
   void
-  set_parameter_type_name_regex_str(const string&);
+  set_parameter_type_name_regex(const regex::regex_t_sptr&);
 };// end class function_suppression::parameter_spec
 
 class variable_suppression;
@@ -679,13 +680,17 @@ public:
 
   variable_suppression(const string& label = "",
 		       const string& name = "",
-		       const string& name_regex_str = "",
+		       const regex::regex_t_sptr& name_regex =
+			 regex::regex_t_sptr(),
 		       const string& symbol_name = "",
-		       const string& symbol_name_regex_str = "",
+		       const regex::regex_t_sptr& symbol_name_regex =
+			 regex::regex_t_sptr(),
 		       const string& symbol_version = "",
-		       const string& symbol_version_regex_str = "",
+		       const regex::regex_t_sptr& symbol_version_regex =
+			 regex::regex_t_sptr(),
 		       const string& type_name = "",
-		       const string& type_name_regex_str = "");
+		       const regex::regex_t_sptr& type_name_regex =
+			 regex::regex_t_sptr());
 
   virtual ~variable_suppression();
 
@@ -704,17 +709,17 @@ public:
   void
   set_name(const string&);
 
-  const string&
-  get_name_regex_str() const;
+  const regex::regex_t_sptr&
+  get_name_regex() const;
 
   void
-  set_name_regex_str(const string&);
+  set_name_regex(const regex::regex_t_sptr&);
 
-  const string&
-  get_name_not_regex_str() const;
+  const regex::regex_t_sptr&
+  get_name_not_regex() const;
 
   void
-  set_name_not_regex_str(const string&);
+  set_name_not_regex(const regex::regex_t_sptr&);
 
   const string&
   get_symbol_name() const;
@@ -722,17 +727,17 @@ public:
   void
   set_symbol_name(const string&);
 
-  const string&
-  get_symbol_name_regex_str() const;
+  const regex::regex_t_sptr&
+  get_symbol_name_regex() const;
 
   void
-  set_symbol_name_regex_str(const string&);
+  set_symbol_name_regex(const regex::regex_t_sptr&);
 
-  const string&
-  get_symbol_name_not_regex_str() const;
+  const regex::regex_t_sptr&
+  get_symbol_name_not_regex() const;
 
   void
-  set_symbol_name_not_regex_str(const string&);
+  set_symbol_name_not_regex(const regex::regex_t_sptr&);
 
   const string&
   get_symbol_version() const;
@@ -740,11 +745,11 @@ public:
   void
   set_symbol_version(const string&);
 
-  const string&
-  get_symbol_version_regex_str() const;
+  const regex::regex_t_sptr&
+  get_symbol_version_regex() const;
 
   void
-  set_symbol_version_regex_str(const string&);
+  set_symbol_version_regex(const regex::regex_t_sptr&);
 
   const string&
   get_type_name() const;
@@ -752,11 +757,11 @@ public:
   void
   set_type_name(const string&);
 
-  const string&
-  get_type_name_regex_str() const;
+  const regex::regex_t_sptr&
+  get_type_name_regex() const;
 
   void
-  set_type_name_regex_str(const string&);
+  set_type_name_regex(const regex::regex_t_sptr&);
 
   bool
   suppresses_diff(const diff* d) const;
@@ -816,8 +821,8 @@ class file_suppression: public suppression_base
 public:
 
   file_suppression(const string& label,
-		   const string& file_name_regex,
-		   const string& file_name_not_regex);
+		   const regex::regex_t_sptr& file_name_regex,
+		   const regex::regex_t_sptr& file_name_not_regex);
 
   virtual bool
   suppresses_diff(const diff* diff) const;
diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
index 8043ebd9..263052d4 100644
--- a/src/abg-suppression-priv.h
+++ b/src/abg-suppression-priv.h
@@ -47,14 +47,10 @@ class suppression_base::priv
   bool					is_artificial_;
   bool					drops_artifact_;
   string				label_;
-  string				file_name_regex_str_;
-  mutable regex::regex_t_sptr		file_name_regex_;
-  string				file_name_not_regex_str_;
-  mutable regex::regex_t_sptr		file_name_not_regex_;
-  string				soname_regex_str_;
-  mutable regex::regex_t_sptr		soname_regex_;
-  string				soname_not_regex_str_;
-  mutable regex::regex_t_sptr		soname_not_regex_;
+  regex::regex_t_sptr			file_name_regex_;
+  regex::regex_t_sptr			file_name_not_regex_;
+  regex::regex_t_sptr			soname_regex_;
+  regex::regex_t_sptr			soname_not_regex_;
 
 public:
   priv()
@@ -69,78 +65,46 @@ public:
   {}
 
   priv(const string& label,
-       const string& file_name_regex_str,
-       const string& file_name_not_regex_str)
+       const regex::regex_t_sptr& file_name_regex,
+       const regex::regex_t_sptr& file_name_not_regex)
     : is_artificial_(),
       drops_artifact_(),
       label_(label),
-      file_name_regex_str_(file_name_regex_str),
-      file_name_not_regex_str_(file_name_not_regex_str)
+      file_name_regex_(file_name_regex),
+      file_name_not_regex_(file_name_not_regex)
   {}
 
   friend class suppression_base;
 
-  /// Get the regular expression object associated to the 'file_name_regex'
-  /// property of @ref suppression_base.
-  ///
-  /// If the regular expression object is not created, this method
-  /// creates it and returns it.
-  ///
-  /// If the 'file_name_regex' property of @ref suppression_base is
-  /// empty then this method returns nil.
+  /// Get the regular expression object associated to the
+  /// 'file_name_regex' property of @ref suppression_base.
   const regex::regex_t_sptr&
   get_file_name_regex() const
   {
-    if (!file_name_regex_ && !file_name_regex_str_.empty())
-      file_name_regex_ = regex::compile(file_name_regex_str_);
     return file_name_regex_;
   }
 
   /// Get the regular expression object associated to the
   /// 'file_name_not_regex' property of @ref suppression_base.
-  ///
-  /// If the regular expression object is not created, this method
-  /// creates it and returns it.
-  ///
-  /// If the 'file_name_not_regex' property of @ref suppression_base
-  /// is empty then this method returns nil.
   const regex::regex_t_sptr&
   get_file_name_not_regex() const
   {
-    if (!file_name_not_regex_ && !file_name_not_regex_str_.empty())
-      file_name_not_regex_ = regex::compile(file_name_not_regex_str_);
     return file_name_not_regex_;
   }
 
-  /// Get the regular expression object associated to the
-  /// 'soname_regex' property of @ref suppression_base.
-  ///
-  /// If the regular expression object is not created, this method
-  /// creates it and returns it.
-  ///
-  /// If the 'soname_regex' property of @ref suppression_base is empty
-  /// then this method returns nil.
+  /// Get the regular expression object associated to the 'soname_regex'
+  /// property of @ref suppression_base.
   const regex::regex_t_sptr&
   get_soname_regex() const
   {
-    if (!soname_regex_ && !soname_regex_str_.empty())
-      soname_regex_ = regex::compile(soname_regex_str_);
     return soname_regex_;
   }
 
   /// Get the regular expression object associated to the
   /// 'soname_not_regex' property of @ref suppression_base.
-  ///
-  /// If the regular expression object is not created, this method
-  /// creates it and returns it.
-  ///
-  /// If the 'soname_not_regex' property of @ref suppression_base is
-  /// empty then this method returns nil.
   const regex::regex_t_sptr&
   get_soname_not_regex() const
   {
-    if (!soname_not_regex_ && !soname_not_regex_str_.empty())
-      soname_not_regex_ = regex::compile(soname_not_regex_str_);
     return soname_not_regex_;
   }
 
@@ -225,8 +189,7 @@ class function_suppression::parameter_spec::priv
 
   size_t				index_;
   string				type_name_;
-  string				type_name_regex_str_;
-  mutable regex::regex_t_sptr		type_name_regex_;
+  regex::regex_t_sptr			type_name_regex_;
 
   priv()
     : index_()
@@ -236,15 +199,16 @@ class function_suppression::parameter_spec::priv
     : index_(i), type_name_(tn)
   {}
 
-  priv(size_t i, const string& tn, const string& tn_regex)
-    : index_(i), type_name_(tn), type_name_regex_str_(tn_regex)
+  priv(size_t i, const string& tn, const regex::regex_t_sptr& tn_regex)
+    : index_(i), type_name_(tn), type_name_regex_(tn_regex)
   {}
 
+  /// Get the regular expression object associated to the
+  /// 'type_name_regex' property of @ref
+  /// function_suppression::parameter_spec.
   const regex::regex_t_sptr
   get_type_name_regex() const
   {
-    if (!type_name_regex_ && !type_name_regex_str_.empty())
-      type_name_regex_ = regex::compile(type_name_regex_str_);
     return type_name_regex_;
   }
 }; // end class function_suppression::parameter_spec::priv
@@ -258,22 +222,16 @@ struct function_suppression::priv
 
   change_kind				change_kind_;
   string				name_;
-  string				name_regex_str_;
-  mutable regex::regex_t_sptr		name_regex_;
-  string				name_not_regex_str_;
-  mutable regex::regex_t_sptr		name_not_regex_;
+  regex::regex_t_sptr			name_regex_;
+  regex::regex_t_sptr			name_not_regex_;
   string				return_type_name_;
-  string				return_type_regex_str_;
-  mutable regex::regex_t_sptr		return_type_regex_;
+  regex::regex_t_sptr			return_type_regex_;
   parameter_specs_type			parm_specs_;
   string				symbol_name_;
-  string				symbol_name_regex_str_;
-  mutable regex::regex_t_sptr		symbol_name_regex_;
-  string				symbol_name_not_regex_str_;
-  mutable regex::regex_t_sptr		symbol_name_not_regex_;
+  regex::regex_t_sptr			symbol_name_regex_;
+  regex::regex_t_sptr			symbol_name_not_regex_;
   string				symbol_version_;
-  string				symbol_version_regex_str_;
-  mutable regex::regex_t_sptr		symbol_version_regex_;
+  regex::regex_t_sptr			symbol_version_regex_;
   bool					allow_other_aliases_;
 
   priv():
@@ -282,127 +240,72 @@ struct function_suppression::priv
   {}
 
   priv(const string&			name,
-       const string&			name_regex_str,
+       const regex::regex_t_sptr&	name_regex,
        const string&			return_type_name,
-       const string&			return_type_regex_str,
+       const regex::regex_t_sptr&	return_type_regex,
        const parameter_specs_type&	parm_specs,
        const string&			symbol_name,
-       const string&			symbol_name_regex_str,
+       const regex::regex_t_sptr&	symbol_name_regex,
        const string&			symbol_version,
-       const string&			symbol_version_regex_str)
+       const regex::regex_t_sptr&	symbol_version_regex)
     : change_kind_(ALL_CHANGE_KIND),
       name_(name),
-      name_regex_str_(name_regex_str),
+      name_regex_(name_regex),
       return_type_name_(return_type_name),
-      return_type_regex_str_(return_type_regex_str),
+      return_type_regex_(return_type_regex),
       parm_specs_(parm_specs),
       symbol_name_(symbol_name),
-      symbol_name_regex_str_(symbol_name_regex_str),
+      symbol_name_regex_(symbol_name_regex),
       symbol_version_(symbol_version),
-      symbol_version_regex_str_(symbol_version_regex_str),
+      symbol_version_regex_(symbol_version_regex),
       allow_other_aliases_(true)
   {}
 
-
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// function_suppression::priv::name_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// function_suppression::priv::name_regex_str_..
+  /// Get the regular expression object associated to the 'name_regex'
+  /// property of @ref function_suppression.
   const regex::regex_t_sptr
   get_name_regex() const
   {
-    if (!name_regex_ && !name_regex_str_.empty())
-      name_regex_ = regex::compile(name_regex_str_);
     return name_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// function_suppression::priv::name_not_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// function_suppression::priv::name_not_regex_str_..
+  /// Get the regular expression object associated to the
+  /// 'name_not_regex' property of @ref function_suppression.
   const regex::regex_t_sptr
   get_name_not_regex() const
   {
-    if (!name_not_regex_ && !name_not_regex_str_.empty())
-      name_not_regex_ = regex::compile(name_not_regex_str_);
     return name_not_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// function_suppression::priv::return_type_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// function_suppression::priv::return_type_regex_str_.
+  /// Get the regular expression object associated to the
+  /// 'return_type_regex' property of @ref function_suppression.
   const regex::regex_t_sptr
   get_return_type_regex() const
   {
-    if (!return_type_regex_ && !return_type_regex_str_.empty())
-      return_type_regex_ = regex::compile(return_type_regex_str_);
     return return_type_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// function_suppression::priv::symbol_name_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// function_suppression::priv::symbol_name_regex_str_.
+  /// Get the regular expression object associated to the
+  /// 'symbol_name_regex' property of @ref function_suppression.
   const regex::regex_t_sptr
   get_symbol_name_regex() const
   {
-    if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
-      symbol_name_regex_ = regex::compile(symbol_name_regex_str_);
     return symbol_name_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// function_suppression::priv::symbol_name_not_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// function_suppression::priv::symbol_name_not_regex_str_.
+  /// Get the regular expression object associated to the
+  /// 'symbol_name_not_regex' property of @ref function_suppression.
   const regex::regex_t_sptr
   get_symbol_name_not_regex() const
   {
-    if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
-      symbol_name_not_regex_ = regex::compile(symbol_name_not_regex_str_);
     return symbol_name_not_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// function_suppression::priv::symbol_version_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// function_suppression::priv::symbol_version_regex_str_.
+  /// Get the regular expression object associated to the
+  /// 'symbol_version_regex' property of @ref function_suppression.
   const regex::regex_t_sptr
   get_symbol_version_regex() const
   {
-    if (!symbol_version_regex_ && !symbol_version_regex_str_.empty())
-      symbol_version_regex_ = regex::compile(symbol_version_regex_str_);
     return symbol_version_regex_;
   }
 }; // end class function_suppression::priv
@@ -481,140 +384,80 @@ struct variable_suppression::priv
 
   change_kind				change_kind_;
   string				name_;
-  string				name_regex_str_;
-  mutable regex::regex_t_sptr		name_regex_;
-  string				name_not_regex_str_;
-  mutable regex::regex_t_sptr		name_not_regex_;
+  regex::regex_t_sptr			name_regex_;
+  regex::regex_t_sptr			name_not_regex_;
   string				symbol_name_;
-  string				symbol_name_regex_str_;
-  mutable regex::regex_t_sptr		symbol_name_regex_;
-  string				symbol_name_not_regex_str_;
-  mutable regex::regex_t_sptr		symbol_name_not_regex_;
+  regex::regex_t_sptr			symbol_name_regex_;
+  regex::regex_t_sptr			symbol_name_not_regex_;
   string				symbol_version_;
-  string				symbol_version_regex_str_;
-  mutable regex::regex_t_sptr		symbol_version_regex_;
+  regex::regex_t_sptr			symbol_version_regex_;
   string				type_name_;
-  string				type_name_regex_str_;
-  mutable regex::regex_t_sptr		type_name_regex_;
+  regex::regex_t_sptr			type_name_regex_;
 
   priv(const string& name,
-       const string& name_regex_str,
+       const regex::regex_t_sptr& name_regex,
        const string& symbol_name,
-       const string& symbol_name_regex_str,
+       const regex::regex_t_sptr& symbol_name_regex,
        const string& symbol_version,
-       const string& symbol_version_regex_str,
+       const regex::regex_t_sptr& symbol_version_regex,
        const string& type_name,
-       const string& type_name_regex_str)
+       const regex::regex_t_sptr& type_name_regex)
     : change_kind_(ALL_CHANGE_KIND),
       name_(name),
-      name_regex_str_(name_regex_str),
+      name_regex_(name_regex),
       symbol_name_(symbol_name),
-      symbol_name_regex_str_(symbol_name_regex_str),
+      symbol_name_regex_(symbol_name_regex),
       symbol_version_(symbol_version),
-      symbol_version_regex_str_(symbol_version_regex_str),
+      symbol_version_regex_(symbol_version_regex),
       type_name_(type_name),
-      type_name_regex_str_(type_name_regex_str)
+      type_name_regex_(type_name_regex)
   {}
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// variable_suppression::priv::name_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// variable_suppression::priv::name_regex_str_.
+  /// Get the regular expression object associated to the 'name_regex'
+  /// property of @ref variable_suppression.
   const regex::regex_t_sptr
   get_name_regex() const
   {
-    if (!name_regex_ && !name_regex_str_.empty())
-      name_regex_ = regex::compile(name_regex_str_);
     return name_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// variable_suppression::priv::name_not_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// variable_suppression::priv::name_not_regex_str_..
+  /// Get the regular expression object associated to the
+  /// 'name_not_regex' property of @ref variable_suppression.
   const regex::regex_t_sptr
   get_name_not_regex() const
   {
-    if (!name_not_regex_ && !name_not_regex_str_.empty())
-      name_not_regex_ = regex::compile(name_not_regex_str_);
     return name_not_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// variable_suppression::priv::symbol_name_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// variable_suppression::priv::symbol_name_regex_str_.
+  /// Get the regular expression object associated to the
+  /// 'symbol_name_regex' property of @ref variable_suppression.
   const regex::regex_t_sptr
   get_symbol_name_regex() const
   {
-    if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
-      symbol_name_regex_ = regex::compile(symbol_name_regex_str_);
     return symbol_name_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// variable_suppression::priv::symbol_name_not_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// variable_suppression::priv::symbol_name_not_regex_str_.
+  /// Get the regular expression object associated to the
+  /// 'symbol_name_not_regex' property of @ref variable_suppression.
   const regex::regex_t_sptr
   get_symbol_name_not_regex() const
   {
-    if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
-      symbol_name_not_regex_ = regex::compile(symbol_name_not_regex_str_);
     return symbol_name_not_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// variable_suppression::priv::symbol_version_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// variable_suppression::priv::symbol_version_regex_str_.
+  /// Get the regular expression object associated to the
+  /// 'symbol_version_regex' property of @ref variable_suppression.
   const regex::regex_t_sptr
   get_symbol_version_regex()  const
   {
-    if (!symbol_version_regex_ && !symbol_version_regex_str_.empty())
-      symbol_version_regex_ = regex::compile(symbol_version_regex_str_);
     return symbol_version_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// variable_suppression::priv::type_name_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// variable_suppression::priv::type_name_regex_str_.
+  /// Get the regular expression object associated to the
+  /// 'type_name_regex' property of @ref variable_suppression.
   const regex::regex_t_sptr
   get_type_name_regex() const
   {
-    if (!type_name_regex_ && !type_name_regex_str_.empty())
-      type_name_regex_ = regex::compile(type_name_regex_str_);
     return type_name_regex_;
   }
 };// end class variable_supppression::priv
@@ -651,31 +494,28 @@ variable_is_suppressed(const ReadContextType&	ctxt,
 /// The private data for @ref type_suppression.
 class type_suppression::priv
 {
-  string				type_name_regex_str_;
-  mutable regex::regex_t_sptr		type_name_regex_;
+  regex::regex_t_sptr			type_name_regex_;
   string				type_name_;
-  string				type_name_not_regex_str_;
-  mutable regex::regex_t_sptr		type_name_not_regex_;
+  regex::regex_t_sptr			type_name_not_regex_;
   bool					consider_type_kind_;
   type_suppression::type_kind		type_kind_;
   bool					consider_reach_kind_;
   type_suppression::reach_kind		reach_kind_;
   type_suppression::insertion_ranges	insertion_ranges_;
   unordered_set<string>			source_locations_to_keep_;
-  string				source_location_to_keep_regex_str_;
-  mutable regex::regex_t_sptr		source_location_to_keep_regex_;
+  regex::regex_t_sptr			source_location_to_keep_regex_;
   mutable vector<string>		changed_enumerator_names_;
 
   priv();
 
 public:
-  priv(const string&			type_name_regexp,
+  priv(const regex::regex_t_sptr&	type_name_regexp,
        const string&			type_name,
        bool				consider_type_kind,
        type_suppression::type_kind	type_kind,
        bool				consider_reach_kind,
        type_suppression::reach_kind	reach_kind)
-    : type_name_regex_str_(type_name_regexp),
+    : type_name_regex_(type_name_regexp),
       type_name_(type_name),
       consider_type_kind_(consider_type_kind),
       type_kind_(type_kind),
@@ -683,19 +523,11 @@ public:
       reach_kind_(reach_kind)
   {}
 
-  /// Get the regular expression object associated to the 'type_name_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_regex' property of @ref type_suppression is
-  /// empty then this method returns nil.
+  /// Get the regular expression object associated to the
+  /// 'type_name_regex' property of @ref type_suppression.
   const regex::regex_t_sptr
   get_type_name_regex() const
   {
-    if (!type_name_regex_ && !type_name_regex_str_.empty())
-      type_name_regex_ = regex::compile(type_name_regex_str_);
     return type_name_regex_;
   }
 
@@ -708,17 +540,9 @@ public:
 
   /// 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 regex::regex_t_sptr
   get_type_name_not_regex() const
   {
-    if (!type_name_not_regex_ && !type_name_not_regex_str_.empty())
-      type_name_not_regex_ = regex::compile(type_name_not_regex_str_);
     return type_name_not_regex_;
   }
 
@@ -729,34 +553,11 @@ public:
   set_type_name_not_regex(regex::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.
+  /// Get the regular expression object associated to the
+  /// 'source_location_to_keep_regex' property of @ref type_suppression.
   const regex::regex_t_sptr
   get_source_location_to_keep_regex() const
   {
-    if (!source_location_to_keep_regex_
-	&& !source_location_to_keep_regex_str_.empty())
-      source_location_to_keep_regex_ =
-	  regex::compile(source_location_to_keep_regex_str_);
     return source_location_to_keep_regex_;
   }
 
diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index c389ed02..6953c18b 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -66,17 +66,17 @@ suppression_base::suppression_base(const string& label)
 /// @param a label for the suppression.  This represents just a
 /// comment.
 ///
-/// @param file_name_regex_str the regular expression that denotes the
+/// @param file_name_regex the regular expression that denotes the
 /// file name to match.
 ///
-/// @param file_name_not_regex_str the regular expression that denotes
+/// @param file_name_not_regex the regular expression that denotes
 /// the file name to *NOT* match.
 suppression_base::suppression_base(const string& label,
-				   const string& file_name_regex_str,
-				   const string& file_name_not_regex_str)
+				   const regex_t_sptr& file_name_regex,
+				   const regex_t_sptr& file_name_not_regex)
   : priv_(new priv(label,
-		   file_name_regex_str,
-		   file_name_not_regex_str))
+		   file_name_regex,
+		   file_name_not_regex))
 {
 }
 
@@ -138,52 +138,50 @@ suppression_base::set_label(const string& label)
 /// Setter for the "file_name_regex" property of the current instance
 /// of @ref suppression_base.
 ///
-/// The "file_name_regex" property is a regular expression string that
+/// The "file_name_regex" property is a regular expression that
 /// designates the file name that contains the ABI artifact this
 /// suppression should apply to.
 ///
-/// @param regexp the new regular expression string.
+/// @param regexp the new regular expression.
 void
-suppression_base::set_file_name_regex_str(const string& regexp)
-{priv_->file_name_regex_str_ = regexp;}
+suppression_base::set_file_name_regex(const regex_t_sptr& regexp)
+{priv_->file_name_regex_ = regexp;}
 
 /// Getter for the "file_name_regex" property of the current instance
 /// of @ref suppression_base.
 ///
-/// The "file_name_regex" property is a regular expression string that
+/// The "file_name_regex" property is a regular expression that
 /// designates the file name that contains the ABI artifacts this
 /// suppression should apply to.
 ///
-/// @return the regular expression string.
-const string&
-suppression_base::get_file_name_regex_str() const
-{return priv_->file_name_regex_str_;}
+/// @return the regular expression.
+const regex_t_sptr&
+suppression_base::get_file_name_regex() const
+{return priv_->file_name_regex_;}
 
 /// Setter for the "file_name_not_regex" property of the current
 /// instance of @ref suppression_base.
 ///
 /// The current suppression specification should apply to ABI
 /// artifacts of a file which name does *NOT* match the regular
-/// expression string designated by the "file_name_not_regex"
-/// property.
+/// expression designated by the "file_name_not_regex" property.
 ///
-/// @param regexp the new regular expression string.
+/// @param regexp the new regular expression.
 void
-suppression_base::set_file_name_not_regex_str(const string& regexp)
-{priv_->file_name_not_regex_str_ = regexp;}
+suppression_base::set_file_name_not_regex(const regex_t_sptr& regexp)
+{priv_->file_name_not_regex_ = regexp;}
 
 /// Getter for the "file_name_not_regex" property of the current
 /// instance of @ref suppression_base.
 ///
 /// The current suppression specification should apply to ABI
 /// artifacts of a file which name does *NOT* match the regular
-/// expression string designated by the "file_name_not_regex"
-/// property.
+/// expression designated by the "file_name_not_regex" property.
 ///
-/// @return the regular expression string.
-const string&
-suppression_base::get_file_name_not_regex_str() const
-{return priv_->file_name_not_regex_str_;}
+/// @return the regular expression.
+const regex_t_sptr&
+suppression_base::get_file_name_not_regex() const
+{return priv_->file_name_not_regex_;}
 
 /// Test if the current suppression has a property related to file
 /// name.
@@ -193,59 +191,56 @@ suppression_base::get_file_name_not_regex_str() const
 bool
 suppression_base::has_file_name_related_property() const
 {
-  return (!(get_file_name_regex_str().empty()
-	    && get_file_name_not_regex_str().empty()));
+  return get_file_name_regex() || get_file_name_not_regex();
 }
 
-/// Setter of the "soname_regex_str property of the current instance
+/// Setter of the "soname_regex" property of the current instance
 /// of @ref suppression_base.
 ///
-/// The "soname_regex_str" is a regular expression string that
-/// designates the soname of the shared library that contains the ABI
-/// artifacts this suppression should apply to.
+/// The "soname_regex" is a regular expression that designates the
+/// soname of the shared library that contains the ABI artifacts this
+/// suppression should apply to.
 ///
-/// @param regexp the new regular expression string.
+/// @param regexp the new regular expression.
 void
-suppression_base::set_soname_regex_str(const string& regexp)
-{priv_->soname_regex_str_ = regexp;}
+suppression_base::set_soname_regex(const regex_t_sptr& regexp)
+{priv_->soname_regex_ = regexp;}
 
-/// Getter of the "soname_regex_str property of the current instance
+/// Getter of the "soname_regex" property of the current instance
 /// of @ref suppression_base.
 ///
-/// The "soname_regex_str" is a regular expression string that
-/// designates the soname of the shared library that contains the ABI
-/// artifacts this suppression should apply to.
+/// The "soname_regex" is a regular expression that designates the
+/// soname of the shared library that contains the ABI artifacts this
+/// suppression should apply to.
 ///
-/// @return the regular expression string.
-const string&
-suppression_base::get_soname_regex_str() const
-{return priv_->soname_regex_str_;}
+/// @return the regular expression.
+const regex_t_sptr&
+suppression_base::get_soname_regex() const
+{return priv_->soname_regex_;}
 
-/// Setter of the "soname_not_regex_str property of the current
+/// Setter of the "soname_not_regex" property of the current
 /// instance of @ref suppression_base.
 ///
 /// The current suppression specification should apply to ABI
 /// artifacts of a shared library which SONAME does *NOT* match the
-/// regular expression string designated by the "soname_not_regex"
-/// property.
+/// regular expression designated by the "soname_not_regex" property.
 ///
-/// @param regexp the new regular expression string.
+/// @param regexp the new regular expression.
 void
-suppression_base::set_soname_not_regex_str(const string& regexp)
-{priv_->soname_not_regex_str_ = regexp;}
+suppression_base::set_soname_not_regex(const regex_t_sptr& regexp)
+{priv_->soname_not_regex_ = regexp;}
 
-/// Getter of the "soname_not_regex_str property of the current
+/// Getter of the "soname_not_regex" property of the current
 /// instance of @ref suppression_base.
 ///
 /// The current suppression specification should apply to ABI
 /// artifacts of a shared library which SONAME does *NOT* match the
-/// regular expression string designated by the "soname_not_regex"
-/// property.
+/// regular expression designated by the "soname_not_regex" property.
 ///
-/// @return the regular expression string.
-const string&
-suppression_base::get_soname_not_regex_str() const
-{return priv_->soname_not_regex_str_;}
+/// @return the regular expression.
+const regex_t_sptr&
+suppression_base::get_soname_not_regex() const
+{return priv_->soname_not_regex_;}
 
 /// Test if the current suppression has a property related to SONAMEs.
 ///
@@ -254,8 +249,7 @@ suppression_base::get_soname_not_regex_str() const
 bool
 suppression_base::has_soname_related_property() const
 {
-  return (!(get_soname_regex_str().empty()
-	    && get_soname_not_regex_str().empty()));
+  return get_soname_regex() || get_soname_not_regex();
 }
 
 /// Check if the SONAMEs of the two binaries being compared match the
@@ -397,8 +391,8 @@ read_suppressions(const string& file_path,
 /// form comment explaining what the suppression is about.
 ///
 /// @param type_name_regexp the regular expression describing the
-/// types about which diff reports should be suppressed.  If it's an
-/// empty string, the parameter is ignored.
+/// types about which diff reports should be suppressed.  If it's a
+/// null shared pointer, the parameter is ignored.
 ///
 /// @param type_name the name of the type about which diff reports
 /// should be suppressed.  If it's an empty string, the parameter is
@@ -408,7 +402,7 @@ read_suppressions(const string& file_path,
 /// should not necessarily be populated.  It usually is either one or
 /// the other that the user wants.
 type_suppression::type_suppression(const string& label,
-				   const string& type_name_regexp,
+				   const regex_t_sptr& type_name_regexp,
 				   const string& type_name)
   : suppression_base(label),
     priv_(new priv(type_name_regexp,
@@ -428,43 +422,43 @@ type_suppression::~type_suppression()
 /// This sets a regular expression that specifies the family of types
 /// about which diff reports should be suppressed.
 ///
-/// @param name_regex_str the new regular expression to set.
+/// @param name_regex the new regular expression to set.
 void
-type_suppression::set_type_name_regex_str(const string& name_regex_str)
-{priv_->type_name_regex_str_ = name_regex_str;}
+type_suppression::set_type_name_regex(const regex_t_sptr& name_regex)
+{priv_->type_name_regex_ = name_regex;}
 
 /// Getter for the "type_name_regex" property of the type suppression
 /// specification.
 ///
-/// This returns a regular expression string that specifies the family
+/// This returns a regular expression that specifies the family
 /// of types about which diff reports should be suppressed.
 ///
-/// @return the regular expression string.
-const string&
-type_suppression::get_type_name_regex_str() const
-{return priv_->type_name_regex_str_;}
+/// @return the regular expression.
+const regex_t_sptr&
+type_suppression::get_type_name_regex() const
+{return priv_->type_name_regex_;}
 
-/// Setter for the "type_name_not_regex_str" property of the type
+/// Setter for the "type_name_not_regex" property of the type
 /// suppression specification.
 ///
-/// This returns a regular expression string that specifies the family
+/// This sets a regular expression 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);}
+type_suppression::set_type_name_not_regex(const regex_t_sptr& r)
+{priv_->set_type_name_not_regex(r);}
 
-/// Getter for the "type_name_not_regex_str" property of the type
+/// Getter for the "type_name_not_regex" property of the type
 /// suppression specification.
 ///
-/// This returns a regular expression string that specifies the family
+/// This returns a regular expression 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();}
+const regex_t_sptr&
+type_suppression::get_type_name_not_regex() const
+{return priv_->type_name_not_regex_;}
 
 /// Setter for the name of the type about which diff reports should be
 /// suppressed.
@@ -612,21 +606,21 @@ type_suppression::set_source_locations_to_keep
 (const unordered_set<string>& l)
 {priv_->source_locations_to_keep_ = l;}
 
-/// Getter of the regular expression string that designates the source
+/// Getter of the regular expression that designates the source
 /// location paths of types that should not be suppressed.
 ///
-/// @return the regular expression string.
-const string&
-type_suppression::get_source_location_to_keep_regex_str() const
-{return priv_->source_location_to_keep_regex_str_;}
+/// @return the regular expression.
+const regex_t_sptr&
+type_suppression::get_source_location_to_keep_regex() const
+{return priv_->source_location_to_keep_regex_;}
 
-/// Setter of the regular expression string that designates the source
+/// Setter of the regular expression that designates the source
 /// location paths of types that should not be suppressed.
 ///
 /// @param r the new regular expression.
 void
-type_suppression::set_source_location_to_keep_regex_str(const string& r)
-{priv_->source_location_to_keep_regex_str_ = r;}
+type_suppression::set_source_location_to_keep_regex(const regex_t_sptr& r)
+{priv_->source_location_to_keep_regex_ = 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
@@ -1563,39 +1557,43 @@ read_type_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr file_name_regex_prop =
     is_simple_property(section.find_property("file_name_regexp"));
-  string file_name_regex_str =
-    file_name_regex_prop ? file_name_regex_prop->get_value()->as_string() : "";
+  regex_t_sptr file_name_regex;
+  if (file_name_regex_prop)
+    file_name_regex =
+      regex::compile(file_name_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr file_name_not_regex_prop =
     is_simple_property(section.find_property("file_name_not_regexp"));
-  string file_name_not_regex_str =
-    file_name_not_regex_prop
-    ? file_name_not_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr file_name_not_regex;
+  if (file_name_not_regex_prop)
+    file_name_not_regex =
+      regex::compile(file_name_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr soname_regex_prop =
     is_simple_property(section.find_property("soname_regexp"));
-  string soname_regex_str =
-    soname_regex_prop ? soname_regex_prop->get_value()->as_string() : "";
+  regex_t_sptr soname_regex;
+  if (soname_regex_prop)
+    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr soname_not_regex_prop =
     is_simple_property(section.find_property("soname_not_regexp"));
-  string soname_not_regex_str =
-    soname_not_regex_prop
-    ? soname_not_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr soname_not_regex;
+  if (soname_not_regex_prop)
+    soname_not_regex =
+      regex::compile(soname_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr name_regex_prop =
     is_simple_property(section.find_property("name_regexp"));
-  string name_regex_str = name_regex_prop
-    ? name_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr name_regex;
+  if (name_regex_prop)
+    name_regex = regex::compile(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()
-    : "";
+  regex_t_sptr name_not_regex;
+  if (name_not_regex_prop)
+    name_not_regex =
+      regex::compile(name_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr name_prop =
     is_simple_property(section.find_property("name"));
@@ -1627,9 +1625,10 @@ read_type_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr srcloc_not_regexp_prop =
     is_simple_property(section.find_property("source_location_not_regexp"));
-  string srcloc_not_regexp_str;
+  regex_t_sptr srcloc_not_regex;
   if (srcloc_not_regexp_prop)
-    srcloc_not_regexp_str = srcloc_not_regexp_prop->get_value()->as_string();
+    srcloc_not_regex =
+      regex::compile(srcloc_not_regexp_prop->get_value()->as_string());
 
   bool consider_type_kind = false;
   type_suppression::type_kind type_kind = type_suppression::UNKNOWN_TYPE_KIND;
@@ -1836,7 +1835,7 @@ read_type_suppression(const ini::config::section& section)
 	changed_enumerator_names.push_back(p->get_value()->as_string());
     }
 
-  result.reset(new type_suppression(label_str, name_regex_str, name_str));
+  result.reset(new type_suppression(label_str, name_regex, name_str));
 
   if (consider_type_kind)
     {
@@ -1853,31 +1852,31 @@ read_type_suppression(const ini::config::section& section)
   if (consider_data_member_insertion)
     result->set_data_member_insertion_ranges(insert_ranges);
 
-  if (!name_not_regex_str.empty())
-    result->set_type_name_not_regex_str(name_not_regex_str);
+  if (name_not_regex)
+    result->set_type_name_not_regex(name_not_regex);
 
-  if (!file_name_regex_str.empty())
-    result->set_file_name_regex_str(file_name_regex_str);
+  if (file_name_regex)
+    result->set_file_name_regex(file_name_regex);
 
-  if (!file_name_not_regex_str.empty())
-    result->set_file_name_not_regex_str(file_name_not_regex_str);
+  if (file_name_not_regex)
+    result->set_file_name_not_regex(file_name_not_regex);
 
-  if (!soname_regex_str.empty())
-    result->set_soname_regex_str(soname_regex_str);
+  if (soname_regex)
+    result->set_soname_regex(soname_regex);
 
-  if (!soname_not_regex_str.empty())
-    result->set_soname_not_regex_str(soname_not_regex_str);
+  if (soname_not_regex)
+    result->set_soname_not_regex(soname_not_regex);
 
   if (!srcloc_not_in.empty())
     result->set_source_locations_to_keep(srcloc_not_in);
 
-  if (!srcloc_not_regexp_str.empty())
-    result->set_source_location_to_keep_regex_str(srcloc_not_regexp_str);
+  if (srcloc_not_regex)
+    result->set_source_location_to_keep_regex(srcloc_not_regex);
 
   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
-      && ((!name_regex_str.empty()
+      && ((name_regex
 	   || !name_str.empty()
-	   || !srcloc_not_regexp_str.empty()
+	   || srcloc_not_regex
 	   || !srcloc_not_in.empty())))
     result->set_drops_artifact_from_ir(true);
 
@@ -1903,7 +1902,7 @@ read_type_suppression(const ini::config::section& section)
 /// account only if the parameter @p tn is empty.
 function_suppression::parameter_spec::parameter_spec(size_t i,
 						     const string& tn,
-						     const string& tn_regex)
+						     const regex_t_sptr& tn_regex)
   : priv_(new priv(i, tn, tn_regex))
 {}
 
@@ -1948,9 +1947,9 @@ function_suppression::parameter_spec::set_parameter_type_name(const string& tn)
 /// empty.
 ///
 /// @return the regular expression or the parameter type name.
-const string&
-function_suppression::parameter_spec::get_parameter_type_name_regex_str() const
-{return priv_->type_name_regex_str_;}
+const regex_t_sptr&
+function_suppression::parameter_spec::get_parameter_type_name_regex() const
+{return priv_->type_name_regex_;}
 
 /// Setter for the regular expression that defines a set of type names
 /// for the parameter designated by this specification.
@@ -1960,12 +1959,12 @@ function_suppression::parameter_spec::get_parameter_type_name_regex_str() const
 /// function_suppression::parameter_spec::get_parameter_type_name() is
 /// empty.
 ///
-/// @param type_name_regex_str the new type name regular expression to
+/// @param type_name_regex the new type name regular expression to
 /// set.
 void
-function_suppression::parameter_spec::set_parameter_type_name_regex_str
-(const string& type_name_regex_str)
-{priv_->type_name_regex_str_ = type_name_regex_str;}
+function_suppression::parameter_spec::set_parameter_type_name_regex
+(const regex_t_sptr& type_name_regex)
+{priv_->type_name_regex_ = type_name_regex;}
 
 /// Default constructor for the @ref function_suppression type.
 ///
@@ -2033,14 +2032,14 @@ function_suppression::function_suppression()
 /// case it's ignored at evaluation time.
 function_suppression::function_suppression(const string&		label,
 					   const string&		name,
-					   const string&		nr,
+					   const regex_t_sptr&		nr,
 					   const string&		ret_tn,
-					   const string&		ret_tr,
+					   const regex_t_sptr&		ret_tr,
 					   parameter_specs_type&	ps,
 					   const string&		sym_n,
-					   const string&		sym_nr,
+					   const regex_t_sptr&		sym_nr,
 					   const string&		sym_v,
-					   const string&		sym_vr)
+					   const regex_t_sptr&		sym_vr)
   : suppression_base(label),
     priv_(new priv(name, nr, ret_tn, ret_tr, ps,
 		   sym_n, sym_nr, sym_v, sym_vr))
@@ -2108,9 +2107,9 @@ function_suppression::set_name(const string& n)
 ///
 /// @return the regular expression for the possible names of the
 /// function(s).
-const string&
-function_suppression::get_name_regex_str() const
-{return priv_->name_regex_str_;}
+const regex_t_sptr&
+function_suppression::get_name_regex() const
+{return priv_->name_regex_;}
 
 /// Setter for a regular expression for a family of names of functions
 /// the user wants the current specification to designate.
@@ -2118,8 +2117,8 @@ function_suppression::get_name_regex_str() const
 /// @param r the new the regular expression for the possible names of
 /// the function(s).
 void
-function_suppression::set_name_regex_str(const string& r)
-{priv_->name_regex_str_ = r;}
+function_suppression::set_name_regex(const regex_t_sptr& r)
+{priv_->name_regex_ = r;}
 
 /// Getter for a regular expression of a family of names of functions
 /// the user wants the current specification to designate the negation
@@ -2127,9 +2126,9 @@ function_suppression::set_name_regex_str(const string& r)
 ///
 /// @return the regular expression for the possible names of the
 /// function(s).
-const string&
-function_suppression::get_name_not_regex_str() const
-{return priv_->name_not_regex_str_;}
+const regex_t_sptr&
+function_suppression::get_name_not_regex() const
+{return priv_->name_not_regex_;}
 
 /// Setter for a regular expression for a family of names of functions
 /// the user wants the current specification to designate the negation
@@ -2138,8 +2137,8 @@ function_suppression::get_name_not_regex_str() const
 /// @param r the new the regular expression for the possible names of
 /// the function(s).
 void
-function_suppression::set_name_not_regex_str(const string& r)
-{priv_->name_not_regex_str_ = r;}
+function_suppression::set_name_not_regex(const regex_t_sptr& r)
+{priv_->name_not_regex_ = r;}
 
 /// Getter for the name of the return type of the function the user
 /// wants this specification to designate.  This property might be
@@ -2171,9 +2170,9 @@ function_suppression::set_return_type_name(const string& tr)
 ///
 /// @return the regular expression for the possible names of the
 /// return types of the function(s).
-const string&
-function_suppression::get_return_type_regex_str() const
-{return priv_->return_type_regex_str_;}
+const regex_t_sptr&
+function_suppression::get_return_type_regex() const
+{return priv_->return_type_regex_;}
 
 /// Setter for a regular expression for a family of return type names
 /// for functions the user wants the current specification to
@@ -2188,8 +2187,8 @@ function_suppression::get_return_type_regex_str() const
 /// @param r the new regular expression for the possible names of the
 /// return types of the function(s) to set.
 void
-function_suppression::set_return_type_regex_str(const string& r)
-{priv_->return_type_regex_str_ = r;}
+function_suppression::set_return_type_regex(const regex_t_sptr& r)
+{priv_->return_type_regex_ = r;}
 
 /// Getter for a vector of parameter specifications to specify
 /// properties of the parameters of the functions the user wants this
@@ -2257,9 +2256,9 @@ function_suppression::set_symbol_name(const string& n)
 ///
 /// @return the regular expression for a family of names of symbols of
 /// functions to designate.
-const string&
-function_suppression::get_symbol_name_regex_str() const
-{return priv_->symbol_name_regex_str_;}
+const regex_t_sptr&
+function_suppression::get_symbol_name_regex() const
+{return priv_->symbol_name_regex_;}
 
 /// Setter for a regular expression for a family of names of symbols
 /// of functions the user wants this specification to designate.
@@ -2274,8 +2273,8 @@ function_suppression::get_symbol_name_regex_str() const
 /// @param r the new regular expression for a family of names of
 /// symbols of functions to set.
 void
-function_suppression::set_symbol_name_regex_str(const string& r)
-{priv_->symbol_name_regex_str_ = r;}
+function_suppression::set_symbol_name_regex(const regex_t_sptr& r)
+{priv_->symbol_name_regex_ = r;}
 
 /// Getter for a regular expression for a family of names of symbols
 /// of functions the user wants this specification to designate.
@@ -2290,11 +2289,11 @@ function_suppression::set_symbol_name_regex_str(const string& r)
 /// This property might be empty, in which case it's ignored at
 /// evaluation time.
 ///
-/// @return the regular expression string for a family of names of
+/// @return the regular expression for a family of names of
 /// symbols that is to be *NOT* suppressed by this suppression specification.
-const string&
-function_suppression::get_symbol_name_not_regex_str() const
-{return priv_->symbol_name_not_regex_str_;}
+const regex_t_sptr&
+function_suppression::get_symbol_name_not_regex() const
+{return priv_->symbol_name_not_regex_;}
 
 /// Setter for a regular expression for a family of names of symbols
 /// of functions the user wants this specification to designate.
@@ -2309,12 +2308,12 @@ function_suppression::get_symbol_name_not_regex_str() const
 /// This property might be empty, in which case it's ignored at
 /// evaluation time.
 ///
-/// @param the new regular expression string for a family of names of
+/// @param the new regular expression for a family of names of
 /// symbols that is to be *NOT* suppressed by this suppression
 /// specification.
 void
-function_suppression::set_symbol_name_not_regex_str(const string& r)
-{priv_->symbol_name_not_regex_str_ = r;}
+function_suppression::set_symbol_name_not_regex(const regex_t_sptr& r)
+{priv_->symbol_name_not_regex_ = r;}
 
 /// Getter for the name of the version of the symbol of the function
 /// the user wants this specification to designate.
@@ -2349,9 +2348,9 @@ function_suppression::set_symbol_version(const string& v)
 ///
 /// @return the regular expression for the versions of symbols of
 /// functions to designate.
-const string&
-function_suppression::get_symbol_version_regex_str() const
-{return priv_->symbol_version_regex_str_;}
+const regex_t_sptr&
+function_suppression::get_symbol_version_regex() const
+{return priv_->symbol_version_regex_;}
 
 /// Setter for a regular expression for a family of versions of
 /// symbols of functions the user wants the current specification to
@@ -2365,8 +2364,8 @@ function_suppression::get_symbol_version_regex_str() const
 /// @param the new regular expression for the versions of symbols of
 /// functions to designate.
 void
-function_suppression::set_symbol_version_regex_str(const string& r)
-{priv_->symbol_version_regex_str_ = r;}
+function_suppression::set_symbol_version_regex(const regex_t_sptr& r)
+{priv_->symbol_version_regex_ = r;}
 
 /// Getter for the "allow_other_aliases" property of the function
 /// suppression specification.
@@ -2769,7 +2768,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
       if (sym_name != get_symbol_name())
 	return false;
     }
-  else if (!get_symbol_name_regex_str().empty())
+  else if (get_symbol_name_regex())
     {
       const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
       if (symbol_name_regex && !regex::match(symbol_name_regex, sym_name))
@@ -2784,7 +2783,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
       if (sym_version != get_symbol_version())
 	return false;
     }
-  else if (!get_symbol_version_regex_str().empty())
+  else if (get_symbol_version_regex())
     {
       const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
@@ -3090,10 +3089,10 @@ read_parameter_spec_from_string(const string& str)
 
   if (!index_str.empty() || !type_name.empty())
     {
-      std::string type_name_regex;
+      regex_t_sptr type_name_regex;
       if (is_regex)
 	{
-	  type_name_regex = type_name;
+	  type_name_regex = regex::compile(type_name);
 	  type_name.clear();
 	}
       function_suppression::parameter_spec* p =
@@ -3143,27 +3142,30 @@ read_function_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr file_name_regex_prop =
     is_simple_property(section.find_property("file_name_regexp"));
-  string file_name_regex_str =
-    file_name_regex_prop ? file_name_regex_prop->get_value()->as_string() : "";
+  regex_t_sptr file_name_regex;
+  if (file_name_regex_prop)
+    file_name_regex =
+      regex::compile(file_name_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr file_name_not_regex_prop =
     is_simple_property(section.find_property("file_name_not_regexp"));
-  string file_name_not_regex_str =
-    file_name_not_regex_prop
-    ? file_name_not_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr file_name_not_regex;
+  if (file_name_not_regex_prop)
+    file_name_not_regex =
+      regex::compile(file_name_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr soname_regex_prop =
     is_simple_property(section.find_property("soname_regexp"));
-  string soname_regex_str =
-    soname_regex_prop ? soname_regex_prop->get_value()->as_string() : "";
+  regex_t_sptr soname_regex;
+  if (soname_regex_prop)
+    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr soname_not_regex_prop =
     is_simple_property(section.find_property("soname_not_regexp"));
-  string soname_not_regex_str =
-    soname_not_regex_prop
-    ? soname_not_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr soname_not_regex;
+  if (soname_not_regex_prop)
+    soname_not_regex =
+      regex::compile(soname_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr name_prop =
     is_simple_property(section.find_property("name"));
@@ -3173,15 +3175,16 @@ read_function_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr name_regex_prop =
     is_simple_property(section.find_property("name_regexp"));
-  string name_regex_str = name_regex_prop
-    ? name_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr name_regex;
+  if (name_regex_prop)
+    name_regex = regex::compile(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()
-    : "";
+  regex_t_sptr name_not_regex;
+  if (name_not_regex_prop)
+    name_not_regex =
+      regex::compile(name_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr return_type_name_prop =
     is_simple_property(section.find_property("return_type_name"));
@@ -3191,9 +3194,10 @@ read_function_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr return_type_regex_prop =
     is_simple_property(section.find_property("return_type_regexp"));
-  string return_type_regex_str = return_type_regex_prop
-    ? return_type_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr return_type_regex;
+  if (return_type_regex_prop)
+    return_type_regex =
+      regex::compile(return_type_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr sym_name_prop =
     is_simple_property(section.find_property("symbol_name"));
@@ -3203,15 +3207,17 @@ read_function_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr sym_name_regex_prop =
     is_simple_property(section.find_property("symbol_name_regexp"));
-  string sym_name_regex_str = sym_name_regex_prop
-    ? sym_name_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr sym_name_regex;
+  if (sym_name_regex_prop)
+    sym_name_regex =
+      regex::compile(sym_name_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr sym_name_not_regex_prop =
     is_simple_property(section.find_property("symbol_name_not_regexp"));
-  string sym_name_not_regex_str = sym_name_not_regex_prop
-    ? sym_name_not_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr sym_name_not_regex;
+  if (sym_name_not_regex_prop)
+    sym_name_not_regex =
+      regex::compile(sym_name_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr sym_ver_prop =
     is_simple_property(section.find_property("symbol_version"));
@@ -3221,9 +3227,10 @@ read_function_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr sym_ver_regex_prop =
     is_simple_property(section.find_property("symbol_version_regexp"));
-  string sym_ver_regex_str = sym_ver_regex_prop
-    ? sym_ver_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr sym_ver_regex;
+  if (sym_ver_regex_prop)
+    sym_ver_regex =
+      regex::compile(sym_ver_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr allow_other_aliases_prop =
     is_simple_property(section.find_property("allow_other_aliases"));
@@ -3248,22 +3255,22 @@ read_function_suppression(const ini::config::section& section)
 
   result.reset(new function_suppression(label_str,
 					name,
-					name_regex_str,
+					name_regex,
 					return_type_name,
-					return_type_regex_str,
+					return_type_regex,
 					parms,
 					sym_name,
-					sym_name_regex_str,
+					sym_name_regex,
 					sym_version,
-					sym_ver_regex_str));
+					sym_ver_regex));
 
   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
       && (!name.empty()
-	  || !name_regex_str.empty()
-	  || !name_not_regex_str.empty()
+	  || name_regex
+	  || name_not_regex
 	  || !sym_name.empty()
-	  || !sym_name_regex_str.empty()
-	  || !sym_name_not_regex_str.empty()))
+	  || sym_name_regex
+	  || sym_name_not_regex))
     result->set_drops_artifact_from_ir(true);
 
   if (!change_kind_str.empty())
@@ -3274,23 +3281,23 @@ read_function_suppression(const ini::config::section& section)
     result->set_allow_other_aliases(allow_other_aliases == "yes"
 				    || allow_other_aliases == "true");
 
-  if (!name_not_regex_str.empty())
-    result->set_name_not_regex_str(name_not_regex_str);
+  if (name_not_regex)
+    result->set_name_not_regex(name_not_regex);
 
-  if (!sym_name_not_regex_str.empty())
-    result->set_symbol_name_not_regex_str(sym_name_not_regex_str);
+  if (sym_name_not_regex)
+    result->set_symbol_name_not_regex(sym_name_not_regex);
 
-  if (!file_name_regex_str.empty())
-    result->set_file_name_regex_str(file_name_regex_str);
+  if (file_name_regex)
+    result->set_file_name_regex(file_name_regex);
 
-  if (!file_name_not_regex_str.empty())
-    result->set_file_name_not_regex_str(file_name_not_regex_str);
+  if (file_name_not_regex)
+    result->set_file_name_not_regex(file_name_not_regex);
 
-  if (!soname_regex_str.empty())
-    result->set_soname_regex_str(soname_regex_str);
+  if (soname_regex)
+    result->set_soname_regex(soname_regex);
 
-  if (!soname_not_regex_str.empty())
-    result->set_soname_not_regex_str(soname_not_regex_str);
+  if (soname_not_regex)
+    result->set_soname_not_regex(soname_not_regex);
 
   return result;
 }
@@ -3310,7 +3317,7 @@ read_function_suppression(const ini::config::section& section)
 /// specification to designate.  This parameter might be empty, in
 /// which case it's ignored at evaluation time.
 ///
-/// @param name_regex_str if @p name is empty, this parameter is a
+/// @param name_regex if @p name is empty, this parameter is a
 /// regular expression for a family of names of variables the user
 /// wants the current specification to designate.  If @p name is not
 /// empty, then this parameter is ignored at evaluation time.  This
@@ -3344,7 +3351,7 @@ read_function_suppression(const ini::config::section& section)
 /// wants the current specification to designate.  This parameter
 /// might be empty, in which case it's ignored at evaluation time.
 ///
-/// @param type_name_regex_str if @p type_name is empty, then this
+/// @param type_name_regex if @p type_name is empty, then this
 /// parameter is a regular expression for a family of type names of
 /// variables the user wants the current specification to designate.
 /// If @p type_name is not empty, then this parameter is ignored at
@@ -3352,18 +3359,18 @@ read_function_suppression(const ini::config::section& section)
 /// ignored at evaluation time.
 variable_suppression::variable_suppression(const string& label,
 					   const string& name,
-					   const string& name_regex_str,
+					   const regex_t_sptr& name_regex,
 					   const string& symbol_name,
-					   const string& symbol_name_regex_str,
+					   const regex_t_sptr& symbol_name_regex,
 					   const string& symbol_version,
-					   const string& symbol_version_regex,
+					   const regex_t_sptr& symbol_version_regex,
 					   const string& type_name,
-					   const string& type_name_regex_str)
+					   const regex_t_sptr& type_name_regex)
   : suppression_base(label),
-    priv_(new priv(name, name_regex_str,
-		   symbol_name, symbol_name_regex_str,
+    priv_(new priv(name, name_regex,
+		   symbol_name, symbol_name_regex,
 		   symbol_version, symbol_version_regex,
-		   type_name, type_name_regex_str))
+		   type_name, type_name_regex))
 {}
 
 /// Virtual destructor for the @erf variable_suppression type.
@@ -3433,9 +3440,9 @@ variable_suppression::set_name(const string& n)
 /// which case it's ignored at evaluation time.
 ///
 /// @return the regular expression for the variable name.
-const string&
-variable_suppression::get_name_regex_str() const
-{return priv_->name_regex_str_;}
+const regex_t_sptr&
+variable_suppression::get_name_regex() const
+{return priv_->name_regex_;}
 
 /// Setter for the regular expression for a family of names of
 /// variables the user wants the current specification to designate.
@@ -3446,22 +3453,22 @@ variable_suppression::get_name_regex_str() const
 ///
 /// @param r the new regular expression for the variable name.
 void
-variable_suppression::set_name_regex_str(const string& r)
-{priv_->name_regex_str_ = r;}
+variable_suppression::set_name_regex(const regex_t_sptr& r)
+{priv_->name_regex_ = r;}
 
 /// Getter for the "name_not_regexp" property of the specification.
 ///
 /// @return the value of the "name_not_regexp" property.
-const string&
-variable_suppression::get_name_not_regex_str() const
-{return priv_->name_not_regex_str_;}
+const regex_t_sptr&
+variable_suppression::get_name_not_regex() const
+{return priv_->name_not_regex_;}
 
 /// Setter for the "name_not_regexp" property of the specification.
 ///
 /// @param r the new value of the "name_not_regexp" property.
 void
-variable_suppression::set_name_not_regex_str(const string& r)
-{priv_->name_not_regex_str_ = r;}
+variable_suppression::set_name_not_regex(const regex_t_sptr& r)
+{priv_->name_not_regex_ = r;}
 
 /// Getter for the name of the symbol of the variable the user wants
 /// the current specification to designate.
@@ -3494,9 +3501,9 @@ variable_suppression::set_symbol_name(const string& n)
 /// empty.
 ///
 /// @return the regular expression for a symbol name of the variable.
-const string&
-variable_suppression::get_symbol_name_regex_str() const
-{return priv_->symbol_name_regex_str_;}
+const regex_t_sptr&
+variable_suppression::get_symbol_name_regex() const
+{return priv_->symbol_name_regex_;}
 
 /// Setter of the regular expression for a family of symbol names of
 /// the variables this specification is about to designate.
@@ -3508,8 +3515,8 @@ variable_suppression::get_symbol_name_regex_str() const
 ///
 /// @param r the regular expression for a symbol name of the variable.
 void
-variable_suppression::set_symbol_name_regex_str(const string& r)
-{priv_->symbol_name_regex_str_ = r;}
+variable_suppression::set_symbol_name_regex(const regex_t_sptr& r)
+{priv_->symbol_name_regex_ = r;}
 
 /// Getter for a regular expression for a family of names of symbols
 /// of variables the user wants this specification to designate.
@@ -3524,11 +3531,11 @@ variable_suppression::set_symbol_name_regex_str(const string& r)
 /// This property might be empty, in which case it's ignored at
 /// evaluation time.
 ///
-/// @return the regular expression string for a family of names of
+/// @return the regular expression for a family of names of
 /// symbols that is to be *NOT* suppressed by this suppression specification.
-const string&
-variable_suppression::get_symbol_name_not_regex_str() const
-{return priv_->symbol_name_not_regex_str_;}
+const regex_t_sptr&
+variable_suppression::get_symbol_name_not_regex() const
+{return priv_->symbol_name_not_regex_;}
 
 /// Setter for a regular expression for a family of names of symbols
 /// of variables the user wants this specification to designate.
@@ -3543,12 +3550,12 @@ variable_suppression::get_symbol_name_not_regex_str() const
 /// This property might be empty, in which case it's ignored at
 /// evaluation time.
 ///
-/// @param the new regular expression string for a family of names of
+/// @param the new regular expression for a family of names of
 /// symbols that is to be *NOT* suppressed by this suppression
 /// specification.
 void
-variable_suppression::set_symbol_name_not_regex_str(const string& r)
-{priv_->symbol_name_not_regex_str_ = r;}
+variable_suppression::set_symbol_name_not_regex(const regex_t_sptr& r)
+{priv_->symbol_name_not_regex_ = r;}
 
 /// Getter for the version of the symbol of the variable the user
 /// wants the current specification to designate.  This property might
@@ -3576,9 +3583,9 @@ variable_suppression::set_symbol_version(const string& v)
 ///
 /// @return the regular expression of the symbol version of the
 /// variable.
-const string&
-variable_suppression::get_symbol_version_regex_str() const
-{return priv_->symbol_version_regex_str_;}
+const regex_t_sptr&
+variable_suppression::get_symbol_version_regex() const
+{return priv_->symbol_version_regex_;}
 
 /// Setter of the regular expression for a family of versions of
 /// symbol for the variables the user wants the current specification
@@ -3589,8 +3596,8 @@ variable_suppression::get_symbol_version_regex_str() const
 /// @param v the new regular expression of the symbol version of the
 /// variable.
 void
-variable_suppression::set_symbol_version_regex_str(const string& r)
-{priv_->symbol_version_regex_str_ = r;}
+variable_suppression::set_symbol_version_regex(const regex_t_sptr& r)
+{priv_->symbol_version_regex_ = r;}
 
 /// Getter for the name of the type of the variable the user wants the
 /// current specification to designate.
@@ -3623,9 +3630,9 @@ variable_suppression::set_type_name(const string& n)
 /// empty, in which case it's ignored at evaluation time.
 ///
 /// @return the regular expression of the variable type name.
-const string&
-variable_suppression::get_type_name_regex_str() const
-{return priv_->type_name_regex_str_;}
+const regex_t_sptr&
+variable_suppression::get_type_name_regex() const
+{return priv_->type_name_regex_;}
 
 /// Setter for the regular expression for a family of type names of
 /// variables the user wants the current specification to designate.
@@ -3637,8 +3644,8 @@ variable_suppression::get_type_name_regex_str() const
 ///
 /// @param r the regular expression of the variable type name.
 void
-variable_suppression::set_type_name_regex_str(const string& r)
-{priv_->type_name_regex_str_ = r;}
+variable_suppression::set_type_name_regex(const regex_t_sptr& r)
+{priv_->type_name_regex_ = r;}
 
 /// Evaluate this suppression specification on a given diff node and
 /// say if the diff node should be suppressed or not.
@@ -3867,7 +3874,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
       if (get_symbol_name() != sym_name)
 	return false;
     }
-  else if (!get_symbol_name_regex_str().empty())
+  else if (get_symbol_name_regex())
     {
       const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
       if (sym_name_regex && !regex::match(sym_name_regex, sym_name))
@@ -3883,7 +3890,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
       if (get_symbol_version() != sym_version)
 	return false;
     }
-  else if (!get_symbol_version_regex_str().empty())
+  else if (get_symbol_version_regex())
     {
       const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
@@ -4001,27 +4008,30 @@ read_variable_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr file_name_regex_prop =
     is_simple_property(section.find_property("file_name_regexp"));
-  string file_name_regex_str =
-    file_name_regex_prop ? file_name_regex_prop->get_value()->as_string() : "";
+  regex_t_sptr file_name_regex;
+  if (file_name_regex_prop)
+    file_name_regex =
+      regex::compile(file_name_regex_prop->get_value()->as_string());
 
  ini::simple_property_sptr file_name_not_regex_prop =
-    is_simple_property(section.find_property("file_name_not_regexp"));
-  string file_name_not_regex_str =
-    file_name_not_regex_prop
-    ? file_name_not_regex_prop->get_value()->as_string()
-    : "";
+  is_simple_property(section.find_property("file_name_not_regexp"));
+ regex_t_sptr file_name_not_regex;
+ if (file_name_not_regex_prop)
+   file_name_not_regex =
+     regex::compile(file_name_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr soname_regex_prop =
     is_simple_property(section.find_property("soname_regexp"));
-  string soname_regex_str =
-    soname_regex_prop ? soname_regex_prop->get_value()->as_string() : "";
+  regex_t_sptr soname_regex;
+  if (soname_regex_prop)
+    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr soname_not_regex_prop =
     is_simple_property(section.find_property("soname_not_regexp"));
-  string soname_not_regex_str =
-    soname_not_regex_prop
-    ? soname_not_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr soname_not_regex;
+  if (soname_not_regex_prop)
+    soname_not_regex =
+      regex::compile(soname_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr name_prop =
     is_simple_property(section.find_property("name"));
@@ -4031,15 +4041,16 @@ read_variable_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr name_regex_prop =
     is_simple_property(section.find_property("name_regexp"));
-  string name_regex_str = (name_regex_prop
-			   ? name_regex_prop->get_value()->as_string()
-			   : "");
+  regex_t_sptr name_regex;
+  if (name_regex_prop)
+    name_regex = regex::compile(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()
-    : "";
+  regex_t_sptr name_not_regex;
+  if (name_not_regex_prop)
+    name_not_regex =
+      regex::compile(name_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr sym_name_prop =
     is_simple_property(section.find_property("symbol_name"));
@@ -4049,15 +4060,17 @@ read_variable_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr sym_name_regex_prop =
     is_simple_property(section.find_property("symbol_name_regexp"));
-  string symbol_name_regex_str = sym_name_regex_prop
-    ? sym_name_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr symbol_name_regex;
+  if (sym_name_regex_prop)
+    symbol_name_regex =
+      regex::compile(sym_name_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr sym_name_not_regex_prop =
     is_simple_property(section.find_property("symbol_name_not_regexp"));
-  string symbol_name_not_regex_str = sym_name_not_regex_prop
-    ? sym_name_not_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr symbol_name_not_regex;
+  if (sym_name_not_regex_prop)
+    symbol_name_not_regex =
+      regex::compile(sym_name_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr sym_version_prop =
     is_simple_property(section.find_property("symbol_version"));
@@ -4067,9 +4080,10 @@ read_variable_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr sym_version_regex_prop =
     is_simple_property(section.find_property("symbol_version_regexp"));
-  string symbol_version_regex_str = sym_version_regex_prop
-    ? sym_version_regex_prop->get_value()->as_string()
-     : "";
+  regex_t_sptr symbol_version_regex;
+  if (sym_version_regex_prop)
+    symbol_version_regex =
+      regex::compile(sym_version_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr type_name_prop =
     is_simple_property(section.find_property("type_name"));
@@ -4079,50 +4093,51 @@ read_variable_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr type_name_regex_prop =
     is_simple_property(section.find_property("type_name_regexp"));
-  string type_name_regex_str = type_name_regex_prop
-    ? type_name_regex_prop->get_value()->as_string()
-     : "";
+  regex_t_sptr type_name_regex;
+  if (type_name_regex_prop)
+    type_name_regex =
+      regex::compile(type_name_regex_prop->get_value()->as_string());
 
   result.reset(new variable_suppression(label_str,
 					name_str,
-					name_regex_str,
+					name_regex,
 					symbol_name,
-					symbol_name_regex_str,
+					symbol_name_regex,
 					symbol_version,
-					symbol_version_regex_str,
+					symbol_version_regex,
 					type_name_str,
-					type_name_regex_str));
+					type_name_regex));
 
   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
       && (!name_str.empty()
-	  || !name_regex_str.empty()
-	  || !name_not_regex_str.empty()
+	  || name_regex
+	  || name_not_regex
 	  || !symbol_name.empty()
-	  || !symbol_name_regex_str.empty()
-	  || !symbol_name_not_regex_str.empty()))
+	  || symbol_name_regex
+	  || symbol_name_not_regex))
     result->set_drops_artifact_from_ir(true);
 
-  if (!name_not_regex_str.empty())
-    result->set_name_not_regex_str(name_not_regex_str);
+  if (name_not_regex)
+    result->set_name_not_regex(name_not_regex);
 
-  if (!symbol_name_not_regex_str.empty())
-    result->set_symbol_name_not_regex_str(symbol_name_not_regex_str);
+  if (symbol_name_not_regex)
+    result->set_symbol_name_not_regex(symbol_name_not_regex);
 
   if (!change_kind_str.empty())
     result->set_change_kind
       (variable_suppression::parse_change_kind(change_kind_str));
 
-  if (!file_name_regex_str.empty())
-    result->set_file_name_regex_str(file_name_regex_str);
+  if (file_name_regex)
+    result->set_file_name_regex(file_name_regex);
 
-  if (!file_name_not_regex_str.empty())
-    result->set_file_name_not_regex_str(file_name_not_regex_str);
+  if (file_name_not_regex)
+    result->set_file_name_not_regex(file_name_not_regex);
 
-  if (!soname_regex_str.empty())
-    result->set_soname_regex_str(soname_regex_str);
+  if (soname_regex)
+    result->set_soname_regex(soname_regex);
 
-  if (!soname_not_regex_str.empty())
-    result->set_soname_not_regex_str(soname_not_regex_str);
+  if (soname_not_regex)
+    result->set_soname_not_regex(soname_not_regex);
 
   return result;
 }
@@ -4135,21 +4150,21 @@ read_variable_suppression(const ini::config::section& section)
 ///
 /// @param label the label of the suppression directive.
 ///
-/// @param fname_regex_str the regular expression string that
+/// @param fname_regex the regular expression that
 /// designates the file name that instances of @ref file_suppression
 /// should match.
 ///
-/// @param fname_not_regex_str the regular expression string that
+/// @param fname_not_regex the regular expression that
 /// designates the file name that instances of @ref file_suppression
 /// shoult *NOT* match.  In other words, this file_suppression should
 /// be activated if its file name does not match the regular
-/// expression @p fname_not_regex_str.
+/// expression @p fname_not_regex.
 file_suppression::file_suppression(const string& label,
-				   const string& fname_regex_str,
-				   const string& fname_not_regex_str)
+				   const regex_t_sptr& fname_regex,
+				   const regex_t_sptr& fname_not_regex)
   : suppression_base(label,
-		     fname_regex_str,
-		     fname_not_regex_str)
+		     fname_regex,
+		     fname_not_regex)
 {}
 
 /// Test if instances of this @ref file_suppression suppresses a
@@ -4229,41 +4244,44 @@ read_file_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr file_name_regex_prop =
     is_simple_property(section.find_property("file_name_regexp"));
-  string file_name_regex_str =
-    file_name_regex_prop ? file_name_regex_prop->get_value()->as_string() : "";
+  regex_t_sptr file_name_regex;
+  if (file_name_regex_prop)
+    file_name_regex =
+      regex::compile(file_name_regex_prop->get_value()->as_string());
 
  ini::simple_property_sptr file_name_not_regex_prop =
     is_simple_property(section.find_property("file_name_not_regexp"));
-  string file_name_not_regex_str =
-    file_name_not_regex_prop
-    ? file_name_not_regex_prop->get_value()->as_string()
-    : "";
+ regex_t_sptr file_name_not_regex;
+ if (file_name_not_regex_prop)
+   file_name_not_regex =
+     regex::compile(file_name_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr soname_regex_prop =
     is_simple_property(section.find_property("soname_regexp"));
-  string soname_regex_str =
-    soname_regex_prop ? soname_regex_prop->get_value()->as_string() : "";
+  regex_t_sptr soname_regex;
+  if (soname_regex_prop)
+    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr soname_not_regex_prop =
     is_simple_property(section.find_property("soname_not_regexp"));
-  string soname_not_regex_str =
-    soname_not_regex_prop
-    ? soname_not_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr soname_not_regex;
+  if (soname_not_regex_prop)
+    soname_not_regex =
+      regex::compile(soname_not_regex_prop->get_value()->as_string());
 
   result.reset(new file_suppression(label_str,
-				    file_name_regex_str,
-				    file_name_not_regex_str));
+				    file_name_regex,
+				    file_name_not_regex));
 
-  if (!soname_regex_str.empty())
+  if (soname_regex)
     {
-      result->set_soname_regex_str(soname_regex_str);
+      result->set_soname_regex(soname_regex);
       result->set_drops_artifact_from_ir(true);
     }
 
-  if (!soname_not_regex_str.empty())
+  if (soname_not_regex)
     {
-      result->set_soname_not_regex_str(soname_not_regex_str);
+      result->set_soname_not_regex(soname_not_regex);
       result->set_drops_artifact_from_ir(true);
     }
 
diff --git a/src/abg-tools-utils.cc b/src/abg-tools-utils.cc
index 11486a21..fe0de750 100644
--- a/src/abg-tools-utils.cc
+++ b/src/abg-tools-utils.cc
@@ -1810,13 +1810,15 @@ handle_file_entry(const string& file_path,
 {
   if (!suppr)
     {
-      suppr.reset(new type_suppression(get_private_types_suppr_spec_label(),
-				       /*type_name_regexp=*/"",
-				       /*type_name=*/""));
+      suppr.reset(
+	new type_suppression(get_private_types_suppr_spec_label(),
+			     /*type_name_regexp=*/regex::regex_t_sptr(),
+			     /*type_name=*/""));
 
       // Types that are defined in system headers are usually
       // OK to be considered as public types.
-      suppr->set_source_location_to_keep_regex_str("^/usr/include/");
+      regex::regex_t_sptr headers_regex = regex::compile("^/usr/include/");
+      suppr->set_source_location_to_keep_regex(headers_regex);
       suppr->set_is_artificial(true);
     }
 
@@ -2004,7 +2006,8 @@ gen_suppr_spec_from_kernel_abi_whitelists
 
       // Build a regular expression representing the union of all
       // the function and variable names expressed in the white list.
-      const std::string regex = regex::generate_from_strings(whitelisted_names);
+      regex::regex_t_sptr regex =
+	regex::compile(regex::generate_from_strings(whitelisted_names));
 
       // Build a suppression specification which *keeps* functions
       // whose ELF symbols match the regular expression contained
@@ -2013,7 +2016,7 @@ gen_suppr_spec_from_kernel_abi_whitelists
       // match this regexp.
       function_suppression_sptr fn_suppr(new function_suppression);
       fn_suppr->set_label("whitelist");
-      fn_suppr->set_symbol_name_not_regex_str(regex);
+      fn_suppr->set_symbol_name_not_regex(regex);
       fn_suppr->set_drops_artifact_from_ir(true);
       result.push_back(fn_suppr);
 
@@ -2024,7 +2027,7 @@ gen_suppr_spec_from_kernel_abi_whitelists
       // match this regexp.
       variable_suppression_sptr var_suppr(new variable_suppression);
       var_suppr->set_label("whitelist");
-      var_suppr->set_symbol_name_not_regex_str(regex);
+      var_suppr->set_symbol_name_not_regex(regex);
       var_suppr->set_drops_artifact_from_ir(true);
       result.push_back(var_suppr);
     }
diff --git a/tests/test-kmi-whitelist.cc b/tests/test-kmi-whitelist.cc
index bcc5adee..16cc1861 100644
--- a/tests/test-kmi-whitelist.cc
+++ b/tests/test-kmi-whitelist.cc
@@ -29,10 +29,14 @@
 #include "lib/catch.hpp"
 
 #include "abg-fwd.h"
-#include "abg-suppression.h"
+#include "abg-regex.h"
 #include "abg-tools-utils.h"
+#include "abg-suppression.h"
 #include "test-utils.h"
 
+using abigail::regex::regex_t_sptr;
+using abigail::regex::compile;
+using abigail::regex::match;
 using abigail::tools_utils::gen_suppr_spec_from_kernel_abi_whitelists;
 using abigail::suppr::suppression_sptr;
 using abigail::suppr::suppressions_type;
@@ -57,9 +61,30 @@ const static std::string whitelist_with_duplicate_entry
     = std::string(abigail::tests::get_src_dir())
       + "/tests/data/test-kmi-whitelist/whitelist-with-duplicate-entry";
 
+// These are strings, not regexes, we cannot exhaustively check all
+// strings, but we can do some sampling and match sure we haven't got
+// the regex logic completely wrong.
+static const char* const random_symbols[] =
+{
+  "",
+  ".*",
+  "^$",
+  "test_symbol",
+  "test-symbol",
+  "test symbol",
+  "Test Symbol",
+  "est_symbo",
+  ".*test_symbol.*",
+  "test_symbol ",
+  " test_symbol",
+  " test_symbol ",
+  "test_another_symbol",
+  "$test_another_symbol",
+};
+
 void
 test_suppressions_are_consistent(const suppressions_type& suppr,
-			    const std::string&	     expr)
+				 const std::string&	  expr)
 {
   REQUIRE(suppr.size() == 2);
 
@@ -74,11 +99,32 @@ test_suppressions_are_consistent(const suppressions_type& suppr,
   // same mode
   REQUIRE(left->get_drops_artifact_from_ir()
 	  == right->get_drops_artifact_from_ir());
-  // same regex
-  REQUIRE(left->get_symbol_name_not_regex_str()
-     == right->get_symbol_name_not_regex_str());
-  // regex as expected
-  REQUIRE(left->get_symbol_name_not_regex_str() == expr);
+
+  // these parts of the symbol name matching should be absent
+  REQUIRE(left->get_symbol_name().empty());
+  REQUIRE(!left->get_symbol_name_regex());
+  REQUIRE(right->get_symbol_name().empty());
+  REQUIRE(!right->get_symbol_name_regex());
+
+  regex_t_sptr left_regex = left->get_symbol_name_not_regex();
+  regex_t_sptr right_regex = right->get_symbol_name_not_regex();
+  regex_t_sptr check_regex = compile(expr);
+
+  // all regexes present (compiled)
+  REQUIRE(left_regex);
+  REQUIRE(right_regex);
+  REQUIRE(check_regex);
+
+  // all regexes match or do not match a random symbol
+  for (size_t i = 0; i < sizeof(random_symbols)/sizeof(random_symbols[0]); ++i)
+    {
+      const std::string symbol(random_symbols[i]);
+      bool left_matches = match(left_regex, symbol);
+      bool right_matches = match(right_regex, symbol);
+      bool check_matches = match(check_regex, symbol);
+      REQUIRE(left_matches == right_matches);
+      REQUIRE(left_matches == check_matches);
+    }
 }
 
 TEST_CASE("NoWhitelists", "[whitelists]")
-- 
2.26.2.303.gf8c07b1a785-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v3 12/21] Reduce direct access to suppression priv_ members.
  2020-04-24  9:21 ` [PATCH v3 00/21]Simplify " Giuliano Procida
                     ` (10 preceding siblings ...)
  2020-04-24  9:21   ` [PATCH v3 11/21] Compile suppression regexes earlier Giuliano Procida
@ 2020-04-24  9:21   ` Giuliano Procida
  2020-04-27 11:54     ` Matthias Maennich
  2020-04-24  9:21   ` [PATCH v3 13/21] Move match methods from priv to suppression_base Giuliano Procida
                     ` (9 subsequent siblings)
  21 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-04-24  9:21 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

Most suppression type functionality is available on the types
themselves via methods, particularly now that there are getters
for all the regex members.

This patch eliminates lots of accesses via priv_ members.

There are no behavioural changes.

	* src/abg-suppression.cc (sonames_of_binaries_match): Use
	suppression_matches_soname helper function.
	(suppression_matches_type_name): Use type_suppression regex getters.
	(suppression_matches_type_location): Use type_suppression
	regex getters.
	(function::suppression::suppresses_function): Use own regex
	getters.
	(function::suppression::suppresses_function_symbol): Use own
	regex getters.
	(suppression_matches_function_name): Use function_suppression
	regex and name getters.
	(suppression_matches_function_sym_name): Use function_suppression
	regex and symbol name getters.
	(suppression_matches_variable_name): Use variable__suppression
	regex and name getters.
	(suppression_matches_variable_sym_name): Use variable_suppression
	regex and symbol name getters.
	(suppression_matches_type): Use type_suppression
	regex getter.
	(variable_suppression::suppresses_variable): Use own regex
	getters.
	(variable_suppression::suppresses_variable_symbol): Use own
	regex getters.
	(type_suppression::suppresses_file): Use own regex getters.
	(suppression_matches_soname_or_filename): Indentation fix, en
	passant.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-suppression.cc | 107 +++++++++++++++++++----------------------
 1 file changed, 50 insertions(+), 57 deletions(-)

diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 6953c18b..7e501c45 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -275,8 +275,8 @@ sonames_of_binaries_match(const suppression_base& suppr,
   if (!suppr.has_soname_related_property())
     return false;
 
-  if (!suppr.priv_->matches_soname(first_soname)
-      && !suppr.priv_->matches_soname(second_soname))
+  if (!suppression_matches_soname(first_soname, suppr)
+      && !suppression_matches_soname(second_soname, suppr))
     return false;
 
   return true;
@@ -969,8 +969,8 @@ suppression_matches_type_name(const type_suppression&	s,
 			      const string&		type_name)
 {
   if (!s.get_type_name().empty()
-      || s.priv_->get_type_name_regex()
-      || s.priv_->get_type_name_not_regex())
+      || s.get_type_name_regex()
+      || s.get_type_name_not_regex())
     {
       // Check if there is an exact type name match.
       if (!s.get_type_name().empty())
@@ -986,14 +986,14 @@ suppression_matches_type_name(const type_suppression&	s,
 	  // the regular expression of the type name, then this
 	  // suppression doesn't apply.
 	  if (const regex_t_sptr& type_name_regex =
-	      s.priv_->get_type_name_regex())
+	      s.get_type_name_regex())
 	    {
 	      if (!regex::match(type_name_regex, type_name))
 		return false;
 	    }
 
 	  if (const regex_t_sptr type_name_not_regex =
-	      s.priv_->get_type_name_not_regex())
+	      s.get_type_name_not_regex())
 	    {
 	      if (regex::match(type_name_not_regex, type_name))
 		return false;
@@ -1041,7 +1041,7 @@ suppression_matches_type_location(const type_suppression&	s,
       unsigned loc_line = 0, loc_column = 0;
       loc.expand(loc_path, loc_line, loc_column);
 
-      if (regex_t_sptr regexp = s.priv_->get_source_location_to_keep_regex())
+      if (regex_t_sptr regexp = s.get_source_location_to_keep_regex())
 	if (regex::match(regexp, loc_path))
 	  return false;
 
@@ -1056,7 +1056,7 @@ suppression_matches_type_location(const type_suppression&	s,
   else
     {
       if (!s.get_source_locations_to_keep().empty()
-	  || s.priv_->get_source_location_to_keep_regex())
+	  || s.get_source_location_to_keep_regex())
 	// The user provided a "source_location_not_regexp" or
 	// a "source_location_not_in" property that was not
 	// triggered.  This means the current type suppression
@@ -1107,7 +1107,7 @@ suppression_matches_type_location(const type_suppression&	s,
 	    }
 	}
       if (!s.get_source_locations_to_keep().empty()
-	  || s.priv_->get_source_location_to_keep_regex())
+	  || s.get_source_location_to_keep_regex())
 	// The user provided a "source_location_not_regexp" or
 	// a "source_location_not_in" property that was not
 	// triggered.  This means the current type suppression
@@ -2481,7 +2481,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
 
   // check if the "name_regexp" property matches.
-  const regex_t_sptr name_regex = priv_->get_name_regex();
+  const regex_t_sptr name_regex = get_name_regex();
   if (name_regex)
     {
       if (!regex::match(name_regex, fname))
@@ -2512,7 +2512,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
 
   // check if the "name_not_regexp" property matches.
-  const regex_t_sptr name_not_regex = priv_->get_name_not_regex();
+  const regex_t_sptr name_not_regex = get_name_not_regex();
   if (name_not_regex)
     {
       if (regex::match(name_not_regex, fname))
@@ -2558,7 +2558,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
   else
     {
-      const regex_t_sptr return_type_regex = priv_->get_return_type_regex();
+      const regex_t_sptr return_type_regex = get_return_type_regex();
       if (return_type_regex
 	  && !regex::match(return_type_regex, fn_return_type_name))
 	return false;
@@ -2596,12 +2596,11 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
   else if (sym)
     {
-      const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
+      const regex_t_sptr symbol_name_regex = get_symbol_name_regex();
       if (symbol_name_regex && !regex::match(symbol_name_regex, fn_sym_name))
 	return false;
 
-      const regex_t_sptr symbol_name_not_regex =
-	priv_->get_symbol_name_not_regex();
+      const regex_t_sptr symbol_name_not_regex = get_symbol_name_not_regex();
       if (symbol_name_not_regex
 	  && regex::match(symbol_name_not_regex, fn_sym_name))
 	return false;
@@ -2638,8 +2637,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
   else if (sym)
     {
-      const regex_t_sptr symbol_version_regex =
-	priv_->get_symbol_version_regex();
+      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
       if (symbol_version_regex
 	  && !regex::match(symbol_version_regex, fn_sym_version))
 	return false;
@@ -2679,7 +2677,7 @@ function_suppression::suppresses_function(const function_decl* fn,
 	  else
 	    {
 	      const regex_t_sptr parm_type_name_regex =
-		(*p)->priv_->get_type_name_regex();
+		(*p)->get_parameter_type_name_regex();
 	      if (parm_type_name_regex)
 		{
 		  if (!regex::match(parm_type_name_regex,
@@ -2770,7 +2768,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
     }
   else if (get_symbol_name_regex())
     {
-      const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
+      const regex_t_sptr symbol_name_regex = get_symbol_name_regex();
       if (symbol_name_regex && !regex::match(symbol_name_regex, sym_name))
 	return false;
     }
@@ -2785,8 +2783,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
     }
   else if (get_symbol_version_regex())
     {
-      const regex_t_sptr symbol_version_regex =
-	priv_->get_symbol_version_regex();
+      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
       if (symbol_version_regex
 	  && !regex::match(symbol_version_regex, sym_version))
 	return false;
@@ -2878,21 +2875,21 @@ bool
 suppression_matches_function_name(const suppr::function_suppression& s,
 				  const string& fn_name)
 {
-  if (regex_t_sptr regexp = s.priv_->get_name_regex())
+  if (regex_t_sptr regexp = s.get_name_regex())
     {
       if (!regex::match(regexp, fn_name))
 	return false;
     }
-  else if (regex_t_sptr regexp = s.priv_->get_name_not_regex())
+  else if (regex_t_sptr regexp = s.get_name_not_regex())
     {
       if (regex::match(regexp, fn_name))
 	return false;
     }
-  else if (s.priv_->name_.empty())
+  else if (s.get_name().empty())
     return false;
-  else // if (!s.priv_->name_.empty())
+  else // if (!s.get_name().empty())
     {
-      if (s.priv_->name_ != fn_name)
+      if (s.get_name() != fn_name)
 	return false;
     }
 
@@ -2914,21 +2911,21 @@ bool
 suppression_matches_function_sym_name(const suppr::function_suppression& s,
 				      const string& fn_linkage_name)
 {
-  if (regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
+  if (regex_t_sptr regexp = s.get_symbol_name_regex())
     {
       if (!regex::match(regexp, fn_linkage_name))
 	return false;
     }
-  else if (regex_t_sptr regexp = s.priv_->get_symbol_name_not_regex())
+  else if (regex_t_sptr regexp = s.get_symbol_name_not_regex())
     {
       if (regex::match(regexp, fn_linkage_name))
 	return false;
     }
-  else if (s.priv_->symbol_name_.empty())
+  else if (s.get_symbol_name().empty())
     return false;
-  else // if (!s.priv_->symbol_name_.empty())
+  else // if (!s.get_symbol_name().empty())
     {
-      if (s.priv_->symbol_name_ != fn_linkage_name)
+      if (s.get_symbol_name() != fn_linkage_name)
 	return false;
     }
 
@@ -2947,21 +2944,21 @@ bool
 suppression_matches_variable_name(const suppr::variable_suppression& s,
 				  const string& var_name)
 {
-  if (regex_t_sptr regexp = s.priv_->get_name_regex())
+  if (regex_t_sptr regexp = s.get_name_regex())
     {
       if (!regex::match(regexp, var_name))
 	return false;
     }
-  else if (regex_t_sptr regexp = s.priv_->get_name_not_regex())
+  else if (regex_t_sptr regexp = s.get_name_not_regex())
     {
       if (regex::match(regexp, var_name))
 	return false;
     }
-  else if (s.priv_->name_.empty())
+  else if (s.get_name().empty())
     return false;
-  else // if (!s.priv_->name_.empty())
+  else // if (!s.get_name().empty())
     {
-      if (s.priv_->name_ != var_name)
+      if (s.get_name() != var_name)
 	return false;
     }
 
@@ -2981,22 +2978,21 @@ bool
 suppression_matches_variable_sym_name(const suppr::variable_suppression& s,
 				      const string& var_linkage_name)
 {
-  if (regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
+  if (regex_t_sptr regexp = s.get_symbol_name_regex())
     {
       if (!regex::match(regexp, var_linkage_name))
 	return false;
     }
-  else if (regex_t_sptr regexp =
-	   s.priv_->get_symbol_name_not_regex())
+  else if (regex_t_sptr regexp = s.get_symbol_name_not_regex())
     {
       if (regex::match(regexp, var_linkage_name))
 	return false;
     }
-  else if (s.priv_->symbol_name_.empty())
+  else if (s.get_symbol_name().empty())
     return false;
-  else // if (!s.priv_->symbol_name_.empty())
+  else // if (!s.get_symbol_name().empty())
     {
-      if (s.priv_->symbol_name_ != var_linkage_name)
+      if (s.get_symbol_name() != var_linkage_name)
 	return false;
     }
 
@@ -3016,7 +3012,7 @@ bool
 suppression_matches_type(const suppr::type_suppression& s,
 			 const string& type_name)
 {
-  if (regex_t_sptr regexp = s.priv_->get_type_name_regex())
+  if (regex_t_sptr regexp = s.get_type_name_regex())
     {
       if (!regex::match(regexp, type_name))
 	return false;
@@ -3725,11 +3721,11 @@ variable_suppression::suppresses_variable(const var_decl* var,
       // "name_regex" and "name_not_regex" properties match
       if (get_name().empty())
 	{
-	  const regex_t_sptr name_regex = priv_->get_name_regex();
+	  const regex_t_sptr name_regex = get_name_regex();
 	  if (name_regex && !regex::match(name_regex, var_name))
 	    return false;
 
-	  const regex_t_sptr name_not_regex = priv_->get_name_not_regex();
+	  const regex_t_sptr name_not_regex = get_name_not_regex();
 	  if (name_not_regex && regex::match(name_not_regex, var_name))
 	    return false;
 	}
@@ -3745,12 +3741,11 @@ variable_suppression::suppresses_variable(const var_decl* var,
     }
   else
     {
-      const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
+      const regex_t_sptr sym_name_regex = get_symbol_name_regex();
       if (sym_name_regex && !regex::match(sym_name_regex, var_sym_name))
 	return false;
 
-      const regex_t_sptr sym_name_not_regex =
-	priv_->get_symbol_name_not_regex();
+      const regex_t_sptr sym_name_not_regex = get_symbol_name_not_regex();
       if (sym_name_not_regex && regex::match(sym_name_not_regex, var_sym_name))
 	return false;
     }
@@ -3765,8 +3760,7 @@ variable_suppression::suppresses_variable(const var_decl* var,
     }
   else
     {
-      const regex_t_sptr symbol_version_regex =
-	priv_->get_symbol_version_regex();
+      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
       if (symbol_version_regex
 	  && !regex::match(symbol_version_regex, var_sym_version))
 	return false;
@@ -3785,7 +3779,7 @@ variable_suppression::suppresses_variable(const var_decl* var,
     {
       if (get_type_name().empty())
 	{
-	  const regex_t_sptr type_name_regex = priv_->get_type_name_regex();
+	  const regex_t_sptr type_name_regex = get_type_name_regex();
 	  if (type_name_regex && !regex::match(type_name_regex, var_type_name))
 	    return false;
 	}
@@ -3876,7 +3870,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
     }
   else if (get_symbol_name_regex())
     {
-      const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
+      const regex_t_sptr sym_name_regex = get_symbol_name_regex();
       if (sym_name_regex && !regex::match(sym_name_regex, sym_name))
 	return false;
     }
@@ -3892,8 +3886,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
     }
   else if (get_symbol_version_regex())
     {
-      const regex_t_sptr symbol_version_regex =
-	priv_->get_symbol_version_regex();
+      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
       if (symbol_version_regex
 	  && !regex::match(symbol_version_regex, sym_version))
 	return false;
@@ -4196,14 +4189,14 @@ file_suppression::suppresses_file(const string& file_path)
 
   bool has_regexp = false;
 
-  if (regex_t_sptr regexp = suppression_base::priv_->get_file_name_regex())
+  if (regex_t_sptr regexp = get_file_name_regex())
     {
       has_regexp = true;
       if (!regex::match(regexp, fname))
 	return false;
     }
 
-  if (regex_t_sptr regexp = suppression_base::priv_->get_file_name_not_regex())
+  if (regex_t_sptr regexp = get_file_name_not_regex())
     {
       has_regexp = true;
       if (regex::match(regexp, fname))
@@ -4357,7 +4350,7 @@ suppression_matches_soname_or_filename(const string& soname,
 				       const suppression_base& suppr)
 {
   return (suppression_matches_soname(soname, suppr)
-	 || suppr.priv_->matches_binary_name(filename));
+	  || suppr.priv_->matches_binary_name(filename));
 }
 
 /// @return the name of the artificial private type suppression
-- 
2.26.2.303.gf8c07b1a785-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v3 13/21] Move match methods from priv to suppression_base.
  2020-04-24  9:21 ` [PATCH v3 00/21]Simplify " Giuliano Procida
                     ` (11 preceding siblings ...)
  2020-04-24  9:21   ` [PATCH v3 12/21] Reduce direct access to suppression priv_ members Giuliano Procida
@ 2020-04-24  9:21   ` Giuliano Procida
  2020-04-27 11:55     ` Matthias Maennich
  2020-04-24  9:21   ` [PATCH v3 14/21] Remove suppression types' priv class methods Giuliano Procida
                     ` (8 subsequent siblings)
  21 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-04-24  9:21 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

The suppression_base::priv methods matches_soname and
matches_binary_name do not require special access to the priv class
and can be moved to the main suppression_base class and use its
getters.

This is a step towards simplifying the suppression type priv classes
to the point they are simple data containers.

There are no behavioural changes.

	* include/abg-suppression.h
	(suppression_base::matches_soname): Add	declaration.
	(suppression_base::matches_binary_name): Add declaration.
	(suppression_base): Remove friend declarations of
	suppression_matches_soname and
	suppression_matches_soname_or_filename.
	* src/abg-dwarf-reader.cc (suppression_can_match): Call
	matches_soname and matches_binary_name on suppression values
	directly.
	* src/abg-reader.cc (suppression_can_match): Call
	matches_soname and matches_binary_name on suppression values
	directly.
	* src/abg-suppression-priv.h
	(suppression_base::priv::matches_soname): Remove method.
	(suppression_base::priv::matches_binary_name): Remove method.
	* src/abg-suppression.cc
	(suppression_base::matches_soname): Add definition.
	(suppression_base::matches_binary_name): Add definition.
	(names_of_binaries_match): Call matches_binary_name on
	suppression values directly. (suppression_matches_soname):
	Call matches_soname on suppression values directly.
	(suppression_matches_soname_or_filename): Call
	matches_binary_name on suppression values directly.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 include/abg-suppression.h  | 15 +++-----
 src/abg-dwarf-reader.cc    |  4 +-
 src/abg-reader.cc          |  4 +-
 src/abg-suppression-priv.h | 71 +----------------------------------
 src/abg-suppression.cc     | 76 ++++++++++++++++++++++++++++++++++++--
 5 files changed, 83 insertions(+), 87 deletions(-)

diff --git a/include/abg-suppression.h b/include/abg-suppression.h
index 1869cbe5..02e77ea9 100644
--- a/include/abg-suppression.h
+++ b/include/abg-suppression.h
@@ -116,19 +116,16 @@ public:
   bool
   has_soname_related_property() const;
 
+  bool
+  matches_soname(const string& soname) const;
+
+  bool
+  matches_binary_name(const string& binary_name) const;
+
   virtual bool
   suppresses_diff(const diff*) const = 0;
 
   virtual ~suppression_base();
-
-  friend bool
-  suppression_matches_soname(const string& soname,
-			     const suppression_base& suppr);
-
-  friend bool
-  suppression_matches_soname_or_filename(const string& soname,
-					 const string& filename,
-					 const suppression_base& suppr);
 }; // end class suppression_base
 
 void
diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
index 850281ad..c9e6f918 100644
--- a/src/abg-dwarf-reader.cc
+++ b/src/abg-dwarf-reader.cc
@@ -7723,14 +7723,14 @@ public:
   bool
   suppression_can_match(const suppr::suppression_base& s) const
   {
-    if (!s.priv_->matches_soname(dt_soname()))
+    if (!s.matches_soname(dt_soname()))
       if (s.has_soname_related_property())
 	// The suppression has some SONAME related properties, but
 	// none of them match the SONAME of the current binary.  So
 	// the suppression cannot match the current binary.
 	return false;
 
-    if (!s.priv_->matches_binary_name(elf_path()))
+    if (!s.matches_binary_name(elf_path()))
       if (s.has_file_name_related_property())
 	// The suppression has some file_name related properties, but
 	// none of them match the file name of the current binary.  So
diff --git a/src/abg-reader.cc b/src/abg-reader.cc
index dcaa27e1..5e0b97e0 100644
--- a/src/abg-reader.cc
+++ b/src/abg-reader.cc
@@ -999,14 +999,14 @@ public:
   {
     corpus_sptr corp = get_corpus();
 
-    if (!s.priv_->matches_soname(corp->get_soname()))
+    if (!s.matches_soname(corp->get_soname()))
       if (s.has_soname_related_property())
 	// The suppression has some SONAME related properties, but
 	// none of them match the SONAME of the current binary.  So
 	// the suppression cannot match the current binary.
 	return false;
 
-    if (!s.priv_->matches_binary_name(corp->get_path()))
+    if (!s.matches_binary_name(corp->get_path()))
       if (s.has_file_name_related_property())
 	// The suppression has some file_name related properties, but
 	// none of them match the file name of the current binary.  So
diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
index 263052d4..5c06d5d0 100644
--- a/src/abg-suppression-priv.h
+++ b/src/abg-suppression-priv.h
@@ -107,76 +107,7 @@ public:
   {
     return soname_not_regex_;
   }
-
-  /// Test if the current suppression matches a given SONAME.
-  ///
-  /// @param soname the SONAME to consider.
-  ///
-  /// @return true iff the suppression matches the SONAME denoted by
-  /// @p soname.
-  ///
-  /// Note that if the suppression contains no property that is
-  /// related to SONAMEs, the function returns false.
-  bool
-  matches_soname(const string& soname) const
-  {
-    bool has_regexp = false;
-    if (regex::regex_t_sptr regexp = get_soname_regex())
-      {
-	has_regexp = true;
-	if (!regex::match(regexp, soname))
-	  return false;
-      }
-
-    if (regex::regex_t_sptr regexp = get_soname_not_regex())
-      {
-	has_regexp = true;
-	if (regex::match(regexp, soname))
-	  return false;
-      }
-
-      if (!has_regexp)
-	return false;
-
-    return true;
-  }
-
-  /// Test if the current suppression matches the full file path to a
-  /// given binary.
-  ///
-  /// @param binary_name the full path to the binary.
-  ///
-  /// @return true iff the suppression matches the path denoted by @p
-  /// binary_name.
-  ///
-  /// Note that if the suppression contains no property that is
-  /// related to file name, the function returns false.
-  bool
-  matches_binary_name(const string& binary_name) const
-  {
-    bool has_regexp = false;
-
-    if (regex::regex_t_sptr regexp = get_file_name_regex())
-      {
-	has_regexp = true;
-	if (!regex::match(regexp, binary_name))
-	  return false;
-      }
-
-    if (regex::regex_t_sptr regexp = get_file_name_not_regex())
-      {
-	has_regexp = true;
-	if (regex::match(regexp, binary_name))
-	  return false;
-      }
-
-    if (!has_regexp)
-      return false;
-
-    return true;
-  }
-
-}; // end clas suppression_base::priv
+}; // end class suppression_base::priv
 
 // </suppression_base stuff>
 
diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 7e501c45..191c65c6 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -252,6 +252,74 @@ suppression_base::has_soname_related_property() const
   return get_soname_regex() || get_soname_not_regex();
 }
 
+/// Test if the current suppression matches a given SONAME.
+///
+/// @param soname the SONAME to consider.
+///
+/// @return true iff the suppression matches the SONAME denoted by
+/// @p soname.
+///
+/// Note that if the suppression contains no property that is
+/// related to SONAMEs, the function returns false.
+bool
+suppression_base::matches_soname(const string& soname) const
+{
+  bool has_regexp = false;
+  if (regex::regex_t_sptr regexp = get_soname_regex())
+    {
+      has_regexp = true;
+      if (!regex::match(regexp, soname))
+        return false;
+    }
+
+  if (regex::regex_t_sptr regexp = get_soname_not_regex())
+    {
+      has_regexp = true;
+      if (regex::match(regexp, soname))
+        return false;
+    }
+
+  if (!has_regexp)
+    return false;
+
+  return true;
+}
+
+/// Test if the current suppression matches the full file path to a
+/// given binary.
+///
+/// @param binary_name the full path to the binary.
+///
+/// @return true iff the suppression matches the path denoted by @p
+/// binary_name.
+///
+/// Note that if the suppression contains no property that is
+/// related to file name, the function returns false.
+bool
+suppression_base::matches_binary_name(const string& binary_name) const
+{
+  bool has_regexp = false;
+
+  if (regex::regex_t_sptr regexp = get_file_name_regex())
+    {
+      has_regexp = true;
+      if (!regex::match(regexp, binary_name))
+        return false;
+    }
+
+  if (regex::regex_t_sptr regexp = get_file_name_not_regex())
+    {
+      has_regexp = true;
+      if (regex::match(regexp, binary_name))
+        return false;
+    }
+
+  if (!has_regexp)
+    return false;
+
+  return true;
+}
+
 /// Check if the SONAMEs of the two binaries being compared match the
 /// content of the properties "soname_regexp" and "soname_not_regexp"
 /// of the current suppression specification.
@@ -305,8 +373,8 @@ names_of_binaries_match(const suppression_base& suppr,
   if (!suppr.has_file_name_related_property())
     return false;
 
-  if (!suppr.priv_->matches_binary_name(first_binary_path)
-      && !suppr.priv_->matches_binary_name(second_binary_path))
+  if (!suppr.matches_binary_name(first_binary_path)
+      && !suppr.matches_binary_name(second_binary_path))
     return false;
 
   return true;
@@ -4330,7 +4398,7 @@ bool
 suppression_matches_soname(const string& soname,
 			   const suppression_base& suppr)
 {
-  return suppr.priv_->matches_soname(soname);
+  return suppr.matches_soname(soname);
 }
 
 /// Test if a given SONAME or file name is matched by a given
@@ -4350,7 +4418,7 @@ suppression_matches_soname_or_filename(const string& soname,
 				       const suppression_base& suppr)
 {
   return (suppression_matches_soname(soname, suppr)
-	  || suppr.priv_->matches_binary_name(filename));
+	  || suppr.matches_binary_name(filename));
 }
 
 /// @return the name of the artificial private type suppression
-- 
2.26.2.303.gf8c07b1a785-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v3 14/21] Remove suppression types' priv class methods.
  2020-04-24  9:21 ` [PATCH v3 00/21]Simplify " Giuliano Procida
                     ` (12 preceding siblings ...)
  2020-04-24  9:21   ` [PATCH v3 13/21] Move match methods from priv to suppression_base Giuliano Procida
@ 2020-04-24  9:21   ` Giuliano Procida
  2020-04-27 11:57     ` Matthias Maennich
  2020-04-24  9:21   ` [PATCH v3 15/21] abg-suppression.cc: More consistent regex matching Giuliano Procida
                     ` (7 subsequent siblings)
  21 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-04-24  9:21 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

The type_suppression::set_type_name_not_regex method is the only
remaining user of all the various suppression_type::priv member
functions. This is easily remedied and all the remaining priv member
functions (regex getters and setters) can be dropped.

This patches leaves all the various suppression priv types as simple
data containers (modulo their constructors).

There are no behavioural changes.

	* src/abg-suppression-priv.h (suppression_base::priv): Drop
	all regex getter methods.
	(function_suppression::parameter_spec::priv): Drop all regex
	getter methods.
	(function_suppression::priv): Drop all regex getter methods.
	(variable_suppression::priv): Drop all regex getter methods.
	(type_suppression::priv): Drop all regex getter and setter
	methods.
	* src/abg-suppression.cc (set_type_name_not_regex): Access
	priv_->type_name_not_regex_ directly.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-suppression-priv.h | 182 -------------------------------------
 src/abg-suppression.cc     |   2 +-
 2 files changed, 1 insertion(+), 183 deletions(-)

diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
index 5c06d5d0..78f11e2f 100644
--- a/src/abg-suppression-priv.h
+++ b/src/abg-suppression-priv.h
@@ -75,38 +75,6 @@ public:
   {}
 
   friend class suppression_base;
-
-  /// Get the regular expression object associated to the
-  /// 'file_name_regex' property of @ref suppression_base.
-  const regex::regex_t_sptr&
-  get_file_name_regex() const
-  {
-    return file_name_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'file_name_not_regex' property of @ref suppression_base.
-  const regex::regex_t_sptr&
-  get_file_name_not_regex() const
-  {
-    return file_name_not_regex_;
-  }
-
-  /// Get the regular expression object associated to the 'soname_regex'
-  /// property of @ref suppression_base.
-  const regex::regex_t_sptr&
-  get_soname_regex() const
-  {
-    return soname_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'soname_not_regex' property of @ref suppression_base.
-  const regex::regex_t_sptr&
-  get_soname_not_regex() const
-  {
-    return soname_not_regex_;
-  }
 }; // end class suppression_base::priv
 
 // </suppression_base stuff>
@@ -133,15 +101,6 @@ class function_suppression::parameter_spec::priv
   priv(size_t i, const string& tn, const regex::regex_t_sptr& tn_regex)
     : index_(i), type_name_(tn), type_name_regex_(tn_regex)
   {}
-
-  /// Get the regular expression object associated to the
-  /// 'type_name_regex' property of @ref
-  /// function_suppression::parameter_spec.
-  const regex::regex_t_sptr
-  get_type_name_regex() const
-  {
-    return type_name_regex_;
-  }
 }; // end class function_suppression::parameter_spec::priv
 
 
@@ -191,54 +150,6 @@ struct function_suppression::priv
       symbol_version_regex_(symbol_version_regex),
       allow_other_aliases_(true)
   {}
-
-  /// Get the regular expression object associated to the 'name_regex'
-  /// property of @ref function_suppression.
-  const regex::regex_t_sptr
-  get_name_regex() const
-  {
-    return name_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'name_not_regex' property of @ref function_suppression.
-  const regex::regex_t_sptr
-  get_name_not_regex() const
-  {
-    return name_not_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'return_type_regex' property of @ref function_suppression.
-  const regex::regex_t_sptr
-  get_return_type_regex() const
-  {
-    return return_type_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'symbol_name_regex' property of @ref function_suppression.
-  const regex::regex_t_sptr
-  get_symbol_name_regex() const
-  {
-    return symbol_name_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'symbol_name_not_regex' property of @ref function_suppression.
-  const regex::regex_t_sptr
-  get_symbol_name_not_regex() const
-  {
-    return symbol_name_not_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'symbol_version_regex' property of @ref function_suppression.
-  const regex::regex_t_sptr
-  get_symbol_version_regex() const
-  {
-    return symbol_version_regex_;
-  }
 }; // end class function_suppression::priv
 
 bool
@@ -343,54 +254,6 @@ struct variable_suppression::priv
       type_name_(type_name),
       type_name_regex_(type_name_regex)
   {}
-
-  /// Get the regular expression object associated to the 'name_regex'
-  /// property of @ref variable_suppression.
-  const regex::regex_t_sptr
-  get_name_regex() const
-  {
-    return name_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'name_not_regex' property of @ref variable_suppression.
-  const regex::regex_t_sptr
-  get_name_not_regex() const
-  {
-    return name_not_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'symbol_name_regex' property of @ref variable_suppression.
-  const regex::regex_t_sptr
-  get_symbol_name_regex() const
-  {
-    return symbol_name_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'symbol_name_not_regex' property of @ref variable_suppression.
-  const regex::regex_t_sptr
-  get_symbol_name_not_regex() const
-  {
-    return symbol_name_not_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'symbol_version_regex' property of @ref variable_suppression.
-  const regex::regex_t_sptr
-  get_symbol_version_regex()  const
-  {
-    return symbol_version_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'type_name_regex' property of @ref variable_suppression.
-  const regex::regex_t_sptr
-  get_type_name_regex() const
-  {
-    return type_name_regex_;
-  }
 };// end class variable_supppression::priv
 
 template <typename ReadContextType>
@@ -454,51 +317,6 @@ public:
       reach_kind_(reach_kind)
   {}
 
-  /// Get the regular expression object associated to the
-  /// 'type_name_regex' property of @ref type_suppression.
-  const regex::regex_t_sptr
-  get_type_name_regex() const
-  {
-    return type_name_regex_;
-  }
-
-  /// Setter for the type_name_regex object.
-  ///
-  /// @param r the new type_name_regex object.
-  void
-  set_type_name_regex(regex::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.
-  const regex::regex_t_sptr
-  get_type_name_not_regex() const
-  {
-    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(regex::regex_t_sptr r)
-  {type_name_not_regex_ = r;}
-
-  /// Get the regular expression object associated to the
-  /// 'source_location_to_keep_regex' property of @ref type_suppression.
-  const regex::regex_t_sptr
-  get_source_location_to_keep_regex() const
-  {
-    return source_location_to_keep_regex_;
-  }
-
-  /// Setter for the source_location_to_keep_regex object.
-  ///
-  /// @param r the new regex object.
-  void
-  set_source_location_to_keep_regex(regex::regex_t_sptr r)
-  {source_location_to_keep_regex_ = r;}
-
   friend class type_suppression;
 }; // class type_suppression::priv
 
diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 191c65c6..331995bf 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -515,7 +515,7 @@ type_suppression::get_type_name_regex() const
 /// @param r the new regexp string.
 void
 type_suppression::set_type_name_not_regex(const regex_t_sptr& r)
-{priv_->set_type_name_not_regex(r);}
+{priv_->type_name_not_regex_ = r;}
 
 /// Getter for the "type_name_not_regex" property of the type
 /// suppression specification.
-- 
2.26.2.303.gf8c07b1a785-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v3 15/21] abg-suppression.cc: More consistent regex matching.
  2020-04-24  9:21 ` [PATCH v3 00/21]Simplify " Giuliano Procida
                     ` (13 preceding siblings ...)
  2020-04-24  9:21   ` [PATCH v3 14/21] Remove suppression types' priv class methods Giuliano Procida
@ 2020-04-24  9:21   ` Giuliano Procida
  2020-04-27 12:07     ` Matthias Maennich
  2020-04-24  9:21   ` [PATCH v3 16/21] abg-tools-utils.cc: Assert generated regexes OK Giuliano Procida
                     ` (6 subsequent siblings)
  21 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-04-24  9:21 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

Following previous patches, various minor inconsistencies in the
suppression regex matching code were more readily apparent.

- regex_t_sptr values are fetched both by reference and by
  value (which has a reference count mutation cost)
- there's a mixture of code styles for testing regex presence
    - regex = ...; if (regex && ...)
    - if (regex = ...) if (...)
  the latter has the advantage that the variable has a smaller scope
  and can be given a shorter name
- in some cases there are redundant tests (always true due to previous
  conditional logic)

This patch ensures all shared pointers to compiled regexes are fetched
by const reference and that the code uses the nested if style of
presence checking where possible. It simplifies some logic where
there's redundancy.

There are no behavioural changes. There may be performance
improvements.

	* src/abg-suppression.cc (suppression_matches_type_name): Get
	regexes by const reference.
	(suppression_matches_type_location): Get regexes by const
	reference. (function_suppression::suppresses_function): Get
	regexes by const reference; use nested if checks; simplify
	logic around symbol version checks.
	(function_suppression::suppresses_function_symbol): Get
	regexes by const reference; use nested if checks; remove
	redundant regex presence checks.
	(suppression_matches_function_name): Get regexes by const
	reference. (suppression_matches_function_sym_name): Get
	regexes by const reference.
	(suppression_matches_variable_name): Get regexes by const
	reference. (suppression_matches_variable_sym_name): Get
	regexes by const reference. (suppression_matches_type): Get
	regexes by const reference.
	(variable_suppression::suppresses_variable): Get regexes by
	const reference; use nested if checks; remove redundant
	type_name empty check.
	(variable_suppression::suppresses_variable_symbol): Get
	regexes by const reference; use nested if checks.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-suppression.cc | 167 +++++++++++++++++++----------------------
 1 file changed, 76 insertions(+), 91 deletions(-)

diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 331995bf..7d411caf 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -1053,15 +1053,14 @@ 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.
-	  if (const regex_t_sptr& type_name_regex =
-	      s.get_type_name_regex())
+	  if (const regex_t_sptr& type_name_regex = s.get_type_name_regex())
 	    {
 	      if (!regex::match(type_name_regex, type_name))
 		return false;
 	    }
 
-	  if (const regex_t_sptr type_name_not_regex =
-	      s.get_type_name_not_regex())
+	  if (const regex_t_sptr& type_name_not_regex =
+		s.get_type_name_not_regex())
 	    {
 	      if (regex::match(type_name_not_regex, type_name))
 		return false;
@@ -1109,7 +1108,7 @@ suppression_matches_type_location(const type_suppression&	s,
       unsigned loc_line = 0, loc_column = 0;
       loc.expand(loc_path, loc_line, loc_column);
 
-      if (regex_t_sptr regexp = s.get_source_location_to_keep_regex())
+      if (const regex_t_sptr& regexp = s.get_source_location_to_keep_regex())
 	if (regex::match(regexp, loc_path))
 	  return false;
 
@@ -2549,7 +2548,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
 
   // check if the "name_regexp" property matches.
-  const regex_t_sptr name_regex = get_name_regex();
+  const regex_t_sptr& name_regex = get_name_regex();
   if (name_regex)
     {
       if (!regex::match(name_regex, fname))
@@ -2580,7 +2579,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
 
   // check if the "name_not_regexp" property matches.
-  const regex_t_sptr name_not_regex = get_name_not_regex();
+  const regex_t_sptr& name_not_regex = get_name_not_regex();
   if (name_not_regex)
     {
       if (regex::match(name_not_regex, fname))
@@ -2624,11 +2623,9 @@ function_suppression::suppresses_function(const function_decl* fn,
       if (fn_return_type_name != get_return_type_name())
 	return false;
     }
-  else
+  else if (const regex_t_sptr& regex = get_return_type_regex())
     {
-      const regex_t_sptr return_type_regex = get_return_type_regex();
-      if (return_type_regex
-	  && !regex::match(return_type_regex, fn_return_type_name))
+      if (!regex::match(regex, fn_return_type_name))
 	return false;
     }
 
@@ -2664,14 +2661,15 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
   else if (sym)
     {
-      const regex_t_sptr symbol_name_regex = get_symbol_name_regex();
-      if (symbol_name_regex && !regex::match(symbol_name_regex, fn_sym_name))
-	return false;
+      const regex_t_sptr& symbol_name_regex = get_symbol_name_regex();
+      const regex_t_sptr& symbol_name_not_regex = get_symbol_name_not_regex();
 
-      const regex_t_sptr symbol_name_not_regex = get_symbol_name_not_regex();
-      if (symbol_name_not_regex
-	  && regex::match(symbol_name_not_regex, fn_sym_name))
-	return false;
+      if (symbol_name_regex)
+	if (!regex::match(symbol_name_regex, fn_sym_name))
+	  return false;
+      if (symbol_name_not_regex)
+	if (regex::match(symbol_name_not_regex, fn_sym_name))
+	  return false;
 
       if (get_allow_other_aliases())
 	{
@@ -2684,13 +2682,13 @@ function_suppression::suppresses_function(const function_decl* fn,
 		   a && !a->is_main_symbol();
 		   a = a->get_next_alias())
 		{
-		  if (symbol_name_regex
-		      && !regex::match(symbol_name_regex, a->get_name()))
-		    return false;
-
-		  if (symbol_name_not_regex
-		      && regex::match(symbol_name_not_regex, a->get_name()))
-		    return false;
+		  const std::string& alias_name = a->get_name();
+		  if (symbol_name_regex)
+		    if (!regex::match(symbol_name_regex, alias_name))
+		      return false;
+		  if (symbol_name_not_regex)
+		    if (regex::match(symbol_name_not_regex, alias_name))
+		      return false;
 		}
 	    }
 	}
@@ -2698,17 +2696,19 @@ function_suppression::suppresses_function(const function_decl* fn,
 
   // Check if the "symbol_version" and "symbol_version_regexp"
   // properties match.
-  if (sym && !get_symbol_version().empty())
-    {
-      if (fn_sym_version != get_symbol_version())
-	return false;
-    }
-  else if (sym)
+  if (sym)
     {
-      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
-      if (symbol_version_regex
-	  && !regex::match(symbol_version_regex, fn_sym_version))
-	return false;
+      if (!get_symbol_version().empty())
+	{
+	  if (fn_sym_version != get_symbol_version())
+	    return false;
+	}
+      else
+	{
+	  if (const regex_t_sptr& regex = get_symbol_version_regex())
+	    if (!regex::match(regex, fn_sym_version))
+	      return false;
+	}
     }
 
   // Check the 'parameter' property.
@@ -2742,16 +2742,11 @@ function_suppression::suppresses_function(const function_decl* fn,
 	      if (tn != fn_parm_type_qualified_name)
 		return false;
 	    }
-	  else
+	  else if (const regex_t_sptr& regex =
+		     (*p)->get_parameter_type_name_regex())
 	    {
-	      const regex_t_sptr parm_type_name_regex =
-		(*p)->get_parameter_type_name_regex();
-	      if (parm_type_name_regex)
-		{
-		  if (!regex::match(parm_type_name_regex,
-				    fn_parm_type_qualified_name))
-		    return false;
-		}
+	      if (!regex::match(regex, fn_parm_type_qualified_name))
+		return false;
 	    }
 	}
     }
@@ -2834,10 +2829,9 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
       if (sym_name != get_symbol_name())
 	return false;
     }
-  else if (get_symbol_name_regex())
+  else if (const regex_t_sptr& regex = get_symbol_name_regex())
     {
-      const regex_t_sptr symbol_name_regex = get_symbol_name_regex();
-      if (symbol_name_regex && !regex::match(symbol_name_regex, sym_name))
+      if (!regex::match(regex, sym_name))
 	return false;
     }
   else
@@ -2849,11 +2843,9 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
       if (sym_version != get_symbol_version())
 	return false;
     }
-  else if (get_symbol_version_regex())
+  else if (const regex_t_sptr& regex = get_symbol_version_regex())
     {
-      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
-      if (symbol_version_regex
-	  && !regex::match(symbol_version_regex, sym_version))
+      if (!regex::match(regex, sym_version))
 	return false;
     }
   else
@@ -2943,12 +2935,12 @@ bool
 suppression_matches_function_name(const suppr::function_suppression& s,
 				  const string& fn_name)
 {
-  if (regex_t_sptr regexp = s.get_name_regex())
+  if (const regex_t_sptr& regexp = s.get_name_regex())
     {
       if (!regex::match(regexp, fn_name))
 	return false;
     }
-  else if (regex_t_sptr regexp = s.get_name_not_regex())
+  else if (const regex_t_sptr& regexp = s.get_name_not_regex())
     {
       if (regex::match(regexp, fn_name))
 	return false;
@@ -2979,12 +2971,12 @@ bool
 suppression_matches_function_sym_name(const suppr::function_suppression& s,
 				      const string& fn_linkage_name)
 {
-  if (regex_t_sptr regexp = s.get_symbol_name_regex())
+  if (const regex_t_sptr& regexp = s.get_symbol_name_regex())
     {
       if (!regex::match(regexp, fn_linkage_name))
 	return false;
     }
-  else if (regex_t_sptr regexp = s.get_symbol_name_not_regex())
+  else if (const regex_t_sptr& regexp = s.get_symbol_name_not_regex())
     {
       if (regex::match(regexp, fn_linkage_name))
 	return false;
@@ -3012,12 +3004,12 @@ bool
 suppression_matches_variable_name(const suppr::variable_suppression& s,
 				  const string& var_name)
 {
-  if (regex_t_sptr regexp = s.get_name_regex())
+  if (const regex_t_sptr& regexp = s.get_name_regex())
     {
       if (!regex::match(regexp, var_name))
 	return false;
     }
-  else if (regex_t_sptr regexp = s.get_name_not_regex())
+  else if (const regex_t_sptr& regexp = s.get_name_not_regex())
     {
       if (regex::match(regexp, var_name))
 	return false;
@@ -3046,12 +3038,12 @@ bool
 suppression_matches_variable_sym_name(const suppr::variable_suppression& s,
 				      const string& var_linkage_name)
 {
-  if (regex_t_sptr regexp = s.get_symbol_name_regex())
+  if (const regex_t_sptr& regexp = s.get_symbol_name_regex())
     {
       if (!regex::match(regexp, var_linkage_name))
 	return false;
     }
-  else if (regex_t_sptr regexp = s.get_symbol_name_not_regex())
+  else if (const regex_t_sptr& regexp = s.get_symbol_name_not_regex())
     {
       if (regex::match(regexp, var_linkage_name))
 	return false;
@@ -3080,7 +3072,7 @@ bool
 suppression_matches_type(const suppr::type_suppression& s,
 			 const string& type_name)
 {
-  if (regex_t_sptr regexp = s.get_type_name_regex())
+  if (const regex_t_sptr& regexp = s.get_type_name_regex())
     {
       if (!regex::match(regexp, type_name))
 	return false;
@@ -3789,13 +3781,13 @@ variable_suppression::suppresses_variable(const var_decl* var,
       // "name_regex" and "name_not_regex" properties match
       if (get_name().empty())
 	{
-	  const regex_t_sptr name_regex = get_name_regex();
-	  if (name_regex && !regex::match(name_regex, var_name))
-	    return false;
+	  if (const regex_t_sptr& regex = get_name_regex())
+	    if (!regex::match(regex, var_name))
+	      return false;
 
-	  const regex_t_sptr name_not_regex = get_name_not_regex();
-	  if (name_not_regex && regex::match(name_not_regex, var_name))
-	    return false;
+	  if (const regex_t_sptr& regex = get_name_not_regex())
+	    if (regex::match(regex, var_name))
+	      return false;
 	}
     }
 
@@ -3809,13 +3801,13 @@ variable_suppression::suppresses_variable(const var_decl* var,
     }
   else
     {
-      const regex_t_sptr sym_name_regex = get_symbol_name_regex();
-      if (sym_name_regex && !regex::match(sym_name_regex, var_sym_name))
-	return false;
+      if (const regex_t_sptr& regex = get_symbol_name_regex())
+	if (!regex::match(regex, var_sym_name))
+	  return false;
 
-      const regex_t_sptr sym_name_not_regex = get_symbol_name_not_regex();
-      if (sym_name_not_regex && regex::match(sym_name_not_regex, var_sym_name))
-	return false;
+      if (const regex_t_sptr& regex = get_symbol_name_not_regex())
+	if (regex::match(regex, var_sym_name))
+	  return false;
     }
 
   // Check for symbol_version and symbol_version_regexp property match
@@ -3828,10 +3820,9 @@ variable_suppression::suppresses_variable(const var_decl* var,
     }
   else
     {
-      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
-      if (symbol_version_regex
-	  && !regex::match(symbol_version_regex, var_sym_version))
-	return false;
+      if (const regex_t_sptr& regex = get_symbol_version_regex())
+	if (!regex::match(regex, var_sym_version))
+	  return false;
     }
 
   // Check for the "type_name" and type_name_regex properties match.
@@ -3845,12 +3836,9 @@ variable_suppression::suppresses_variable(const var_decl* var,
     }
   else
     {
-      if (get_type_name().empty())
-	{
-	  const regex_t_sptr type_name_regex = get_type_name_regex();
-	  if (type_name_regex && !regex::match(type_name_regex, var_type_name))
-	    return false;
-	}
+      if (const regex_t_sptr& regex = get_type_name_regex())
+	if (!regex::match(regex, var_type_name))
+	  return false;
     }
 
   return true;
@@ -3936,10 +3924,9 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
       if (get_symbol_name() != sym_name)
 	return false;
     }
-  else if (get_symbol_name_regex())
+  else if (const regex_t_sptr& regex = get_symbol_name_regex())
     {
-      const regex_t_sptr sym_name_regex = get_symbol_name_regex();
-      if (sym_name_regex && !regex::match(sym_name_regex, sym_name))
+      if (!regex::match(regex, sym_name))
 	return false;
     }
   else
@@ -3952,11 +3939,9 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
       if (get_symbol_version() != sym_version)
 	return false;
     }
-  else if (get_symbol_version_regex())
+  else if (const regex_t_sptr& regex = get_symbol_version_regex())
     {
-      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
-      if (symbol_version_regex
-	  && !regex::match(symbol_version_regex, sym_version))
+      if (!regex::match(regex, sym_version))
 	return false;
     }
   else
@@ -4257,14 +4242,14 @@ file_suppression::suppresses_file(const string& file_path)
 
   bool has_regexp = false;
 
-  if (regex_t_sptr regexp = get_file_name_regex())
+  if (const regex_t_sptr& regexp = get_file_name_regex())
     {
       has_regexp = true;
       if (!regex::match(regexp, fname))
 	return false;
     }
 
-  if (regex_t_sptr regexp = get_file_name_not_regex())
+  if (const regex_t_sptr& regexp = get_file_name_not_regex())
     {
       has_regexp = true;
       if (regex::match(regexp, fname))
-- 
2.26.2.303.gf8c07b1a785-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v3 16/21] abg-tools-utils.cc: Assert generated regexes OK.
  2020-04-24  9:21 ` [PATCH v3 00/21]Simplify " Giuliano Procida
                     ` (14 preceding siblings ...)
  2020-04-24  9:21   ` [PATCH v3 15/21] abg-suppression.cc: More consistent regex matching Giuliano Procida
@ 2020-04-24  9:21   ` Giuliano Procida
  2020-04-27 12:08     ` Matthias Maennich
  2020-04-24  9:21   ` [PATCH v3 17/21] Refactor suppression property string parsing Giuliano Procida
                     ` (5 subsequent siblings)
  21 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-04-24  9:21 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

There are a couple of places where regexes are generated interally.
Assert they compile OK.

This is just paranoia. There should be no behavioural changes.

	* src/abg-tools-utils.cc (handle_file_entry): Assert
	internally-generated regex compiles.
	(gen_suppr_spec_from_kernel_abi_whitelists): Assert
	internally-generated regex compiles.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-tools-utils.cc | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/abg-tools-utils.cc b/src/abg-tools-utils.cc
index fe0de750..3af9fc49 100644
--- a/src/abg-tools-utils.cc
+++ b/src/abg-tools-utils.cc
@@ -1818,6 +1818,7 @@ handle_file_entry(const string& file_path,
       // Types that are defined in system headers are usually
       // OK to be considered as public types.
       regex::regex_t_sptr headers_regex = regex::compile("^/usr/include/");
+      ABG_ASSERT(headers_regex);
       suppr->set_source_location_to_keep_regex(headers_regex);
       suppr->set_is_artificial(true);
     }
@@ -2008,6 +2009,7 @@ gen_suppr_spec_from_kernel_abi_whitelists
       // the function and variable names expressed in the white list.
       regex::regex_t_sptr regex =
 	regex::compile(regex::generate_from_strings(whitelisted_names));
+      ABG_ASSERT(regex);
 
       // Build a suppression specification which *keeps* functions
       // whose ELF symbols match the regular expression contained
-- 
2.26.2.303.gf8c07b1a785-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v3 17/21] Refactor suppression property string parsing.
  2020-04-24  9:21 ` [PATCH v3 00/21]Simplify " Giuliano Procida
                     ` (15 preceding siblings ...)
  2020-04-24  9:21   ` [PATCH v3 16/21] abg-tools-utils.cc: Assert generated regexes OK Giuliano Procida
@ 2020-04-24  9:21   ` Giuliano Procida
  2020-04-27 12:17     ` Matthias Maennich
  2020-04-24  9:21   ` [PATCH v3 18/21] Refactor suppression property regex parsing Giuliano Procida
                     ` (4 subsequent siblings)
  21 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-04-24  9:21 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

This patch introduces a helper function to look up a key in an ini
configuration section and get a string value. All string look-ups now
use this.

There are no behavioural changes.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-suppression.cc | 198 ++++++++++++++++-------------------------
 1 file changed, 78 insertions(+), 120 deletions(-)

diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 7d411caf..84c9b78f 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -1594,6 +1594,31 @@ read_suppression_reach_kind(const string& input)
     return type_suppression::DIRECT_REACH_KIND;
 }
 
+/// Maybe fetch a property to a string.
+///
+/// Attempt to find a simple property in an ini section and copy it
+/// to a string
+///
+/// @param section the ini section to look in
+///
+/// @param prop the property name
+///
+/// @param str the string to compile into
+///
+/// @return whether the property was found
+static bool
+maybe_get_string_prop(const ini::config::section& section,
+                      const std::string& name,
+                      std::string& str)
+{
+  ini::simple_property_sptr prop =
+    is_simple_property(section.find_property(name));
+  if (!prop)
+    return false;
+  str = prop->get_value()->as_string();
+  return true;
+}
+
 /// Read a type suppression from an instance of ini::config::section
 /// and build a @ref type_suppression as a result.
 ///
@@ -1609,18 +1634,12 @@ read_type_suppression(const ini::config::section& section)
   if (section.get_name() != "suppress_type")
     return result;
 
-  ini::simple_property_sptr drop_artifact =
-    is_simple_property(section.find_property("drop_artifact"));
-  if (!drop_artifact)
-    drop_artifact = is_simple_property(section.find_property("drop"));
-
-  string drop_artifact_str = drop_artifact
-    ? drop_artifact->get_value()->as_string()
-    : "";
+  string drop_artifact_str;
+  maybe_get_string_prop(section, "drop_artifact", drop_artifact_str)
+    || maybe_get_string_prop(section, "drop", drop_artifact_str);
 
-  ini::simple_property_sptr label =
-    is_simple_property(section.find_property("label"));
-  string label_str = label ? label->get_value()->as_string() : "";
+  string label_str;
+  maybe_get_string_prop(section, "label", label_str);
 
   ini::simple_property_sptr file_name_regex_prop =
     is_simple_property(section.find_property("file_name_regexp"));
@@ -1662,11 +1681,8 @@ read_type_suppression(const ini::config::section& section)
     name_not_regex =
       regex::compile(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
-    ? name_prop->get_value()->as_string()
-    : "";
+  string name_str;
+  maybe_get_string_prop(section, "name", name_str);
 
   ini::property_sptr srcloc_not_in_prop =
     section.find_property("source_location_not_in");
@@ -1697,25 +1713,19 @@ read_type_suppression(const ini::config::section& section)
     srcloc_not_regex =
       regex::compile(srcloc_not_regexp_prop->get_value()->as_string());
 
-  bool consider_type_kind = false;
-  type_suppression::type_kind type_kind = type_suppression::UNKNOWN_TYPE_KIND;
-  if (ini::simple_property_sptr type_kind_prop =
-      is_simple_property(section.find_property("type_kind")))
-    {
-      consider_type_kind = true;
-      type_kind =
-	read_type_kind_string(type_kind_prop->get_value()->as_string());
-    }
+  std::string type_kind_str;
+  bool consider_type_kind =
+    maybe_get_string_prop(section, "type_kind", type_kind_str);
+  type_suppression::type_kind type_kind = consider_type_kind
+    ? read_type_kind_string(type_kind_str)
+    : type_suppression::UNKNOWN_TYPE_KIND;
 
-  bool consider_reach_kind = false;
-  type_suppression::reach_kind reach_kind = type_suppression::DIRECT_REACH_KIND;
-  if (ini::simple_property_sptr reach_kind_prop =
-      is_simple_property(section.find_property("accessed_through")))
-    {
-      consider_reach_kind = true;
-      reach_kind =
-	read_suppression_reach_kind(reach_kind_prop->get_value()->as_string());
-    }
+  std::string reach_kind_str;
+  bool consider_reach_kind =
+      maybe_get_string_prop(section, "accessed_through", reach_kind_str);
+  type_suppression::reach_kind reach_kind = consider_reach_kind
+    ? read_suppression_reach_kind(reach_kind_str)
+    : type_suppression::DIRECT_REACH_KIND;
 
   // Support has_data_member_inserted_at
   vector<type_suppression::insertion_range_sptr> insert_ranges;
@@ -3175,26 +3185,15 @@ read_function_suppression(const ini::config::section& section)
   if (section.get_name() != "suppress_function")
     return result;
 
-  ini::simple_property_sptr drop_artifact =
-    is_simple_property(section.find_property("drop_artifact"));
-  if (!drop_artifact)
-    drop_artifact = is_simple_property(section.find_property("drop"));
-
-  string drop_artifact_str = drop_artifact
-    ? drop_artifact->get_value()->as_string()
-    : "";
+  string drop_artifact_str;
+  maybe_get_string_prop(section, "drop_artifact", drop_artifact_str)
+    || maybe_get_string_prop(section, "drop", drop_artifact_str);
 
-  ini::simple_property_sptr change_kind_prop =
-    is_simple_property(section.find_property("change_kind"));
-  string change_kind_str = change_kind_prop
-    ? change_kind_prop->get_value()->as_string()
-    : "";
+  string change_kind_str;
+  maybe_get_string_prop(section, "change_kind", change_kind_str);
 
-  ini::simple_property_sptr label_prop =
-    is_simple_property(section.find_property("label"));
-  string label_str = label_prop
-    ? label_prop->get_value()->as_string()
-    : "";
+  string label_str;
+  maybe_get_string_prop(section, "label", label_str);
 
   ini::simple_property_sptr file_name_regex_prop =
     is_simple_property(section.find_property("file_name_regexp"));
@@ -3223,11 +3222,8 @@ read_function_suppression(const ini::config::section& section)
     soname_not_regex =
       regex::compile(soname_not_regex_prop->get_value()->as_string());
 
-  ini::simple_property_sptr name_prop =
-    is_simple_property(section.find_property("name"));
-  string name = name_prop
-    ? name_prop->get_value()->as_string()
-    : "";
+  string name;
+  maybe_get_string_prop(section, "name", name);
 
   ini::simple_property_sptr name_regex_prop =
     is_simple_property(section.find_property("name_regexp"));
@@ -3242,11 +3238,8 @@ read_function_suppression(const ini::config::section& section)
     name_not_regex =
       regex::compile(name_not_regex_prop->get_value()->as_string());
 
-  ini::simple_property_sptr return_type_name_prop =
-    is_simple_property(section.find_property("return_type_name"));
-  string return_type_name = return_type_name_prop
-    ? return_type_name_prop->get_value()->as_string()
-    : "";
+  string return_type_name;
+  maybe_get_string_prop(section, "return_type_name", return_type_name);
 
   ini::simple_property_sptr return_type_regex_prop =
     is_simple_property(section.find_property("return_type_regexp"));
@@ -3255,11 +3248,8 @@ read_function_suppression(const ini::config::section& section)
     return_type_regex =
       regex::compile(return_type_regex_prop->get_value()->as_string());
 
-  ini::simple_property_sptr sym_name_prop =
-    is_simple_property(section.find_property("symbol_name"));
-  string sym_name = sym_name_prop
-    ? sym_name_prop->get_value()->as_string()
-    : "";
+  string sym_name;
+  maybe_get_string_prop(section, "symbol_name", sym_name);
 
   ini::simple_property_sptr sym_name_regex_prop =
     is_simple_property(section.find_property("symbol_name_regexp"));
@@ -3275,11 +3265,8 @@ read_function_suppression(const ini::config::section& section)
     sym_name_not_regex =
       regex::compile(sym_name_not_regex_prop->get_value()->as_string());
 
-  ini::simple_property_sptr sym_ver_prop =
-    is_simple_property(section.find_property("symbol_version"));
-  string sym_version = sym_ver_prop
-    ? sym_ver_prop->get_value()->as_string()
-    : "";
+  string sym_version;
+  maybe_get_string_prop(section, "symbol_version", sym_version);
 
   ini::simple_property_sptr sym_ver_regex_prop =
     is_simple_property(section.find_property("symbol_version_regexp"));
@@ -3288,11 +3275,8 @@ read_function_suppression(const ini::config::section& section)
     sym_ver_regex =
       regex::compile(sym_ver_regex_prop->get_value()->as_string());
 
-  ini::simple_property_sptr allow_other_aliases_prop =
-    is_simple_property(section.find_property("allow_other_aliases"));
-  string allow_other_aliases = allow_other_aliases_prop
-    ? allow_other_aliases_prop->get_value()->as_string()
-    : "";
+  string allow_other_aliases;
+  maybe_get_string_prop(section, "allow_other_aliases", allow_other_aliases);
 
   function_suppression::parameter_spec_sptr parm;
   function_suppression::parameter_specs_type parms;
@@ -4031,26 +4015,15 @@ read_variable_suppression(const ini::config::section& section)
   if (section.get_name() != "suppress_variable")
     return result;
 
-  ini::simple_property_sptr drop_artifact =
-    is_simple_property(section.find_property("drop_artifact"));
-  if (!drop_artifact)
-    drop_artifact = is_simple_property(section.find_property("drop"));
-
-  string drop_artifact_str = drop_artifact
-    ? drop_artifact->get_value()->as_string()
-    : "";
+  string drop_artifact_str;
+  maybe_get_string_prop(section, "drop_artifact", drop_artifact_str)
+    || maybe_get_string_prop(section, "drop", drop_artifact_str);
 
-  ini::simple_property_sptr change_kind_prop =
-    is_simple_property(section.find_property("change_kind"));
-  string change_kind_str = change_kind_prop
-    ? change_kind_prop->get_value()->as_string()
-    : "";
+  string change_kind_str;
+  maybe_get_string_prop(section, "change_kind", change_kind_str);
 
-  ini::simple_property_sptr label_prop =
-    is_simple_property(section.find_property("label"));
-  string label_str = (label_prop
-		      ? label_prop->get_value()->as_string()
-		      : "");
+  string label_str;
+  maybe_get_string_prop(section, "label", label_str);
 
   ini::simple_property_sptr file_name_regex_prop =
     is_simple_property(section.find_property("file_name_regexp"));
@@ -4079,11 +4052,8 @@ read_variable_suppression(const ini::config::section& section)
     soname_not_regex =
       regex::compile(soname_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
-		     ? name_prop->get_value()->as_string()
-		     : "");
+  string name_str;
+  maybe_get_string_prop(section, "name", name_str);
 
   ini::simple_property_sptr name_regex_prop =
     is_simple_property(section.find_property("name_regexp"));
@@ -4098,11 +4068,8 @@ read_variable_suppression(const ini::config::section& section)
     name_not_regex =
       regex::compile(name_not_regex_prop->get_value()->as_string());
 
-  ini::simple_property_sptr sym_name_prop =
-    is_simple_property(section.find_property("symbol_name"));
-  string symbol_name = (sym_name_prop
-			? sym_name_prop->get_value()->as_string()
-			: "");
+  string symbol_name;
+  maybe_get_string_prop(section, "symbol_name", symbol_name);
 
   ini::simple_property_sptr sym_name_regex_prop =
     is_simple_property(section.find_property("symbol_name_regexp"));
@@ -4118,11 +4085,8 @@ read_variable_suppression(const ini::config::section& section)
     symbol_name_not_regex =
       regex::compile(sym_name_not_regex_prop->get_value()->as_string());
 
-  ini::simple_property_sptr sym_version_prop =
-    is_simple_property(section.find_property("symbol_version"));
-  string symbol_version = sym_version_prop
-    ? sym_version_prop->get_value()->as_string()
-    : "";
+  string symbol_version;
+  maybe_get_string_prop(section, "symbol_version", symbol_version);
 
   ini::simple_property_sptr sym_version_regex_prop =
     is_simple_property(section.find_property("symbol_version_regexp"));
@@ -4131,11 +4095,8 @@ read_variable_suppression(const ini::config::section& section)
     symbol_version_regex =
       regex::compile(sym_version_regex_prop->get_value()->as_string());
 
-  ini::simple_property_sptr type_name_prop =
-    is_simple_property(section.find_property("type_name"));
-  string type_name_str = type_name_prop
-    ? type_name_prop->get_value()->as_string()
-    : "";
+  string type_name_str;
+  maybe_get_string_prop(section, "type_name", type_name_str);
 
   ini::simple_property_sptr type_name_regex_prop =
     is_simple_property(section.find_property("type_name_regexp"));
@@ -4282,11 +4243,8 @@ read_file_suppression(const ini::config::section& section)
   if (section.get_name() != "suppress_file")
     return result;
 
-  ini::simple_property_sptr label_prop =
-    is_simple_property(section.find_property("label"));
-  string label_str = (label_prop
-		      ? label_prop->get_value()->as_string()
-		      : "");
+  string label_str;
+  maybe_get_string_prop(section, "label", label_str);
 
   ini::simple_property_sptr file_name_regex_prop =
     is_simple_property(section.find_property("file_name_regexp"));
-- 
2.26.2.303.gf8c07b1a785-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v3 18/21] Refactor suppression property regex parsing.
  2020-04-24  9:21 ` [PATCH v3 00/21]Simplify " Giuliano Procida
                     ` (16 preceding siblings ...)
  2020-04-24  9:21   ` [PATCH v3 17/21] Refactor suppression property string parsing Giuliano Procida
@ 2020-04-24  9:21   ` Giuliano Procida
  2020-04-27 14:55     ` Matthias Maennich
  2020-04-24  9:21   ` [PATCH v3 19/21] Warn if user-supplied regexes fail to compile Giuliano Procida
                     ` (3 subsequent siblings)
  21 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-04-24  9:21 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

This patch introduces a helper function to look up a key in an ini
configuration section and get a compiled regex value. All regex
look-ups now use this.

There are no behavioural changes.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-suppression.cc | 215 ++++++++++++-----------------------------
 1 file changed, 61 insertions(+), 154 deletions(-)

diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 84c9b78f..8b3631fd 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -1619,6 +1619,30 @@ maybe_get_string_prop(const ini::config::section& section,
   return true;
 }
 
+/// Maybe compile a property to a regex.
+///
+/// Attempt to find a simple property in an ini section and compile it
+/// to a regex.
+///
+/// @param section the ini section to look in
+///
+/// @param prop the property name
+///
+/// @param r the regex to compile into
+///
+/// @return whether the property was found
+static bool
+maybe_get_regex_prop(const ini::config::section& section,
+                     const std::string& name,
+                     regex_t_sptr& regex)
+{
+  string str;
+  if (!maybe_get_string_prop(section, name, str))
+    return false;
+  regex = regex::compile(str);
+  return true;
+}
+
 /// Read a type suppression from an instance of ini::config::section
 /// and build a @ref type_suppression as a result.
 ///
@@ -1641,45 +1665,23 @@ read_type_suppression(const ini::config::section& section)
   string label_str;
   maybe_get_string_prop(section, "label", label_str);
 
-  ini::simple_property_sptr file_name_regex_prop =
-    is_simple_property(section.find_property("file_name_regexp"));
   regex_t_sptr file_name_regex;
-  if (file_name_regex_prop)
-    file_name_regex =
-      regex::compile(file_name_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "file_name_regexp", file_name_regex);
 
-  ini::simple_property_sptr file_name_not_regex_prop =
-    is_simple_property(section.find_property("file_name_not_regexp"));
   regex_t_sptr file_name_not_regex;
-  if (file_name_not_regex_prop)
-    file_name_not_regex =
-      regex::compile(file_name_not_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "file_name_not_regexp", file_name_not_regex);
 
-  ini::simple_property_sptr soname_regex_prop =
-    is_simple_property(section.find_property("soname_regexp"));
   regex_t_sptr soname_regex;
-  if (soname_regex_prop)
-    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "soname_regexp", soname_regex);
 
-  ini::simple_property_sptr soname_not_regex_prop =
-    is_simple_property(section.find_property("soname_not_regexp"));
   regex_t_sptr soname_not_regex;
-  if (soname_not_regex_prop)
-    soname_not_regex =
-      regex::compile(soname_not_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "soname_not_regexp", soname_not_regex);
 
-  ini::simple_property_sptr name_regex_prop =
-    is_simple_property(section.find_property("name_regexp"));
   regex_t_sptr name_regex;
-  if (name_regex_prop)
-    name_regex = regex::compile(name_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "name_regexp", name_regex);
 
-  ini::simple_property_sptr name_not_regex_prop =
-    is_simple_property(section.find_property("name_not_regexp"));
   regex_t_sptr name_not_regex;
-  if (name_not_regex_prop)
-    name_not_regex =
-      regex::compile(name_not_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "name_not_regexp", name_not_regex);
 
   string name_str;
   maybe_get_string_prop(section, "name", name_str);
@@ -1706,12 +1708,8 @@ read_type_suppression(const ini::config::section& section)
 	}
     }
 
-  ini::simple_property_sptr srcloc_not_regexp_prop =
-    is_simple_property(section.find_property("source_location_not_regexp"));
   regex_t_sptr srcloc_not_regex;
-  if (srcloc_not_regexp_prop)
-    srcloc_not_regex =
-      regex::compile(srcloc_not_regexp_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "source_location_not_regexp", srcloc_not_regex);
 
   std::string type_kind_str;
   bool consider_type_kind =
@@ -3195,85 +3193,47 @@ read_function_suppression(const ini::config::section& section)
   string label_str;
   maybe_get_string_prop(section, "label", label_str);
 
-  ini::simple_property_sptr file_name_regex_prop =
-    is_simple_property(section.find_property("file_name_regexp"));
   regex_t_sptr file_name_regex;
-  if (file_name_regex_prop)
-    file_name_regex =
-      regex::compile(file_name_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "file_name_regexp", file_name_regex);
 
-  ini::simple_property_sptr file_name_not_regex_prop =
-    is_simple_property(section.find_property("file_name_not_regexp"));
   regex_t_sptr file_name_not_regex;
-  if (file_name_not_regex_prop)
-    file_name_not_regex =
-      regex::compile(file_name_not_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "file_name_not_regexp", file_name_not_regex);
 
-  ini::simple_property_sptr soname_regex_prop =
-    is_simple_property(section.find_property("soname_regexp"));
   regex_t_sptr soname_regex;
-  if (soname_regex_prop)
-    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "soname_regexp", soname_regex);
 
-  ini::simple_property_sptr soname_not_regex_prop =
-    is_simple_property(section.find_property("soname_not_regexp"));
   regex_t_sptr soname_not_regex;
-  if (soname_not_regex_prop)
-    soname_not_regex =
-      regex::compile(soname_not_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "soname_not_regexp", soname_not_regex);
 
   string name;
   maybe_get_string_prop(section, "name", name);
 
-  ini::simple_property_sptr name_regex_prop =
-    is_simple_property(section.find_property("name_regexp"));
   regex_t_sptr name_regex;
-  if (name_regex_prop)
-    name_regex = regex::compile(name_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "name_regexp", name_regex);
 
-  ini::simple_property_sptr name_not_regex_prop =
-    is_simple_property(section.find_property("name_not_regexp"));
   regex_t_sptr name_not_regex;
-  if (name_not_regex_prop)
-    name_not_regex =
-      regex::compile(name_not_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "name_not_regexp", name_not_regex);
 
   string return_type_name;
   maybe_get_string_prop(section, "return_type_name", return_type_name);
 
-  ini::simple_property_sptr return_type_regex_prop =
-    is_simple_property(section.find_property("return_type_regexp"));
   regex_t_sptr return_type_regex;
-  if (return_type_regex_prop)
-    return_type_regex =
-      regex::compile(return_type_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "return_type_regexp", return_type_regex);
 
   string sym_name;
   maybe_get_string_prop(section, "symbol_name", sym_name);
 
-  ini::simple_property_sptr sym_name_regex_prop =
-    is_simple_property(section.find_property("symbol_name_regexp"));
   regex_t_sptr sym_name_regex;
-  if (sym_name_regex_prop)
-    sym_name_regex =
-      regex::compile(sym_name_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "symbol_name_regexp", sym_name_regex);
 
-  ini::simple_property_sptr sym_name_not_regex_prop =
-    is_simple_property(section.find_property("symbol_name_not_regexp"));
   regex_t_sptr sym_name_not_regex;
-  if (sym_name_not_regex_prop)
-    sym_name_not_regex =
-      regex::compile(sym_name_not_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "symbol_name_not_regexp", sym_name_not_regex);
 
   string sym_version;
   maybe_get_string_prop(section, "symbol_version", sym_version);
 
-  ini::simple_property_sptr sym_ver_regex_prop =
-    is_simple_property(section.find_property("symbol_version_regexp"));
   regex_t_sptr sym_ver_regex;
-  if (sym_ver_regex_prop)
-    sym_ver_regex =
-      regex::compile(sym_ver_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "symbol_version_regexp", sym_ver_regex);
 
   string allow_other_aliases;
   maybe_get_string_prop(section, "allow_other_aliases", allow_other_aliases);
@@ -4025,85 +3985,47 @@ read_variable_suppression(const ini::config::section& section)
   string label_str;
   maybe_get_string_prop(section, "label", label_str);
 
-  ini::simple_property_sptr file_name_regex_prop =
-    is_simple_property(section.find_property("file_name_regexp"));
   regex_t_sptr file_name_regex;
-  if (file_name_regex_prop)
-    file_name_regex =
-      regex::compile(file_name_regex_prop->get_value()->as_string());
-
- ini::simple_property_sptr file_name_not_regex_prop =
-  is_simple_property(section.find_property("file_name_not_regexp"));
- regex_t_sptr file_name_not_regex;
- if (file_name_not_regex_prop)
-   file_name_not_regex =
-     regex::compile(file_name_not_regex_prop->get_value()->as_string());
-
-  ini::simple_property_sptr soname_regex_prop =
-    is_simple_property(section.find_property("soname_regexp"));
+  maybe_get_regex_prop(section, "file_name_regexp", file_name_regex);
+
+  regex_t_sptr file_name_not_regex;
+  maybe_get_regex_prop(section, "file_name_not_regexp", file_name_not_regex);
+
   regex_t_sptr soname_regex;
-  if (soname_regex_prop)
-    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "soname_regexp", soname_regex);
 
-  ini::simple_property_sptr soname_not_regex_prop =
-    is_simple_property(section.find_property("soname_not_regexp"));
   regex_t_sptr soname_not_regex;
-  if (soname_not_regex_prop)
-    soname_not_regex =
-      regex::compile(soname_not_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "soname_not_regexp", soname_not_regex);
 
   string name_str;
   maybe_get_string_prop(section, "name", name_str);
 
-  ini::simple_property_sptr name_regex_prop =
-    is_simple_property(section.find_property("name_regexp"));
   regex_t_sptr name_regex;
-  if (name_regex_prop)
-    name_regex = regex::compile(name_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "name_regexp", name_regex);
 
-  ini::simple_property_sptr name_not_regex_prop =
-    is_simple_property(section.find_property("name_not_regexp"));
   regex_t_sptr name_not_regex;
-  if (name_not_regex_prop)
-    name_not_regex =
-      regex::compile(name_not_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "name_not_regexp", name_not_regex);
 
   string symbol_name;
   maybe_get_string_prop(section, "symbol_name", symbol_name);
 
-  ini::simple_property_sptr sym_name_regex_prop =
-    is_simple_property(section.find_property("symbol_name_regexp"));
   regex_t_sptr symbol_name_regex;
-  if (sym_name_regex_prop)
-    symbol_name_regex =
-      regex::compile(sym_name_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "symbol_name_regexp", symbol_name_regex);
 
-  ini::simple_property_sptr sym_name_not_regex_prop =
-    is_simple_property(section.find_property("symbol_name_not_regexp"));
   regex_t_sptr symbol_name_not_regex;
-  if (sym_name_not_regex_prop)
-    symbol_name_not_regex =
-      regex::compile(sym_name_not_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "symbol_name_not_regexp", symbol_name_not_regex);
 
   string symbol_version;
   maybe_get_string_prop(section, "symbol_version", symbol_version);
 
-  ini::simple_property_sptr sym_version_regex_prop =
-    is_simple_property(section.find_property("symbol_version_regexp"));
   regex_t_sptr symbol_version_regex;
-  if (sym_version_regex_prop)
-    symbol_version_regex =
-      regex::compile(sym_version_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "symbol_version_regexp", symbol_version_regex);
 
   string type_name_str;
   maybe_get_string_prop(section, "type_name", type_name_str);
 
-  ini::simple_property_sptr type_name_regex_prop =
-    is_simple_property(section.find_property("type_name_regexp"));
   regex_t_sptr type_name_regex;
-  if (type_name_regex_prop)
-    type_name_regex =
-      regex::compile(type_name_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "type_name_regexp", type_name_regex);
 
   result.reset(new variable_suppression(label_str,
 					name_str,
@@ -4246,32 +4168,17 @@ read_file_suppression(const ini::config::section& section)
   string label_str;
   maybe_get_string_prop(section, "label", label_str);
 
-  ini::simple_property_sptr file_name_regex_prop =
-    is_simple_property(section.find_property("file_name_regexp"));
   regex_t_sptr file_name_regex;
-  if (file_name_regex_prop)
-    file_name_regex =
-      regex::compile(file_name_regex_prop->get_value()->as_string());
-
- ini::simple_property_sptr file_name_not_regex_prop =
-    is_simple_property(section.find_property("file_name_not_regexp"));
- regex_t_sptr file_name_not_regex;
- if (file_name_not_regex_prop)
-   file_name_not_regex =
-     regex::compile(file_name_not_regex_prop->get_value()->as_string());
-
-  ini::simple_property_sptr soname_regex_prop =
-    is_simple_property(section.find_property("soname_regexp"));
+  maybe_get_regex_prop(section, "file_name_regexp", file_name_regex);
+
+  regex_t_sptr file_name_not_regex;
+  maybe_get_regex_prop(section, "file_name_not_regexp", file_name_not_regex);
+
   regex_t_sptr soname_regex;
-  if (soname_regex_prop)
-    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "soname_regexp", soname_regex);
 
-  ini::simple_property_sptr soname_not_regex_prop =
-    is_simple_property(section.find_property("soname_not_regexp"));
   regex_t_sptr soname_not_regex;
-  if (soname_not_regex_prop)
-    soname_not_regex =
-      regex::compile(soname_not_regex_prop->get_value()->as_string());
+  maybe_get_regex_prop(section, "soname_not_regexp", soname_not_regex);
 
   result.reset(new file_suppression(label_str,
 				    file_name_regex,
-- 
2.26.2.303.gf8c07b1a785-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v3 19/21] Warn if user-supplied regexes fail to compile.
  2020-04-24  9:21 ` [PATCH v3 00/21]Simplify " Giuliano Procida
                     ` (17 preceding siblings ...)
  2020-04-24  9:21   ` [PATCH v3 18/21] Refactor suppression property regex parsing Giuliano Procida
@ 2020-04-24  9:21   ` Giuliano Procida
  2020-04-27 15:36     ` Matthias Maennich
  2020-04-24  9:21   ` [PATCH v3 20/21] Default construct suppression types Giuliano Procida
                     ` (2 subsequent siblings)
  21 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-04-24  9:21 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

There are not many calls to regex::compile in the code base. Two of
these pass internally-generated regexes and are followed by assertions
that the regexes compile.

The remaining cases deal with user-supplied regexes. If these fail to
compile they are currently silently ignored.

This patch makes sure failures now result in warning messages on
stderr, but otherwise does not change program behaviour.

	* src/abg-corpus-priv.h
	(corpus::exported_decls_builder::priv::compiled_regex_fns_suppress):
	Emit a warning message if regex::compile fails.
	(corpus::exported_decls_builder::priv::compiled_regex_fns_keep):
	Ditto.
	(corpus::exported_decls_builder::priv::compiled_regex_vars_suppress):
	Ditto.
	(corpus::exported_decls_builder::priv::compiled_regex_vars_keep):
	Ditto.
	* src/abg-suppression.cc (maybe_get_string_prop): Ditto.
	(read_parameter_spec_from_string): Ditto.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-corpus-priv.h  | 10 ++++++++++
 src/abg-suppression.cc |  4 ++++
 2 files changed, 14 insertions(+)

diff --git a/src/abg-corpus-priv.h b/src/abg-corpus-priv.h
index 2618e2d0..a06a1a23 100644
--- a/src/abg-corpus-priv.h
+++ b/src/abg-corpus-priv.h
@@ -29,6 +29,8 @@
 #ifndef __ABG_CORPUS_PRIV_H__
 #define __ABG_CORPUS_PRIV_H__
 
+#include <iostream>
+
 #include "abg-sptr-utils.h"
 #include "abg-regex.h"
 #include "abg-internal.h"
@@ -126,6 +128,8 @@ public:
 	    regex_t_sptr r = regex::compile(*i);
 	    if (r)
 	      compiled_fns_suppress_regexp_.push_back(r);
+	    else
+	      std::cerr << "warning: bad regex '" << *i << "'\n";
 	  }
       }
     return compiled_fns_suppress_regexp_;
@@ -148,6 +152,8 @@ public:
 	    regex_t_sptr r = regex::compile(*i);
 	    if (r)
 	      compiled_fns_keep_regexps_.push_back(r);
+	    else
+	      std::cerr << "warning: bad regex '" << *i << "'\n";
 	  }
       }
     return compiled_fns_keep_regexps_;
@@ -170,6 +176,8 @@ public:
 	    regex_t_sptr r = regex::compile(*i);
 	    if (r)
 	      compiled_vars_suppress_regexp_.push_back(r);
+	    else
+	      std::cerr << "warning: bad regex '" << *i << "'\n";
 	  }
       }
     return compiled_vars_suppress_regexp_;
@@ -192,6 +200,8 @@ public:
 	    regex_t_sptr r = regex::compile(*i);
 	    if (r)
 	      compiled_vars_keep_regexps_.push_back(r);
+	    else
+	      std::cerr << "warning: bad regex '" << *i << "'\n";
 	  }
       }
     return compiled_vars_keep_regexps_;
diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 8b3631fd..e4b6554c 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -1640,6 +1640,8 @@ maybe_get_regex_prop(const ini::config::section& section,
   if (!maybe_get_string_prop(section, name, str))
     return false;
   regex = regex::compile(str);
+  if (!regex)
+    std::cerr << "warning: bad regex '" << str << "'\n";
   return true;
 }
 
@@ -3157,6 +3159,8 @@ read_parameter_spec_from_string(const string& str)
       if (is_regex)
 	{
 	  type_name_regex = regex::compile(type_name);
+	  if (!type_name_regex)
+	    std::cerr << "warning: bad regex '" << type_name << "'\n";
 	  type_name.clear();
 	}
       function_suppression::parameter_spec* p =
-- 
2.26.2.303.gf8c07b1a785-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v3 20/21] Default construct suppression types.
  2020-04-24  9:21 ` [PATCH v3 00/21]Simplify " Giuliano Procida
                     ` (18 preceding siblings ...)
  2020-04-24  9:21   ` [PATCH v3 19/21] Warn if user-supplied regexes fail to compile Giuliano Procida
@ 2020-04-24  9:21   ` Giuliano Procida
  2020-04-27 15:40     ` Matthias Maennich
  2020-04-24  9:21   ` [PATCH v3 21/21] Remove unused suppression type priv constructors Giuliano Procida
  2020-05-04 12:34   ` [PATCH v4 00/15] Simplify regex and suppression parsing Giuliano Procida
  21 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-04-24  9:21 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

The current constructors for the various suppression types are not a
good match for their current uses. Given that every member is
effectively optional, default constructing these to a default
unpopulated state makes the code simpler.

There are no behavioural changes.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 include/abg-suppression.h  |  48 +------
 src/abg-suppression-priv.h |  28 ++--
 src/abg-suppression.cc     | 272 ++++++-------------------------------
 src/abg-tools-utils.cc     |   7 +-
 4 files changed, 59 insertions(+), 296 deletions(-)

diff --git a/include/abg-suppression.h b/include/abg-suppression.h
index 02e77ea9..4c987a79 100644
--- a/include/abg-suppression.h
+++ b/include/abg-suppression.h
@@ -56,17 +56,10 @@ class suppression_base
   class priv;
   typedef shared_ptr<priv> priv_sptr;
 
-  // Forbid default constructor
-  suppression_base();
-
 public:
   priv_sptr priv_;
 
-  suppression_base(const string& label);
-
-  suppression_base(const string& label,
-		   const regex::regex_t_sptr& file_name_regex,
-		   const regex::regex_t_sptr& file_name_not_regex);
+  suppression_base();
 
   bool
   get_drops_artifact_from_ir() const;
@@ -153,9 +146,6 @@ class type_suppression : public suppression_base
   class priv;
   typedef shared_ptr<priv> priv_sptr;
 
-  // Forbid this;
-  type_suppression();
-
 public:
 
   priv_sptr priv_;
@@ -201,9 +191,7 @@ public:
   /// A convenience typedef for a vector of @ref insertion_range_sptr.
   typedef vector<insertion_range_sptr> insertion_ranges;
 
-  type_suppression(const string& label,
-		   const regex::regex_t_sptr& type_name_regexp,
-		   const string& type_name);
+  type_suppression();
 
   virtual ~type_suppression();
 
@@ -458,17 +446,6 @@ public:
 
   function_suppression();
 
-  function_suppression(const string&			label,
-		       const string&			name,
-		       const regex::regex_t_sptr&	name_regex,
-		       const string&			return_type_name,
-		       const regex::regex_t_sptr&	return_type_regex,
-		       parameter_specs_type&		parm_specs,
-		       const string&			symbol_name,
-		       const regex::regex_t_sptr&	symbol_name_regex,
-		       const string&			symbol_version,
-		       const regex::regex_t_sptr&	symbol_version_regex);
-
   virtual ~function_suppression();
 
   static change_kind
@@ -675,19 +652,7 @@ public:
 
   priv_sptr priv_;
 
-  variable_suppression(const string& label = "",
-		       const string& name = "",
-		       const regex::regex_t_sptr& name_regex =
-			 regex::regex_t_sptr(),
-		       const string& symbol_name = "",
-		       const regex::regex_t_sptr& symbol_name_regex =
-			 regex::regex_t_sptr(),
-		       const string& symbol_version = "",
-		       const regex::regex_t_sptr& symbol_version_regex =
-			 regex::regex_t_sptr(),
-		       const string& type_name = "",
-		       const regex::regex_t_sptr& type_name_regex =
-			 regex::regex_t_sptr());
+  variable_suppression();
 
   virtual ~variable_suppression();
 
@@ -812,14 +777,9 @@ class file_suppression: public suppression_base
 
   priv_sptr priv_;
 
-  // Forbid this
-  file_suppression();
-
 public:
 
-  file_suppression(const string& label,
-		   const regex::regex_t_sptr& file_name_regex,
-		   const regex::regex_t_sptr& file_name_not_regex);
+  file_suppression();
 
   virtual bool
   suppresses_diff(const diff* diff) const;
diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
index 78f11e2f..7f98fb08 100644
--- a/src/abg-suppression-priv.h
+++ b/src/abg-suppression-priv.h
@@ -236,23 +236,8 @@ struct variable_suppression::priv
   string				type_name_;
   regex::regex_t_sptr			type_name_regex_;
 
-  priv(const string& name,
-       const regex::regex_t_sptr& name_regex,
-       const string& symbol_name,
-       const regex::regex_t_sptr& symbol_name_regex,
-       const string& symbol_version,
-       const regex::regex_t_sptr& symbol_version_regex,
-       const string& type_name,
-       const regex::regex_t_sptr& type_name_regex)
-    : change_kind_(ALL_CHANGE_KIND),
-      name_(name),
-      name_regex_(name_regex),
-      symbol_name_(symbol_name),
-      symbol_name_regex_(symbol_name_regex),
-      symbol_version_(symbol_version),
-      symbol_version_regex_(symbol_version_regex),
-      type_name_(type_name),
-      type_name_regex_(type_name_regex)
+  priv()
+    : change_kind_(ALL_CHANGE_KIND)
   {}
 };// end class variable_supppression::priv
 
@@ -300,9 +285,14 @@ class type_suppression::priv
   regex::regex_t_sptr			source_location_to_keep_regex_;
   mutable vector<string>		changed_enumerator_names_;
 
-  priv();
-
 public:
+  priv()
+    : consider_type_kind_(false),
+      type_kind_(CLASS_TYPE_KIND),
+      consider_reach_kind_(false),
+      reach_kind_(DIRECT_REACH_KIND)
+  {}
+
   priv(const regex::regex_t_sptr&	type_name_regexp,
        const string&			type_name,
        bool				consider_type_kind,
diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index e4b6554c..7dc3b2d1 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -53,33 +53,11 @@ using regex::regex_t_sptr;
 
 // <suppression_base stuff>
 
-/// Constructor for @ref suppression_base
-///
-/// @param a label for the suppression.  This represents just a
-/// comment.
-suppression_base::suppression_base(const string& label)
-  : priv_(new priv(label))
+/// Default constructor for @ref suppression_base
+suppression_base::suppression_base()
+  : priv_(new priv())
 {}
 
-/// Constructor for @ref suppression_base
-///
-/// @param a label for the suppression.  This represents just a
-/// comment.
-///
-/// @param file_name_regex the regular expression that denotes the
-/// file name to match.
-///
-/// @param file_name_not_regex the regular expression that denotes
-/// the file name to *NOT* match.
-suppression_base::suppression_base(const string& label,
-				   const regex_t_sptr& file_name_regex,
-				   const regex_t_sptr& file_name_not_regex)
-  : priv_(new priv(label,
-		   file_name_regex,
-		   file_name_not_regex))
-{
-}
-
 /// Tests if the current suppression specification is to avoid adding
 /// the matched ABI artifact to the internal representation or not.
 ///
@@ -453,32 +431,9 @@ read_suppressions(const string& file_path,
 
 // <type_suppression stuff>
 
-/// Constructor for @ref type_suppression.
-///
-/// @param label the label of the suppression.  This is just a free
-/// form comment explaining what the suppression is about.
-///
-/// @param type_name_regexp the regular expression describing the
-/// types about which diff reports should be suppressed.  If it's a
-/// null shared pointer, the parameter is ignored.
-///
-/// @param type_name the name of the type about which diff reports
-/// should be suppressed.  If it's an empty string, the parameter is
-/// ignored.
-///
-/// Note that parameter @p type_name_regexp and @p type_name_regexp
-/// should not necessarily be populated.  It usually is either one or
-/// the other that the user wants.
-type_suppression::type_suppression(const string& label,
-				   const regex_t_sptr& type_name_regexp,
-				   const string& type_name)
-  : suppression_base(label),
-    priv_(new priv(type_name_regexp,
-		   type_name,
-		   /*consider_type_kind=*/false,
-		   /*type_kind=*/CLASS_TYPE_KIND,
-		   /*consider_reach_kind=*/false,
-		   /*reach_kind=*/DIRECT_REACH_KIND))
+/// Default constructor for @ref type_suppression.
+type_suppression::type_suppression()
+  : suppression_base(), priv_(new priv)
 {}
 
 type_suppression::~type_suppression()
@@ -1912,7 +1867,10 @@ read_type_suppression(const ini::config::section& section)
 	changed_enumerator_names.push_back(p->get_value()->as_string());
     }
 
-  result.reset(new type_suppression(label_str, name_regex, name_str));
+  result.reset(new type_suppression());
+  result->set_label(label_str);
+  result->set_type_name_regex(name_regex);
+  result->set_type_name(name_str);
 
   if (consider_type_kind)
     {
@@ -2049,77 +2007,7 @@ function_suppression::parameter_spec::set_parameter_type_name_regex
 /// specified by using the various accessors of the @ref
 /// function_suppression type.
 function_suppression::function_suppression()
-  :  suppression_base(/*label=*/""), priv_(new priv)
-{}
-
-/// Constructor for the @ref function_suppression type.
-///
-/// @param label an informative text string that the evalution code
-/// might use to designate this function suppression specification in
-/// error messages.  This parameter might be empty, in which case it's
-/// ignored at evaluation time.
-///
-/// @param the name of the function the user wants the current
-/// specification to designate.  This parameter might be empty, in
-/// which case it's ignored at evaluation time.
-///
-/// @param nr if @p name is empty this parameter is a regular
-/// expression for a family of names of functions the user wants the
-/// current specification to designate.  If @p name is not empty, this
-/// parameter is ignored at specification evaluation time.  This
-/// parameter might be empty, in which case it's ignored at evaluation
-/// time.
-///
-/// @param ret_tn the name of the return type of the function the user
-/// wants this specification to designate.  This parameter might be
-/// empty, in which case it's ignored at evaluation time.
-///
-/// @param ret_tr if @p ret_tn is empty, then this is a regular
-/// expression for a family of return type names for functions the
-/// user wants the current specification to designate.  If @p ret_tn
-/// is not empty, then this parameter is ignored at specification
-/// evaluation time.  This parameter might be empty, in which case
-/// it's ignored at evaluation time.
-///
-/// @param ps a vector of parameter specifications to specify
-/// properties of the parameters of the functions the user wants this
-/// specification to designate.  This parameter might be empty, in
-/// which case it's ignored at evaluation time.
-///
-/// @param sym_n the name of symbol of the function the user wants
-/// this specification to designate.  This parameter might be empty,
-/// in which case it's ignored at evaluation time.
-///
-/// @param sym_nr if the parameter @p sym_n is empty, then this
-/// parameter is a regular expression for a family of names of symbols
-/// of functions the user wants this specification to designate.  If
-/// the parameter @p sym_n is not empty, then this parameter is
-/// ignored at specification evaluation time.  This parameter might be
-/// empty, in which case it's ignored at evaluation time.
-///
-/// @param sym_v the name of the version of the symbol of the function
-/// the user wants this specification to designate.  This parameter
-/// might be empty, in which case it's ignored at evaluation time.
-///
-/// @param sym_vr if the parameter @p sym_v is empty, then this
-/// parameter is a regular expression for a family of versions of
-/// symbols of functions the user wants the current specification to
-/// designate.  If the parameter @p sym_v is non empty, then this
-/// parameter is ignored.  This parameter might be empty, in which
-/// case it's ignored at evaluation time.
-function_suppression::function_suppression(const string&		label,
-					   const string&		name,
-					   const regex_t_sptr&		nr,
-					   const string&		ret_tn,
-					   const regex_t_sptr&		ret_tr,
-					   parameter_specs_type&	ps,
-					   const string&		sym_n,
-					   const regex_t_sptr&		sym_nr,
-					   const string&		sym_v,
-					   const regex_t_sptr&		sym_vr)
-  : suppression_base(label),
-    priv_(new priv(name, nr, ret_tn, ret_tr, ps,
-		   sym_n, sym_nr, sym_v, sym_vr))
+  : suppression_base(), priv_(new priv)
 {}
 
 function_suppression::~function_suppression()
@@ -3257,16 +3145,17 @@ read_function_suppression(const ini::config::section& section)
 	  parms.push_back(parm);
       }
 
-  result.reset(new function_suppression(label_str,
-					name,
-					name_regex,
-					return_type_name,
-					return_type_regex,
-					parms,
-					sym_name,
-					sym_name_regex,
-					sym_version,
-					sym_ver_regex));
+  result.reset(new function_suppression());
+  result->set_label(label_str);
+  result->set_name(name);
+  result->set_name_regex(name_regex);
+  result->set_return_type_name(return_type_name);
+  result->set_return_type_regex(return_type_regex);
+  result->set_parameter_specs(parms);
+  result->set_symbol_name(sym_name);
+  result->set_symbol_name_regex(sym_name_regex);
+  result->set_symbol_version(sym_version);
+  result->set_symbol_version_regex(sym_ver_regex);
 
   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
       && (!name.empty()
@@ -3310,71 +3199,13 @@ read_function_suppression(const ini::config::section& section)
 
 // <variable_suppression stuff>
 
-/// Constructor for the @ref variable_suppression type.
-///
-/// @param label an informative text string that the evalution code
-/// might use to designate this variable suppression specification in
-/// error messages.  This parameter might be empty, in which case it's
-/// ignored at evaluation time.
-///
-/// @param name the name of the variable the user wants the current
-/// specification to designate.  This parameter might be empty, in
-/// which case it's ignored at evaluation time.
-///
-/// @param name_regex if @p name is empty, this parameter is a
-/// regular expression for a family of names of variables the user
-/// wants the current specification to designate.  If @p name is not
-/// empty, then this parameter is ignored at evaluation time.  This
-/// parameter might be empty, in which case it's ignored at evaluation
-/// time.
-///
-/// @param symbol_name the name of the symbol of the variable the user
-/// wants the current specification to designate.  This parameter
-/// might be empty, in which case it's ignored at evaluation time.
-///
-/// @param symbol_name_str if @p symbol_name is empty, this parameter
-/// is a regular expression for a family of names of symbols of
-/// variables the user wants the current specification to designate.
-/// If @p symbol_name is not empty, then this parameter is ignored at
-/// evaluation time.  This parameter might be empty, in which case
-/// it's ignored at evaluation time.
-///
-/// @param symbol_version the version of the symbol of the variable
-/// the user wants the current specification to designate.  This
-/// parameter might be empty, in which case it's ignored at evaluation
-/// time.
-///
-/// @param symbol_version_regex if @p symbol_version is empty, then
-/// this parameter is a regular expression for a family of versions of
-/// symbol for the variables the user wants the current specification
-/// to designate.  If @p symbol_version is not empty, then this
-/// parameter is ignored at evaluation time.  This parameter might be
-/// empty, in which case it's ignored at evaluation time.
-///
-/// @param type_name the name of the type of the variable the user
-/// wants the current specification to designate.  This parameter
-/// might be empty, in which case it's ignored at evaluation time.
+/// Default constructor for the @ref variable_suppression type.
 ///
-/// @param type_name_regex if @p type_name is empty, then this
-/// parameter is a regular expression for a family of type names of
-/// variables the user wants the current specification to designate.
-/// If @p type_name is not empty, then this parameter is ignored at
-/// evluation time.  This parameter might be empty, in which case it's
-/// ignored at evaluation time.
-variable_suppression::variable_suppression(const string& label,
-					   const string& name,
-					   const regex_t_sptr& name_regex,
-					   const string& symbol_name,
-					   const regex_t_sptr& symbol_name_regex,
-					   const string& symbol_version,
-					   const regex_t_sptr& symbol_version_regex,
-					   const string& type_name,
-					   const regex_t_sptr& type_name_regex)
-  : suppression_base(label),
-    priv_(new priv(name, name_regex,
-		   symbol_name, symbol_name_regex,
-		   symbol_version, symbol_version_regex,
-		   type_name, type_name_regex))
+/// It defines no suppression for now.  Suppressions have to be
+/// specified by using the various accessors of the @ref
+/// variable_suppression type.
+variable_suppression::variable_suppression()
+  : suppression_base(), priv_(new priv)
 {}
 
 /// Virtual destructor for the @erf variable_suppression type.
@@ -4031,15 +3862,16 @@ read_variable_suppression(const ini::config::section& section)
   regex_t_sptr type_name_regex;
   maybe_get_regex_prop(section, "type_name_regexp", type_name_regex);
 
-  result.reset(new variable_suppression(label_str,
-					name_str,
-					name_regex,
-					symbol_name,
-					symbol_name_regex,
-					symbol_version,
-					symbol_version_regex,
-					type_name_str,
-					type_name_regex));
+  result.reset(new variable_suppression);
+  result->set_label(label_str);
+  result->set_name(name_str);
+  result->set_name_regex(name_regex);
+  result->set_symbol_name(symbol_name);
+  result->set_symbol_name_regex(symbol_name_regex);
+  result->set_symbol_version(symbol_version);
+  result->set_symbol_version_regex(symbol_version_regex);
+  result->set_type_name(type_name_str);
+  result->set_type_name_regex(type_name_regex);
 
   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
       && (!name_str.empty()
@@ -4079,25 +3911,8 @@ read_variable_suppression(const ini::config::section& section)
 
 // <file_suppression stuff>
 
-/// Constructor for the the @ref file_suppression type.
-///
-/// @param label the label of the suppression directive.
-///
-/// @param fname_regex the regular expression that
-/// designates the file name that instances of @ref file_suppression
-/// should match.
-///
-/// @param fname_not_regex the regular expression that
-/// designates the file name that instances of @ref file_suppression
-/// shoult *NOT* match.  In other words, this file_suppression should
-/// be activated if its file name does not match the regular
-/// expression @p fname_not_regex.
-file_suppression::file_suppression(const string& label,
-				   const regex_t_sptr& fname_regex,
-				   const regex_t_sptr& fname_not_regex)
-  : suppression_base(label,
-		     fname_regex,
-		     fname_not_regex)
+/// Default constructor for the the @ref file_suppression type.
+file_suppression::file_suppression()
 {}
 
 /// Test if instances of this @ref file_suppression suppresses a
@@ -4184,9 +3999,10 @@ read_file_suppression(const ini::config::section& section)
   regex_t_sptr soname_not_regex;
   maybe_get_regex_prop(section, "soname_not_regexp", soname_not_regex);
 
-  result.reset(new file_suppression(label_str,
-				    file_name_regex,
-				    file_name_not_regex));
+  result.reset(new file_suppression);
+  result->set_label(label_str);
+  result->set_file_name_regex(file_name_regex);
+  result->set_file_name_not_regex(file_name_not_regex);
 
   if (soname_regex)
     {
diff --git a/src/abg-tools-utils.cc b/src/abg-tools-utils.cc
index 3af9fc49..4cef400d 100644
--- a/src/abg-tools-utils.cc
+++ b/src/abg-tools-utils.cc
@@ -1810,11 +1810,8 @@ handle_file_entry(const string& file_path,
 {
   if (!suppr)
     {
-      suppr.reset(
-	new type_suppression(get_private_types_suppr_spec_label(),
-			     /*type_name_regexp=*/regex::regex_t_sptr(),
-			     /*type_name=*/""));
-
+      suppr.reset(new type_suppression());
+      suppr->set_label(get_private_types_suppr_spec_label());
       // Types that are defined in system headers are usually
       // OK to be considered as public types.
       regex::regex_t_sptr headers_regex = regex::compile("^/usr/include/");
-- 
2.26.2.303.gf8c07b1a785-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v3 21/21] Remove unused suppression type priv constructors.
  2020-04-24  9:21 ` [PATCH v3 00/21]Simplify " Giuliano Procida
                     ` (19 preceding siblings ...)
  2020-04-24  9:21   ` [PATCH v3 20/21] Default construct suppression types Giuliano Procida
@ 2020-04-24  9:21   ` Giuliano Procida
  2020-04-27 15:41     ` Matthias Maennich
  2020-05-04 12:34   ` [PATCH v4 00/15] Simplify regex and suppression parsing Giuliano Procida
  21 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-04-24  9:21 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

Following on from the previous commit, many constructors for the
various priv types are now unused. This patch drops them.

There are no behavioural changes.

	* src/abg-suppression-priv.h (suppression_base::priv) Drop all
	but default constructor.
	(function_suppression::parameter_spec::priv): Drop all but
	3-argument constructor. (function_suppression::priv): Drop all
	but default constructor. (type_suppression::priv): Drop all
	but default constructor.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-suppression-priv.h | 60 --------------------------------------
 1 file changed, 60 deletions(-)

diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
index 7f98fb08..97c163fe 100644
--- a/src/abg-suppression-priv.h
+++ b/src/abg-suppression-priv.h
@@ -58,22 +58,6 @@ public:
       drops_artifact_()
   {}
 
-  priv(const string& label)
-    : is_artificial_(),
-      drops_artifact_(),
-      label_(label)
-  {}
-
-  priv(const string& label,
-       const regex::regex_t_sptr& file_name_regex,
-       const regex::regex_t_sptr& file_name_not_regex)
-    : is_artificial_(),
-      drops_artifact_(),
-      label_(label),
-      file_name_regex_(file_name_regex),
-      file_name_not_regex_(file_name_not_regex)
-  {}
-
   friend class suppression_base;
 }; // end class suppression_base::priv
 
@@ -90,14 +74,6 @@ class function_suppression::parameter_spec::priv
   string				type_name_;
   regex::regex_t_sptr			type_name_regex_;
 
-  priv()
-    : index_()
-  {}
-
-  priv(size_t i, const string& tn)
-    : index_(i), type_name_(tn)
-  {}
-
   priv(size_t i, const string& tn, const regex::regex_t_sptr& tn_regex)
     : index_(i), type_name_(tn), type_name_regex_(tn_regex)
   {}
@@ -128,28 +104,6 @@ struct function_suppression::priv
     change_kind_(ALL_CHANGE_KIND),
     allow_other_aliases_(true)
   {}
-
-  priv(const string&			name,
-       const regex::regex_t_sptr&	name_regex,
-       const string&			return_type_name,
-       const regex::regex_t_sptr&	return_type_regex,
-       const parameter_specs_type&	parm_specs,
-       const string&			symbol_name,
-       const regex::regex_t_sptr&	symbol_name_regex,
-       const string&			symbol_version,
-       const regex::regex_t_sptr&	symbol_version_regex)
-    : change_kind_(ALL_CHANGE_KIND),
-      name_(name),
-      name_regex_(name_regex),
-      return_type_name_(return_type_name),
-      return_type_regex_(return_type_regex),
-      parm_specs_(parm_specs),
-      symbol_name_(symbol_name),
-      symbol_name_regex_(symbol_name_regex),
-      symbol_version_(symbol_version),
-      symbol_version_regex_(symbol_version_regex),
-      allow_other_aliases_(true)
-  {}
 }; // end class function_suppression::priv
 
 bool
@@ -293,20 +247,6 @@ public:
       reach_kind_(DIRECT_REACH_KIND)
   {}
 
-  priv(const regex::regex_t_sptr&	type_name_regexp,
-       const string&			type_name,
-       bool				consider_type_kind,
-       type_suppression::type_kind	type_kind,
-       bool				consider_reach_kind,
-       type_suppression::reach_kind	reach_kind)
-    : type_name_regex_(type_name_regexp),
-      type_name_(type_name),
-      consider_type_kind_(consider_type_kind),
-      type_kind_(type_kind),
-      consider_reach_kind_(consider_reach_kind),
-      reach_kind_(reach_kind)
-  {}
-
   friend class type_suppression;
 }; // class type_suppression::priv
 
-- 
2.26.2.303.gf8c07b1a785-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 01/21] Move regex definitions to own files.
  2020-04-24  9:21   ` [PATCH v3 01/21] Move regex definitions to own files Giuliano Procida
@ 2020-04-27 10:52     ` Matthias Maennich
  2020-04-29 14:19       ` Dodji Seketeli
  2020-05-04  9:19     ` Dodji Seketeli
  1 sibling, 1 reply; 120+ messages in thread
From: Matthias Maennich @ 2020-04-27 10:52 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, dodji, kernel-team

On Fri, Apr 24, 2020 at 10:21:12AM +0100, Giuliano Procida wrote:
>As a prelude to adding wrapper and helper functions for regex
>functionality, it makes sense to move the existing regex code (the
>shared pointer type and its specialised deleter) to their own files.
>
>This patch does this and also moves various entities into a new
>namespace, abigail::regex. It removes the file abg-sptr-utils.cc which
>only contained regex things.
>
>There are no behavioural changes.
>
>	* include/Makefile.am: Add abg-regex.h.
>	* src/Makefile.am: Remove abg-sptr-utils.h, add abg-regex.cc
>	* include/abg-sptr-utils.h (regex_t_sptr): Remove this
>	typedef, from namespace abigail::sptr_utils.
>	(regex_t_deleter): Remove this struct, from namespace
>	abigail::sptr_utils. (build_sptr): Remove these template
>	specialisations, in duplicate, for regex_t_sptr.
>	* include/abg-regex.h: New file, introduces namespace
>	abigail::regex. (regex_t_sptr): Add this typedef, to namespace
>	abigail::regex. (regex_t_deleter): Add this struct, to
>	namespace abigail::regex. (build_sptr): Add these template
>	specialisations for regex_t_sptr
>	* src/abg-sptr-utils.cc: Remove this file.
>	* src/abg-regex.cc: Add new file with contents effectively
>	the same as abg-sptr-utils.cc.
>	* src/abg-corpus-priv.h: Update regex_t_sptr namespace
>	qualification.
>	* src/abg-corpus.cc: Ditto.
>	* src/abg-suppression-priv.h: Ditto.
>	* src/abg-suppression.cc: Ditto.
>
>Signed-off-by: Giuliano Procida <gprocida@google.com>
>---
> include/Makefile.am                     |   3 +-
> include/abg-regex.h                     |  83 ++++++++++++++
> include/abg-sptr-utils.h                |  49 ---------
> src/Makefile.am                         |   2 +-
> src/abg-corpus-priv.h                   |   3 +-
> src/abg-corpus.cc                       |   2 +-
> src/{abg-sptr-utils.cc => abg-regex.cc} |  19 ++--
> src/abg-suppression-priv.h              | 137 ++++++++++++------------
> src/abg-suppression.cc                  |  73 ++++++-------
> 9 files changed, 198 insertions(+), 173 deletions(-)
> create mode 100644 include/abg-regex.h
> rename src/{abg-sptr-utils.cc => abg-regex.cc} (84%)
>
>diff --git a/include/Makefile.am b/include/Makefile.am
>index ae97f674..b5475252 100644
>--- a/include/Makefile.am
>+++ b/include/Makefile.am
>@@ -24,6 +24,7 @@ abg-cxx-compat.h	\
> abg-version.h		\
> abg-viz-common.h	\
> abg-viz-dot.h		\
>-abg-viz-svg.h		
>+abg-viz-svg.h		\
>+abg-regex.h
>
> EXTRA_DIST = abg-version.h.in
>diff --git a/include/abg-regex.h b/include/abg-regex.h
>new file mode 100644
>index 00000000..84c386a9
>--- /dev/null
>+++ b/include/abg-regex.h
>@@ -0,0 +1,83 @@
>+// -*- mode: C++ -*-
>+//
>+// Copyright (C) 2013-2020 Red Hat, Inc.
>+//
>+// This file is part of the GNU Application Binary Interface Generic
>+// Analysis and Instrumentation Library (libabigail).  This library is
>+// free software; you can redistribute it and/or modify it under the
>+// terms of the GNU Lesser General Public License as published by the
>+// Free Software Foundation; either version 3, or (at your option) any
>+// later version.
>+
>+// This library is distributed in the hope that it will be useful, but
>+// WITHOUT ANY WARRANTY; without even the implied warranty of
>+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>+// General Lesser Public License for more details.
>+
>+// You should have received a copy of the GNU Lesser General Public
>+// License along with this program; see the file COPYING-LGPLV3.  If
>+// not, see <http://www.gnu.org/licenses/>.
>+
>+/// @file
>+///
>+/// Wrappers around regex types and functions.
>+
>+#ifndef __ABG_REGEX_H__
>+#define __ABG_REGEX_H__
>+
>+#include <regex.h>
>+
>+#include "abg-cxx-compat.h"
>+#include "abg-sptr-utils.h"
>+
>+namespace abigail
>+{
>+
>+/// Namespace for regex types and functions.
>+namespace regex
>+{
>+
>+/// A convenience typedef for a shared pointer of regex_t.
>+typedef abg_compat::shared_ptr<regex_t> regex_t_sptr;
>+
>+/// A delete functor for a shared_ptr of regex_t.
>+struct regex_t_deleter
>+{
>+  /// The operator called to de-allocate the pointer to regex_t
>+  /// embedded in a shared_ptr<regex_t>
>+  ///
>+  /// @param r the pointer to regex_t to de-allocate.
>+  void
>+  operator()(::regex_t* r)
>+  {
>+    regfree(r);
>+    delete r;
>+  }
>+};//end struct regex_deleter
>+
>+}// end namespace regex
>+
>+/// Specialization of sptr_utils::build_sptr for regex_t.
>+///
>+/// This is used to wrap a pointer to regex_t into a
>+/// shared_ptr<regex_t>.
>+///
>+/// @param p the bare pointer to regex_t to wrap into a shared_ptr<regex_t>.
>+///
>+/// @return the shared_ptr<regex_t> that wraps @p p.
>+template<>
>+regex::regex_t_sptr
>+sptr_utils::build_sptr<regex_t>(regex_t *p);
>+
>+/// Specialization of sptr_utils::build_sptr for regex_t.
>+///
>+/// This creates a pointer to regex_t and wraps it into a shared_ptr<regex_t>.
>+///
>+/// @return the shared_ptr<regex_t> wrapping the newly created regex_t*
>+template<>
>+regex::regex_t_sptr
>+sptr_utils::build_sptr<regex_t>();
>+
>+}// end namespace abigail
>+
>+#endif //__ABG_REGEX_H__
>diff --git a/include/abg-sptr-utils.h b/include/abg-sptr-utils.h
>index 0adedbb3..9737fe5f 100644
>--- a/include/abg-sptr-utils.h
>+++ b/include/abg-sptr-utils.h
>@@ -78,19 +78,6 @@ typedef shared_ptr<xmlChar> xml_char_sptr;
> template<>
> xml_char_sptr build_sptr<xmlChar>(xmlChar *p);
>
>-/// A convenience typedef for a shared pointer of regex_t.
>-typedef shared_ptr<regex_t> regex_t_sptr;
>-
>-/// Specialization of sptr_utils::build_sptr for regex_t.
>-template<>
>-regex_t_sptr
>-build_sptr<regex_t>(regex_t *p);
>-
>-/// Specialization of sptr_utils::build_sptr for regex_t.
>-template<>
>-regex_t_sptr
>-build_sptr<regex_t>();
>-
> /// A deleter for shared pointers that ... doesn't delete the object
> /// managed by the shared pointer.
> struct noop_deleter
>@@ -101,42 +88,6 @@ struct noop_deleter
>   {}
> };
>
>-/// A delete functor for a shared_ptr of regex_t.
>-struct regex_t_deleter
>-{
>-  /// The operator called to de-allocate the pointer to regex_t
>-  /// embedded in a shared_ptr<regex_t>
>-  ///
>-  /// @param r the pointer to regex_t to de-allocate.
>-  void
>-  operator()(::regex_t* r)
>-  {
>-    regfree(r);
>-    delete r;
>-  }
>-};//end struct regex_deleter
>-
>-/// Specialization of sptr_utils::build_sptr for regex_t.
>-///
>-/// This is used to wrap a pointer to regex_t into a
>-/// shared_ptr<regex_t>.
>-///
>-/// @param p the bare pointer to regex_t to wrap into a shared_ptr<regex_t>.
>-///
>-/// @return the shared_ptr<regex_t> that wraps @p p.
>-template<>
>-regex_t_sptr
>-build_sptr<regex_t>(regex_t *p);
>-
>-/// Specialization of sptr_utils::build_sptr for regex_t.
>-///
>-/// This creates a pointer to regex_t and wraps it into a shared_ptr<regex_t>.
>-///
>-/// @return the shared_ptr<regex_t> wrapping the newly created regex_t*
>-template<>
>-regex_t_sptr
>-build_sptr<regex_t>();
>-
> }// end namespace sptr_utils
> }// end namespace abigail
>
>diff --git a/src/Makefile.am b/src/Makefile.am
>index fafab853..1153a5f8 100644
>--- a/src/Makefile.am
>+++ b/src/Makefile.am
>@@ -13,7 +13,6 @@ endif
>
> libabigail_la_SOURCES =			\
> abg-internal.h				\
>-abg-sptr-utils.cc			\
> abg-traverse.cc				\
> abg-ir-priv.h				\
> abg-ir.cc				\
>@@ -41,6 +40,7 @@ abg-workers.cc				\
> abg-tools-utils.cc			\
> abg-elf-helpers.h			\
> abg-elf-helpers.cc			\
>+abg-regex.cc				\
> $(CXX11_SOURCES)
>
> libabigail_la_LIBADD = $(DEPS_LIBS)
>diff --git a/src/abg-corpus-priv.h b/src/abg-corpus-priv.h
>index 4cb2e43c..e65f7c8f 100644
>--- a/src/abg-corpus-priv.h
>+++ b/src/abg-corpus-priv.h
>@@ -30,6 +30,7 @@
> #define __ABG_CORPUS_PRIV_H__
>
> #include "abg-sptr-utils.h"
>+#include "abg-regex.h"
> #include "abg-internal.h"

While it was not before, please sort those includes.

>
> namespace abigail
>@@ -42,7 +43,7 @@ namespace sptr_utils
> namespace ir
> {
>
>-using sptr_utils::regex_t_sptr;
>+using regex::regex_t_sptr;
>
> /// A convenience typedef for std::vector<regex_t_sptr>.
> typedef vector<regex_t_sptr> regex_t_sptrs_type;
>diff --git a/src/abg-corpus.cc b/src/abg-corpus.cc
>index 12f44fd1..2e9f304d 100644
>--- a/src/abg-corpus.cc
>+++ b/src/abg-corpus.cc
>@@ -67,7 +67,7 @@ using zip_utils::open_archive;
> using zip_utils::open_file_in_archive;
> #endif // WITH_ZIP_ARCHIVE
>
>-using sptr_utils::regex_t_sptr;
>+using regex::regex_t_sptr;
>
> /// Constructor of @ref corpus::exported_decls_builder.
> ///
>diff --git a/src/abg-sptr-utils.cc b/src/abg-regex.cc
>similarity index 84%
>rename from src/abg-sptr-utils.cc
>rename to src/abg-regex.cc
>index 2a6739a8..13f5841d 100644
>--- a/src/abg-sptr-utils.cc
>+++ b/src/abg-regex.cc
>@@ -24,13 +24,11 @@
> ///
>
> #include "abg-sptr-utils.h"
>+#include "abg-regex.h"

Sort.

>
> namespace abigail
> {
>
>-namespace sptr_utils
>-{
>-
> /// Specialization of sptr_utils::build_sptr for regex_t.
> ///
> /// This is used to wrap a pointer to regex_t into a
>@@ -40,9 +38,9 @@ namespace sptr_utils
> ///
> /// @return the shared_ptr<regex_t> that wraps @p p.
> template<>
>-regex_t_sptr
>-build_sptr<regex_t>(regex_t *p)
>-{return regex_t_sptr(p, regex_t_deleter());}
>+regex::regex_t_sptr
>+sptr_utils::build_sptr<regex_t>(regex_t *p)
>+{return regex::regex_t_sptr(p, regex::regex_t_deleter());}
>
> /// Specialization of sptr_utils::build_sptr for regex_t.
> ///
>@@ -50,9 +48,8 @@ build_sptr<regex_t>(regex_t *p)
> ///
> /// @return the shared_ptr<regex_t> wrapping the newly created regex_t*
> template<>
>-regex_t_sptr
>-build_sptr<regex_t>()
>-{return build_sptr(new regex_t);}
>+regex::regex_t_sptr
>+sptr_utils::build_sptr<regex_t>()
>+{return sptr_utils::build_sptr(new regex_t);}
>
>-}
>-}
>+}//end namespace abigail
>diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
>index 1a9a7207..c37ceff6 100644
>--- a/src/abg-suppression-priv.h
>+++ b/src/abg-suppression-priv.h
>@@ -31,6 +31,7 @@
> #include "abg-fwd.h"
> #include "abg-suppression.h"
> #include "abg-sptr-utils.h"
>+#include "abg-regex.h"

Sort includes alphabetical.

With the above fixed:
Reviewed-by: Matthias Maennich <maennich@google.com>

Cheers,
Matthias
>
> namespace abigail
> {
>@@ -47,13 +48,13 @@ class suppression_base::priv
>   bool					drops_artifact_;
>   string				label_;
>   string				file_name_regex_str_;
>-  mutable sptr_utils::regex_t_sptr	file_name_regex_;
>+  mutable regex::regex_t_sptr		file_name_regex_;
>   string				file_name_not_regex_str_;
>-  mutable sptr_utils::regex_t_sptr	file_name_not_regex_;
>+  mutable regex::regex_t_sptr		file_name_not_regex_;
>   string				soname_regex_str_;
>-  mutable sptr_utils::regex_t_sptr	soname_regex_;
>+  mutable regex::regex_t_sptr		soname_regex_;
>   string				soname_not_regex_str_;
>-  mutable sptr_utils::regex_t_sptr	soname_not_regex_;
>+  mutable regex::regex_t_sptr		soname_not_regex_;
>
> public:
>   priv()
>@@ -87,14 +88,14 @@ public:
>   ///
>   /// If the 'file_name_regex' property of @ref suppression_base is
>   /// empty then this method returns nil.
>-  const sptr_utils::regex_t_sptr&
>+  const regex::regex_t_sptr&
>   get_file_name_regex() const
>   {
>     if (!file_name_regex_)
>       {
> 	if (!file_name_regex_str_.empty())
> 	  {
>-	    sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>+	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> 	    if (regcomp(r.get(),
> 			file_name_regex_str_.c_str(),
> 			REG_EXTENDED) == 0)
>@@ -112,14 +113,14 @@ public:
>   ///
>   /// If the 'file_name_not_regex' property of @ref suppression_base
>   /// is empty then this method returns nil.
>-  const sptr_utils::regex_t_sptr&
>+  const regex::regex_t_sptr&
>   get_file_name_not_regex() const
>   {
>     if (!file_name_not_regex_)
>       {
> 	if (!file_name_not_regex_str_.empty())
> 	  {
>-	    sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>+	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> 	    if (regcomp(r.get(),
> 			file_name_not_regex_str_.c_str(),
> 			REG_EXTENDED) == 0)
>@@ -137,14 +138,14 @@ public:
>   ///
>   /// If the 'soname_regex' property of @ref suppression_base is empty
>   /// then this method returns nil.
>-  const sptr_utils::regex_t_sptr&
>+  const regex::regex_t_sptr&
>   get_soname_regex() const
>   {
>     if (!soname_regex_)
>       {
> 	if (!soname_regex_str_.empty())
> 	  {
>-	    sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>+	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> 	    if (regcomp(r.get(),
> 			soname_regex_str_.c_str(),
> 			REG_EXTENDED) == 0)
>@@ -162,14 +163,14 @@ public:
>   ///
>   /// If the 'soname_not_regex' property of @ref suppression_base is
>   /// empty then this method returns nil.
>-  const sptr_utils::regex_t_sptr&
>+  const regex::regex_t_sptr&
>   get_soname_not_regex() const
>   {
>     if (!soname_not_regex_)
>       {
> 	if (!soname_not_regex_str_.empty())
> 	  {
>-	    sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>+	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> 	    if (regcomp(r.get(),
> 			soname_not_regex_str_.c_str(),
> 			REG_EXTENDED) == 0)
>@@ -192,14 +193,14 @@ public:
>   matches_soname(const string& soname) const
>   {
>     bool has_regexp = false;
>-    if (sptr_utils::regex_t_sptr regexp = get_soname_regex())
>+    if (regex::regex_t_sptr regexp = get_soname_regex())
>       {
> 	has_regexp = true;
> 	if (regexec(regexp.get(), soname.c_str(), 0, NULL, 0) != 0)
> 	  return false;
>       }
>
>-    if (sptr_utils::regex_t_sptr regexp = get_soname_not_regex())
>+    if (regex::regex_t_sptr regexp = get_soname_not_regex())
>       {
> 	has_regexp = true;
> 	if (regexec(regexp.get(), soname.c_str(), 0, NULL, 0) == 0)
>@@ -227,7 +228,7 @@ public:
>   {
>     bool has_regexp = false;
>
>-    if (sptr_utils::regex_t_sptr regexp = get_file_name_regex())
>+    if (regex::regex_t_sptr regexp = get_file_name_regex())
>       {
> 	has_regexp = true;
> 	if (regexec(regexp.get(), binary_name.c_str(),
>@@ -235,7 +236,7 @@ public:
> 	  return false;
>       }
>
>-    if (sptr_utils::regex_t_sptr regexp = get_file_name_not_regex())
>+    if (regex::regex_t_sptr regexp = get_file_name_not_regex())
>       {
> 	has_regexp = true;
> 	if (regexec(regexp.get(), binary_name.c_str(),
>@@ -263,7 +264,7 @@ class function_suppression::parameter_spec::priv
>   size_t				index_;
>   string				type_name_;
>   string				type_name_regex_str_;
>-  mutable sptr_utils::regex_t_sptr	type_name_regex_;
>+  mutable regex::regex_t_sptr		type_name_regex_;
>
>   priv()
>     : index_()
>@@ -277,12 +278,12 @@ class function_suppression::parameter_spec::priv
>     : index_(i), type_name_(tn), type_name_regex_str_(tn_regex)
>   {}
>
>-  const sptr_utils::regex_t_sptr
>+  const regex::regex_t_sptr
>   get_type_name_regex() const
>   {
>     if (!type_name_regex_ && !type_name_regex_str_.empty())
>       {
>-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> 	if (regcomp(r.get(),
> 		    type_name_regex_str_.c_str(),
> 		    REG_EXTENDED) == 0)
>@@ -302,21 +303,21 @@ struct function_suppression::priv
>   change_kind				change_kind_;
>   string				name_;
>   string				name_regex_str_;
>-  mutable sptr_utils::regex_t_sptr	name_regex_;
>+  mutable regex::regex_t_sptr		name_regex_;
>   string				name_not_regex_str_;
>-  mutable sptr_utils::regex_t_sptr	name_not_regex_;
>+  mutable regex::regex_t_sptr		name_not_regex_;
>   string				return_type_name_;
>   string				return_type_regex_str_;
>-  mutable sptr_utils::regex_t_sptr	return_type_regex_;
>+  mutable regex::regex_t_sptr		return_type_regex_;
>   parameter_specs_type			parm_specs_;
>   string				symbol_name_;
>   string				symbol_name_regex_str_;
>-  mutable sptr_utils::regex_t_sptr	symbol_name_regex_;
>+  mutable regex::regex_t_sptr		symbol_name_regex_;
>   string				symbol_name_not_regex_str_;
>-  mutable sptr_utils::regex_t_sptr	symbol_name_not_regex_;
>+  mutable regex::regex_t_sptr		symbol_name_not_regex_;
>   string				symbol_version_;
>   string				symbol_version_regex_str_;
>-  mutable sptr_utils::regex_t_sptr	symbol_version_regex_;
>+  mutable regex::regex_t_sptr		symbol_version_regex_;
>   bool					allow_other_aliases_;
>
>   priv():
>@@ -356,12 +357,12 @@ struct function_suppression::priv
>   ///
>   /// @return a pointer to the regular expression object of
>   /// function_suppression::priv::name_regex_str_..
>-  const sptr_utils::regex_t_sptr
>+  const regex::regex_t_sptr
>   get_name_regex() const
>   {
>     if (!name_regex_ && !name_regex_str_.empty())
>       {
>-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> 	if (regcomp(r.get(),
> 		    name_regex_str_.c_str(),
> 		    REG_EXTENDED) == 0)
>@@ -379,12 +380,12 @@ struct function_suppression::priv
>   ///
>   /// @return a pointer to the regular expression object of
>   /// function_suppression::priv::name_not_regex_str_..
>-  const sptr_utils::regex_t_sptr
>+  const regex::regex_t_sptr
>   get_name_not_regex() const
>   {
>     if (!name_not_regex_ && !name_not_regex_str_.empty())
>       {
>-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> 	if (regcomp(r.get(),
> 		    name_not_regex_str_.c_str(),
> 		    REG_EXTENDED) == 0)
>@@ -402,12 +403,12 @@ struct function_suppression::priv
>   ///
>   /// @return a pointer to the regular expression object of
>   /// function_suppression::priv::return_type_regex_str_.
>-  const sptr_utils::regex_t_sptr
>+  const regex::regex_t_sptr
>   get_return_type_regex() const
>   {
>     if (!return_type_regex_ && !return_type_regex_str_.empty())
>       {
>-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> 	if (regcomp(r.get(),
> 		    return_type_regex_str_.c_str(),
> 		    REG_EXTENDED) == 0)
>@@ -425,12 +426,12 @@ struct function_suppression::priv
>   ///
>   /// @return a pointer to the regular expression object of
>   /// function_suppression::priv::symbol_name_regex_str_.
>-  const sptr_utils::regex_t_sptr
>+  const regex::regex_t_sptr
>   get_symbol_name_regex() const
>   {
>     if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
>       {
>-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> 	if (regcomp(r.get(),
> 		    symbol_name_regex_str_.c_str(),
> 		    REG_EXTENDED) == 0)
>@@ -448,12 +449,12 @@ struct function_suppression::priv
>   ///
>   /// @return a pointer to the regular expression object of
>   /// function_suppression::priv::symbol_name_not_regex_str_.
>-  const sptr_utils::regex_t_sptr
>+  const regex::regex_t_sptr
>   get_symbol_name_not_regex() const
>   {
>     if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
>       {
>-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> 	if (regcomp(r.get(),
> 		    symbol_name_not_regex_str_.c_str(),
> 		    REG_EXTENDED) == 0)
>@@ -471,12 +472,12 @@ struct function_suppression::priv
>   ///
>   /// @return a pointer to the regular expression object of
>   /// function_suppression::priv::symbol_version_regex_str_.
>-  const sptr_utils::regex_t_sptr
>+  const regex::regex_t_sptr
>   get_symbol_version_regex() const
>   {
>     if (!symbol_version_regex_ && ! symbol_version_regex_str_.empty())
>       {
>-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> 	if (regcomp(r.get(),
> 		    symbol_version_regex_str_.c_str(),
> 		    REG_EXTENDED) == 0)
>@@ -561,20 +562,20 @@ struct variable_suppression::priv
>   change_kind				change_kind_;
>   string				name_;
>   string				name_regex_str_;
>-  mutable sptr_utils::regex_t_sptr	name_regex_;
>+  mutable regex::regex_t_sptr		name_regex_;
>   string				name_not_regex_str_;
>-  mutable sptr_utils::regex_t_sptr	name_not_regex_;
>+  mutable regex::regex_t_sptr		name_not_regex_;
>   string				symbol_name_;
>   string				symbol_name_regex_str_;
>-  mutable sptr_utils::regex_t_sptr	symbol_name_regex_;
>+  mutable regex::regex_t_sptr		symbol_name_regex_;
>   string				symbol_name_not_regex_str_;
>-  mutable sptr_utils::regex_t_sptr	symbol_name_not_regex_;
>+  mutable regex::regex_t_sptr		symbol_name_not_regex_;
>   string				symbol_version_;
>   string				symbol_version_regex_str_;
>-  mutable sptr_utils::regex_t_sptr	symbol_version_regex_;
>+  mutable regex::regex_t_sptr		symbol_version_regex_;
>   string				type_name_;
>   string				type_name_regex_str_;
>-  mutable sptr_utils::regex_t_sptr	type_name_regex_;
>+  mutable regex::regex_t_sptr		type_name_regex_;
>
>   priv(const string& name,
>        const string& name_regex_str,
>@@ -604,12 +605,12 @@ struct variable_suppression::priv
>   ///
>   /// @return a pointer to the regular expression object of
>   /// variable_suppression::priv::name_regex_str_.
>-  const sptr_utils::regex_t_sptr
>+  const regex::regex_t_sptr
>   get_name_regex() const
>   {
>     if (!name_regex_ && !name_regex_str_.empty())
>       {
>-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> 	if (regcomp(r.get(),
> 		    name_regex_str_.c_str(),
> 		    REG_EXTENDED) == 0)
>@@ -627,12 +628,12 @@ struct variable_suppression::priv
>   ///
>   /// @return a pointer to the regular expression object of
>   /// variable_suppression::priv::name_not_regex_str_..
>-  const sptr_utils::regex_t_sptr
>+  const regex::regex_t_sptr
>   get_name_not_regex() const
>   {
>     if (!name_not_regex_ && !name_not_regex_str_.empty())
>       {
>-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> 	if (regcomp(r.get(),
> 		    name_not_regex_str_.c_str(),
> 		    REG_EXTENDED) == 0)
>@@ -650,12 +651,12 @@ struct variable_suppression::priv
>   ///
>   /// @return a pointer to the regular expression object of
>   /// variable_suppression::priv::symbol_name_regex_str_.
>-  const sptr_utils::regex_t_sptr
>+  const regex::regex_t_sptr
>   get_symbol_name_regex() const
>   {
>     if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
>       {
>-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> 	if (regcomp(r.get(),
> 		    symbol_name_regex_str_.c_str(),
> 		    REG_EXTENDED) == 0)
>@@ -673,12 +674,12 @@ struct variable_suppression::priv
>   ///
>   /// @return a pointer to the regular expression object of
>   /// variable_suppression::priv::symbol_name_not_regex_str_.
>-  const sptr_utils::regex_t_sptr
>+  const regex::regex_t_sptr
>   get_symbol_name_not_regex() const
>   {
>     if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
>       {
>-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> 	if (regcomp(r.get(), symbol_name_not_regex_str_.c_str(),
> 		    REG_EXTENDED) == 0)
> 	  symbol_name_not_regex_ = r;
>@@ -695,12 +696,12 @@ struct variable_suppression::priv
>   ///
>   /// @return a pointer to the regular expression object of
>   /// variable_suppression::priv::symbol_version_regex_str_.
>-  const sptr_utils::regex_t_sptr
>+  const regex::regex_t_sptr
>   get_symbol_version_regex()  const
>   {
>     if (!symbol_version_regex_ && !symbol_version_regex_str_.empty())
>       {
>-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> 	if (regcomp(r.get(),
> 		    symbol_version_regex_str_.c_str(),
> 		    REG_EXTENDED) == 0)
>@@ -718,12 +719,12 @@ struct variable_suppression::priv
>   ///
>   /// @return a pointer to the regular expression object of
>   /// variable_suppression::priv::type_name_regex_str_.
>-  const sptr_utils::regex_t_sptr
>+  const regex::regex_t_sptr
>   get_type_name_regex() const
>   {
>     if (!type_name_regex_ && !type_name_regex_str_.empty())
>       {
>-	sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>+	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> 	if (regcomp(r.get(),
> 		    type_name_regex_str_.c_str(),
> 		    REG_EXTENDED) == 0)
>@@ -766,18 +767,18 @@ variable_is_suppressed(const ReadContextType&	ctxt,
> class type_suppression::priv
> {
>   string				type_name_regex_str_;
>-  mutable sptr_utils::regex_t_sptr	type_name_regex_;
>+  mutable regex::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_;
>+  mutable regex::regex_t_sptr		type_name_not_regex_;
>   bool					consider_type_kind_;
>   type_suppression::type_kind		type_kind_;
>   bool					consider_reach_kind_;
>   type_suppression::reach_kind		reach_kind_;
>   type_suppression::insertion_ranges	insertion_ranges_;
>-  unordered_set<string>		source_locations_to_keep_;
>+  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 regex::regex_t_sptr		source_location_to_keep_regex_;
>   mutable vector<string>		changed_enumerator_names_;
>
>   priv();
>@@ -805,14 +806,14 @@ public:
>   ///
>   /// If the 'type_name_regex' property of @ref type_suppression is
>   /// empty then this method returns nil.
>-  const sptr_utils::regex_t_sptr
>+  const regex::regex_t_sptr
>   get_type_name_regex() const
>   {
>     if (!type_name_regex_)
>       {
> 	if (!type_name_regex_str_.empty())
> 	  {
>-	    sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>+	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> 	    if (regcomp(r.get(),
> 			type_name_regex_str_.c_str(),
> 			REG_EXTENDED) == 0)
>@@ -826,7 +827,7 @@ public:
>   ///
>   /// @param r the new type_name_regex object.
>   void
>-  set_type_name_regex(sptr_utils::regex_t_sptr r)
>+  set_type_name_regex(regex::regex_t_sptr r)
>   {type_name_regex_ = r;}
>
>   /// Get the regular expression object associated to the
>@@ -837,14 +838,14 @@ public:
>   ///
>   /// If the 'type_name_not_regex' property of @ref type_suppression is
>   /// empty then this method returns nil.
>-  const sptr_utils::regex_t_sptr
>+  const regex::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>();
>+	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> 	    if (regcomp(r.get(),
> 			type_name_not_regex_str_.c_str(),
> 			REG_EXTENDED) == 0)
>@@ -858,7 +859,7 @@ public:
>   ///
>   /// @param r the new type_name_not_regex object.
>   void
>-  set_type_name_not_regex(sptr_utils::regex_t_sptr r)
>+  set_type_name_not_regex(regex::regex_t_sptr r)
>   {type_name_not_regex_ = r;}
>
>   /// Getter for the string that denotes the 'type_name_not_regex'
>@@ -882,14 +883,14 @@ public:
>   /// Getter for the source_location_to_keep_regex object.
>   ///
>   /// This function builds the regex if it's not yet built.
>-  const sptr_utils::regex_t_sptr
>+  const regex::regex_t_sptr
>   get_source_location_to_keep_regex() const
>   {
>     if (!source_location_to_keep_regex_)
>       {
> 	if (!source_location_to_keep_regex_str_.empty())
> 	  {
>-	    sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>+	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> 	    if (regcomp(r.get(),
> 			source_location_to_keep_regex_str_.c_str(),
> 			REG_EXTENDED) == 0)
>@@ -903,7 +904,7 @@ public:
>   ///
>   /// @param r the new regex object.
>   void
>-  set_source_location_to_keep_regex(sptr_utils::regex_t_sptr r)
>+  set_source_location_to_keep_regex(regex::regex_t_sptr r)
>   {source_location_to_keep_regex_ = r;}
>
>   friend class type_suppression;
>diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
>index d3ccb63c..f26c9208 100644
>--- a/src/abg-suppression.cc
>+++ b/src/abg-suppression.cc
>@@ -49,6 +49,7 @@ namespace suppr
> {
>
> using abg_compat::dynamic_pointer_cast;
>+using regex::regex_t_sptr;
>
> // <suppression_base stuff>
>
>@@ -990,7 +991,7 @@ 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.
>-	  if (const sptr_utils::regex_t_sptr& type_name_regex =
>+	  if (const regex_t_sptr& type_name_regex =
> 	      s.priv_->get_type_name_regex())
> 	    {
> 	      if (regexec(type_name_regex.get(),
>@@ -999,7 +1000,7 @@ suppression_matches_type_name(const type_suppression&	s,
> 		return false;
> 	    }
>
>-	  if (const sptr_utils::regex_t_sptr type_name_not_regex =
>+	  if (const regex_t_sptr type_name_not_regex =
> 	      s.priv_->get_type_name_not_regex())
> 	    {
> 	      if (regexec(type_name_not_regex.get(),
>@@ -1050,8 +1051,7 @@ suppression_matches_type_location(const type_suppression&	s,
>       unsigned loc_line = 0, loc_column = 0;
>       loc.expand(loc_path, loc_line, loc_column);
>
>-      if (sptr_utils::regex_t_sptr regexp =
>-	  s.priv_->get_source_location_to_keep_regex())
>+      if (regex_t_sptr regexp = s.priv_->get_source_location_to_keep_regex())
> 	if (regexec(regexp.get(), loc_path.c_str(), 0, NULL, 0) == 0)
> 	  return false;
>
>@@ -2500,7 +2500,7 @@ function_suppression::suppresses_function(const function_decl* fn,
>     }
>
>   // check if the "name_regexp" property matches.
>-  const sptr_utils::regex_t_sptr name_regex = priv_->get_name_regex();
>+  const regex_t_sptr name_regex = priv_->get_name_regex();
>   if (name_regex)
>     {
>       if (regexec(name_regex.get(),
>@@ -2535,7 +2535,7 @@ function_suppression::suppresses_function(const function_decl* fn,
>     }
>
>   // check if the "name_not_regexp" property matches.
>-  const sptr_utils::regex_t_sptr name_not_regex = priv_->get_name_not_regex();
>+  const regex_t_sptr name_not_regex = priv_->get_name_not_regex();
>   if (name_not_regex)
>     {
>       if (regexec(name_not_regex.get(),
>@@ -2585,8 +2585,7 @@ function_suppression::suppresses_function(const function_decl* fn,
>     }
>   else
>     {
>-      const sptr_utils::regex_t_sptr return_type_regex =
>-	priv_->get_return_type_regex();
>+      const regex_t_sptr return_type_regex = priv_->get_return_type_regex();
>       if (return_type_regex
> 	  && (regexec(return_type_regex.get(),
> 		      fn_return_type_name.c_str(),
>@@ -2626,15 +2625,14 @@ function_suppression::suppresses_function(const function_decl* fn,
>     }
>   else if (sym)
>     {
>-      const sptr_utils::regex_t_sptr symbol_name_regex =
>-	priv_->get_symbol_name_regex();
>+      const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
>       if (symbol_name_regex
> 	  && (regexec(symbol_name_regex.get(),
> 		      fn_sym_name.c_str(),
> 		      0, NULL, 0) != 0))
> 	return false;
>
>-      const sptr_utils::regex_t_sptr symbol_name_not_regex =
>+      const regex_t_sptr symbol_name_not_regex =
> 	priv_->get_symbol_name_not_regex();
>       if (symbol_name_not_regex
> 	  && (regexec(symbol_name_not_regex.get(),
>@@ -2678,7 +2676,7 @@ function_suppression::suppresses_function(const function_decl* fn,
>     }
>   else if (sym)
>     {
>-      const sptr_utils::regex_t_sptr symbol_version_regex =
>+      const regex_t_sptr symbol_version_regex =
> 	priv_->get_symbol_version_regex();
>       if (symbol_version_regex
> 	  && (regexec(symbol_version_regex.get(),
>@@ -2720,7 +2718,7 @@ function_suppression::suppresses_function(const function_decl* fn,
> 	    }
> 	  else
> 	    {
>-	      const sptr_utils::regex_t_sptr parm_type_name_regex =
>+	      const regex_t_sptr parm_type_name_regex =
> 		(*p)->priv_->get_type_name_regex();
> 	      if (parm_type_name_regex)
> 		{
>@@ -2813,8 +2811,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
>     }
>   else if (!get_symbol_name_regex_str().empty())
>     {
>-      const sptr_utils::regex_t_sptr symbol_name_regex =
>-	priv_->get_symbol_name_regex();
>+      const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
>       if (symbol_name_regex
> 	  && (regexec(symbol_name_regex.get(),
> 		      sym_name.c_str(),
>@@ -2832,7 +2829,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
>     }
>   else if (!get_symbol_version_regex_str().empty())
>     {
>-      const sptr_utils::regex_t_sptr symbol_version_regex =
>+      const regex_t_sptr symbol_version_regex =
> 	priv_->get_symbol_version_regex();
>       if (symbol_version_regex
> 	  && (regexec(symbol_version_regex.get(),
>@@ -2927,12 +2924,12 @@ bool
> suppression_matches_function_name(const suppr::function_suppression& s,
> 				  const string& fn_name)
> {
>-  if (sptr_utils::regex_t_sptr regexp = s.priv_->get_name_regex())
>+  if (regex_t_sptr regexp = s.priv_->get_name_regex())
>     {
>       if (regexec(regexp.get(), fn_name.c_str(), 0, NULL, 0) != 0)
> 	return false;
>     }
>-  else if (sptr_utils::regex_t_sptr regexp = s.priv_->get_name_not_regex())
>+  else if (regex_t_sptr regexp = s.priv_->get_name_not_regex())
>     {
>       if (regexec(regexp.get(), fn_name.c_str(), 0, NULL, 0) == 0)
> 	return false;
>@@ -2963,12 +2960,12 @@ bool
> suppression_matches_function_sym_name(const suppr::function_suppression& s,
> 				      const string& fn_linkage_name)
> {
>-  if (sptr_utils::regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
>+  if (regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
>     {
>       if (regexec(regexp.get(), fn_linkage_name.c_str(), 0, NULL, 0) != 0)
> 	return false;
>     }
>-  else if (sptr_utils::regex_t_sptr regexp = s.priv_->get_symbol_name_not_regex())
>+  else if (regex_t_sptr regexp = s.priv_->get_symbol_name_not_regex())
>     {
>       if (regexec(regexp.get(), fn_linkage_name.c_str(), 0, NULL, 0) == 0)
> 	return false;
>@@ -2996,12 +2993,12 @@ bool
> suppression_matches_variable_name(const suppr::variable_suppression& s,
> 				  const string& var_name)
> {
>-  if (sptr_utils::regex_t_sptr regexp = s.priv_->get_name_regex())
>+  if (regex_t_sptr regexp = s.priv_->get_name_regex())
>     {
>       if (regexec(regexp.get(), var_name.c_str(), 0, NULL, 0) != 0)
> 	return false;
>     }
>-  else if (sptr_utils::regex_t_sptr regexp = s.priv_->get_name_not_regex())
>+  else if (regex_t_sptr regexp = s.priv_->get_name_not_regex())
>     {
>       if (regexec(regexp.get(), var_name.c_str(), 0, NULL, 0) == 0)
> 	return false;
>@@ -3030,12 +3027,12 @@ bool
> suppression_matches_variable_sym_name(const suppr::variable_suppression& s,
> 				      const string& var_linkage_name)
> {
>-  if (sptr_utils::regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
>+  if (regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
>     {
>       if (regexec(regexp.get(), var_linkage_name.c_str(), 0, NULL, 0) != 0)
> 	return false;
>     }
>-  else if (sptr_utils::regex_t_sptr regexp =
>+  else if (regex_t_sptr regexp =
> 	   s.priv_->get_symbol_name_not_regex())
>     {
>       if (regexec(regexp.get(), var_linkage_name.c_str(), 0, NULL, 0) == 0)
>@@ -3065,7 +3062,7 @@ bool
> suppression_matches_type(const suppr::type_suppression& s,
> 			 const string& type_name)
> {
>-  if (sptr_utils::regex_t_sptr regexp = s.priv_->get_type_name_regex())
>+  if (regex_t_sptr regexp = s.priv_->get_type_name_regex())
>     {
>       if (regexec(regexp.get(), type_name.c_str(), 0, NULL, 0) != 0)
> 	return false;
>@@ -3780,14 +3777,13 @@ variable_suppression::suppresses_variable(const var_decl* var,
>       // "name_regex" and "name_not_regex" properties match
>       if (get_name().empty())
> 	{
>-	  const sptr_utils::regex_t_sptr name_regex = priv_->get_name_regex();
>+	  const regex_t_sptr name_regex = priv_->get_name_regex();
> 	  if (name_regex
> 	      && (regexec(name_regex.get(), var_name.c_str(),
> 			  0, NULL, 0) != 0))
> 	    return false;
>
>-	  const sptr_utils::regex_t_sptr name_not_regex =
>-	    priv_->get_name_not_regex();
>+	  const regex_t_sptr name_not_regex = priv_->get_name_not_regex();
> 	  if (name_not_regex
> 	      && (regexec(name_not_regex.get(), var_name.c_str(),
> 			  0, NULL, 0) == 0))
>@@ -3805,14 +3801,13 @@ variable_suppression::suppresses_variable(const var_decl* var,
>     }
>   else
>     {
>-      const sptr_utils::regex_t_sptr sym_name_regex =
>-	priv_->get_symbol_name_regex();
>+      const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
>       if (sym_name_regex
> 	  && (regexec(sym_name_regex.get(), var_sym_name.c_str(),
> 		      0, NULL, 0) != 0))
> 	return false;
>
>-      const sptr_utils::regex_t_sptr sym_name_not_regex =
>+      const regex_t_sptr sym_name_not_regex =
> 	priv_->get_symbol_name_not_regex();
>       if (sym_name_not_regex
> 	  && (regexec(sym_name_not_regex.get(), var_sym_name.c_str(),
>@@ -3830,7 +3825,7 @@ variable_suppression::suppresses_variable(const var_decl* var,
>     }
>   else
>     {
>-      const sptr_utils::regex_t_sptr symbol_version_regex =
>+      const regex_t_sptr symbol_version_regex =
> 	priv_->get_symbol_version_regex();
>       if (symbol_version_regex
> 	  && (regexec(symbol_version_regex.get(),
>@@ -3852,8 +3847,7 @@ variable_suppression::suppresses_variable(const var_decl* var,
>     {
>       if (get_type_name().empty())
> 	{
>-	  const sptr_utils::regex_t_sptr type_name_regex =
>-	    priv_->get_type_name_regex();
>+	  const regex_t_sptr type_name_regex = priv_->get_type_name_regex();
> 	  if (type_name_regex
> 	      && (regexec(type_name_regex.get(), var_type_name.c_str(),
> 			  0, NULL, 0) != 0))
>@@ -3946,8 +3940,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
>     }
>   else if (!get_symbol_name_regex_str().empty())
>     {
>-      const sptr_utils::regex_t_sptr sym_name_regex =
>-	priv_->get_symbol_name_regex();
>+      const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
>       if (sym_name_regex
> 	  && (regexec(sym_name_regex.get(), sym_name.c_str(),
> 		      0, NULL, 0) != 0))
>@@ -3965,7 +3958,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
>     }
>   else if (!get_symbol_version_regex_str().empty())
>     {
>-      const sptr_utils::regex_t_sptr symbol_version_regex =
>+      const regex_t_sptr symbol_version_regex =
> 	priv_->get_symbol_version_regex();
>       if (symbol_version_regex
> 	  && (regexec(symbol_version_regex.get(),
>@@ -4275,16 +4268,14 @@ file_suppression::suppresses_file(const string& file_path)
>
>   bool has_regexp = false;
>
>-  if (sptr_utils::regex_t_sptr regexp =
>-      suppression_base::priv_->get_file_name_regex())
>+  if (regex_t_sptr regexp = suppression_base::priv_->get_file_name_regex())
>     {
>       has_regexp = true;
>       if (regexec(regexp.get(), fname.c_str(), 0, NULL, 0) != 0)
> 	return false;
>     }
>
>-  if (sptr_utils::regex_t_sptr regexp =
>-      suppression_base::priv_->get_file_name_not_regex())
>+  if (regex_t_sptr regexp = suppression_base::priv_->get_file_name_not_regex())
>     {
>       has_regexp = true;
>       if (regexec(regexp.get(), fname.c_str(), 0, NULL, 0) == 0)
>-- 
>2.26.2.303.gf8c07b1a785-goog
>

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 02/21] Move libxml bits out of abg-sptr-utils.h.
  2020-04-24  9:21   ` [PATCH v3 02/21] Move libxml bits out of abg-sptr-utils.h Giuliano Procida
@ 2020-04-27 10:53     ` Matthias Maennich
  2020-04-29 14:30     ` Dodji Seketeli
  2020-05-04  9:20     ` Dodji Seketeli
  2 siblings, 0 replies; 120+ messages in thread
From: Matthias Maennich @ 2020-04-27 10:53 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, dodji, kernel-team

On Fri, Apr 24, 2020 at 10:21:13AM +0100, Giuliano Procida wrote:
>The header file abg-sptr-utils.h contains generic things relating to
>shared pointers. It also contains shared pointer typedefs (in the
>sptr_utils namespace) and template specialisations for XML types.
>
>The last of these more naturally belong in abg-libxml-utils.h (and in
>the xml namespace). This patch moves them.
>
>There are no behavioural changes.
>
>	* include/abg-sptr-utils.h: Remove reader_sptr and
>	xml_char_sptr typedefs, from namespace
>	sptr_utils. (build_sptr): Remove corresponding template
>	function specialisations for these types.
>	* include/abg-libxml-utils.h: Add reader_sptr and
>	xml_char_sptr typedefs, to namespace xml. (build_sptr): Add
>	corresponding template function specialisations for these
>	types.
>
>Signed-off-by: Giuliano Procida <gprocida@google.com>

Reviewed-by: Matthias Maennich <maennich@google.com>

Cheers,
Matthias

>---
> include/abg-libxml-utils.h | 21 +++++++++++++++++++--
> include/abg-sptr-utils.h   | 17 +----------------
> 2 files changed, 20 insertions(+), 18 deletions(-)
>
>diff --git a/include/abg-libxml-utils.h b/include/abg-libxml-utils.h
>index 6331bde5..1e46d950 100644
>--- a/include/abg-libxml-utils.h
>+++ b/include/abg-libxml-utils.h
>@@ -23,7 +23,10 @@
> #ifndef __ABG_LIBXML_UTILS_H__
> #define __ABG_LIBXML_UTILS_H__
>
>+#include <libxml/xmlreader.h>
>+
> #include <istream>
>+
> #include "abg-sptr-utils.h"
> #include "abg-cxx-compat.h"
>
>@@ -36,8 +39,12 @@ namespace xml
>
> using sptr_utils::build_sptr;
> using abg_compat::shared_ptr;
>-using sptr_utils::reader_sptr;
>-using sptr_utils::xml_char_sptr;
>+
>+/// A convenience typedef for a shared pointer of xmlTextReader.
>+typedef shared_ptr<xmlTextReader> reader_sptr;
>+
>+/// A convenience typedef for a shared pointer of xmlChar.
>+typedef shared_ptr<xmlChar> xml_char_sptr;
>
> /// This functor is used to instantiate a shared_ptr for the
> /// xmlTextReader.
>@@ -121,5 +128,15 @@ std::string
> unescape_xml_comment(const std::string& str);
>
> }//end namespace xml
>+
>+/// Specialization of sptr_utils::build_sptr for xmlTextReader
>+template<>
>+xml::reader_sptr
>+sptr_utils::build_sptr<xmlTextReader>(xmlTextReader *p);
>+
>+/// Specialization of build_str for xmlChar.
>+template<>
>+xml::xml_char_sptr sptr_utils::build_sptr<xmlChar>(xmlChar *p);
>+
> }//end namespace abigail
> #endif //__ABG_LIBXML_UTILS_H__
>diff --git a/include/abg-sptr-utils.h b/include/abg-sptr-utils.h
>index 9737fe5f..2a12707b 100644
>--- a/include/abg-sptr-utils.h
>+++ b/include/abg-sptr-utils.h
>@@ -26,7 +26,7 @@
> #define __ABG_SPTR_UTILS_H__
>
> #include <regex.h>
>-#include <libxml/xmlreader.h>
>+
> #include "abg-cxx-compat.h"
>
> namespace abigail
>@@ -63,21 +63,6 @@ template<class T>
> shared_ptr<T>
> build_sptr();
>
>-/// A convenience typedef for a shared pointer of xmlTextReader.
>-typedef shared_ptr<xmlTextReader> reader_sptr;
>-
>-/// Specialization of sptr_utils::build_sptr for xmlTextReader
>-template<>
>-reader_sptr
>-build_sptr<xmlTextReader>(xmlTextReader *p);
>-
>-/// A convenience typedef for a shared pointer of xmlChar.
>-typedef shared_ptr<xmlChar> xml_char_sptr;
>-
>-/// Specialization of build_str for xmlChar.
>-template<>
>-xml_char_sptr build_sptr<xmlChar>(xmlChar *p);
>-
> /// A deleter for shared pointers that ... doesn't delete the object
> /// managed by the shared pointer.
> struct noop_deleter
>-- 
>2.26.2.303.gf8c07b1a785-goog
>

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 03/21] Simplify generation of symbol whitelist regex.
  2020-04-24  9:21   ` [PATCH v3 03/21] Simplify generation of symbol whitelist regex Giuliano Procida
@ 2020-04-27 11:01     ` Matthias Maennich
  2020-04-27 15:31       ` Giuliano Procida
  2020-05-04  9:20     ` Dodji Seketeli
  1 sibling, 1 reply; 120+ messages in thread
From: Matthias Maennich @ 2020-04-27 11:01 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, dodji, kernel-team

On Fri, Apr 24, 2020 at 10:21:14AM +0100, Giuliano Procida wrote:
>The code to build the symbol whitelist regex uses things like seekp
>and tellp to generate regexes like "^foo$|^bar$".
>
>This patch simplifies the code, for further enhancement, resulting in
>generated regexes like "^(foo|bar)$".
>
>There should be no change in behaviour, unless whitelisted symbol
>names contain special regex characters.
>
>	* include/abg-regex.h (generate_from_strings): Declare new
>	function to build a regex from some strings, representing a
>	membership test.
>	* src/abg-regex.cc (generate_from_strings): Implement new
>	function to build a regex from some strings, representing a
>	membership test, in a straightfoward fashion.
>	* src/abg-tools-utils.cc
>	(gen_suppr_spec_from_kernel_abi_whitelists): Replace
>	regex-building code with a call to generate_from_strings.
>	* tests/test-kmi-whitelist.cc: Update regexes in test.
>
>Signed-off-by: Giuliano Procida <gprocida@google.com>
>---
> include/abg-regex.h         |  6 ++++++
> src/abg-regex.cc            | 28 ++++++++++++++++++++++++++++
> src/abg-tools-utils.cc      | 10 +++-------
> tests/test-kmi-whitelist.cc | 10 +++++-----
> 4 files changed, 42 insertions(+), 12 deletions(-)
>
>diff --git a/include/abg-regex.h b/include/abg-regex.h
>index 84c386a9..2f638ef2 100644
>--- a/include/abg-regex.h
>+++ b/include/abg-regex.h
>@@ -27,6 +27,9 @@
>
> #include <regex.h>
>
>+#include <string>
>+#include <vector>
>+
> #include "abg-cxx-compat.h"
> #include "abg-sptr-utils.h"
>
>@@ -55,6 +58,9 @@ struct regex_t_deleter
>   }
> };//end struct regex_deleter
>
>+std::string
>+generate_from_strings(const std::vector<std::string>& strs);
>+
> }// end namespace regex
>
> /// Specialization of sptr_utils::build_sptr for regex_t.
>diff --git a/src/abg-regex.cc b/src/abg-regex.cc
>index 13f5841d..79a89033 100644
>--- a/src/abg-regex.cc
>+++ b/src/abg-regex.cc
>@@ -23,6 +23,7 @@
> /// Some specialization for shared pointer utility templates.
> ///
>
>+#include <sstream>
> #include "abg-sptr-utils.h"
> #include "abg-regex.h"
>
>@@ -52,4 +53,31 @@ regex::regex_t_sptr
> sptr_utils::build_sptr<regex_t>()
> {return sptr_utils::build_sptr(new regex_t);}
>
>+namespace regex
>+{
>+
>+/// Generate a regex pattern equivalent to testing set membership.
>+///
>+/// A string will match the resulting pattern regex, if and only if it
>+/// was present in the vector.
>+///
>+/// @param strs a vector of strings
>+///
>+/// @return a regex pattern
>+std::string
>+generate_from_strings(const std::vector<std::string>& strs)
>+{
>+  if (strs.empty())
>+    return "^_^";

I am not aware of this constant. Looks like an invalid regex. Can you
document it? Or am I missing the joke? :-)

Cheers,
Matthias

>+  std::ostringstream os;
>+  std::vector<std::string>::const_iterator i = strs.begin();
>+  os << "^(" << *i++;
>+  while (i != strs.end())
>+    os << "|" << *i++;
>+  os << ")$";
>+  return os.str();
>+}
>+
>+}//end namespace regex
>+
> }//end namespace abigail
>diff --git a/src/abg-tools-utils.cc b/src/abg-tools-utils.cc
>index a06e8615..11486a21 100644
>--- a/src/abg-tools-utils.cc
>+++ b/src/abg-tools-utils.cc
>@@ -61,6 +61,8 @@
> #include "abg-dwarf-reader.h"
> #include "abg-internal.h"
> #include "abg-cxx-compat.h"
>+#include "abg-regex.h"
>+
> // <headers defining libabigail's API go under here>
> ABG_BEGIN_EXPORT_DECLARATIONS
>
>@@ -2002,13 +2004,7 @@ gen_suppr_spec_from_kernel_abi_whitelists
>
>       // Build a regular expression representing the union of all
>       // the function and variable names expressed in the white list.
>-      std::stringstream regex_ss;
>-      regex_ss << "^";
>-      std::copy(whitelisted_names.begin(), whitelisted_names.end(),
>-		std::ostream_iterator<std::string>(regex_ss, "$|^"));
>-      regex_ss.seekp(0, std::ios::end);
>-      const std::string& regex =
>-	  regex_ss.str().substr(0, static_cast<size_t>(regex_ss.tellp()) - 2);
>+      const std::string regex = regex::generate_from_strings(whitelisted_names);
>
>       // Build a suppression specification which *keeps* functions
>       // whose ELF symbols match the regular expression contained
>diff --git a/tests/test-kmi-whitelist.cc b/tests/test-kmi-whitelist.cc
>index 2aa0f463..bcc5adee 100644
>--- a/tests/test-kmi-whitelist.cc
>+++ b/tests/test-kmi-whitelist.cc
>@@ -96,7 +96,7 @@ TEST_CASE("WhitelistWithASingleEntry", "[whitelists]")
>   suppressions_type suppr
>       = gen_suppr_spec_from_kernel_abi_whitelists(abi_whitelist_paths);
>   REQUIRE(!suppr.empty());
>-  test_suppressions_are_consistent(suppr, "^test_symbol$");
>+  test_suppressions_are_consistent(suppr, "^(test_symbol)$");
> }
>
> TEST_CASE("WhitelistWithADuplicateEntry", "[whitelists]")
>@@ -106,7 +106,7 @@ TEST_CASE("WhitelistWithADuplicateEntry", "[whitelists]")
>   suppressions_type suppr
>       = gen_suppr_spec_from_kernel_abi_whitelists(abi_whitelist_paths);
>   REQUIRE(!suppr.empty());
>-  test_suppressions_are_consistent(suppr, "^test_symbol$");
>+  test_suppressions_are_consistent(suppr, "^(test_symbol)$");
> }
>
> TEST_CASE("TwoWhitelists", "[whitelists]")
>@@ -118,7 +118,7 @@ TEST_CASE("TwoWhitelists", "[whitelists]")
>       gen_suppr_spec_from_kernel_abi_whitelists(abi_whitelist_paths);
>   REQUIRE(!suppr.empty());
>   test_suppressions_are_consistent(suppr,
>-				   "^test_another_symbol$|^test_symbol$");
>+				   "^(test_another_symbol|test_symbol)$");
> }
>
> TEST_CASE("TwoWhitelistsWithDuplicates", "[whitelists]")
>@@ -130,7 +130,7 @@ TEST_CASE("TwoWhitelistsWithDuplicates", "[whitelists]")
>       = gen_suppr_spec_from_kernel_abi_whitelists(abi_whitelist_paths);
>   REQUIRE(!suppr.empty());
>   test_suppressions_are_consistent(suppr,
>-				   "^test_another_symbol$|^test_symbol$");
>+				   "^(test_another_symbol|test_symbol)$");
> }
>
> TEST_CASE("WhitelistWithTwoSections", "[whitelists]")
>@@ -140,5 +140,5 @@ TEST_CASE("WhitelistWithTwoSections", "[whitelists]")
>   suppressions_type suppr
>       = gen_suppr_spec_from_kernel_abi_whitelists(abi_whitelist_paths);
>   REQUIRE(!suppr.empty());
>-  test_suppressions_are_consistent(suppr, "^test_symbol1$|^test_symbol2$");
>+  test_suppressions_are_consistent(suppr, "^(test_symbol1|test_symbol2)$");
> }
>-- 
>2.26.2.303.gf8c07b1a785-goog
>

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 04/21] Escape names used in symbol whitelisting regex.
  2020-04-24  9:21   ` [PATCH v3 04/21] Escape names used in symbol whitelisting regex Giuliano Procida
@ 2020-04-27 11:14     ` Matthias Maennich
  2020-04-27 15:37       ` Giuliano Procida
  0 siblings, 1 reply; 120+ messages in thread
From: Matthias Maennich @ 2020-04-27 11:14 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, dodji, kernel-team

On Fri, Apr 24, 2020 at 10:21:15AM +0100, Giuliano Procida wrote:
>There is the theoretical possibility that symbols may contain special
>regex characters like '.' and '$'. This patch ensures all such
>characters in symbol names are escaped before they are added to the
>whitelisting regex.
>
>	* include/regex.h (escape): New string reference holder
>	class. (operator<<): Declaration of std::ostream,
>	regex::escape overload.
>	* include/regex.cc (operator<<): New std::ostream,
>	regex::escape overload that outputs regex-escaped strings.
>	* src/abg-tools-utils.cc
>	(gen_suppr_spec_from_kernel_abi_whitelists): Make sure any
>	special regex characters in symbol names are escaped.
>
>Signed-off-by: Giuliano Procida <gprocida@google.com>
>---
> include/abg-regex.h | 10 ++++++++++
> src/abg-regex.cc    | 27 +++++++++++++++++++++++++--
> 2 files changed, 35 insertions(+), 2 deletions(-)
>
>diff --git a/include/abg-regex.h b/include/abg-regex.h
>index 2f638ef2..59976794 100644
>--- a/include/abg-regex.h
>+++ b/include/abg-regex.h
>@@ -58,6 +58,16 @@ struct regex_t_deleter
>   }
> };//end struct regex_deleter
>
>+/// A class to hold a reference to a string to regex escape.
>+struct escape
>+{
>+  escape(const std::string& str) : ref(str) { }
>+  const std::string& ref;
>+};
>+
>+std::ostream&
>+operator<<(std::ostream& os, const escape& esc);
>+
> std::string
> generate_from_strings(const std::vector<std::string>& strs);
>
>diff --git a/src/abg-regex.cc b/src/abg-regex.cc
>index 79a89033..90e4d144 100644
>--- a/src/abg-regex.cc
>+++ b/src/abg-regex.cc
>@@ -24,6 +24,7 @@
> ///
>
> #include <sstream>
>+#include <ostream>
Sort.

> #include "abg-sptr-utils.h"
> #include "abg-regex.h"
>
>@@ -56,6 +57,28 @@ sptr_utils::build_sptr<regex_t>()
> namespace regex
> {
>
>+/// Escape regex special charaters in input string.
>+///
>+/// @param os the output stream being written to.
>+///
>+/// @param esc the regex_escape object holding a reference to the string
>+/// needing to be escaped.
>+///
>+/// @return the output stream.
>+std::ostream&
>+operator<<(std::ostream& os, const escape& esc)
>+{
>+  static const std::string specials = "^.[$()|*+?{\\";

What about ']' and '}' ?

Cheers,
Matthias

>+  const std::string str = esc.ref;
>+  for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
>+    {
>+      if (specials.find(*i) != std::string::npos)
>+        os << '\\';
>+      os << *i;
>+    }
>+  return os;
>+}
>+
> /// Generate a regex pattern equivalent to testing set membership.
> ///
> /// A string will match the resulting pattern regex, if and only if it
>@@ -71,9 +94,9 @@ generate_from_strings(const std::vector<std::string>& strs)
>     return "^_^";
>   std::ostringstream os;
>   std::vector<std::string>::const_iterator i = strs.begin();
>-  os << "^(" << *i++;
>+  os << "^(" << escape(*i++);
>   while (i != strs.end())
>-    os << "|" << *i++;
>+    os << "|" << escape(*i++);
>   os << ")$";
>   return os.str();
> }
>-- 
>2.26.2.303.gf8c07b1a785-goog
>

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 05/21] abg-suppression.cc: More uniform variable naming.
  2020-04-24  9:21   ` [PATCH v3 05/21] abg-suppression.cc: More uniform variable naming Giuliano Procida
@ 2020-04-27 11:17     ` Matthias Maennich
  0 siblings, 0 replies; 120+ messages in thread
From: Matthias Maennich @ 2020-04-27 11:17 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, dodji, kernel-team

On Fri, Apr 24, 2020 at 10:21:16AM +0100, Giuliano Procida wrote:
>In abg-suppression.cc most of the read_foo functions populate and
>return a single variable "result". Others vary a little from this,
>having variables "nil" or "suppr".
>
>This patch makes all the functions use a single variable "result".
>This will make the next patches a bit simpler.
>
>There are no behavioural changes.
>
>	* src/abg-suppression.cc (read_type_suppression): Rename "nil"
>	variable to "result" and reset it instead of introducing
>	"suppr" later on. (read_function_suppression): Rename "nil"
>	variable to "result" and reset it instead of introducing
>	"result" later on.
>
>Signed-off-by: Giuliano Procida <gprocida@google.com>

Reviewed-by: Matthias Maennich <maennich@google.com>

Cheers,
Matthias

>---
> src/abg-suppression.cc | 64 +++++++++++++++++++++---------------------
> 1 file changed, 32 insertions(+), 32 deletions(-)
>
>diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
>index f26c9208..2fbbd61b 100644
>--- a/src/abg-suppression.cc
>+++ b/src/abg-suppression.cc
>@@ -1547,10 +1547,10 @@ read_suppression_reach_kind(const string& input)
> static type_suppression_sptr
> read_type_suppression(const ini::config::section& section)
> {
>-  type_suppression_sptr nil;
>+  type_suppression_sptr result;
>
>   if (section.get_name() != "suppress_type")
>-    return nil;
>+    return result;
>
>   ini::simple_property_sptr drop_artifact =
>     is_simple_property(section.find_property("drop_artifact"));
>@@ -1674,7 +1674,7 @@ read_type_suppression(const ini::config::section& section)
> 	       type_suppression::insertion_range::create_fn_call_expr_boundary(ini::read_function_call_expr(ins_point)))
> 	begin = expr;
>       else
>-	return nil;
>+	return result;
>
>       end = type_suppression::insertion_range::create_integer_boundary(-1);
>       type_suppression::insertion_range_sptr insert_range
>@@ -1717,7 +1717,7 @@ read_type_suppression(const ini::config::section& section)
> 		   type_suppression::insertion_range::create_fn_call_expr_boundary(ini::read_function_call_expr(str)))
> 	    begin = expr;
> 	  else
>-	    return nil;
>+	    return result;
>
> 	  str = val->get_content()[1];
> 	  if (str == "end")
>@@ -1730,7 +1730,7 @@ read_type_suppression(const ini::config::section& section)
> 		   type_suppression::insertion_range::create_fn_call_expr_boundary(ini::read_function_call_expr(str)))
> 	    end = expr;
> 	  else
>-	    return nil;
>+	    return result;
>
> 	  type_suppression::insertion_range_sptr insert_range
> 	    (new type_suppression::insertion_range(begin, end));
>@@ -1741,7 +1741,7 @@ read_type_suppression(const ini::config::section& section)
> 	// the 'has_data_member_inserted_between' property has a wrong
> 	// value type, so let's discard the endire [suppress_type]
> 	// section.
>-	return nil;
>+	return result;
>     }
>
>   // Support has_data_members_inserted_between
>@@ -1792,7 +1792,7 @@ read_type_suppression(const ini::config::section& section)
> 		   type_suppression::insertion_range::create_fn_call_expr_boundary(ini::read_function_call_expr(str)))
> 	    begin = expr;
> 	  else
>-	    return nil;
>+	    return result;
>
> 	  str = list_value->get_content()[1];
> 	  if (str == "end")
>@@ -1805,7 +1805,7 @@ read_type_suppression(const ini::config::section& section)
> 		   type_suppression::insertion_range::create_fn_call_expr_boundary(ini::read_function_call_expr(str)))
> 	    end = expr;
> 	  else
>-	    return nil;
>+	    return result;
>
> 	  type_suppression::insertion_range_sptr insert_range
> 	    (new type_suppression::insertion_range(begin, end));
>@@ -1813,7 +1813,7 @@ read_type_suppression(const ini::config::section& section)
> 	  consider_data_member_insertion = true;
> 	}
>       if (!is_well_formed)
>-	return nil;
>+	return result;
>     }
>
>   /// Support 'changed_enumerators = foo, bar, baz'
>@@ -1851,59 +1851,58 @@ read_type_suppression(const ini::config::section& section)
>       && !consider_type_kind
>       && srcloc_not_regexp_str.empty()
>       && srcloc_not_in.empty())
>-    return nil;
>+    return result;
>+
>+  result.reset(new type_suppression(label_str, name_regex_str, name_str));
>
>-  type_suppression_sptr suppr(new type_suppression(label_str,
>-						   name_regex_str,
>-						   name_str));
>   if (consider_type_kind)
>     {
>-      suppr->set_consider_type_kind(true);
>-      suppr->set_type_kind(type_kind);
>+      result->set_consider_type_kind(true);
>+      result->set_type_kind(type_kind);
>     }
>
>   if (consider_reach_kind)
>     {
>-      suppr->set_consider_reach_kind(true);
>-      suppr->set_reach_kind(reach_kind);
>+      result->set_consider_reach_kind(true);
>+      result->set_reach_kind(reach_kind);
>     }
>
>   if (consider_data_member_insertion)
>-    suppr->set_data_member_insertion_ranges(insert_ranges);
>+    result->set_data_member_insertion_ranges(insert_ranges);
>
>   if (!name_not_regex_str.empty())
>-    suppr->set_type_name_not_regex_str(name_not_regex_str);
>+    result->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);
>+    result->set_file_name_regex_str(file_name_regex_str);
>
>   if (!file_name_not_regex_str.empty())
>-    suppr->set_file_name_not_regex_str(file_name_not_regex_str);
>+    result->set_file_name_not_regex_str(file_name_not_regex_str);
>
>   if (!soname_regex_str.empty())
>-    suppr->set_soname_regex_str(soname_regex_str);
>+    result->set_soname_regex_str(soname_regex_str);
>
>   if (!soname_not_regex_str.empty())
>-    suppr->set_soname_not_regex_str(soname_not_regex_str);
>+    result->set_soname_not_regex_str(soname_not_regex_str);
>
>   if (!srcloc_not_in.empty())
>-    suppr->set_source_locations_to_keep(srcloc_not_in);
>+    result->set_source_locations_to_keep(srcloc_not_in);
>
>   if (!srcloc_not_regexp_str.empty())
>-    suppr->set_source_location_to_keep_regex_str(srcloc_not_regexp_str);
>+    result->set_source_location_to_keep_regex_str(srcloc_not_regexp_str);
>
>   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
>       && ((!name_regex_str.empty()
> 	   || !name_str.empty()
> 	   || !srcloc_not_regexp_str.empty()
> 	   || !srcloc_not_in.empty())))
>-    suppr->set_drops_artifact_from_ir(true);
>+    result->set_drops_artifact_from_ir(true);
>
>-  if (suppr->get_type_kind() == type_suppression::ENUM_TYPE_KIND
>+  if (result->get_type_kind() == type_suppression::ENUM_TYPE_KIND
>       && !changed_enumerator_names.empty())
>-    suppr->set_changed_enumerator_names(changed_enumerator_names);
>+    result->set_changed_enumerator_names(changed_enumerator_names);
>
>-  return suppr;
>+  return result;
> }
>
> // <function_suppression stuff>
>@@ -3158,10 +3157,10 @@ read_parameter_spec_from_string(const string& str)
> static function_suppression_sptr
> read_function_suppression(const ini::config::section& section)
> {
>-  function_suppression_sptr nil;
>+  function_suppression_sptr result;
>
>   if (section.get_name() != "suppress_function")
>-    return nil;
>+    return result;
>
>   ini::simple_property_sptr drop_artifact =
>     is_simple_property(section.find_property("drop_artifact"));
>@@ -3289,7 +3288,6 @@ read_function_suppression(const ini::config::section& section)
> 	  parms.push_back(parm);
>       }
>
>-  function_suppression_sptr result;
>   if (!label_str.empty()
>       || !name.empty()
>       || !name_regex_str.empty()
>@@ -3306,6 +3304,7 @@ read_function_suppression(const ini::config::section& section)
>       || !sym_version.empty()
>       || !sym_ver_regex_str.empty()
>       || !parms.empty())
>+
>     result.reset(new function_suppression(label_str, name,
> 					  name_regex_str,
> 					  return_type_name,
>@@ -4343,6 +4342,7 @@ read_file_suppression(const ini::config::section& section)
>       && soname_regex_str.empty()
>       && soname_not_regex_str.empty())
>     return result;
>+
>   result.reset(new file_suppression(label_str,
> 				    file_name_regex_str,
> 				    file_name_not_regex_str));
>-- 
>2.26.2.303.gf8c07b1a785-goog
>

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 07/21] Add POSIX regex wrapper functions.
  2020-04-24  9:21   ` [PATCH v3 07/21] Add POSIX regex wrapper functions Giuliano Procida
@ 2020-04-27 11:23     ` Matthias Maennich
  0 siblings, 0 replies; 120+ messages in thread
From: Matthias Maennich @ 2020-04-27 11:23 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, dodji, kernel-team

On Fri, Apr 24, 2020 at 10:21:18AM +0100, Giuliano Procida wrote:
>libabigail code uses the POSIX regex library consistently:
>
>    - compile std::string to regex, with the flag REG_EXTENDED
>    - store regex using a shared pointer wrapper
>    - check match of regex against std::string
>
>All the C string / std::string logic and so on is repeated at every
>call site. This patch introduces wrapper functions to take care of
>this logic.
>
>There are no behavioural changes.
>
>	* include/abg-regex.h (compile): Declare new function.
>	(match): Declare new function.
>	* src/abg-regex.cc (compile): Add new function wrapping
>	regcomp. (match): Add new function wrapping regexec.
>
>Signed-off-by: Giuliano Procida <gprocida@google.com>

Reviewed-by: Matthias Maennich <maennich@google.com>

Cheers,
Matthias
>---
> include/abg-regex.h |  6 ++++++
> src/abg-regex.cc    | 41 +++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 47 insertions(+)
>
>diff --git a/include/abg-regex.h b/include/abg-regex.h
>index 59976794..c7951a8f 100644
>--- a/include/abg-regex.h
>+++ b/include/abg-regex.h
>@@ -71,6 +71,12 @@ operator<<(std::ostream& os, const escape& esc);
> std::string
> generate_from_strings(const std::vector<std::string>& strs);
>
>+regex_t_sptr
>+compile(const std::string& str);
>+
>+bool
>+match(const regex_t_sptr& r, const std::string& str);
>+
> }// end namespace regex
>
> /// Specialization of sptr_utils::build_sptr for regex_t.
>diff --git a/src/abg-regex.cc b/src/abg-regex.cc
>index 90e4d144..7e5277e2 100644
>--- a/src/abg-regex.cc
>+++ b/src/abg-regex.cc
>@@ -23,11 +23,22 @@
> /// Some specialization for shared pointer utility templates.
> ///
>
>+#include "config.h"
>+
> #include <sstream>
> #include <ostream>
>+
>+#include "abg-internal.h"
>+
>+// <headers defining libabigail's API go under here>
>+ABG_BEGIN_EXPORT_DECLARATIONS
>+
> #include "abg-sptr-utils.h"
> #include "abg-regex.h"
>
>+ABG_END_EXPORT_DECLARATIONS
>+// </headers defining libabigail's API>
>+
> namespace abigail
> {
>
>@@ -101,6 +112,36 @@ generate_from_strings(const std::vector<std::string>& strs)
>   return os.str();
> }
>
>+/// Compile a regex from a string.
>+///
>+/// The result is held in a shared pointer. This will be null if regex
>+/// compilation fails.
>+///
>+/// @param str the string representation of the regex.
>+///
>+/// @return shared pointer holder of a compiled regex object.
>+regex_t_sptr
>+compile(const std::string& str)
>+{
>+  regex_t_sptr r = sptr_utils::build_sptr(new regex_t);
>+  if (regcomp(r.get(), str.c_str(), REG_EXTENDED))
>+    r.reset();
>+  return r;
>+}
>+
>+/// See if a string matches a regex.
>+///
>+/// @param r a shared pointer holder of a compiled regex object.
>+///
>+/// @param str a string.
>+///
>+/// @return whether there was a match.
>+bool
>+match(const regex_t_sptr& r, const std::string& str)
>+{
>+  return !regexec(r.get(), str.c_str(), 0, NULL, 0);
>+}
>+
> }//end namespace regex
>
> }//end namespace abigail
>-- 
>2.26.2.303.gf8c07b1a785-goog
>

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 08/21] Use regex::compile wrapper instead of regcomp.
  2020-04-24  9:21   ` [PATCH v3 08/21] Use regex::compile wrapper instead of regcomp Giuliano Procida
@ 2020-04-27 11:34     ` Matthias Maennich
  2020-04-27 16:01       ` Giuliano Procida
  0 siblings, 1 reply; 120+ messages in thread
From: Matthias Maennich @ 2020-04-27 11:34 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, dodji, kernel-team

On Fri, Apr 24, 2020 at 10:21:19AM +0100, Giuliano Procida wrote:
>This patch eliminates all calls to regcomp except that by
>regex::compile itself.
>
>	* src/abg-corpus-priv.h: Mechanically substitute use of
>	regcomp with regex::compile wrapper.
>	* src/abg-suppression-priv.h: Ditto.
>
>There are no behavioural changes.
>
>Signed-off-by: Giuliano Procida <gprocida@google.com>
>---
> src/abg-corpus-priv.h      |  16 +--
> src/abg-suppression-priv.h | 198 ++++++-------------------------------
> 2 files changed, 38 insertions(+), 176 deletions(-)
>
>diff --git a/src/abg-corpus-priv.h b/src/abg-corpus-priv.h
>index e65f7c8f..544fac54 100644
>--- a/src/abg-corpus-priv.h
>+++ b/src/abg-corpus-priv.h
>@@ -123,8 +123,8 @@ public:
> 	     i != fns_suppress_regexps_.end();
> 	     ++i)
> 	  {
>-	    regex_t_sptr r = sptr_utils::build_sptr(new regex_t);
>-	    if (regcomp(r.get(), i->c_str(), REG_EXTENDED) == 0)
>+	    regex_t_sptr r = regex::compile(*i);
>+	    if (r)
> 	      compiled_fns_suppress_regexp_.push_back(r);
> 	  }
>       }
>@@ -145,8 +145,8 @@ public:
> 	     i != fns_keep_regexps_.end();
> 	     ++i)
> 	  {
>-	    regex_t_sptr r = sptr_utils::build_sptr(new regex_t);
>-	    if (regcomp(r.get(), i->c_str(), REG_EXTENDED) == 0)
>+	    regex_t_sptr r = regex::compile(*i);
>+	    if (r)
> 	      compiled_fns_keep_regexps_.push_back(r);
> 	  }
>       }
>@@ -167,8 +167,8 @@ public:
> 	     i != vars_suppress_regexps_.end();
> 	     ++i)
> 	  {
>-	    regex_t_sptr r = sptr_utils::build_sptr(new regex_t);
>-	    if (regcomp(r.get(), i->c_str(), REG_EXTENDED) == 0)
>+	    regex_t_sptr r = regex::compile(*i);
>+	    if (r)
> 	      compiled_vars_suppress_regexp_.push_back(r);
> 	  }
>       }
>@@ -189,8 +189,8 @@ public:
> 	     i != vars_keep_regexps_.end();
> 	     ++i)
> 	  {
>-	    regex_t_sptr r = sptr_utils::build_sptr(new regex_t);
>-	    if (regcomp(r.get(), i->c_str(), REG_EXTENDED) == 0)
>+	    regex_t_sptr r = regex::compile(*i);
>+	    if (r)
> 	      compiled_vars_keep_regexps_.push_back(r);
> 	  }
>       }
>diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
>index c37ceff6..4959cdbb 100644
>--- a/src/abg-suppression-priv.h
>+++ b/src/abg-suppression-priv.h
>@@ -91,17 +91,8 @@ public:
>   const regex::regex_t_sptr&
>   get_file_name_regex() const
>   {
>-    if (!file_name_regex_)
>-      {
>-	if (!file_name_regex_str_.empty())
>-	  {
>-	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>-	    if (regcomp(r.get(),
>-			file_name_regex_str_.c_str(),
>-			REG_EXTENDED) == 0)
>-	      file_name_regex_ = r;
>-	  }
>-      }
>+    if (!file_name_regex_ && !file_name_regex_str_.empty())

Those made me thinkg whether regex::compile should return NULL for empty
regex strings? Not necessarily something to address in this change.

Reviewed-by: Matthias Maennich <maennich@google.com>

Cheers,
Matthias

>+      file_name_regex_ = regex::compile(file_name_regex_str_);
>     return file_name_regex_;
>   }
>
>@@ -116,17 +107,8 @@ public:
>   const regex::regex_t_sptr&
>   get_file_name_not_regex() const
>   {
>-    if (!file_name_not_regex_)
>-      {
>-	if (!file_name_not_regex_str_.empty())
>-	  {
>-	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>-	    if (regcomp(r.get(),
>-			file_name_not_regex_str_.c_str(),
>-			REG_EXTENDED) == 0)
>-	      file_name_not_regex_ = r;
>-	  }
>-      }
>+    if (!file_name_not_regex_ && !file_name_not_regex_str_.empty())
>+      file_name_not_regex_ = regex::compile(file_name_not_regex_str_);
>     return file_name_not_regex_;
>   }
>
>@@ -141,17 +123,8 @@ public:
>   const regex::regex_t_sptr&
>   get_soname_regex() const
>   {
>-    if (!soname_regex_)
>-      {
>-	if (!soname_regex_str_.empty())
>-	  {
>-	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>-	    if (regcomp(r.get(),
>-			soname_regex_str_.c_str(),
>-			REG_EXTENDED) == 0)
>-	      soname_regex_ = r;
>-	  }
>-      }
>+    if (!soname_regex_ && !soname_regex_str_.empty())
>+      soname_regex_ = regex::compile(soname_regex_str_);
>     return soname_regex_;
>   }
>
>@@ -166,17 +139,8 @@ public:
>   const regex::regex_t_sptr&
>   get_soname_not_regex() const
>   {
>-    if (!soname_not_regex_)
>-      {
>-	if (!soname_not_regex_str_.empty())
>-	  {
>-	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>-	    if (regcomp(r.get(),
>-			soname_not_regex_str_.c_str(),
>-			REG_EXTENDED) == 0)
>-	      soname_not_regex_ = r;
>-	  }
>-      }
>+    if (!soname_not_regex_ && !soname_not_regex_str_.empty())
>+      soname_not_regex_ = regex::compile(soname_not_regex_str_);
>     return soname_not_regex_;
>   }
>
>@@ -282,13 +246,7 @@ class function_suppression::parameter_spec::priv
>   get_type_name_regex() const
>   {
>     if (!type_name_regex_ && !type_name_regex_str_.empty())
>-      {
>-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>-	if (regcomp(r.get(),
>-		    type_name_regex_str_.c_str(),
>-		    REG_EXTENDED) == 0)
>-	  type_name_regex_ = r;
>-      }
>+      type_name_regex_ = regex::compile(type_name_regex_str_);
>     return type_name_regex_;
>   }
> }; // end class function_suppression::parameter_spec::priv
>@@ -361,13 +319,7 @@ struct function_suppression::priv
>   get_name_regex() const
>   {
>     if (!name_regex_ && !name_regex_str_.empty())
>-      {
>-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>-	if (regcomp(r.get(),
>-		    name_regex_str_.c_str(),
>-		    REG_EXTENDED) == 0)
>-	  name_regex_ = r;
>-      }
>+      name_regex_ = regex::compile(name_regex_str_);
>     return name_regex_;
>   }
>
>@@ -384,13 +336,7 @@ struct function_suppression::priv
>   get_name_not_regex() const
>   {
>     if (!name_not_regex_ && !name_not_regex_str_.empty())
>-      {
>-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>-	if (regcomp(r.get(),
>-		    name_not_regex_str_.c_str(),
>-		    REG_EXTENDED) == 0)
>-	  name_not_regex_ = r;
>-      }
>+      name_not_regex_ = regex::compile(name_not_regex_str_);
>     return name_not_regex_;
>   }
>
>@@ -407,13 +353,7 @@ struct function_suppression::priv
>   get_return_type_regex() const
>   {
>     if (!return_type_regex_ && !return_type_regex_str_.empty())
>-      {
>-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>-	if (regcomp(r.get(),
>-		    return_type_regex_str_.c_str(),
>-		    REG_EXTENDED) == 0)
>-	  return_type_regex_ = r;
>-      }
>+      return_type_regex_ = regex::compile(return_type_regex_str_);
>     return return_type_regex_;
>   }
>
>@@ -430,13 +370,7 @@ struct function_suppression::priv
>   get_symbol_name_regex() const
>   {
>     if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
>-      {
>-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>-	if (regcomp(r.get(),
>-		    symbol_name_regex_str_.c_str(),
>-		    REG_EXTENDED) == 0)
>-	  symbol_name_regex_ = r;
>-      }
>+      symbol_name_regex_ = regex::compile(symbol_name_regex_str_);
>     return symbol_name_regex_;
>   }
>
>@@ -453,13 +387,7 @@ struct function_suppression::priv
>   get_symbol_name_not_regex() const
>   {
>     if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
>-      {
>-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>-	if (regcomp(r.get(),
>-		    symbol_name_not_regex_str_.c_str(),
>-		    REG_EXTENDED) == 0)
>-	  symbol_name_not_regex_ = r;
>-      }
>+      symbol_name_not_regex_ = regex::compile(symbol_name_not_regex_str_);
>     return symbol_name_not_regex_;
>   }
>
>@@ -475,14 +403,8 @@ struct function_suppression::priv
>   const regex::regex_t_sptr
>   get_symbol_version_regex() const
>   {
>-    if (!symbol_version_regex_ && ! symbol_version_regex_str_.empty())
>-      {
>-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>-	if (regcomp(r.get(),
>-		    symbol_version_regex_str_.c_str(),
>-		    REG_EXTENDED) == 0)
>-	  symbol_version_regex_ = r;
>-      }
>+    if (!symbol_version_regex_ && !symbol_version_regex_str_.empty())
>+      symbol_version_regex_ = regex::compile(symbol_version_regex_str_);
>     return symbol_version_regex_;
>   }
> }; // end class function_suppression::priv
>@@ -609,13 +531,7 @@ struct variable_suppression::priv
>   get_name_regex() const
>   {
>     if (!name_regex_ && !name_regex_str_.empty())
>-      {
>-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>-	if (regcomp(r.get(),
>-		    name_regex_str_.c_str(),
>-		    REG_EXTENDED) == 0)
>-	  name_regex_ = r;
>-      }
>+      name_regex_ = regex::compile(name_regex_str_);
>     return name_regex_;
>   }
>
>@@ -632,13 +548,7 @@ struct variable_suppression::priv
>   get_name_not_regex() const
>   {
>     if (!name_not_regex_ && !name_not_regex_str_.empty())
>-      {
>-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>-	if (regcomp(r.get(),
>-		    name_not_regex_str_.c_str(),
>-		    REG_EXTENDED) == 0)
>-	  name_not_regex_ = r;
>-      }
>+      name_not_regex_ = regex::compile(name_not_regex_str_);
>     return name_not_regex_;
>   }
>
>@@ -655,13 +565,7 @@ struct variable_suppression::priv
>   get_symbol_name_regex() const
>   {
>     if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
>-      {
>-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>-	if (regcomp(r.get(),
>-		    symbol_name_regex_str_.c_str(),
>-		    REG_EXTENDED) == 0)
>-	  symbol_name_regex_ = r;
>-      }
>+      symbol_name_regex_ = regex::compile(symbol_name_regex_str_);
>     return symbol_name_regex_;
>   }
>
>@@ -678,12 +582,7 @@ struct variable_suppression::priv
>   get_symbol_name_not_regex() const
>   {
>     if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
>-      {
>-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>-	if (regcomp(r.get(), symbol_name_not_regex_str_.c_str(),
>-		    REG_EXTENDED) == 0)
>-	  symbol_name_not_regex_ = r;
>-      }
>+      symbol_name_not_regex_ = regex::compile(symbol_name_not_regex_str_);
>     return symbol_name_not_regex_;
>   }
>
>@@ -700,13 +599,7 @@ struct variable_suppression::priv
>   get_symbol_version_regex()  const
>   {
>     if (!symbol_version_regex_ && !symbol_version_regex_str_.empty())
>-      {
>-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>-	if (regcomp(r.get(),
>-		    symbol_version_regex_str_.c_str(),
>-		    REG_EXTENDED) == 0)
>-	  symbol_version_regex_ = r;
>-      }
>+      symbol_version_regex_ = regex::compile(symbol_version_regex_str_);
>     return symbol_version_regex_;
>   }
>
>@@ -723,13 +616,7 @@ struct variable_suppression::priv
>   get_type_name_regex() const
>   {
>     if (!type_name_regex_ && !type_name_regex_str_.empty())
>-      {
>-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>-	if (regcomp(r.get(),
>-		    type_name_regex_str_.c_str(),
>-		    REG_EXTENDED) == 0)
>-	  type_name_regex_ = r;
>-      }
>+      type_name_regex_ = regex::compile(type_name_regex_str_);
>     return type_name_regex_;
>   }
> };// end class variable_supppression::priv
>@@ -809,17 +696,8 @@ public:
>   const regex::regex_t_sptr
>   get_type_name_regex() const
>   {
>-    if (!type_name_regex_)
>-      {
>-	if (!type_name_regex_str_.empty())
>-	  {
>-	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>-	    if (regcomp(r.get(),
>-			type_name_regex_str_.c_str(),
>-			REG_EXTENDED) == 0)
>-	      type_name_regex_ = r;
>-	  }
>-      }
>+    if (!type_name_regex_ && !type_name_regex_str_.empty())
>+      type_name_regex_ = regex::compile(type_name_regex_str_);
>     return type_name_regex_;
>   }
>
>@@ -841,17 +719,8 @@ public:
>   const regex::regex_t_sptr
>   get_type_name_not_regex() const
>   {
>-    if (!type_name_not_regex_)
>-      {
>-	if (!type_name_not_regex_str_.empty())
>-	  {
>-	    regex::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;
>-	  }
>-      }
>+    if (!type_name_not_regex_ && !type_name_not_regex_str_.empty())
>+      type_name_not_regex_ = regex::compile(type_name_not_regex_str_);
>     return type_name_not_regex_;
>   }
>
>@@ -886,17 +755,10 @@ public:
>   const regex::regex_t_sptr
>   get_source_location_to_keep_regex() const
>   {
>-    if (!source_location_to_keep_regex_)
>-      {
>-	if (!source_location_to_keep_regex_str_.empty())
>-	  {
>-	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
>-	    if (regcomp(r.get(),
>-			source_location_to_keep_regex_str_.c_str(),
>-			REG_EXTENDED) == 0)
>-	      source_location_to_keep_regex_ = r;
>-	  }
>-      }
>+    if (!source_location_to_keep_regex_
>+	&& !source_location_to_keep_regex_str_.empty())
>+      source_location_to_keep_regex_ =
>+	  regex::compile(source_location_to_keep_regex_str_);
>     return source_location_to_keep_regex_;
>   }
>
>-- 
>2.26.2.303.gf8c07b1a785-goog
>

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 09/21] Use regex::match wrapper instead of regexec.
  2020-04-24  9:21   ` [PATCH v3 09/21] Use regex::match wrapper instead of regexec Giuliano Procida
@ 2020-04-27 11:38     ` Matthias Maennich
  0 siblings, 0 replies; 120+ messages in thread
From: Matthias Maennich @ 2020-04-27 11:38 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, dodji, kernel-team

On Fri, Apr 24, 2020 at 10:21:20AM +0100, Giuliano Procida wrote:
>This patch eliminates all calls to regexec except that by regex::match
>itself.
>
>There are no behavioural changes.
>
>	* src/abg-corpus-priv.h: Mechanically substitute use of
>	regexec with regex::match wrapper.
>	* src/abg-suppression-priv.h: Ditto.
>	* src/abg-suppression.cc: Ditto.
>
>Signed-off-by: Giuliano Procida <gprocida@google.com>

Reviewed-by: Matthias Maennich <maennich@google.com>

Cheers,
Matthias

>---
> src/abg-corpus-priv.h      |   8 +--
> src/abg-suppression-priv.h |  10 ++--
> src/abg-suppression.cc     | 119 +++++++++++--------------------------
> 3 files changed, 44 insertions(+), 93 deletions(-)
>
>diff --git a/src/abg-corpus-priv.h b/src/abg-corpus-priv.h
>index 544fac54..2618e2d0 100644
>--- a/src/abg-corpus-priv.h
>+++ b/src/abg-corpus-priv.h
>@@ -521,7 +521,7 @@ public:
> 	   compiled_regex_fns_suppress().begin();
> 	 i != compiled_regex_fns_suppress().end();
> 	 ++i)
>-      if (regexec(i->get(), frep.c_str(), 0, NULL, 0) == 0)
>+      if (regex::match(*i, frep))
> 	{
> 	  keep = false;
> 	  break;
>@@ -554,7 +554,7 @@ public:
> 	     compiled_regex_fns_keep().begin();
> 	   i != compiled_regex_fns_keep().end();
> 	   ++i)
>-	if (regexec(i->get(), frep.c_str(), 0, NULL, 0) == 0)
>+	if (regex::match(*i, frep))
> 	  {
> 	    keep = true;
> 	    break;
>@@ -628,7 +628,7 @@ public:
> 	   compiled_regex_vars_suppress().begin();
> 	 i != compiled_regex_vars_suppress().end();
> 	 ++i)
>-      if (regexec(i->get(), frep.c_str(), 0, NULL, 0) == 0)
>+      if (regex::match(*i, frep))
> 	{
> 	  keep = false;
> 	  break;
>@@ -662,7 +662,7 @@ public:
> 	       compiled_regex_vars_keep().begin();
> 	     i != compiled_regex_vars_keep().end();
> 	     ++i)
>-	  if (regexec(i->get(), frep.c_str(), 0, NULL, 0) == 0)
>+	  if (regex::match(*i, frep))
> 	    {
> 	      keep = true;
> 	      break;
>diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
>index 4959cdbb..8043ebd9 100644
>--- a/src/abg-suppression-priv.h
>+++ b/src/abg-suppression-priv.h
>@@ -160,14 +160,14 @@ public:
>     if (regex::regex_t_sptr regexp = get_soname_regex())
>       {
> 	has_regexp = true;
>-	if (regexec(regexp.get(), soname.c_str(), 0, NULL, 0) != 0)
>+	if (!regex::match(regexp, soname))
> 	  return false;
>       }
>
>     if (regex::regex_t_sptr regexp = get_soname_not_regex())
>       {
> 	has_regexp = true;
>-	if (regexec(regexp.get(), soname.c_str(), 0, NULL, 0) == 0)
>+	if (regex::match(regexp, soname))
> 	  return false;
>       }
>
>@@ -195,16 +195,14 @@ public:
>     if (regex::regex_t_sptr regexp = get_file_name_regex())
>       {
> 	has_regexp = true;
>-	if (regexec(regexp.get(), binary_name.c_str(),
>-	  0, NULL, 0) != 0)
>+	if (!regex::match(regexp, binary_name))
> 	  return false;
>       }
>
>     if (regex::regex_t_sptr regexp = get_file_name_not_regex())
>       {
> 	has_regexp = true;
>-	if (regexec(regexp.get(), binary_name.c_str(),
>-	  0, NULL, 0) == 0)
>+	if (regex::match(regexp, binary_name))
> 	  return false;
>       }
>
>diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
>index 831a61ef..73e422a3 100644
>--- a/src/abg-suppression.cc
>+++ b/src/abg-suppression.cc
>@@ -994,18 +994,14 @@ suppression_matches_type_name(const type_suppression&	s,
> 	  if (const 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)
>+	      if (!regex::match(type_name_regex, type_name))
> 		return false;
> 	    }
>
> 	  if (const 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)
>+	      if (regex::match(type_name_not_regex, type_name))
> 		return false;
> 	    }
> 	}
>@@ -1052,7 +1048,7 @@ suppression_matches_type_location(const type_suppression&	s,
>       loc.expand(loc_path, loc_line, loc_column);
>
>       if (regex_t_sptr regexp = s.priv_->get_source_location_to_keep_regex())
>-	if (regexec(regexp.get(), loc_path.c_str(), 0, NULL, 0) == 0)
>+	if (regex::match(regexp, loc_path))
> 	  return false;
>
>       tools_utils::base_name(loc_path, loc_path_base);
>@@ -2489,9 +2485,7 @@ function_suppression::suppresses_function(const function_decl* fn,
>   const regex_t_sptr name_regex = priv_->get_name_regex();
>   if (name_regex)
>     {
>-      if (regexec(name_regex.get(),
>-		  fname.c_str(),
>-		  0, NULL, 0) != 0)
>+      if (!regex::match(name_regex, fname))
> 	return false;
>
>       if (get_allow_other_aliases()
>@@ -2512,9 +2506,7 @@ function_suppression::suppresses_function(const function_decl* fn,
> 	      for (elf_symbol_sptr a = sym->get_next_alias();
> 		   a && !a->is_main_symbol();
> 		   a = a->get_next_alias())
>-		if (regexec(name_regex.get(),
>-			    a->get_name().c_str(),
>-			    0, NULL, 0) != 0)
>+		if (!regex::match(name_regex, a->get_name()))
> 		  return false;
> 	    }
> 	}
>@@ -2524,9 +2516,7 @@ function_suppression::suppresses_function(const function_decl* fn,
>   const regex_t_sptr name_not_regex = priv_->get_name_not_regex();
>   if (name_not_regex)
>     {
>-      if (regexec(name_not_regex.get(),
>-		  fname.c_str(),
>-		  0, NULL, 0) == 0)
>+      if (regex::match(name_not_regex, fname))
> 	return false;
>
>       if (get_allow_other_aliases()
>@@ -2547,9 +2537,7 @@ function_suppression::suppresses_function(const function_decl* fn,
> 	      for (elf_symbol_sptr a = sym->get_next_alias();
> 		   a && !a->is_main_symbol();
> 		   a = a->get_next_alias())
>-		if (regexec(name_regex.get(),
>-			    a->get_name().c_str(),
>-			    0, NULL, 0) == 0)
>+		if (regex::match(name_regex, a->get_name()))
> 		  return false;
> 	    }
> 	}
>@@ -2573,9 +2561,7 @@ function_suppression::suppresses_function(const function_decl* fn,
>     {
>       const regex_t_sptr return_type_regex = priv_->get_return_type_regex();
>       if (return_type_regex
>-	  && (regexec(return_type_regex.get(),
>-		      fn_return_type_name.c_str(),
>-		      0, NULL, 0) != 0))
>+	  && !regex::match(return_type_regex, fn_return_type_name))
> 	return false;
>     }
>
>@@ -2612,18 +2598,13 @@ function_suppression::suppresses_function(const function_decl* fn,
>   else if (sym)
>     {
>       const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
>-      if (symbol_name_regex
>-	  && (regexec(symbol_name_regex.get(),
>-		      fn_sym_name.c_str(),
>-		      0, NULL, 0) != 0))
>+      if (symbol_name_regex && !regex::match(symbol_name_regex, fn_sym_name))
> 	return false;
>
>       const regex_t_sptr symbol_name_not_regex =
> 	priv_->get_symbol_name_not_regex();
>       if (symbol_name_not_regex
>-	  && (regexec(symbol_name_not_regex.get(),
>-		      fn_sym_name.c_str(),
>-		      0, NULL, 0) == 0))
>+	  && regex::match(symbol_name_not_regex, fn_sym_name))
> 	return false;
>
>       if (get_allow_other_aliases())
>@@ -2638,15 +2619,11 @@ function_suppression::suppresses_function(const function_decl* fn,
> 		   a = a->get_next_alias())
> 		{
> 		  if (symbol_name_regex
>-		      && (regexec(symbol_name_regex.get(),
>-				  a->get_name().c_str(),
>-				  0, NULL, 0) != 0))
>+		      && !regex::match(symbol_name_regex, a->get_name()))
> 		    return false;
>
> 		  if (symbol_name_not_regex
>-		      && (regexec(symbol_name_not_regex.get(),
>-				  a->get_name().c_str(),
>-				  0, NULL, 0) == 0))
>+		      && regex::match(symbol_name_not_regex, a->get_name()))
> 		    return false;
> 		}
> 	    }
>@@ -2665,9 +2642,7 @@ function_suppression::suppresses_function(const function_decl* fn,
>       const regex_t_sptr symbol_version_regex =
> 	priv_->get_symbol_version_regex();
>       if (symbol_version_regex
>-	  && (regexec(symbol_version_regex.get(),
>-		      fn_sym_version.c_str(),
>-		      0, NULL, 0) != 0))
>+	  && !regex::match(symbol_version_regex, fn_sym_version))
> 	return false;
>     }
>
>@@ -2708,9 +2683,8 @@ function_suppression::suppresses_function(const function_decl* fn,
> 		(*p)->priv_->get_type_name_regex();
> 	      if (parm_type_name_regex)
> 		{
>-		  if ((regexec(parm_type_name_regex.get(),
>-			       fn_parm_type_qualified_name.c_str(),
>-			       0, NULL, 0) != 0))
>+		  if (!regex::match(parm_type_name_regex,
>+				    fn_parm_type_qualified_name))
> 		    return false;
> 		}
> 	    }
>@@ -2798,10 +2772,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
>   else if (!get_symbol_name_regex_str().empty())
>     {
>       const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
>-      if (symbol_name_regex
>-	  && (regexec(symbol_name_regex.get(),
>-		      sym_name.c_str(),
>-		      0, NULL, 0) != 0))
>+      if (symbol_name_regex && !regex::match(symbol_name_regex, sym_name))
> 	return false;
>     }
>   else
>@@ -2818,9 +2789,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
>       const regex_t_sptr symbol_version_regex =
> 	priv_->get_symbol_version_regex();
>       if (symbol_version_regex
>-	  && (regexec(symbol_version_regex.get(),
>-		      sym_version.c_str(),
>-		      0, NULL, 0) != 0))
>+	  && !regex::match(symbol_version_regex, sym_version))
> 	return false;
>     }
>   else
>@@ -2912,12 +2881,12 @@ suppression_matches_function_name(const suppr::function_suppression& s,
> {
>   if (regex_t_sptr regexp = s.priv_->get_name_regex())
>     {
>-      if (regexec(regexp.get(), fn_name.c_str(), 0, NULL, 0) != 0)
>+      if (!regex::match(regexp, fn_name))
> 	return false;
>     }
>   else if (regex_t_sptr regexp = s.priv_->get_name_not_regex())
>     {
>-      if (regexec(regexp.get(), fn_name.c_str(), 0, NULL, 0) == 0)
>+      if (regex::match(regexp, fn_name))
> 	return false;
>     }
>   else if (s.priv_->name_.empty())
>@@ -2948,12 +2917,12 @@ suppression_matches_function_sym_name(const suppr::function_suppression& s,
> {
>   if (regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
>     {
>-      if (regexec(regexp.get(), fn_linkage_name.c_str(), 0, NULL, 0) != 0)
>+      if (!regex::match(regexp, fn_linkage_name))
> 	return false;
>     }
>   else if (regex_t_sptr regexp = s.priv_->get_symbol_name_not_regex())
>     {
>-      if (regexec(regexp.get(), fn_linkage_name.c_str(), 0, NULL, 0) == 0)
>+      if (regex::match(regexp, fn_linkage_name))
> 	return false;
>     }
>   else if (s.priv_->symbol_name_.empty())
>@@ -2981,12 +2950,12 @@ suppression_matches_variable_name(const suppr::variable_suppression& s,
> {
>   if (regex_t_sptr regexp = s.priv_->get_name_regex())
>     {
>-      if (regexec(regexp.get(), var_name.c_str(), 0, NULL, 0) != 0)
>+      if (!regex::match(regexp, var_name))
> 	return false;
>     }
>   else if (regex_t_sptr regexp = s.priv_->get_name_not_regex())
>     {
>-      if (regexec(regexp.get(), var_name.c_str(), 0, NULL, 0) == 0)
>+      if (regex::match(regexp, var_name))
> 	return false;
>     }
>   else if (s.priv_->name_.empty())
>@@ -3015,13 +2984,13 @@ suppression_matches_variable_sym_name(const suppr::variable_suppression& s,
> {
>   if (regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
>     {
>-      if (regexec(regexp.get(), var_linkage_name.c_str(), 0, NULL, 0) != 0)
>+      if (!regex::match(regexp, var_linkage_name))
> 	return false;
>     }
>   else if (regex_t_sptr regexp =
> 	   s.priv_->get_symbol_name_not_regex())
>     {
>-      if (regexec(regexp.get(), var_linkage_name.c_str(), 0, NULL, 0) == 0)
>+      if (regex::match(regexp, var_linkage_name))
> 	return false;
>     }
>   else if (s.priv_->symbol_name_.empty())
>@@ -3050,7 +3019,7 @@ suppression_matches_type(const suppr::type_suppression& s,
> {
>   if (regex_t_sptr regexp = s.priv_->get_type_name_regex())
>     {
>-      if (regexec(regexp.get(), type_name.c_str(), 0, NULL, 0) != 0)
>+      if (!regex::match(regexp, type_name))
> 	return false;
>     }
>   else if (!s.get_type_name().empty())
>@@ -3748,15 +3717,11 @@ variable_suppression::suppresses_variable(const var_decl* var,
>       if (get_name().empty())
> 	{
> 	  const regex_t_sptr name_regex = priv_->get_name_regex();
>-	  if (name_regex
>-	      && (regexec(name_regex.get(), var_name.c_str(),
>-			  0, NULL, 0) != 0))
>+	  if (name_regex && !regex::match(name_regex, var_name))
> 	    return false;
>
> 	  const regex_t_sptr name_not_regex = priv_->get_name_not_regex();
>-	  if (name_not_regex
>-	      && (regexec(name_not_regex.get(), var_name.c_str(),
>-			  0, NULL, 0) == 0))
>+	  if (name_not_regex && regex::match(name_not_regex, var_name))
> 	    return false;
> 	}
>     }
>@@ -3772,16 +3737,12 @@ variable_suppression::suppresses_variable(const var_decl* var,
>   else
>     {
>       const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
>-      if (sym_name_regex
>-	  && (regexec(sym_name_regex.get(), var_sym_name.c_str(),
>-		      0, NULL, 0) != 0))
>+      if (sym_name_regex && !regex::match(sym_name_regex, var_sym_name))
> 	return false;
>
>       const regex_t_sptr sym_name_not_regex =
> 	priv_->get_symbol_name_not_regex();
>-      if (sym_name_not_regex
>-	  && (regexec(sym_name_not_regex.get(), var_sym_name.c_str(),
>-		      0, NULL, 0) == 0))
>+      if (sym_name_not_regex && regex::match(sym_name_not_regex, var_sym_name))
> 	return false;
>     }
>
>@@ -3798,9 +3759,7 @@ variable_suppression::suppresses_variable(const var_decl* var,
>       const regex_t_sptr symbol_version_regex =
> 	priv_->get_symbol_version_regex();
>       if (symbol_version_regex
>-	  && (regexec(symbol_version_regex.get(),
>-		      var_sym_version.c_str(),
>-		      0, NULL, 0) != 0))
>+	  && !regex::match(symbol_version_regex, var_sym_version))
> 	return false;
>     }
>
>@@ -3818,9 +3777,7 @@ variable_suppression::suppresses_variable(const var_decl* var,
>       if (get_type_name().empty())
> 	{
> 	  const regex_t_sptr type_name_regex = priv_->get_type_name_regex();
>-	  if (type_name_regex
>-	      && (regexec(type_name_regex.get(), var_type_name.c_str(),
>-			  0, NULL, 0) != 0))
>+	  if (type_name_regex && !regex::match(type_name_regex, var_type_name))
> 	    return false;
> 	}
>     }
>@@ -3911,9 +3868,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
>   else if (!get_symbol_name_regex_str().empty())
>     {
>       const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
>-      if (sym_name_regex
>-	  && (regexec(sym_name_regex.get(), sym_name.c_str(),
>-		      0, NULL, 0) != 0))
>+      if (sym_name_regex && !regex::match(sym_name_regex, sym_name))
> 	return false;
>     }
>   else
>@@ -3931,9 +3886,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
>       const regex_t_sptr symbol_version_regex =
> 	priv_->get_symbol_version_regex();
>       if (symbol_version_regex
>-	  && (regexec(symbol_version_regex.get(),
>-		      sym_version.c_str(),
>-		      0, NULL, 0) != 0))
>+	  && !regex::match(symbol_version_regex, sym_version))
> 	return false;
>     }
>   else
>@@ -4229,14 +4182,14 @@ file_suppression::suppresses_file(const string& file_path)
>   if (regex_t_sptr regexp = suppression_base::priv_->get_file_name_regex())
>     {
>       has_regexp = true;
>-      if (regexec(regexp.get(), fname.c_str(), 0, NULL, 0) != 0)
>+      if (!regex::match(regexp, fname))
> 	return false;
>     }
>
>   if (regex_t_sptr regexp = suppression_base::priv_->get_file_name_not_regex())
>     {
>       has_regexp = true;
>-      if (regexec(regexp.get(), fname.c_str(), 0, NULL, 0) == 0)
>+      if (regex::match(regexp, fname))
> 	return false;
>     }
>
>-- 
>2.26.2.303.gf8c07b1a785-goog
>

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 12/21] Reduce direct access to suppression priv_ members.
  2020-04-24  9:21   ` [PATCH v3 12/21] Reduce direct access to suppression priv_ members Giuliano Procida
@ 2020-04-27 11:54     ` Matthias Maennich
  0 siblings, 0 replies; 120+ messages in thread
From: Matthias Maennich @ 2020-04-27 11:54 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, dodji, kernel-team

On Fri, Apr 24, 2020 at 10:21:23AM +0100, Giuliano Procida wrote:
>Most suppression type functionality is available on the types
>themselves via methods, particularly now that there are getters
>for all the regex members.
>
>This patch eliminates lots of accesses via priv_ members.
>
>There are no behavioural changes.
>
>	* src/abg-suppression.cc (sonames_of_binaries_match): Use
>	suppression_matches_soname helper function.
>	(suppression_matches_type_name): Use type_suppression regex getters.
>	(suppression_matches_type_location): Use type_suppression
>	regex getters.
>	(function::suppression::suppresses_function): Use own regex
>	getters.
>	(function::suppression::suppresses_function_symbol): Use own
>	regex getters.
>	(suppression_matches_function_name): Use function_suppression
>	regex and name getters.
>	(suppression_matches_function_sym_name): Use function_suppression
>	regex and symbol name getters.
>	(suppression_matches_variable_name): Use variable__suppression
>	regex and name getters.
>	(suppression_matches_variable_sym_name): Use variable_suppression
>	regex and symbol name getters.
>	(suppression_matches_type): Use type_suppression
>	regex getter.
>	(variable_suppression::suppresses_variable): Use own regex
>	getters.
>	(variable_suppression::suppresses_variable_symbol): Use own
>	regex getters.
>	(type_suppression::suppresses_file): Use own regex getters.
>	(suppression_matches_soname_or_filename): Indentation fix, en
>	passant.
>
>Signed-off-by: Giuliano Procida <gprocida@google.com>

Reviewed-by: Matthias Maennich <maennich@google.com>

Cheers,
Matthias

>---
> src/abg-suppression.cc | 107 +++++++++++++++++++----------------------
> 1 file changed, 50 insertions(+), 57 deletions(-)
>
>diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
>index 6953c18b..7e501c45 100644
>--- a/src/abg-suppression.cc
>+++ b/src/abg-suppression.cc
>@@ -275,8 +275,8 @@ sonames_of_binaries_match(const suppression_base& suppr,
>   if (!suppr.has_soname_related_property())
>     return false;
>
>-  if (!suppr.priv_->matches_soname(first_soname)
>-      && !suppr.priv_->matches_soname(second_soname))
>+  if (!suppression_matches_soname(first_soname, suppr)
>+      && !suppression_matches_soname(second_soname, suppr))
>     return false;
>
>   return true;
>@@ -969,8 +969,8 @@ suppression_matches_type_name(const type_suppression&	s,
> 			      const string&		type_name)
> {
>   if (!s.get_type_name().empty()
>-      || s.priv_->get_type_name_regex()
>-      || s.priv_->get_type_name_not_regex())
>+      || s.get_type_name_regex()
>+      || s.get_type_name_not_regex())
>     {
>       // Check if there is an exact type name match.
>       if (!s.get_type_name().empty())
>@@ -986,14 +986,14 @@ suppression_matches_type_name(const type_suppression&	s,
> 	  // the regular expression of the type name, then this
> 	  // suppression doesn't apply.
> 	  if (const regex_t_sptr& type_name_regex =
>-	      s.priv_->get_type_name_regex())
>+	      s.get_type_name_regex())
> 	    {
> 	      if (!regex::match(type_name_regex, type_name))
> 		return false;
> 	    }
>
> 	  if (const regex_t_sptr type_name_not_regex =
>-	      s.priv_->get_type_name_not_regex())
>+	      s.get_type_name_not_regex())
> 	    {
> 	      if (regex::match(type_name_not_regex, type_name))
> 		return false;
>@@ -1041,7 +1041,7 @@ suppression_matches_type_location(const type_suppression&	s,
>       unsigned loc_line = 0, loc_column = 0;
>       loc.expand(loc_path, loc_line, loc_column);
>
>-      if (regex_t_sptr regexp = s.priv_->get_source_location_to_keep_regex())
>+      if (regex_t_sptr regexp = s.get_source_location_to_keep_regex())
> 	if (regex::match(regexp, loc_path))
> 	  return false;
>
>@@ -1056,7 +1056,7 @@ suppression_matches_type_location(const type_suppression&	s,
>   else
>     {
>       if (!s.get_source_locations_to_keep().empty()
>-	  || s.priv_->get_source_location_to_keep_regex())
>+	  || s.get_source_location_to_keep_regex())
> 	// The user provided a "source_location_not_regexp" or
> 	// a "source_location_not_in" property that was not
> 	// triggered.  This means the current type suppression
>@@ -1107,7 +1107,7 @@ suppression_matches_type_location(const type_suppression&	s,
> 	    }
> 	}
>       if (!s.get_source_locations_to_keep().empty()
>-	  || s.priv_->get_source_location_to_keep_regex())
>+	  || s.get_source_location_to_keep_regex())
> 	// The user provided a "source_location_not_regexp" or
> 	// a "source_location_not_in" property that was not
> 	// triggered.  This means the current type suppression
>@@ -2481,7 +2481,7 @@ function_suppression::suppresses_function(const function_decl* fn,
>     }
>
>   // check if the "name_regexp" property matches.
>-  const regex_t_sptr name_regex = priv_->get_name_regex();
>+  const regex_t_sptr name_regex = get_name_regex();
>   if (name_regex)
>     {
>       if (!regex::match(name_regex, fname))
>@@ -2512,7 +2512,7 @@ function_suppression::suppresses_function(const function_decl* fn,
>     }
>
>   // check if the "name_not_regexp" property matches.
>-  const regex_t_sptr name_not_regex = priv_->get_name_not_regex();
>+  const regex_t_sptr name_not_regex = get_name_not_regex();
>   if (name_not_regex)
>     {
>       if (regex::match(name_not_regex, fname))
>@@ -2558,7 +2558,7 @@ function_suppression::suppresses_function(const function_decl* fn,
>     }
>   else
>     {
>-      const regex_t_sptr return_type_regex = priv_->get_return_type_regex();
>+      const regex_t_sptr return_type_regex = get_return_type_regex();
>       if (return_type_regex
> 	  && !regex::match(return_type_regex, fn_return_type_name))
> 	return false;
>@@ -2596,12 +2596,11 @@ function_suppression::suppresses_function(const function_decl* fn,
>     }
>   else if (sym)
>     {
>-      const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
>+      const regex_t_sptr symbol_name_regex = get_symbol_name_regex();
>       if (symbol_name_regex && !regex::match(symbol_name_regex, fn_sym_name))
> 	return false;
>
>-      const regex_t_sptr symbol_name_not_regex =
>-	priv_->get_symbol_name_not_regex();
>+      const regex_t_sptr symbol_name_not_regex = get_symbol_name_not_regex();
>       if (symbol_name_not_regex
> 	  && regex::match(symbol_name_not_regex, fn_sym_name))
> 	return false;
>@@ -2638,8 +2637,7 @@ function_suppression::suppresses_function(const function_decl* fn,
>     }
>   else if (sym)
>     {
>-      const regex_t_sptr symbol_version_regex =
>-	priv_->get_symbol_version_regex();
>+      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
>       if (symbol_version_regex
> 	  && !regex::match(symbol_version_regex, fn_sym_version))
> 	return false;
>@@ -2679,7 +2677,7 @@ function_suppression::suppresses_function(const function_decl* fn,
> 	  else
> 	    {
> 	      const regex_t_sptr parm_type_name_regex =
>-		(*p)->priv_->get_type_name_regex();
>+		(*p)->get_parameter_type_name_regex();
> 	      if (parm_type_name_regex)
> 		{
> 		  if (!regex::match(parm_type_name_regex,
>@@ -2770,7 +2768,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
>     }
>   else if (get_symbol_name_regex())
>     {
>-      const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
>+      const regex_t_sptr symbol_name_regex = get_symbol_name_regex();
>       if (symbol_name_regex && !regex::match(symbol_name_regex, sym_name))
> 	return false;
>     }
>@@ -2785,8 +2783,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
>     }
>   else if (get_symbol_version_regex())
>     {
>-      const regex_t_sptr symbol_version_regex =
>-	priv_->get_symbol_version_regex();
>+      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
>       if (symbol_version_regex
> 	  && !regex::match(symbol_version_regex, sym_version))
> 	return false;
>@@ -2878,21 +2875,21 @@ bool
> suppression_matches_function_name(const suppr::function_suppression& s,
> 				  const string& fn_name)
> {
>-  if (regex_t_sptr regexp = s.priv_->get_name_regex())
>+  if (regex_t_sptr regexp = s.get_name_regex())
>     {
>       if (!regex::match(regexp, fn_name))
> 	return false;
>     }
>-  else if (regex_t_sptr regexp = s.priv_->get_name_not_regex())
>+  else if (regex_t_sptr regexp = s.get_name_not_regex())
>     {
>       if (regex::match(regexp, fn_name))
> 	return false;
>     }
>-  else if (s.priv_->name_.empty())
>+  else if (s.get_name().empty())
>     return false;
>-  else // if (!s.priv_->name_.empty())
>+  else // if (!s.get_name().empty())
>     {
>-      if (s.priv_->name_ != fn_name)
>+      if (s.get_name() != fn_name)
> 	return false;
>     }
>
>@@ -2914,21 +2911,21 @@ bool
> suppression_matches_function_sym_name(const suppr::function_suppression& s,
> 				      const string& fn_linkage_name)
> {
>-  if (regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
>+  if (regex_t_sptr regexp = s.get_symbol_name_regex())
>     {
>       if (!regex::match(regexp, fn_linkage_name))
> 	return false;
>     }
>-  else if (regex_t_sptr regexp = s.priv_->get_symbol_name_not_regex())
>+  else if (regex_t_sptr regexp = s.get_symbol_name_not_regex())
>     {
>       if (regex::match(regexp, fn_linkage_name))
> 	return false;
>     }
>-  else if (s.priv_->symbol_name_.empty())
>+  else if (s.get_symbol_name().empty())
>     return false;
>-  else // if (!s.priv_->symbol_name_.empty())
>+  else // if (!s.get_symbol_name().empty())
>     {
>-      if (s.priv_->symbol_name_ != fn_linkage_name)
>+      if (s.get_symbol_name() != fn_linkage_name)
> 	return false;
>     }
>
>@@ -2947,21 +2944,21 @@ bool
> suppression_matches_variable_name(const suppr::variable_suppression& s,
> 				  const string& var_name)
> {
>-  if (regex_t_sptr regexp = s.priv_->get_name_regex())
>+  if (regex_t_sptr regexp = s.get_name_regex())
>     {
>       if (!regex::match(regexp, var_name))
> 	return false;
>     }
>-  else if (regex_t_sptr regexp = s.priv_->get_name_not_regex())
>+  else if (regex_t_sptr regexp = s.get_name_not_regex())
>     {
>       if (regex::match(regexp, var_name))
> 	return false;
>     }
>-  else if (s.priv_->name_.empty())
>+  else if (s.get_name().empty())
>     return false;
>-  else // if (!s.priv_->name_.empty())
>+  else // if (!s.get_name().empty())
>     {
>-      if (s.priv_->name_ != var_name)
>+      if (s.get_name() != var_name)
> 	return false;
>     }
>
>@@ -2981,22 +2978,21 @@ bool
> suppression_matches_variable_sym_name(const suppr::variable_suppression& s,
> 				      const string& var_linkage_name)
> {
>-  if (regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
>+  if (regex_t_sptr regexp = s.get_symbol_name_regex())
>     {
>       if (!regex::match(regexp, var_linkage_name))
> 	return false;
>     }
>-  else if (regex_t_sptr regexp =
>-	   s.priv_->get_symbol_name_not_regex())
>+  else if (regex_t_sptr regexp = s.get_symbol_name_not_regex())
>     {
>       if (regex::match(regexp, var_linkage_name))
> 	return false;
>     }
>-  else if (s.priv_->symbol_name_.empty())
>+  else if (s.get_symbol_name().empty())
>     return false;
>-  else // if (!s.priv_->symbol_name_.empty())
>+  else // if (!s.get_symbol_name().empty())
>     {
>-      if (s.priv_->symbol_name_ != var_linkage_name)
>+      if (s.get_symbol_name() != var_linkage_name)
> 	return false;
>     }
>
>@@ -3016,7 +3012,7 @@ bool
> suppression_matches_type(const suppr::type_suppression& s,
> 			 const string& type_name)
> {
>-  if (regex_t_sptr regexp = s.priv_->get_type_name_regex())
>+  if (regex_t_sptr regexp = s.get_type_name_regex())
>     {
>       if (!regex::match(regexp, type_name))
> 	return false;
>@@ -3725,11 +3721,11 @@ variable_suppression::suppresses_variable(const var_decl* var,
>       // "name_regex" and "name_not_regex" properties match
>       if (get_name().empty())
> 	{
>-	  const regex_t_sptr name_regex = priv_->get_name_regex();
>+	  const regex_t_sptr name_regex = get_name_regex();
> 	  if (name_regex && !regex::match(name_regex, var_name))
> 	    return false;
>
>-	  const regex_t_sptr name_not_regex = priv_->get_name_not_regex();
>+	  const regex_t_sptr name_not_regex = get_name_not_regex();
> 	  if (name_not_regex && regex::match(name_not_regex, var_name))
> 	    return false;
> 	}
>@@ -3745,12 +3741,11 @@ variable_suppression::suppresses_variable(const var_decl* var,
>     }
>   else
>     {
>-      const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
>+      const regex_t_sptr sym_name_regex = get_symbol_name_regex();
>       if (sym_name_regex && !regex::match(sym_name_regex, var_sym_name))
> 	return false;
>
>-      const regex_t_sptr sym_name_not_regex =
>-	priv_->get_symbol_name_not_regex();
>+      const regex_t_sptr sym_name_not_regex = get_symbol_name_not_regex();
>       if (sym_name_not_regex && regex::match(sym_name_not_regex, var_sym_name))
> 	return false;
>     }
>@@ -3765,8 +3760,7 @@ variable_suppression::suppresses_variable(const var_decl* var,
>     }
>   else
>     {
>-      const regex_t_sptr symbol_version_regex =
>-	priv_->get_symbol_version_regex();
>+      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
>       if (symbol_version_regex
> 	  && !regex::match(symbol_version_regex, var_sym_version))
> 	return false;
>@@ -3785,7 +3779,7 @@ variable_suppression::suppresses_variable(const var_decl* var,
>     {
>       if (get_type_name().empty())
> 	{
>-	  const regex_t_sptr type_name_regex = priv_->get_type_name_regex();
>+	  const regex_t_sptr type_name_regex = get_type_name_regex();
> 	  if (type_name_regex && !regex::match(type_name_regex, var_type_name))
> 	    return false;
> 	}
>@@ -3876,7 +3870,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
>     }
>   else if (get_symbol_name_regex())
>     {
>-      const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
>+      const regex_t_sptr sym_name_regex = get_symbol_name_regex();
>       if (sym_name_regex && !regex::match(sym_name_regex, sym_name))
> 	return false;
>     }
>@@ -3892,8 +3886,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
>     }
>   else if (get_symbol_version_regex())
>     {
>-      const regex_t_sptr symbol_version_regex =
>-	priv_->get_symbol_version_regex();
>+      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
>       if (symbol_version_regex
> 	  && !regex::match(symbol_version_regex, sym_version))
> 	return false;
>@@ -4196,14 +4189,14 @@ file_suppression::suppresses_file(const string& file_path)
>
>   bool has_regexp = false;
>
>-  if (regex_t_sptr regexp = suppression_base::priv_->get_file_name_regex())
>+  if (regex_t_sptr regexp = get_file_name_regex())
>     {
>       has_regexp = true;
>       if (!regex::match(regexp, fname))
> 	return false;
>     }
>
>-  if (regex_t_sptr regexp = suppression_base::priv_->get_file_name_not_regex())
>+  if (regex_t_sptr regexp = get_file_name_not_regex())
>     {
>       has_regexp = true;
>       if (regex::match(regexp, fname))
>@@ -4357,7 +4350,7 @@ suppression_matches_soname_or_filename(const string& soname,
> 				       const suppression_base& suppr)
> {
>   return (suppression_matches_soname(soname, suppr)
>-	 || suppr.priv_->matches_binary_name(filename));
>+	  || suppr.priv_->matches_binary_name(filename));
> }
>
> /// @return the name of the artificial private type suppression
>-- 
>2.26.2.303.gf8c07b1a785-goog
>

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 13/21] Move match methods from priv to suppression_base.
  2020-04-24  9:21   ` [PATCH v3 13/21] Move match methods from priv to suppression_base Giuliano Procida
@ 2020-04-27 11:55     ` Matthias Maennich
  0 siblings, 0 replies; 120+ messages in thread
From: Matthias Maennich @ 2020-04-27 11:55 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, dodji, kernel-team

On Fri, Apr 24, 2020 at 10:21:24AM +0100, Giuliano Procida wrote:
>The suppression_base::priv methods matches_soname and
>matches_binary_name do not require special access to the priv class
>and can be moved to the main suppression_base class and use its
>getters.
>
>This is a step towards simplifying the suppression type priv classes
>to the point they are simple data containers.
>
>There are no behavioural changes.
>
>	* include/abg-suppression.h
>	(suppression_base::matches_soname): Add	declaration.
>	(suppression_base::matches_binary_name): Add declaration.
>	(suppression_base): Remove friend declarations of
>	suppression_matches_soname and
>	suppression_matches_soname_or_filename.
>	* src/abg-dwarf-reader.cc (suppression_can_match): Call
>	matches_soname and matches_binary_name on suppression values
>	directly.
>	* src/abg-reader.cc (suppression_can_match): Call
>	matches_soname and matches_binary_name on suppression values
>	directly.
>	* src/abg-suppression-priv.h
>	(suppression_base::priv::matches_soname): Remove method.
>	(suppression_base::priv::matches_binary_name): Remove method.
>	* src/abg-suppression.cc
>	(suppression_base::matches_soname): Add definition.
>	(suppression_base::matches_binary_name): Add definition.
>	(names_of_binaries_match): Call matches_binary_name on
>	suppression values directly. (suppression_matches_soname):
>	Call matches_soname on suppression values directly.
>	(suppression_matches_soname_or_filename): Call
>	matches_binary_name on suppression values directly.
>
>Signed-off-by: Giuliano Procida <gprocida@google.com>

Reviewed-by: Matthias Maennich <maennich@google.com>

Cheers,
Matthias

>---
> include/abg-suppression.h  | 15 +++-----
> src/abg-dwarf-reader.cc    |  4 +-
> src/abg-reader.cc          |  4 +-
> src/abg-suppression-priv.h | 71 +----------------------------------
> src/abg-suppression.cc     | 76 ++++++++++++++++++++++++++++++++++++--
> 5 files changed, 83 insertions(+), 87 deletions(-)
>
>diff --git a/include/abg-suppression.h b/include/abg-suppression.h
>index 1869cbe5..02e77ea9 100644
>--- a/include/abg-suppression.h
>+++ b/include/abg-suppression.h
>@@ -116,19 +116,16 @@ public:
>   bool
>   has_soname_related_property() const;
>
>+  bool
>+  matches_soname(const string& soname) const;
>+
>+  bool
>+  matches_binary_name(const string& binary_name) const;
>+
>   virtual bool
>   suppresses_diff(const diff*) const = 0;
>
>   virtual ~suppression_base();
>-
>-  friend bool
>-  suppression_matches_soname(const string& soname,
>-			     const suppression_base& suppr);
>-
>-  friend bool
>-  suppression_matches_soname_or_filename(const string& soname,
>-					 const string& filename,
>-					 const suppression_base& suppr);
> }; // end class suppression_base
>
> void
>diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
>index 850281ad..c9e6f918 100644
>--- a/src/abg-dwarf-reader.cc
>+++ b/src/abg-dwarf-reader.cc
>@@ -7723,14 +7723,14 @@ public:
>   bool
>   suppression_can_match(const suppr::suppression_base& s) const
>   {
>-    if (!s.priv_->matches_soname(dt_soname()))
>+    if (!s.matches_soname(dt_soname()))
>       if (s.has_soname_related_property())
> 	// The suppression has some SONAME related properties, but
> 	// none of them match the SONAME of the current binary.  So
> 	// the suppression cannot match the current binary.
> 	return false;
>
>-    if (!s.priv_->matches_binary_name(elf_path()))
>+    if (!s.matches_binary_name(elf_path()))
>       if (s.has_file_name_related_property())
> 	// The suppression has some file_name related properties, but
> 	// none of them match the file name of the current binary.  So
>diff --git a/src/abg-reader.cc b/src/abg-reader.cc
>index dcaa27e1..5e0b97e0 100644
>--- a/src/abg-reader.cc
>+++ b/src/abg-reader.cc
>@@ -999,14 +999,14 @@ public:
>   {
>     corpus_sptr corp = get_corpus();
>
>-    if (!s.priv_->matches_soname(corp->get_soname()))
>+    if (!s.matches_soname(corp->get_soname()))
>       if (s.has_soname_related_property())
> 	// The suppression has some SONAME related properties, but
> 	// none of them match the SONAME of the current binary.  So
> 	// the suppression cannot match the current binary.
> 	return false;
>
>-    if (!s.priv_->matches_binary_name(corp->get_path()))
>+    if (!s.matches_binary_name(corp->get_path()))
>       if (s.has_file_name_related_property())
> 	// The suppression has some file_name related properties, but
> 	// none of them match the file name of the current binary.  So
>diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
>index 263052d4..5c06d5d0 100644
>--- a/src/abg-suppression-priv.h
>+++ b/src/abg-suppression-priv.h
>@@ -107,76 +107,7 @@ public:
>   {
>     return soname_not_regex_;
>   }
>-
>-  /// Test if the current suppression matches a given SONAME.
>-  ///
>-  /// @param soname the SONAME to consider.
>-  ///
>-  /// @return true iff the suppression matches the SONAME denoted by
>-  /// @p soname.
>-  ///
>-  /// Note that if the suppression contains no property that is
>-  /// related to SONAMEs, the function returns false.
>-  bool
>-  matches_soname(const string& soname) const
>-  {
>-    bool has_regexp = false;
>-    if (regex::regex_t_sptr regexp = get_soname_regex())
>-      {
>-	has_regexp = true;
>-	if (!regex::match(regexp, soname))
>-	  return false;
>-      }
>-
>-    if (regex::regex_t_sptr regexp = get_soname_not_regex())
>-      {
>-	has_regexp = true;
>-	if (regex::match(regexp, soname))
>-	  return false;
>-      }
>-
>-      if (!has_regexp)
>-	return false;
>-
>-    return true;
>-  }
>-
>-  /// Test if the current suppression matches the full file path to a
>-  /// given binary.
>-  ///
>-  /// @param binary_name the full path to the binary.
>-  ///
>-  /// @return true iff the suppression matches the path denoted by @p
>-  /// binary_name.
>-  ///
>-  /// Note that if the suppression contains no property that is
>-  /// related to file name, the function returns false.
>-  bool
>-  matches_binary_name(const string& binary_name) const
>-  {
>-    bool has_regexp = false;
>-
>-    if (regex::regex_t_sptr regexp = get_file_name_regex())
>-      {
>-	has_regexp = true;
>-	if (!regex::match(regexp, binary_name))
>-	  return false;
>-      }
>-
>-    if (regex::regex_t_sptr regexp = get_file_name_not_regex())
>-      {
>-	has_regexp = true;
>-	if (regex::match(regexp, binary_name))
>-	  return false;
>-      }
>-
>-    if (!has_regexp)
>-      return false;
>-
>-    return true;
>-  }
>-
>-}; // end clas suppression_base::priv
>+}; // end class suppression_base::priv
>
> // </suppression_base stuff>
>
>diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
>index 7e501c45..191c65c6 100644
>--- a/src/abg-suppression.cc
>+++ b/src/abg-suppression.cc
>@@ -252,6 +252,74 @@ suppression_base::has_soname_related_property() const
>   return get_soname_regex() || get_soname_not_regex();
> }
>
>+/// Test if the current suppression matches a given SONAME.
>+///
>+/// @param soname the SONAME to consider.
>+///
>+/// @return true iff the suppression matches the SONAME denoted by
>+/// @p soname.
>+///
>+/// Note that if the suppression contains no property that is
>+/// related to SONAMEs, the function returns false.
>+bool
>+suppression_base::matches_soname(const string& soname) const
>+{
>+  bool has_regexp = false;
>+  if (regex::regex_t_sptr regexp = get_soname_regex())
>+    {
>+      has_regexp = true;
>+      if (!regex::match(regexp, soname))
>+        return false;
>+    }
>+
>+  if (regex::regex_t_sptr regexp = get_soname_not_regex())
>+    {
>+      has_regexp = true;
>+      if (regex::match(regexp, soname))
>+        return false;
>+    }
>+
>+  if (!has_regexp)
>+    return false;
>+
>+  return true;
>+}
>+
>+/// Test if the current suppression matches the full file path to a
>+/// given binary.
>+///
>+/// @param binary_name the full path to the binary.
>+///
>+/// @return true iff the suppression matches the path denoted by @p
>+/// binary_name.
>+///
>+/// Note that if the suppression contains no property that is
>+/// related to file name, the function returns false.
>+bool
>+suppression_base::matches_binary_name(const string& binary_name) const
>+{
>+  bool has_regexp = false;
>+
>+  if (regex::regex_t_sptr regexp = get_file_name_regex())
>+    {
>+      has_regexp = true;
>+      if (!regex::match(regexp, binary_name))
>+        return false;
>+    }
>+
>+  if (regex::regex_t_sptr regexp = get_file_name_not_regex())
>+    {
>+      has_regexp = true;
>+      if (regex::match(regexp, binary_name))
>+        return false;
>+    }
>+
>+  if (!has_regexp)
>+    return false;
>+
>+  return true;
>+}
>+
> /// Check if the SONAMEs of the two binaries being compared match the
> /// content of the properties "soname_regexp" and "soname_not_regexp"
> /// of the current suppression specification.
>@@ -305,8 +373,8 @@ names_of_binaries_match(const suppression_base& suppr,
>   if (!suppr.has_file_name_related_property())
>     return false;
>
>-  if (!suppr.priv_->matches_binary_name(first_binary_path)
>-      && !suppr.priv_->matches_binary_name(second_binary_path))
>+  if (!suppr.matches_binary_name(first_binary_path)
>+      && !suppr.matches_binary_name(second_binary_path))
>     return false;
>
>   return true;
>@@ -4330,7 +4398,7 @@ bool
> suppression_matches_soname(const string& soname,
> 			   const suppression_base& suppr)
> {
>-  return suppr.priv_->matches_soname(soname);
>+  return suppr.matches_soname(soname);
> }
>
> /// Test if a given SONAME or file name is matched by a given
>@@ -4350,7 +4418,7 @@ suppression_matches_soname_or_filename(const string& soname,
> 				       const suppression_base& suppr)
> {
>   return (suppression_matches_soname(soname, suppr)
>-	  || suppr.priv_->matches_binary_name(filename));
>+	  || suppr.matches_binary_name(filename));
> }
>
> /// @return the name of the artificial private type suppression
>-- 
>2.26.2.303.gf8c07b1a785-goog
>

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 14/21] Remove suppression types' priv class methods.
  2020-04-24  9:21   ` [PATCH v3 14/21] Remove suppression types' priv class methods Giuliano Procida
@ 2020-04-27 11:57     ` Matthias Maennich
  0 siblings, 0 replies; 120+ messages in thread
From: Matthias Maennich @ 2020-04-27 11:57 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, dodji, kernel-team

On Fri, Apr 24, 2020 at 10:21:25AM +0100, Giuliano Procida wrote:
>The type_suppression::set_type_name_not_regex method is the only
>remaining user of all the various suppression_type::priv member
>functions. This is easily remedied and all the remaining priv member
>functions (regex getters and setters) can be dropped.
>
>This patches leaves all the various suppression priv types as simple
>data containers (modulo their constructors).
>
>There are no behavioural changes.
>
>	* src/abg-suppression-priv.h (suppression_base::priv): Drop
>	all regex getter methods.
>	(function_suppression::parameter_spec::priv): Drop all regex
>	getter methods.
>	(function_suppression::priv): Drop all regex getter methods.
>	(variable_suppression::priv): Drop all regex getter methods.
>	(type_suppression::priv): Drop all regex getter and setter
>	methods.
>	* src/abg-suppression.cc (set_type_name_not_regex): Access
>	priv_->type_name_not_regex_ directly.
>
>Signed-off-by: Giuliano Procida <gprocida@google.com>

Reviewed-by: Matthias Maennich <maennich@google.com>

Cheers,
Matthias

>---
> src/abg-suppression-priv.h | 182 -------------------------------------
> src/abg-suppression.cc     |   2 +-
> 2 files changed, 1 insertion(+), 183 deletions(-)
>
>diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
>index 5c06d5d0..78f11e2f 100644
>--- a/src/abg-suppression-priv.h
>+++ b/src/abg-suppression-priv.h
>@@ -75,38 +75,6 @@ public:
>   {}
>
>   friend class suppression_base;
>-
>-  /// Get the regular expression object associated to the
>-  /// 'file_name_regex' property of @ref suppression_base.
>-  const regex::regex_t_sptr&
>-  get_file_name_regex() const
>-  {
>-    return file_name_regex_;
>-  }
>-
>-  /// Get the regular expression object associated to the
>-  /// 'file_name_not_regex' property of @ref suppression_base.
>-  const regex::regex_t_sptr&
>-  get_file_name_not_regex() const
>-  {
>-    return file_name_not_regex_;
>-  }
>-
>-  /// Get the regular expression object associated to the 'soname_regex'
>-  /// property of @ref suppression_base.
>-  const regex::regex_t_sptr&
>-  get_soname_regex() const
>-  {
>-    return soname_regex_;
>-  }
>-
>-  /// Get the regular expression object associated to the
>-  /// 'soname_not_regex' property of @ref suppression_base.
>-  const regex::regex_t_sptr&
>-  get_soname_not_regex() const
>-  {
>-    return soname_not_regex_;
>-  }
> }; // end class suppression_base::priv
>
> // </suppression_base stuff>
>@@ -133,15 +101,6 @@ class function_suppression::parameter_spec::priv
>   priv(size_t i, const string& tn, const regex::regex_t_sptr& tn_regex)
>     : index_(i), type_name_(tn), type_name_regex_(tn_regex)
>   {}
>-
>-  /// Get the regular expression object associated to the
>-  /// 'type_name_regex' property of @ref
>-  /// function_suppression::parameter_spec.
>-  const regex::regex_t_sptr
>-  get_type_name_regex() const
>-  {
>-    return type_name_regex_;
>-  }
> }; // end class function_suppression::parameter_spec::priv
>
>
>@@ -191,54 +150,6 @@ struct function_suppression::priv
>       symbol_version_regex_(symbol_version_regex),
>       allow_other_aliases_(true)
>   {}
>-
>-  /// Get the regular expression object associated to the 'name_regex'
>-  /// property of @ref function_suppression.
>-  const regex::regex_t_sptr
>-  get_name_regex() const
>-  {
>-    return name_regex_;
>-  }
>-
>-  /// Get the regular expression object associated to the
>-  /// 'name_not_regex' property of @ref function_suppression.
>-  const regex::regex_t_sptr
>-  get_name_not_regex() const
>-  {
>-    return name_not_regex_;
>-  }
>-
>-  /// Get the regular expression object associated to the
>-  /// 'return_type_regex' property of @ref function_suppression.
>-  const regex::regex_t_sptr
>-  get_return_type_regex() const
>-  {
>-    return return_type_regex_;
>-  }
>-
>-  /// Get the regular expression object associated to the
>-  /// 'symbol_name_regex' property of @ref function_suppression.
>-  const regex::regex_t_sptr
>-  get_symbol_name_regex() const
>-  {
>-    return symbol_name_regex_;
>-  }
>-
>-  /// Get the regular expression object associated to the
>-  /// 'symbol_name_not_regex' property of @ref function_suppression.
>-  const regex::regex_t_sptr
>-  get_symbol_name_not_regex() const
>-  {
>-    return symbol_name_not_regex_;
>-  }
>-
>-  /// Get the regular expression object associated to the
>-  /// 'symbol_version_regex' property of @ref function_suppression.
>-  const regex::regex_t_sptr
>-  get_symbol_version_regex() const
>-  {
>-    return symbol_version_regex_;
>-  }
> }; // end class function_suppression::priv
>
> bool
>@@ -343,54 +254,6 @@ struct variable_suppression::priv
>       type_name_(type_name),
>       type_name_regex_(type_name_regex)
>   {}
>-
>-  /// Get the regular expression object associated to the 'name_regex'
>-  /// property of @ref variable_suppression.
>-  const regex::regex_t_sptr
>-  get_name_regex() const
>-  {
>-    return name_regex_;
>-  }
>-
>-  /// Get the regular expression object associated to the
>-  /// 'name_not_regex' property of @ref variable_suppression.
>-  const regex::regex_t_sptr
>-  get_name_not_regex() const
>-  {
>-    return name_not_regex_;
>-  }
>-
>-  /// Get the regular expression object associated to the
>-  /// 'symbol_name_regex' property of @ref variable_suppression.
>-  const regex::regex_t_sptr
>-  get_symbol_name_regex() const
>-  {
>-    return symbol_name_regex_;
>-  }
>-
>-  /// Get the regular expression object associated to the
>-  /// 'symbol_name_not_regex' property of @ref variable_suppression.
>-  const regex::regex_t_sptr
>-  get_symbol_name_not_regex() const
>-  {
>-    return symbol_name_not_regex_;
>-  }
>-
>-  /// Get the regular expression object associated to the
>-  /// 'symbol_version_regex' property of @ref variable_suppression.
>-  const regex::regex_t_sptr
>-  get_symbol_version_regex()  const
>-  {
>-    return symbol_version_regex_;
>-  }
>-
>-  /// Get the regular expression object associated to the
>-  /// 'type_name_regex' property of @ref variable_suppression.
>-  const regex::regex_t_sptr
>-  get_type_name_regex() const
>-  {
>-    return type_name_regex_;
>-  }
> };// end class variable_supppression::priv
>
> template <typename ReadContextType>
>@@ -454,51 +317,6 @@ public:
>       reach_kind_(reach_kind)
>   {}
>
>-  /// Get the regular expression object associated to the
>-  /// 'type_name_regex' property of @ref type_suppression.
>-  const regex::regex_t_sptr
>-  get_type_name_regex() const
>-  {
>-    return type_name_regex_;
>-  }
>-
>-  /// Setter for the type_name_regex object.
>-  ///
>-  /// @param r the new type_name_regex object.
>-  void
>-  set_type_name_regex(regex::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.
>-  const regex::regex_t_sptr
>-  get_type_name_not_regex() const
>-  {
>-    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(regex::regex_t_sptr r)
>-  {type_name_not_regex_ = r;}
>-
>-  /// Get the regular expression object associated to the
>-  /// 'source_location_to_keep_regex' property of @ref type_suppression.
>-  const regex::regex_t_sptr
>-  get_source_location_to_keep_regex() const
>-  {
>-    return source_location_to_keep_regex_;
>-  }
>-
>-  /// Setter for the source_location_to_keep_regex object.
>-  ///
>-  /// @param r the new regex object.
>-  void
>-  set_source_location_to_keep_regex(regex::regex_t_sptr r)
>-  {source_location_to_keep_regex_ = r;}
>-
>   friend class type_suppression;
> }; // class type_suppression::priv
>
>diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
>index 191c65c6..331995bf 100644
>--- a/src/abg-suppression.cc
>+++ b/src/abg-suppression.cc
>@@ -515,7 +515,7 @@ type_suppression::get_type_name_regex() const
> /// @param r the new regexp string.
> void
> type_suppression::set_type_name_not_regex(const regex_t_sptr& r)
>-{priv_->set_type_name_not_regex(r);}
>+{priv_->type_name_not_regex_ = r;}
>
> /// Getter for the "type_name_not_regex" property of the type
> /// suppression specification.
>-- 
>2.26.2.303.gf8c07b1a785-goog
>

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 15/21] abg-suppression.cc: More consistent regex matching.
  2020-04-24  9:21   ` [PATCH v3 15/21] abg-suppression.cc: More consistent regex matching Giuliano Procida
@ 2020-04-27 12:07     ` Matthias Maennich
  2020-04-27 16:18       ` Giuliano Procida
  0 siblings, 1 reply; 120+ messages in thread
From: Matthias Maennich @ 2020-04-27 12:07 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, dodji, kernel-team

On Fri, Apr 24, 2020 at 10:21:26AM +0100, Giuliano Procida wrote:
>Following previous patches, various minor inconsistencies in the
>suppression regex matching code were more readily apparent.
>
>- regex_t_sptr values are fetched both by reference and by
>  value (which has a reference count mutation cost)
>- there's a mixture of code styles for testing regex presence
>    - regex = ...; if (regex && ...)
>    - if (regex = ...) if (...)
>  the latter has the advantage that the variable has a smaller scope
>  and can be given a shorter name
>- in some cases there are redundant tests (always true due to previous
>  conditional logic)
>
>This patch ensures all shared pointers to compiled regexes are fetched
>by const reference and that the code uses the nested if style of
>presence checking where possible. It simplifies some logic where
>there's redundancy.
>
>There are no behavioural changes. There may be performance
>improvements.
>
>	* src/abg-suppression.cc (suppression_matches_type_name): Get
>	regexes by const reference.
>	(suppression_matches_type_location): Get regexes by const
>	reference. (function_suppression::suppresses_function): Get
>	regexes by const reference; use nested if checks; simplify
>	logic around symbol version checks.
>	(function_suppression::suppresses_function_symbol): Get
>	regexes by const reference; use nested if checks; remove
>	redundant regex presence checks.
>	(suppression_matches_function_name): Get regexes by const
>	reference. (suppression_matches_function_sym_name): Get
>	regexes by const reference.
>	(suppression_matches_variable_name): Get regexes by const
>	reference. (suppression_matches_variable_sym_name): Get
>	regexes by const reference. (suppression_matches_type): Get
>	regexes by const reference.
>	(variable_suppression::suppresses_variable): Get regexes by
>	const reference; use nested if checks; remove redundant
>	type_name empty check.
>	(variable_suppression::suppresses_variable_symbol): Get
>	regexes by const reference; use nested if checks.
>
>Signed-off-by: Giuliano Procida <gprocida@google.com>
>---
> src/abg-suppression.cc | 167 +++++++++++++++++++----------------------
> 1 file changed, 76 insertions(+), 91 deletions(-)
>
>diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
>index 331995bf..7d411caf 100644
>--- a/src/abg-suppression.cc
>+++ b/src/abg-suppression.cc
>@@ -1053,15 +1053,14 @@ 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.
>-	  if (const regex_t_sptr& type_name_regex =
>-	      s.get_type_name_regex())
>+	  if (const regex_t_sptr& type_name_regex = s.get_type_name_regex())
> 	    {
> 	      if (!regex::match(type_name_regex, type_name))
> 		return false;
> 	    }
>
>-	  if (const regex_t_sptr type_name_not_regex =
>-	      s.get_type_name_not_regex())
>+	  if (const regex_t_sptr& type_name_not_regex =
>+		s.get_type_name_not_regex())
> 	    {
> 	      if (regex::match(type_name_not_regex, type_name))
> 		return false;
>@@ -1109,7 +1108,7 @@ suppression_matches_type_location(const type_suppression&	s,
>       unsigned loc_line = 0, loc_column = 0;
>       loc.expand(loc_path, loc_line, loc_column);
>
>-      if (regex_t_sptr regexp = s.get_source_location_to_keep_regex())
>+      if (const regex_t_sptr& regexp = s.get_source_location_to_keep_regex())
> 	if (regex::match(regexp, loc_path))
> 	  return false;
>
>@@ -2549,7 +2548,7 @@ function_suppression::suppresses_function(const function_decl* fn,
>     }
>
>   // check if the "name_regexp" property matches.
>-  const regex_t_sptr name_regex = get_name_regex();
>+  const regex_t_sptr& name_regex = get_name_regex();
>   if (name_regex)
>     {
>       if (!regex::match(name_regex, fname))
>@@ -2580,7 +2579,7 @@ function_suppression::suppresses_function(const function_decl* fn,
>     }
>
>   // check if the "name_not_regexp" property matches.
>-  const regex_t_sptr name_not_regex = get_name_not_regex();
>+  const regex_t_sptr& name_not_regex = get_name_not_regex();
>   if (name_not_regex)
>     {
>       if (regex::match(name_not_regex, fname))
>@@ -2624,11 +2623,9 @@ function_suppression::suppresses_function(const function_decl* fn,
>       if (fn_return_type_name != get_return_type_name())
> 	return false;
>     }
>-  else
>+  else if (const regex_t_sptr& regex = get_return_type_regex())
>     {
>-      const regex_t_sptr return_type_regex = get_return_type_regex();
>-      if (return_type_regex
>-	  && !regex::match(return_type_regex, fn_return_type_name))
>+      if (!regex::match(regex, fn_return_type_name))

Not sure, but maybe.

else if (const regex_t_sptr& regex = get_return_type_regex()
          && (!regex::match(regex, fn_return_type_name)))
          return false;

I am not too much for this, but this pattern seems to repeat throughout
the whole patch. So, for consistency sake, we could always do:
   if (regex = get_regex() && regex::match(...))

> 	return false;
>     }
>
>@@ -2664,14 +2661,15 @@ function_suppression::suppresses_function(const function_decl* fn,
>     }
>   else if (sym)
>     {
>-      const regex_t_sptr symbol_name_regex = get_symbol_name_regex();
>-      if (symbol_name_regex && !regex::match(symbol_name_regex, fn_sym_name))
>-	return false;
>+      const regex_t_sptr& symbol_name_regex = get_symbol_name_regex();
>+      const regex_t_sptr& symbol_name_not_regex = get_symbol_name_not_regex();
>
>-      const regex_t_sptr symbol_name_not_regex = get_symbol_name_not_regex();
>-      if (symbol_name_not_regex
>-	  && regex::match(symbol_name_not_regex, fn_sym_name))
>-	return false;
>+      if (symbol_name_regex)
>+	if (!regex::match(symbol_name_regex, fn_sym_name))

if (symbol_name_regex && !regex::match(symbol_name_regex, fn_sym_name))
   return false;

More examples of this further down.

Other than that:

Reviewed-by: Matthias Maennich <maennich@google.com>

Cheers,
Matthias

>+	  return false;
>+      if (symbol_name_not_regex)
>+	if (regex::match(symbol_name_not_regex, fn_sym_name))
>+	  return false;
>
>       if (get_allow_other_aliases())
> 	{
>@@ -2684,13 +2682,13 @@ function_suppression::suppresses_function(const function_decl* fn,
> 		   a && !a->is_main_symbol();
> 		   a = a->get_next_alias())
> 		{
>-		  if (symbol_name_regex
>-		      && !regex::match(symbol_name_regex, a->get_name()))
>-		    return false;
>-
>-		  if (symbol_name_not_regex
>-		      && regex::match(symbol_name_not_regex, a->get_name()))
>-		    return false;
>+		  const std::string& alias_name = a->get_name();
>+		  if (symbol_name_regex)
>+		    if (!regex::match(symbol_name_regex, alias_name))
>+		      return false;
>+		  if (symbol_name_not_regex)
>+		    if (regex::match(symbol_name_not_regex, alias_name))
>+		      return false;
> 		}
> 	    }
> 	}
>@@ -2698,17 +2696,19 @@ function_suppression::suppresses_function(const function_decl* fn,
>
>   // Check if the "symbol_version" and "symbol_version_regexp"
>   // properties match.
>-  if (sym && !get_symbol_version().empty())
>-    {
>-      if (fn_sym_version != get_symbol_version())
>-	return false;
>-    }
>-  else if (sym)
>+  if (sym)
>     {
>-      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
>-      if (symbol_version_regex
>-	  && !regex::match(symbol_version_regex, fn_sym_version))
>-	return false;
>+      if (!get_symbol_version().empty())
>+	{
>+	  if (fn_sym_version != get_symbol_version())
>+	    return false;
>+	}
>+      else
>+	{
>+	  if (const regex_t_sptr& regex = get_symbol_version_regex())
>+	    if (!regex::match(regex, fn_sym_version))
>+	      return false;
>+	}
>     }
>
>   // Check the 'parameter' property.
>@@ -2742,16 +2742,11 @@ function_suppression::suppresses_function(const function_decl* fn,
> 	      if (tn != fn_parm_type_qualified_name)
> 		return false;
> 	    }
>-	  else
>+	  else if (const regex_t_sptr& regex =
>+		     (*p)->get_parameter_type_name_regex())
> 	    {
>-	      const regex_t_sptr parm_type_name_regex =
>-		(*p)->get_parameter_type_name_regex();
>-	      if (parm_type_name_regex)
>-		{
>-		  if (!regex::match(parm_type_name_regex,
>-				    fn_parm_type_qualified_name))
>-		    return false;
>-		}
>+	      if (!regex::match(regex, fn_parm_type_qualified_name))
>+		return false;
> 	    }
> 	}
>     }
>@@ -2834,10 +2829,9 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
>       if (sym_name != get_symbol_name())
> 	return false;
>     }
>-  else if (get_symbol_name_regex())
>+  else if (const regex_t_sptr& regex = get_symbol_name_regex())
>     {
>-      const regex_t_sptr symbol_name_regex = get_symbol_name_regex();
>-      if (symbol_name_regex && !regex::match(symbol_name_regex, sym_name))
>+      if (!regex::match(regex, sym_name))
> 	return false;
>     }
>   else
>@@ -2849,11 +2843,9 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
>       if (sym_version != get_symbol_version())
> 	return false;
>     }
>-  else if (get_symbol_version_regex())
>+  else if (const regex_t_sptr& regex = get_symbol_version_regex())
>     {
>-      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
>-      if (symbol_version_regex
>-	  && !regex::match(symbol_version_regex, sym_version))
>+      if (!regex::match(regex, sym_version))
> 	return false;
>     }
>   else
>@@ -2943,12 +2935,12 @@ bool
> suppression_matches_function_name(const suppr::function_suppression& s,
> 				  const string& fn_name)
> {
>-  if (regex_t_sptr regexp = s.get_name_regex())
>+  if (const regex_t_sptr& regexp = s.get_name_regex())
>     {
>       if (!regex::match(regexp, fn_name))
> 	return false;
>     }
>-  else if (regex_t_sptr regexp = s.get_name_not_regex())
>+  else if (const regex_t_sptr& regexp = s.get_name_not_regex())
>     {
>       if (regex::match(regexp, fn_name))
> 	return false;
>@@ -2979,12 +2971,12 @@ bool
> suppression_matches_function_sym_name(const suppr::function_suppression& s,
> 				      const string& fn_linkage_name)
> {
>-  if (regex_t_sptr regexp = s.get_symbol_name_regex())
>+  if (const regex_t_sptr& regexp = s.get_symbol_name_regex())
>     {
>       if (!regex::match(regexp, fn_linkage_name))
> 	return false;
>     }
>-  else if (regex_t_sptr regexp = s.get_symbol_name_not_regex())
>+  else if (const regex_t_sptr& regexp = s.get_symbol_name_not_regex())
>     {
>       if (regex::match(regexp, fn_linkage_name))
> 	return false;
>@@ -3012,12 +3004,12 @@ bool
> suppression_matches_variable_name(const suppr::variable_suppression& s,
> 				  const string& var_name)
> {
>-  if (regex_t_sptr regexp = s.get_name_regex())
>+  if (const regex_t_sptr& regexp = s.get_name_regex())
>     {
>       if (!regex::match(regexp, var_name))
> 	return false;
>     }
>-  else if (regex_t_sptr regexp = s.get_name_not_regex())
>+  else if (const regex_t_sptr& regexp = s.get_name_not_regex())
>     {
>       if (regex::match(regexp, var_name))
> 	return false;
>@@ -3046,12 +3038,12 @@ bool
> suppression_matches_variable_sym_name(const suppr::variable_suppression& s,
> 				      const string& var_linkage_name)
> {
>-  if (regex_t_sptr regexp = s.get_symbol_name_regex())
>+  if (const regex_t_sptr& regexp = s.get_symbol_name_regex())
>     {
>       if (!regex::match(regexp, var_linkage_name))
> 	return false;
>     }
>-  else if (regex_t_sptr regexp = s.get_symbol_name_not_regex())
>+  else if (const regex_t_sptr& regexp = s.get_symbol_name_not_regex())
>     {
>       if (regex::match(regexp, var_linkage_name))
> 	return false;
>@@ -3080,7 +3072,7 @@ bool
> suppression_matches_type(const suppr::type_suppression& s,
> 			 const string& type_name)
> {
>-  if (regex_t_sptr regexp = s.get_type_name_regex())
>+  if (const regex_t_sptr& regexp = s.get_type_name_regex())
>     {
>       if (!regex::match(regexp, type_name))
> 	return false;
>@@ -3789,13 +3781,13 @@ variable_suppression::suppresses_variable(const var_decl* var,
>       // "name_regex" and "name_not_regex" properties match
>       if (get_name().empty())
> 	{
>-	  const regex_t_sptr name_regex = get_name_regex();
>-	  if (name_regex && !regex::match(name_regex, var_name))
>-	    return false;
>+	  if (const regex_t_sptr& regex = get_name_regex())
>+	    if (!regex::match(regex, var_name))
>+	      return false;
>
>-	  const regex_t_sptr name_not_regex = get_name_not_regex();
>-	  if (name_not_regex && regex::match(name_not_regex, var_name))
>-	    return false;
>+	  if (const regex_t_sptr& regex = get_name_not_regex())
>+	    if (regex::match(regex, var_name))
>+	      return false;
> 	}
>     }
>
>@@ -3809,13 +3801,13 @@ variable_suppression::suppresses_variable(const var_decl* var,
>     }
>   else
>     {
>-      const regex_t_sptr sym_name_regex = get_symbol_name_regex();
>-      if (sym_name_regex && !regex::match(sym_name_regex, var_sym_name))
>-	return false;
>+      if (const regex_t_sptr& regex = get_symbol_name_regex())
>+	if (!regex::match(regex, var_sym_name))
>+	  return false;
>
>-      const regex_t_sptr sym_name_not_regex = get_symbol_name_not_regex();
>-      if (sym_name_not_regex && regex::match(sym_name_not_regex, var_sym_name))
>-	return false;
>+      if (const regex_t_sptr& regex = get_symbol_name_not_regex())
>+	if (regex::match(regex, var_sym_name))
>+	  return false;
>     }
>
>   // Check for symbol_version and symbol_version_regexp property match
>@@ -3828,10 +3820,9 @@ variable_suppression::suppresses_variable(const var_decl* var,
>     }
>   else
>     {
>-      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
>-      if (symbol_version_regex
>-	  && !regex::match(symbol_version_regex, var_sym_version))
>-	return false;
>+      if (const regex_t_sptr& regex = get_symbol_version_regex())
>+	if (!regex::match(regex, var_sym_version))
>+	  return false;
>     }
>
>   // Check for the "type_name" and type_name_regex properties match.
>@@ -3845,12 +3836,9 @@ variable_suppression::suppresses_variable(const var_decl* var,
>     }
>   else
>     {
>-      if (get_type_name().empty())
>-	{
>-	  const regex_t_sptr type_name_regex = get_type_name_regex();
>-	  if (type_name_regex && !regex::match(type_name_regex, var_type_name))
>-	    return false;
>-	}
>+      if (const regex_t_sptr& regex = get_type_name_regex())
>+	if (!regex::match(regex, var_type_name))
>+	  return false;
>     }
>
>   return true;
>@@ -3936,10 +3924,9 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
>       if (get_symbol_name() != sym_name)
> 	return false;
>     }
>-  else if (get_symbol_name_regex())
>+  else if (const regex_t_sptr& regex = get_symbol_name_regex())
>     {
>-      const regex_t_sptr sym_name_regex = get_symbol_name_regex();
>-      if (sym_name_regex && !regex::match(sym_name_regex, sym_name))
>+      if (!regex::match(regex, sym_name))
> 	return false;
>     }
>   else
>@@ -3952,11 +3939,9 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
>       if (get_symbol_version() != sym_version)
> 	return false;
>     }
>-  else if (get_symbol_version_regex())
>+  else if (const regex_t_sptr& regex = get_symbol_version_regex())
>     {
>-      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
>-      if (symbol_version_regex
>-	  && !regex::match(symbol_version_regex, sym_version))
>+      if (!regex::match(regex, sym_version))
> 	return false;
>     }
>   else
>@@ -4257,14 +4242,14 @@ file_suppression::suppresses_file(const string& file_path)
>
>   bool has_regexp = false;
>
>-  if (regex_t_sptr regexp = get_file_name_regex())
>+  if (const regex_t_sptr& regexp = get_file_name_regex())
>     {
>       has_regexp = true;
>       if (!regex::match(regexp, fname))
> 	return false;
>     }
>
>-  if (regex_t_sptr regexp = get_file_name_not_regex())
>+  if (const regex_t_sptr& regexp = get_file_name_not_regex())
>     {
>       has_regexp = true;
>       if (regex::match(regexp, fname))
>-- 
>2.26.2.303.gf8c07b1a785-goog
>

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 16/21] abg-tools-utils.cc: Assert generated regexes OK.
  2020-04-24  9:21   ` [PATCH v3 16/21] abg-tools-utils.cc: Assert generated regexes OK Giuliano Procida
@ 2020-04-27 12:08     ` Matthias Maennich
  2020-04-27 16:21       ` Giuliano Procida
  0 siblings, 1 reply; 120+ messages in thread
From: Matthias Maennich @ 2020-04-27 12:08 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, dodji, kernel-team

On Fri, Apr 24, 2020 at 10:21:27AM +0100, Giuliano Procida wrote:
>There are a couple of places where regexes are generated interally.
                                                              ^^^ typo
>Assert they compile OK.
>
>This is just paranoia. There should be no behavioural changes.
>
>	* src/abg-tools-utils.cc (handle_file_entry): Assert
>	internally-generated regex compiles.
>	(gen_suppr_spec_from_kernel_abi_whitelists): Assert
>	internally-generated regex compiles.
>
>Signed-off-by: Giuliano Procida <gprocida@google.com>

Reviewed-by: Matthias Maennich <maennich@google.com>

Cheers,
Matthias

>---
> src/abg-tools-utils.cc | 2 ++
> 1 file changed, 2 insertions(+)
>
>diff --git a/src/abg-tools-utils.cc b/src/abg-tools-utils.cc
>index fe0de750..3af9fc49 100644
>--- a/src/abg-tools-utils.cc
>+++ b/src/abg-tools-utils.cc
>@@ -1818,6 +1818,7 @@ handle_file_entry(const string& file_path,
>       // Types that are defined in system headers are usually
>       // OK to be considered as public types.
>       regex::regex_t_sptr headers_regex = regex::compile("^/usr/include/");
>+      ABG_ASSERT(headers_regex);
>       suppr->set_source_location_to_keep_regex(headers_regex);
>       suppr->set_is_artificial(true);
>     }
>@@ -2008,6 +2009,7 @@ gen_suppr_spec_from_kernel_abi_whitelists
>       // the function and variable names expressed in the white list.
>       regex::regex_t_sptr regex =
> 	regex::compile(regex::generate_from_strings(whitelisted_names));
>+      ABG_ASSERT(regex);
>
>       // Build a suppression specification which *keeps* functions
>       // whose ELF symbols match the regular expression contained
>-- 
>2.26.2.303.gf8c07b1a785-goog
>

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 17/21] Refactor suppression property string parsing.
  2020-04-24  9:21   ` [PATCH v3 17/21] Refactor suppression property string parsing Giuliano Procida
@ 2020-04-27 12:17     ` Matthias Maennich
  2020-04-27 16:42       ` Giuliano Procida
  0 siblings, 1 reply; 120+ messages in thread
From: Matthias Maennich @ 2020-04-27 12:17 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, dodji, kernel-team

On Fri, Apr 24, 2020 at 10:21:28AM +0100, Giuliano Procida wrote:
>This patch introduces a helper function to look up a key in an ini
>configuration section and get a string value. All string look-ups now
>use this.
>
>There are no behavioural changes.
>
>Signed-off-by: Giuliano Procida <gprocida@google.com>
>---
> src/abg-suppression.cc | 198 ++++++++++++++++-------------------------
> 1 file changed, 78 insertions(+), 120 deletions(-)
>
>diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
>index 7d411caf..84c9b78f 100644
>--- a/src/abg-suppression.cc
>+++ b/src/abg-suppression.cc
>@@ -1594,6 +1594,31 @@ read_suppression_reach_kind(const string& input)
>     return type_suppression::DIRECT_REACH_KIND;
> }
>
>+/// Maybe fetch a property to a string.
>+///
>+/// Attempt to find a simple property in an ini section and copy it
>+/// to a string
>+///
>+/// @param section the ini section to look in
>+///
>+/// @param prop the property name
>+///
>+/// @param str the string to compile into
>+///
>+/// @return whether the property was found
>+static bool
>+maybe_get_string_prop(const ini::config::section& section,
>+                      const std::string& name,
>+                      std::string& str)

I would prefer a signature like

std::string get_string_prop(... section, ... name, std::string default = "");

In fact, this could be also

   template<typename T>
   T get_prop(... section, ... name, T default);

if prop->get_value() would be changed accordingly.

This does not play nicely with several keys to lookup though ...

Cheers,
Matthias

>+{
>+  ini::simple_property_sptr prop =
>+    is_simple_property(section.find_property(name));
>+  if (!prop)
>+    return false;
>+  str = prop->get_value()->as_string();
>+  return true;
>+}
>+
> /// Read a type suppression from an instance of ini::config::section
> /// and build a @ref type_suppression as a result.
> ///
>@@ -1609,18 +1634,12 @@ read_type_suppression(const ini::config::section& section)
>   if (section.get_name() != "suppress_type")
>     return result;
>
>-  ini::simple_property_sptr drop_artifact =
>-    is_simple_property(section.find_property("drop_artifact"));
>-  if (!drop_artifact)
>-    drop_artifact = is_simple_property(section.find_property("drop"));
>-
>-  string drop_artifact_str = drop_artifact
>-    ? drop_artifact->get_value()->as_string()
>-    : "";
>+  string drop_artifact_str;
>+  maybe_get_string_prop(section, "drop_artifact", drop_artifact_str)
>+    || maybe_get_string_prop(section, "drop", drop_artifact_str);
>
>-  ini::simple_property_sptr label =
>-    is_simple_property(section.find_property("label"));
>-  string label_str = label ? label->get_value()->as_string() : "";
>+  string label_str;
>+  maybe_get_string_prop(section, "label", label_str);
>
>   ini::simple_property_sptr file_name_regex_prop =
>     is_simple_property(section.find_property("file_name_regexp"));
>@@ -1662,11 +1681,8 @@ read_type_suppression(const ini::config::section& section)
>     name_not_regex =
>       regex::compile(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
>-    ? name_prop->get_value()->as_string()
>-    : "";
>+  string name_str;
>+  maybe_get_string_prop(section, "name", name_str);
>
>   ini::property_sptr srcloc_not_in_prop =
>     section.find_property("source_location_not_in");
>@@ -1697,25 +1713,19 @@ read_type_suppression(const ini::config::section& section)
>     srcloc_not_regex =
>       regex::compile(srcloc_not_regexp_prop->get_value()->as_string());
>
>-  bool consider_type_kind = false;
>-  type_suppression::type_kind type_kind = type_suppression::UNKNOWN_TYPE_KIND;
>-  if (ini::simple_property_sptr type_kind_prop =
>-      is_simple_property(section.find_property("type_kind")))
>-    {
>-      consider_type_kind = true;
>-      type_kind =
>-	read_type_kind_string(type_kind_prop->get_value()->as_string());
>-    }
>+  std::string type_kind_str;
>+  bool consider_type_kind =
>+    maybe_get_string_prop(section, "type_kind", type_kind_str);
>+  type_suppression::type_kind type_kind = consider_type_kind
>+    ? read_type_kind_string(type_kind_str)
>+    : type_suppression::UNKNOWN_TYPE_KIND;
>
>-  bool consider_reach_kind = false;
>-  type_suppression::reach_kind reach_kind = type_suppression::DIRECT_REACH_KIND;
>-  if (ini::simple_property_sptr reach_kind_prop =
>-      is_simple_property(section.find_property("accessed_through")))
>-    {
>-      consider_reach_kind = true;
>-      reach_kind =
>-	read_suppression_reach_kind(reach_kind_prop->get_value()->as_string());
>-    }
>+  std::string reach_kind_str;
>+  bool consider_reach_kind =
>+      maybe_get_string_prop(section, "accessed_through", reach_kind_str);
>+  type_suppression::reach_kind reach_kind = consider_reach_kind
>+    ? read_suppression_reach_kind(reach_kind_str)
>+    : type_suppression::DIRECT_REACH_KIND;
>
>   // Support has_data_member_inserted_at
>   vector<type_suppression::insertion_range_sptr> insert_ranges;
>@@ -3175,26 +3185,15 @@ read_function_suppression(const ini::config::section& section)
>   if (section.get_name() != "suppress_function")
>     return result;
>
>-  ini::simple_property_sptr drop_artifact =
>-    is_simple_property(section.find_property("drop_artifact"));
>-  if (!drop_artifact)
>-    drop_artifact = is_simple_property(section.find_property("drop"));
>-
>-  string drop_artifact_str = drop_artifact
>-    ? drop_artifact->get_value()->as_string()
>-    : "";
>+  string drop_artifact_str;
>+  maybe_get_string_prop(section, "drop_artifact", drop_artifact_str)
>+    || maybe_get_string_prop(section, "drop", drop_artifact_str);
>
>-  ini::simple_property_sptr change_kind_prop =
>-    is_simple_property(section.find_property("change_kind"));
>-  string change_kind_str = change_kind_prop
>-    ? change_kind_prop->get_value()->as_string()
>-    : "";
>+  string change_kind_str;
>+  maybe_get_string_prop(section, "change_kind", change_kind_str);
>
>-  ini::simple_property_sptr label_prop =
>-    is_simple_property(section.find_property("label"));
>-  string label_str = label_prop
>-    ? label_prop->get_value()->as_string()
>-    : "";
>+  string label_str;
>+  maybe_get_string_prop(section, "label", label_str);
>
>   ini::simple_property_sptr file_name_regex_prop =
>     is_simple_property(section.find_property("file_name_regexp"));
>@@ -3223,11 +3222,8 @@ read_function_suppression(const ini::config::section& section)
>     soname_not_regex =
>       regex::compile(soname_not_regex_prop->get_value()->as_string());
>
>-  ini::simple_property_sptr name_prop =
>-    is_simple_property(section.find_property("name"));
>-  string name = name_prop
>-    ? name_prop->get_value()->as_string()
>-    : "";
>+  string name;
>+  maybe_get_string_prop(section, "name", name);
>
>   ini::simple_property_sptr name_regex_prop =
>     is_simple_property(section.find_property("name_regexp"));
>@@ -3242,11 +3238,8 @@ read_function_suppression(const ini::config::section& section)
>     name_not_regex =
>       regex::compile(name_not_regex_prop->get_value()->as_string());
>
>-  ini::simple_property_sptr return_type_name_prop =
>-    is_simple_property(section.find_property("return_type_name"));
>-  string return_type_name = return_type_name_prop
>-    ? return_type_name_prop->get_value()->as_string()
>-    : "";
>+  string return_type_name;
>+  maybe_get_string_prop(section, "return_type_name", return_type_name);
>
>   ini::simple_property_sptr return_type_regex_prop =
>     is_simple_property(section.find_property("return_type_regexp"));
>@@ -3255,11 +3248,8 @@ read_function_suppression(const ini::config::section& section)
>     return_type_regex =
>       regex::compile(return_type_regex_prop->get_value()->as_string());
>
>-  ini::simple_property_sptr sym_name_prop =
>-    is_simple_property(section.find_property("symbol_name"));
>-  string sym_name = sym_name_prop
>-    ? sym_name_prop->get_value()->as_string()
>-    : "";
>+  string sym_name;
>+  maybe_get_string_prop(section, "symbol_name", sym_name);
>
>   ini::simple_property_sptr sym_name_regex_prop =
>     is_simple_property(section.find_property("symbol_name_regexp"));
>@@ -3275,11 +3265,8 @@ read_function_suppression(const ini::config::section& section)
>     sym_name_not_regex =
>       regex::compile(sym_name_not_regex_prop->get_value()->as_string());
>
>-  ini::simple_property_sptr sym_ver_prop =
>-    is_simple_property(section.find_property("symbol_version"));
>-  string sym_version = sym_ver_prop
>-    ? sym_ver_prop->get_value()->as_string()
>-    : "";
>+  string sym_version;
>+  maybe_get_string_prop(section, "symbol_version", sym_version);
>
>   ini::simple_property_sptr sym_ver_regex_prop =
>     is_simple_property(section.find_property("symbol_version_regexp"));
>@@ -3288,11 +3275,8 @@ read_function_suppression(const ini::config::section& section)
>     sym_ver_regex =
>       regex::compile(sym_ver_regex_prop->get_value()->as_string());
>
>-  ini::simple_property_sptr allow_other_aliases_prop =
>-    is_simple_property(section.find_property("allow_other_aliases"));
>-  string allow_other_aliases = allow_other_aliases_prop
>-    ? allow_other_aliases_prop->get_value()->as_string()
>-    : "";
>+  string allow_other_aliases;
>+  maybe_get_string_prop(section, "allow_other_aliases", allow_other_aliases);
>
>   function_suppression::parameter_spec_sptr parm;
>   function_suppression::parameter_specs_type parms;
>@@ -4031,26 +4015,15 @@ read_variable_suppression(const ini::config::section& section)
>   if (section.get_name() != "suppress_variable")
>     return result;
>
>-  ini::simple_property_sptr drop_artifact =
>-    is_simple_property(section.find_property("drop_artifact"));
>-  if (!drop_artifact)
>-    drop_artifact = is_simple_property(section.find_property("drop"));
>-
>-  string drop_artifact_str = drop_artifact
>-    ? drop_artifact->get_value()->as_string()
>-    : "";
>+  string drop_artifact_str;
>+  maybe_get_string_prop(section, "drop_artifact", drop_artifact_str)
>+    || maybe_get_string_prop(section, "drop", drop_artifact_str);
>
>-  ini::simple_property_sptr change_kind_prop =
>-    is_simple_property(section.find_property("change_kind"));
>-  string change_kind_str = change_kind_prop
>-    ? change_kind_prop->get_value()->as_string()
>-    : "";
>+  string change_kind_str;
>+  maybe_get_string_prop(section, "change_kind", change_kind_str);
>
>-  ini::simple_property_sptr label_prop =
>-    is_simple_property(section.find_property("label"));
>-  string label_str = (label_prop
>-		      ? label_prop->get_value()->as_string()
>-		      : "");
>+  string label_str;
>+  maybe_get_string_prop(section, "label", label_str);
>
>   ini::simple_property_sptr file_name_regex_prop =
>     is_simple_property(section.find_property("file_name_regexp"));
>@@ -4079,11 +4052,8 @@ read_variable_suppression(const ini::config::section& section)
>     soname_not_regex =
>       regex::compile(soname_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
>-		     ? name_prop->get_value()->as_string()
>-		     : "");
>+  string name_str;
>+  maybe_get_string_prop(section, "name", name_str);
>
>   ini::simple_property_sptr name_regex_prop =
>     is_simple_property(section.find_property("name_regexp"));
>@@ -4098,11 +4068,8 @@ read_variable_suppression(const ini::config::section& section)
>     name_not_regex =
>       regex::compile(name_not_regex_prop->get_value()->as_string());
>
>-  ini::simple_property_sptr sym_name_prop =
>-    is_simple_property(section.find_property("symbol_name"));
>-  string symbol_name = (sym_name_prop
>-			? sym_name_prop->get_value()->as_string()
>-			: "");
>+  string symbol_name;
>+  maybe_get_string_prop(section, "symbol_name", symbol_name);
>
>   ini::simple_property_sptr sym_name_regex_prop =
>     is_simple_property(section.find_property("symbol_name_regexp"));
>@@ -4118,11 +4085,8 @@ read_variable_suppression(const ini::config::section& section)
>     symbol_name_not_regex =
>       regex::compile(sym_name_not_regex_prop->get_value()->as_string());
>
>-  ini::simple_property_sptr sym_version_prop =
>-    is_simple_property(section.find_property("symbol_version"));
>-  string symbol_version = sym_version_prop
>-    ? sym_version_prop->get_value()->as_string()
>-    : "";
>+  string symbol_version;
>+  maybe_get_string_prop(section, "symbol_version", symbol_version);
>
>   ini::simple_property_sptr sym_version_regex_prop =
>     is_simple_property(section.find_property("symbol_version_regexp"));
>@@ -4131,11 +4095,8 @@ read_variable_suppression(const ini::config::section& section)
>     symbol_version_regex =
>       regex::compile(sym_version_regex_prop->get_value()->as_string());
>
>-  ini::simple_property_sptr type_name_prop =
>-    is_simple_property(section.find_property("type_name"));
>-  string type_name_str = type_name_prop
>-    ? type_name_prop->get_value()->as_string()
>-    : "";
>+  string type_name_str;
>+  maybe_get_string_prop(section, "type_name", type_name_str);
>
>   ini::simple_property_sptr type_name_regex_prop =
>     is_simple_property(section.find_property("type_name_regexp"));
>@@ -4282,11 +4243,8 @@ read_file_suppression(const ini::config::section& section)
>   if (section.get_name() != "suppress_file")
>     return result;
>
>-  ini::simple_property_sptr label_prop =
>-    is_simple_property(section.find_property("label"));
>-  string label_str = (label_prop
>-		      ? label_prop->get_value()->as_string()
>-		      : "");
>+  string label_str;
>+  maybe_get_string_prop(section, "label", label_str);
>
>   ini::simple_property_sptr file_name_regex_prop =
>     is_simple_property(section.find_property("file_name_regexp"));
>-- 
>2.26.2.303.gf8c07b1a785-goog
>

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 18/21] Refactor suppression property regex parsing.
  2020-04-24  9:21   ` [PATCH v3 18/21] Refactor suppression property regex parsing Giuliano Procida
@ 2020-04-27 14:55     ` Matthias Maennich
  2020-04-27 16:59       ` Giuliano Procida
  0 siblings, 1 reply; 120+ messages in thread
From: Matthias Maennich @ 2020-04-27 14:55 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, dodji, kernel-team

On Fri, Apr 24, 2020 at 10:21:29AM +0100, Giuliano Procida wrote:
>This patch introduces a helper function to look up a key in an ini
>configuration section and get a compiled regex value. All regex
>look-ups now use this.
>
>There are no behavioural changes.
>

That is an awesome simplification!

I basically have the same comment as before: Getting different data
types from the ini asks (in my opinion) for a bit generic code.

But I am also ok with this version.

Reviewed-by: Matthias Maennich <maennich@google.com>

Cheers,
Matthias

>Signed-off-by: Giuliano Procida <gprocida@google.com>
>---
> src/abg-suppression.cc | 215 ++++++++++++-----------------------------
> 1 file changed, 61 insertions(+), 154 deletions(-)
>
>diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
>index 84c9b78f..8b3631fd 100644
>--- a/src/abg-suppression.cc
>+++ b/src/abg-suppression.cc
>@@ -1619,6 +1619,30 @@ maybe_get_string_prop(const ini::config::section& section,
>   return true;
> }
>
>+/// Maybe compile a property to a regex.
>+///
>+/// Attempt to find a simple property in an ini section and compile it
>+/// to a regex.
>+///
>+/// @param section the ini section to look in
>+///
>+/// @param prop the property name
>+///
>+/// @param r the regex to compile into
>+///
>+/// @return whether the property was found
>+static bool
>+maybe_get_regex_prop(const ini::config::section& section,
>+                     const std::string& name,
>+                     regex_t_sptr& regex)
>+{
>+  string str;
>+  if (!maybe_get_string_prop(section, name, str))
>+    return false;
>+  regex = regex::compile(str);
>+  return true;
>+}
>+
> /// Read a type suppression from an instance of ini::config::section
> /// and build a @ref type_suppression as a result.
> ///
>@@ -1641,45 +1665,23 @@ read_type_suppression(const ini::config::section& section)
>   string label_str;
>   maybe_get_string_prop(section, "label", label_str);
>
>-  ini::simple_property_sptr file_name_regex_prop =
>-    is_simple_property(section.find_property("file_name_regexp"));
>   regex_t_sptr file_name_regex;
>-  if (file_name_regex_prop)
>-    file_name_regex =
>-      regex::compile(file_name_regex_prop->get_value()->as_string());
>+  maybe_get_regex_prop(section, "file_name_regexp", file_name_regex);
>
>-  ini::simple_property_sptr file_name_not_regex_prop =
>-    is_simple_property(section.find_property("file_name_not_regexp"));
>   regex_t_sptr file_name_not_regex;
>-  if (file_name_not_regex_prop)
>-    file_name_not_regex =
>-      regex::compile(file_name_not_regex_prop->get_value()->as_string());
>+  maybe_get_regex_prop(section, "file_name_not_regexp", file_name_not_regex);
>
>-  ini::simple_property_sptr soname_regex_prop =
>-    is_simple_property(section.find_property("soname_regexp"));
>   regex_t_sptr soname_regex;
>-  if (soname_regex_prop)
>-    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
>+  maybe_get_regex_prop(section, "soname_regexp", soname_regex);
>
>-  ini::simple_property_sptr soname_not_regex_prop =
>-    is_simple_property(section.find_property("soname_not_regexp"));
>   regex_t_sptr soname_not_regex;
>-  if (soname_not_regex_prop)
>-    soname_not_regex =
>-      regex::compile(soname_not_regex_prop->get_value()->as_string());
>+  maybe_get_regex_prop(section, "soname_not_regexp", soname_not_regex);
>
>-  ini::simple_property_sptr name_regex_prop =
>-    is_simple_property(section.find_property("name_regexp"));
>   regex_t_sptr name_regex;
>-  if (name_regex_prop)
>-    name_regex = regex::compile(name_regex_prop->get_value()->as_string());
>+  maybe_get_regex_prop(section, "name_regexp", name_regex);
>
>-  ini::simple_property_sptr name_not_regex_prop =
>-    is_simple_property(section.find_property("name_not_regexp"));
>   regex_t_sptr name_not_regex;
>-  if (name_not_regex_prop)
>-    name_not_regex =
>-      regex::compile(name_not_regex_prop->get_value()->as_string());
>+  maybe_get_regex_prop(section, "name_not_regexp", name_not_regex);
>
>   string name_str;
>   maybe_get_string_prop(section, "name", name_str);
>@@ -1706,12 +1708,8 @@ read_type_suppression(const ini::config::section& section)
> 	}
>     }
>
>-  ini::simple_property_sptr srcloc_not_regexp_prop =
>-    is_simple_property(section.find_property("source_location_not_regexp"));
>   regex_t_sptr srcloc_not_regex;
>-  if (srcloc_not_regexp_prop)
>-    srcloc_not_regex =
>-      regex::compile(srcloc_not_regexp_prop->get_value()->as_string());
>+  maybe_get_regex_prop(section, "source_location_not_regexp", srcloc_not_regex);
>
>   std::string type_kind_str;
>   bool consider_type_kind =
>@@ -3195,85 +3193,47 @@ read_function_suppression(const ini::config::section& section)
>   string label_str;
>   maybe_get_string_prop(section, "label", label_str);
>
>-  ini::simple_property_sptr file_name_regex_prop =
>-    is_simple_property(section.find_property("file_name_regexp"));
>   regex_t_sptr file_name_regex;
>-  if (file_name_regex_prop)
>-    file_name_regex =
>-      regex::compile(file_name_regex_prop->get_value()->as_string());
>+  maybe_get_regex_prop(section, "file_name_regexp", file_name_regex);
>
>-  ini::simple_property_sptr file_name_not_regex_prop =
>-    is_simple_property(section.find_property("file_name_not_regexp"));
>   regex_t_sptr file_name_not_regex;
>-  if (file_name_not_regex_prop)
>-    file_name_not_regex =
>-      regex::compile(file_name_not_regex_prop->get_value()->as_string());
>+  maybe_get_regex_prop(section, "file_name_not_regexp", file_name_not_regex);
>
>-  ini::simple_property_sptr soname_regex_prop =
>-    is_simple_property(section.find_property("soname_regexp"));
>   regex_t_sptr soname_regex;
>-  if (soname_regex_prop)
>-    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
>+  maybe_get_regex_prop(section, "soname_regexp", soname_regex);
>
>-  ini::simple_property_sptr soname_not_regex_prop =
>-    is_simple_property(section.find_property("soname_not_regexp"));
>   regex_t_sptr soname_not_regex;
>-  if (soname_not_regex_prop)
>-    soname_not_regex =
>-      regex::compile(soname_not_regex_prop->get_value()->as_string());
>+  maybe_get_regex_prop(section, "soname_not_regexp", soname_not_regex);
>
>   string name;
>   maybe_get_string_prop(section, "name", name);
>
>-  ini::simple_property_sptr name_regex_prop =
>-    is_simple_property(section.find_property("name_regexp"));
>   regex_t_sptr name_regex;
>-  if (name_regex_prop)
>-    name_regex = regex::compile(name_regex_prop->get_value()->as_string());
>+  maybe_get_regex_prop(section, "name_regexp", name_regex);
>
>-  ini::simple_property_sptr name_not_regex_prop =
>-    is_simple_property(section.find_property("name_not_regexp"));
>   regex_t_sptr name_not_regex;
>-  if (name_not_regex_prop)
>-    name_not_regex =
>-      regex::compile(name_not_regex_prop->get_value()->as_string());
>+  maybe_get_regex_prop(section, "name_not_regexp", name_not_regex);
>
>   string return_type_name;
>   maybe_get_string_prop(section, "return_type_name", return_type_name);
>
>-  ini::simple_property_sptr return_type_regex_prop =
>-    is_simple_property(section.find_property("return_type_regexp"));
>   regex_t_sptr return_type_regex;
>-  if (return_type_regex_prop)
>-    return_type_regex =
>-      regex::compile(return_type_regex_prop->get_value()->as_string());
>+  maybe_get_regex_prop(section, "return_type_regexp", return_type_regex);
>
>   string sym_name;
>   maybe_get_string_prop(section, "symbol_name", sym_name);
>
>-  ini::simple_property_sptr sym_name_regex_prop =
>-    is_simple_property(section.find_property("symbol_name_regexp"));
>   regex_t_sptr sym_name_regex;
>-  if (sym_name_regex_prop)
>-    sym_name_regex =
>-      regex::compile(sym_name_regex_prop->get_value()->as_string());
>+  maybe_get_regex_prop(section, "symbol_name_regexp", sym_name_regex);
>
>-  ini::simple_property_sptr sym_name_not_regex_prop =
>-    is_simple_property(section.find_property("symbol_name_not_regexp"));
>   regex_t_sptr sym_name_not_regex;
>-  if (sym_name_not_regex_prop)
>-    sym_name_not_regex =
>-      regex::compile(sym_name_not_regex_prop->get_value()->as_string());
>+  maybe_get_regex_prop(section, "symbol_name_not_regexp", sym_name_not_regex);
>
>   string sym_version;
>   maybe_get_string_prop(section, "symbol_version", sym_version);
>
>-  ini::simple_property_sptr sym_ver_regex_prop =
>-    is_simple_property(section.find_property("symbol_version_regexp"));
>   regex_t_sptr sym_ver_regex;
>-  if (sym_ver_regex_prop)
>-    sym_ver_regex =
>-      regex::compile(sym_ver_regex_prop->get_value()->as_string());
>+  maybe_get_regex_prop(section, "symbol_version_regexp", sym_ver_regex);
>
>   string allow_other_aliases;
>   maybe_get_string_prop(section, "allow_other_aliases", allow_other_aliases);
>@@ -4025,85 +3985,47 @@ read_variable_suppression(const ini::config::section& section)
>   string label_str;
>   maybe_get_string_prop(section, "label", label_str);
>
>-  ini::simple_property_sptr file_name_regex_prop =
>-    is_simple_property(section.find_property("file_name_regexp"));
>   regex_t_sptr file_name_regex;
>-  if (file_name_regex_prop)
>-    file_name_regex =
>-      regex::compile(file_name_regex_prop->get_value()->as_string());
>-
>- ini::simple_property_sptr file_name_not_regex_prop =
>-  is_simple_property(section.find_property("file_name_not_regexp"));
>- regex_t_sptr file_name_not_regex;
>- if (file_name_not_regex_prop)
>-   file_name_not_regex =
>-     regex::compile(file_name_not_regex_prop->get_value()->as_string());
>-
>-  ini::simple_property_sptr soname_regex_prop =
>-    is_simple_property(section.find_property("soname_regexp"));
>+  maybe_get_regex_prop(section, "file_name_regexp", file_name_regex);
>+
>+  regex_t_sptr file_name_not_regex;
>+  maybe_get_regex_prop(section, "file_name_not_regexp", file_name_not_regex);
>+
>   regex_t_sptr soname_regex;
>-  if (soname_regex_prop)
>-    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
>+  maybe_get_regex_prop(section, "soname_regexp", soname_regex);
>
>-  ini::simple_property_sptr soname_not_regex_prop =
>-    is_simple_property(section.find_property("soname_not_regexp"));
>   regex_t_sptr soname_not_regex;
>-  if (soname_not_regex_prop)
>-    soname_not_regex =
>-      regex::compile(soname_not_regex_prop->get_value()->as_string());
>+  maybe_get_regex_prop(section, "soname_not_regexp", soname_not_regex);
>
>   string name_str;
>   maybe_get_string_prop(section, "name", name_str);
>
>-  ini::simple_property_sptr name_regex_prop =
>-    is_simple_property(section.find_property("name_regexp"));
>   regex_t_sptr name_regex;
>-  if (name_regex_prop)
>-    name_regex = regex::compile(name_regex_prop->get_value()->as_string());
>+  maybe_get_regex_prop(section, "name_regexp", name_regex);
>
>-  ini::simple_property_sptr name_not_regex_prop =
>-    is_simple_property(section.find_property("name_not_regexp"));
>   regex_t_sptr name_not_regex;
>-  if (name_not_regex_prop)
>-    name_not_regex =
>-      regex::compile(name_not_regex_prop->get_value()->as_string());
>+  maybe_get_regex_prop(section, "name_not_regexp", name_not_regex);
>
>   string symbol_name;
>   maybe_get_string_prop(section, "symbol_name", symbol_name);
>
>-  ini::simple_property_sptr sym_name_regex_prop =
>-    is_simple_property(section.find_property("symbol_name_regexp"));
>   regex_t_sptr symbol_name_regex;
>-  if (sym_name_regex_prop)
>-    symbol_name_regex =
>-      regex::compile(sym_name_regex_prop->get_value()->as_string());
>+  maybe_get_regex_prop(section, "symbol_name_regexp", symbol_name_regex);
>
>-  ini::simple_property_sptr sym_name_not_regex_prop =
>-    is_simple_property(section.find_property("symbol_name_not_regexp"));
>   regex_t_sptr symbol_name_not_regex;
>-  if (sym_name_not_regex_prop)
>-    symbol_name_not_regex =
>-      regex::compile(sym_name_not_regex_prop->get_value()->as_string());
>+  maybe_get_regex_prop(section, "symbol_name_not_regexp", symbol_name_not_regex);
>
>   string symbol_version;
>   maybe_get_string_prop(section, "symbol_version", symbol_version);
>
>-  ini::simple_property_sptr sym_version_regex_prop =
>-    is_simple_property(section.find_property("symbol_version_regexp"));
>   regex_t_sptr symbol_version_regex;
>-  if (sym_version_regex_prop)
>-    symbol_version_regex =
>-      regex::compile(sym_version_regex_prop->get_value()->as_string());
>+  maybe_get_regex_prop(section, "symbol_version_regexp", symbol_version_regex);
>
>   string type_name_str;
>   maybe_get_string_prop(section, "type_name", type_name_str);
>
>-  ini::simple_property_sptr type_name_regex_prop =
>-    is_simple_property(section.find_property("type_name_regexp"));
>   regex_t_sptr type_name_regex;
>-  if (type_name_regex_prop)
>-    type_name_regex =
>-      regex::compile(type_name_regex_prop->get_value()->as_string());
>+  maybe_get_regex_prop(section, "type_name_regexp", type_name_regex);
>
>   result.reset(new variable_suppression(label_str,
> 					name_str,
>@@ -4246,32 +4168,17 @@ read_file_suppression(const ini::config::section& section)
>   string label_str;
>   maybe_get_string_prop(section, "label", label_str);
>
>-  ini::simple_property_sptr file_name_regex_prop =
>-    is_simple_property(section.find_property("file_name_regexp"));
>   regex_t_sptr file_name_regex;
>-  if (file_name_regex_prop)
>-    file_name_regex =
>-      regex::compile(file_name_regex_prop->get_value()->as_string());
>-
>- ini::simple_property_sptr file_name_not_regex_prop =
>-    is_simple_property(section.find_property("file_name_not_regexp"));
>- regex_t_sptr file_name_not_regex;
>- if (file_name_not_regex_prop)
>-   file_name_not_regex =
>-     regex::compile(file_name_not_regex_prop->get_value()->as_string());
>-
>-  ini::simple_property_sptr soname_regex_prop =
>-    is_simple_property(section.find_property("soname_regexp"));
>+  maybe_get_regex_prop(section, "file_name_regexp", file_name_regex);
>+
>+  regex_t_sptr file_name_not_regex;
>+  maybe_get_regex_prop(section, "file_name_not_regexp", file_name_not_regex);
>+
>   regex_t_sptr soname_regex;
>-  if (soname_regex_prop)
>-    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
>+  maybe_get_regex_prop(section, "soname_regexp", soname_regex);
>
>-  ini::simple_property_sptr soname_not_regex_prop =
>-    is_simple_property(section.find_property("soname_not_regexp"));
>   regex_t_sptr soname_not_regex;
>-  if (soname_not_regex_prop)
>-    soname_not_regex =
>-      regex::compile(soname_not_regex_prop->get_value()->as_string());
>+  maybe_get_regex_prop(section, "soname_not_regexp", soname_not_regex);
>
>   result.reset(new file_suppression(label_str,
> 				    file_name_regex,
>-- 
>2.26.2.303.gf8c07b1a785-goog
>

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 03/21] Simplify generation of symbol whitelist regex.
  2020-04-27 11:01     ` Matthias Maennich
@ 2020-04-27 15:31       ` Giuliano Procida
  0 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-27 15:31 UTC (permalink / raw)
  To: Matthias Maennich; +Cc: libabigail, Dodji Seketeli, kernel-team

It is an efficient and nice-looking regex that will never match anything.

I'll add a code and a commit comment.

Giuliano.

On Mon, 27 Apr 2020 at 12:01, Matthias Maennich <maennich@google.com> wrote:
>
> On Fri, Apr 24, 2020 at 10:21:14AM +0100, Giuliano Procida wrote:
> >The code to build the symbol whitelist regex uses things like seekp
> >and tellp to generate regexes like "^foo$|^bar$".
> >
> >This patch simplifies the code, for further enhancement, resulting in
> >generated regexes like "^(foo|bar)$".
> >
> >There should be no change in behaviour, unless whitelisted symbol
> >names contain special regex characters.
> >
> >       * include/abg-regex.h (generate_from_strings): Declare new
> >       function to build a regex from some strings, representing a
> >       membership test.
> >       * src/abg-regex.cc (generate_from_strings): Implement new
> >       function to build a regex from some strings, representing a
> >       membership test, in a straightfoward fashion.
> >       * src/abg-tools-utils.cc
> >       (gen_suppr_spec_from_kernel_abi_whitelists): Replace
> >       regex-building code with a call to generate_from_strings.
> >       * tests/test-kmi-whitelist.cc: Update regexes in test.
> >
> >Signed-off-by: Giuliano Procida <gprocida@google.com>
> >---
> > include/abg-regex.h         |  6 ++++++
> > src/abg-regex.cc            | 28 ++++++++++++++++++++++++++++
> > src/abg-tools-utils.cc      | 10 +++-------
> > tests/test-kmi-whitelist.cc | 10 +++++-----
> > 4 files changed, 42 insertions(+), 12 deletions(-)
> >
> >diff --git a/include/abg-regex.h b/include/abg-regex.h
> >index 84c386a9..2f638ef2 100644
> >--- a/include/abg-regex.h
> >+++ b/include/abg-regex.h
> >@@ -27,6 +27,9 @@
> >
> > #include <regex.h>
> >
> >+#include <string>
> >+#include <vector>
> >+
> > #include "abg-cxx-compat.h"
> > #include "abg-sptr-utils.h"
> >
> >@@ -55,6 +58,9 @@ struct regex_t_deleter
> >   }
> > };//end struct regex_deleter
> >
> >+std::string
> >+generate_from_strings(const std::vector<std::string>& strs);
> >+
> > }// end namespace regex
> >
> > /// Specialization of sptr_utils::build_sptr for regex_t.
> >diff --git a/src/abg-regex.cc b/src/abg-regex.cc
> >index 13f5841d..79a89033 100644
> >--- a/src/abg-regex.cc
> >+++ b/src/abg-regex.cc
> >@@ -23,6 +23,7 @@
> > /// Some specialization for shared pointer utility templates.
> > ///
> >
> >+#include <sstream>
> > #include "abg-sptr-utils.h"
> > #include "abg-regex.h"
> >
> >@@ -52,4 +53,31 @@ regex::regex_t_sptr
> > sptr_utils::build_sptr<regex_t>()
> > {return sptr_utils::build_sptr(new regex_t);}
> >
> >+namespace regex
> >+{
> >+
> >+/// Generate a regex pattern equivalent to testing set membership.
> >+///
> >+/// A string will match the resulting pattern regex, if and only if it
> >+/// was present in the vector.
> >+///
> >+/// @param strs a vector of strings
> >+///
> >+/// @return a regex pattern
> >+std::string
> >+generate_from_strings(const std::vector<std::string>& strs)
> >+{
> >+  if (strs.empty())
> >+    return "^_^";
>
> I am not aware of this constant. Looks like an invalid regex. Can you
> document it? Or am I missing the joke? :-)
>
> Cheers,
> Matthias
>
> >+  std::ostringstream os;
> >+  std::vector<std::string>::const_iterator i = strs.begin();
> >+  os << "^(" << *i++;
> >+  while (i != strs.end())
> >+    os << "|" << *i++;
> >+  os << ")$";
> >+  return os.str();
> >+}
> >+
> >+}//end namespace regex
> >+
> > }//end namespace abigail
> >diff --git a/src/abg-tools-utils.cc b/src/abg-tools-utils.cc
> >index a06e8615..11486a21 100644
> >--- a/src/abg-tools-utils.cc
> >+++ b/src/abg-tools-utils.cc
> >@@ -61,6 +61,8 @@
> > #include "abg-dwarf-reader.h"
> > #include "abg-internal.h"
> > #include "abg-cxx-compat.h"
> >+#include "abg-regex.h"
> >+
> > // <headers defining libabigail's API go under here>
> > ABG_BEGIN_EXPORT_DECLARATIONS
> >
> >@@ -2002,13 +2004,7 @@ gen_suppr_spec_from_kernel_abi_whitelists
> >
> >       // Build a regular expression representing the union of all
> >       // the function and variable names expressed in the white list.
> >-      std::stringstream regex_ss;
> >-      regex_ss << "^";
> >-      std::copy(whitelisted_names.begin(), whitelisted_names.end(),
> >-              std::ostream_iterator<std::string>(regex_ss, "$|^"));
> >-      regex_ss.seekp(0, std::ios::end);
> >-      const std::string& regex =
> >-        regex_ss.str().substr(0, static_cast<size_t>(regex_ss.tellp()) - 2);
> >+      const std::string regex = regex::generate_from_strings(whitelisted_names);
> >
> >       // Build a suppression specification which *keeps* functions
> >       // whose ELF symbols match the regular expression contained
> >diff --git a/tests/test-kmi-whitelist.cc b/tests/test-kmi-whitelist.cc
> >index 2aa0f463..bcc5adee 100644
> >--- a/tests/test-kmi-whitelist.cc
> >+++ b/tests/test-kmi-whitelist.cc
> >@@ -96,7 +96,7 @@ TEST_CASE("WhitelistWithASingleEntry", "[whitelists]")
> >   suppressions_type suppr
> >       = gen_suppr_spec_from_kernel_abi_whitelists(abi_whitelist_paths);
> >   REQUIRE(!suppr.empty());
> >-  test_suppressions_are_consistent(suppr, "^test_symbol$");
> >+  test_suppressions_are_consistent(suppr, "^(test_symbol)$");
> > }
> >
> > TEST_CASE("WhitelistWithADuplicateEntry", "[whitelists]")
> >@@ -106,7 +106,7 @@ TEST_CASE("WhitelistWithADuplicateEntry", "[whitelists]")
> >   suppressions_type suppr
> >       = gen_suppr_spec_from_kernel_abi_whitelists(abi_whitelist_paths);
> >   REQUIRE(!suppr.empty());
> >-  test_suppressions_are_consistent(suppr, "^test_symbol$");
> >+  test_suppressions_are_consistent(suppr, "^(test_symbol)$");
> > }
> >
> > TEST_CASE("TwoWhitelists", "[whitelists]")
> >@@ -118,7 +118,7 @@ TEST_CASE("TwoWhitelists", "[whitelists]")
> >       gen_suppr_spec_from_kernel_abi_whitelists(abi_whitelist_paths);
> >   REQUIRE(!suppr.empty());
> >   test_suppressions_are_consistent(suppr,
> >-                                 "^test_another_symbol$|^test_symbol$");
> >+                                 "^(test_another_symbol|test_symbol)$");
> > }
> >
> > TEST_CASE("TwoWhitelistsWithDuplicates", "[whitelists]")
> >@@ -130,7 +130,7 @@ TEST_CASE("TwoWhitelistsWithDuplicates", "[whitelists]")
> >       = gen_suppr_spec_from_kernel_abi_whitelists(abi_whitelist_paths);
> >   REQUIRE(!suppr.empty());
> >   test_suppressions_are_consistent(suppr,
> >-                                 "^test_another_symbol$|^test_symbol$");
> >+                                 "^(test_another_symbol|test_symbol)$");
> > }
> >
> > TEST_CASE("WhitelistWithTwoSections", "[whitelists]")
> >@@ -140,5 +140,5 @@ TEST_CASE("WhitelistWithTwoSections", "[whitelists]")
> >   suppressions_type suppr
> >       = gen_suppr_spec_from_kernel_abi_whitelists(abi_whitelist_paths);
> >   REQUIRE(!suppr.empty());
> >-  test_suppressions_are_consistent(suppr, "^test_symbol1$|^test_symbol2$");
> >+  test_suppressions_are_consistent(suppr, "^(test_symbol1|test_symbol2)$");
> > }
> >--
> >2.26.2.303.gf8c07b1a785-goog
> >

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 19/21] Warn if user-supplied regexes fail to compile.
  2020-04-24  9:21   ` [PATCH v3 19/21] Warn if user-supplied regexes fail to compile Giuliano Procida
@ 2020-04-27 15:36     ` Matthias Maennich
  2020-05-01  8:49       ` Giuliano Procida
  0 siblings, 1 reply; 120+ messages in thread
From: Matthias Maennich @ 2020-04-27 15:36 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, dodji, kernel-team

On Fri, Apr 24, 2020 at 10:21:30AM +0100, Giuliano Procida wrote:
>There are not many calls to regex::compile in the code base. Two of
>these pass internally-generated regexes and are followed by assertions
>that the regexes compile.
>
>The remaining cases deal with user-supplied regexes. If these fail to
>compile they are currently silently ignored.
>
>This patch makes sure failures now result in warning messages on
>stderr, but otherwise does not change program behaviour.
>
>	* src/abg-corpus-priv.h
>	(corpus::exported_decls_builder::priv::compiled_regex_fns_suppress):
>	Emit a warning message if regex::compile fails.
>	(corpus::exported_decls_builder::priv::compiled_regex_fns_keep):
>	Ditto.
>	(corpus::exported_decls_builder::priv::compiled_regex_vars_suppress):
>	Ditto.
>	(corpus::exported_decls_builder::priv::compiled_regex_vars_keep):
>	Ditto.
>	* src/abg-suppression.cc (maybe_get_string_prop): Ditto.
>	(read_parameter_spec_from_string): Ditto.

Is there an option to fail and terminate if such a configuration issue
is detected?

But reporting the regex is already great as such!

Reviewed-by: Matthias Maennich <maennich@google.com>

Cheers,
Matthias

>
>Signed-off-by: Giuliano Procida <gprocida@google.com>
>---
> src/abg-corpus-priv.h  | 10 ++++++++++
> src/abg-suppression.cc |  4 ++++
> 2 files changed, 14 insertions(+)
>
>diff --git a/src/abg-corpus-priv.h b/src/abg-corpus-priv.h
>index 2618e2d0..a06a1a23 100644
>--- a/src/abg-corpus-priv.h
>+++ b/src/abg-corpus-priv.h
>@@ -29,6 +29,8 @@
> #ifndef __ABG_CORPUS_PRIV_H__
> #define __ABG_CORPUS_PRIV_H__
>
>+#include <iostream>
>+
> #include "abg-sptr-utils.h"
> #include "abg-regex.h"
> #include "abg-internal.h"
>@@ -126,6 +128,8 @@ public:
> 	    regex_t_sptr r = regex::compile(*i);
> 	    if (r)
> 	      compiled_fns_suppress_regexp_.push_back(r);
>+	    else
>+	      std::cerr << "warning: bad regex '" << *i << "'\n";
> 	  }
>       }
>     return compiled_fns_suppress_regexp_;
>@@ -148,6 +152,8 @@ public:
> 	    regex_t_sptr r = regex::compile(*i);
> 	    if (r)
> 	      compiled_fns_keep_regexps_.push_back(r);
>+	    else
>+	      std::cerr << "warning: bad regex '" << *i << "'\n";
> 	  }
>       }
>     return compiled_fns_keep_regexps_;
>@@ -170,6 +176,8 @@ public:
> 	    regex_t_sptr r = regex::compile(*i);
> 	    if (r)
> 	      compiled_vars_suppress_regexp_.push_back(r);
>+	    else
>+	      std::cerr << "warning: bad regex '" << *i << "'\n";
> 	  }
>       }
>     return compiled_vars_suppress_regexp_;
>@@ -192,6 +200,8 @@ public:
> 	    regex_t_sptr r = regex::compile(*i);
> 	    if (r)
> 	      compiled_vars_keep_regexps_.push_back(r);
>+	    else
>+	      std::cerr << "warning: bad regex '" << *i << "'\n";
> 	  }
>       }
>     return compiled_vars_keep_regexps_;
>diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
>index 8b3631fd..e4b6554c 100644
>--- a/src/abg-suppression.cc
>+++ b/src/abg-suppression.cc
>@@ -1640,6 +1640,8 @@ maybe_get_regex_prop(const ini::config::section& section,
>   if (!maybe_get_string_prop(section, name, str))
>     return false;
>   regex = regex::compile(str);
>+  if (!regex)
>+    std::cerr << "warning: bad regex '" << str << "'\n";
>   return true;
> }
>
>@@ -3157,6 +3159,8 @@ read_parameter_spec_from_string(const string& str)
>       if (is_regex)
> 	{
> 	  type_name_regex = regex::compile(type_name);
>+	  if (!type_name_regex)
>+	    std::cerr << "warning: bad regex '" << type_name << "'\n";
> 	  type_name.clear();
> 	}
>       function_suppression::parameter_spec* p =
>-- 
>2.26.2.303.gf8c07b1a785-goog
>

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 04/21] Escape names used in symbol whitelisting regex.
  2020-04-27 11:14     ` Matthias Maennich
@ 2020-04-27 15:37       ` Giuliano Procida
  0 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-27 15:37 UTC (permalink / raw)
  To: Matthias Maennich; +Cc: libabigail, Dodji Seketeli, kernel-team

Hi.

On Mon, 27 Apr 2020 at 12:14, Matthias Maennich <maennich@google.com> wrote:
>
> On Fri, Apr 24, 2020 at 10:21:15AM +0100, Giuliano Procida wrote:
> >There is the theoretical possibility that symbols may contain special
> >regex characters like '.' and '$'. This patch ensures all such
> >characters in symbol names are escaped before they are added to the
> >whitelisting regex.
> >
> >       * include/regex.h (escape): New string reference holder
> >       class. (operator<<): Declaration of std::ostream,
> >       regex::escape overload.
> >       * include/regex.cc (operator<<): New std::ostream,
> >       regex::escape overload that outputs regex-escaped strings.
> >       * src/abg-tools-utils.cc
> >       (gen_suppr_spec_from_kernel_abi_whitelists): Make sure any
> >       special regex characters in symbol names are escaped.
> >
> >Signed-off-by: Giuliano Procida <gprocida@google.com>
> >---
> > include/abg-regex.h | 10 ++++++++++
> > src/abg-regex.cc    | 27 +++++++++++++++++++++++++--
> > 2 files changed, 35 insertions(+), 2 deletions(-)
> >
> >diff --git a/include/abg-regex.h b/include/abg-regex.h
> >index 2f638ef2..59976794 100644
> >--- a/include/abg-regex.h
> >+++ b/include/abg-regex.h
> >@@ -58,6 +58,16 @@ struct regex_t_deleter
> >   }
> > };//end struct regex_deleter
> >
> >+/// A class to hold a reference to a string to regex escape.
> >+struct escape
> >+{
> >+  escape(const std::string& str) : ref(str) { }
> >+  const std::string& ref;
> >+};
> >+
> >+std::ostream&
> >+operator<<(std::ostream& os, const escape& esc);
> >+
> > std::string
> > generate_from_strings(const std::vector<std::string>& strs);
> >
> >diff --git a/src/abg-regex.cc b/src/abg-regex.cc
> >index 79a89033..90e4d144 100644
> >--- a/src/abg-regex.cc
> >+++ b/src/abg-regex.cc
> >@@ -24,6 +24,7 @@
> > ///
> >
> > #include <sstream>
> >+#include <ostream>
> Sort.

Done.

> > #include "abg-sptr-utils.h"
> > #include "abg-regex.h"
> >
> >@@ -56,6 +57,28 @@ sptr_utils::build_sptr<regex_t>()
> > namespace regex
> > {
> >
> >+/// Escape regex special charaters in input string.
> >+///
> >+/// @param os the output stream being written to.
> >+///
> >+/// @param esc the regex_escape object holding a reference to the string
> >+/// needing to be escaped.
> >+///
> >+/// @return the output stream.
> >+std::ostream&
> >+operator<<(std::ostream& os, const escape& esc)
> >+{
> >+  static const std::string specials = "^.[$()|*+?{\\";
>
> What about ']' and '}' ?

I stole my list from somewhere, possibly Wikipedia. To answer your
question, because ']' and '}' are only special when preceded by '['
and '{' respectively.

However, it can be confusing for humans, so I'll add them.

> Cheers,
> Matthias
>
> >+  const std::string str = esc.ref;
> >+  for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
> >+    {
> >+      if (specials.find(*i) != std::string::npos)
> >+        os << '\\';
> >+      os << *i;
> >+    }
> >+  return os;
> >+}
> >+
> > /// Generate a regex pattern equivalent to testing set membership.
> > ///
> > /// A string will match the resulting pattern regex, if and only if it
> >@@ -71,9 +94,9 @@ generate_from_strings(const std::vector<std::string>& strs)
> >     return "^_^";
> >   std::ostringstream os;
> >   std::vector<std::string>::const_iterator i = strs.begin();
> >-  os << "^(" << *i++;
> >+  os << "^(" << escape(*i++);
> >   while (i != strs.end())
> >-    os << "|" << *i++;
> >+    os << "|" << escape(*i++);
> >   os << ")$";
> >   return os.str();
> > }
> >--
> >2.26.2.303.gf8c07b1a785-goog
> >

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 20/21] Default construct suppression types.
  2020-04-24  9:21   ` [PATCH v3 20/21] Default construct suppression types Giuliano Procida
@ 2020-04-27 15:40     ` Matthias Maennich
  0 siblings, 0 replies; 120+ messages in thread
From: Matthias Maennich @ 2020-04-27 15:40 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, dodji, kernel-team

On Fri, Apr 24, 2020 at 10:21:31AM +0100, Giuliano Procida wrote:
>The current constructors for the various suppression types are not a
>good match for their current uses. Given that every member is
>effectively optional, default constructing these to a default
>unpopulated state makes the code simpler.
>
>There are no behavioural changes.
>
>Signed-off-by: Giuliano Procida <gprocida@google.com>

Reviewed-by: Matthias Maennich <maennich@google.com>

Cheers,
Matthias

>---
> include/abg-suppression.h  |  48 +------
> src/abg-suppression-priv.h |  28 ++--
> src/abg-suppression.cc     | 272 ++++++-------------------------------
> src/abg-tools-utils.cc     |   7 +-
> 4 files changed, 59 insertions(+), 296 deletions(-)
>
>diff --git a/include/abg-suppression.h b/include/abg-suppression.h
>index 02e77ea9..4c987a79 100644
>--- a/include/abg-suppression.h
>+++ b/include/abg-suppression.h
>@@ -56,17 +56,10 @@ class suppression_base
>   class priv;
>   typedef shared_ptr<priv> priv_sptr;
>
>-  // Forbid default constructor
>-  suppression_base();
>-
> public:
>   priv_sptr priv_;
>
>-  suppression_base(const string& label);
>-
>-  suppression_base(const string& label,
>-		   const regex::regex_t_sptr& file_name_regex,
>-		   const regex::regex_t_sptr& file_name_not_regex);
>+  suppression_base();
>
>   bool
>   get_drops_artifact_from_ir() const;
>@@ -153,9 +146,6 @@ class type_suppression : public suppression_base
>   class priv;
>   typedef shared_ptr<priv> priv_sptr;
>
>-  // Forbid this;
>-  type_suppression();
>-
> public:
>
>   priv_sptr priv_;
>@@ -201,9 +191,7 @@ public:
>   /// A convenience typedef for a vector of @ref insertion_range_sptr.
>   typedef vector<insertion_range_sptr> insertion_ranges;
>
>-  type_suppression(const string& label,
>-		   const regex::regex_t_sptr& type_name_regexp,
>-		   const string& type_name);
>+  type_suppression();
>
>   virtual ~type_suppression();
>
>@@ -458,17 +446,6 @@ public:
>
>   function_suppression();
>
>-  function_suppression(const string&			label,
>-		       const string&			name,
>-		       const regex::regex_t_sptr&	name_regex,
>-		       const string&			return_type_name,
>-		       const regex::regex_t_sptr&	return_type_regex,
>-		       parameter_specs_type&		parm_specs,
>-		       const string&			symbol_name,
>-		       const regex::regex_t_sptr&	symbol_name_regex,
>-		       const string&			symbol_version,
>-		       const regex::regex_t_sptr&	symbol_version_regex);
>-
>   virtual ~function_suppression();
>
>   static change_kind
>@@ -675,19 +652,7 @@ public:
>
>   priv_sptr priv_;
>
>-  variable_suppression(const string& label = "",
>-		       const string& name = "",
>-		       const regex::regex_t_sptr& name_regex =
>-			 regex::regex_t_sptr(),
>-		       const string& symbol_name = "",
>-		       const regex::regex_t_sptr& symbol_name_regex =
>-			 regex::regex_t_sptr(),
>-		       const string& symbol_version = "",
>-		       const regex::regex_t_sptr& symbol_version_regex =
>-			 regex::regex_t_sptr(),
>-		       const string& type_name = "",
>-		       const regex::regex_t_sptr& type_name_regex =
>-			 regex::regex_t_sptr());
>+  variable_suppression();
>
>   virtual ~variable_suppression();
>
>@@ -812,14 +777,9 @@ class file_suppression: public suppression_base
>
>   priv_sptr priv_;
>
>-  // Forbid this
>-  file_suppression();
>-
> public:
>
>-  file_suppression(const string& label,
>-		   const regex::regex_t_sptr& file_name_regex,
>-		   const regex::regex_t_sptr& file_name_not_regex);
>+  file_suppression();
>
>   virtual bool
>   suppresses_diff(const diff* diff) const;
>diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
>index 78f11e2f..7f98fb08 100644
>--- a/src/abg-suppression-priv.h
>+++ b/src/abg-suppression-priv.h
>@@ -236,23 +236,8 @@ struct variable_suppression::priv
>   string				type_name_;
>   regex::regex_t_sptr			type_name_regex_;
>
>-  priv(const string& name,
>-       const regex::regex_t_sptr& name_regex,
>-       const string& symbol_name,
>-       const regex::regex_t_sptr& symbol_name_regex,
>-       const string& symbol_version,
>-       const regex::regex_t_sptr& symbol_version_regex,
>-       const string& type_name,
>-       const regex::regex_t_sptr& type_name_regex)
>-    : change_kind_(ALL_CHANGE_KIND),
>-      name_(name),
>-      name_regex_(name_regex),
>-      symbol_name_(symbol_name),
>-      symbol_name_regex_(symbol_name_regex),
>-      symbol_version_(symbol_version),
>-      symbol_version_regex_(symbol_version_regex),
>-      type_name_(type_name),
>-      type_name_regex_(type_name_regex)
>+  priv()
>+    : change_kind_(ALL_CHANGE_KIND)
>   {}
> };// end class variable_supppression::priv
>
>@@ -300,9 +285,14 @@ class type_suppression::priv
>   regex::regex_t_sptr			source_location_to_keep_regex_;
>   mutable vector<string>		changed_enumerator_names_;
>
>-  priv();
>-
> public:
>+  priv()
>+    : consider_type_kind_(false),
>+      type_kind_(CLASS_TYPE_KIND),
>+      consider_reach_kind_(false),
>+      reach_kind_(DIRECT_REACH_KIND)
>+  {}
>+
>   priv(const regex::regex_t_sptr&	type_name_regexp,
>        const string&			type_name,
>        bool				consider_type_kind,
>diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
>index e4b6554c..7dc3b2d1 100644
>--- a/src/abg-suppression.cc
>+++ b/src/abg-suppression.cc
>@@ -53,33 +53,11 @@ using regex::regex_t_sptr;
>
> // <suppression_base stuff>
>
>-/// Constructor for @ref suppression_base
>-///
>-/// @param a label for the suppression.  This represents just a
>-/// comment.
>-suppression_base::suppression_base(const string& label)
>-  : priv_(new priv(label))
>+/// Default constructor for @ref suppression_base
>+suppression_base::suppression_base()
>+  : priv_(new priv())
> {}
>
>-/// Constructor for @ref suppression_base
>-///
>-/// @param a label for the suppression.  This represents just a
>-/// comment.
>-///
>-/// @param file_name_regex the regular expression that denotes the
>-/// file name to match.
>-///
>-/// @param file_name_not_regex the regular expression that denotes
>-/// the file name to *NOT* match.
>-suppression_base::suppression_base(const string& label,
>-				   const regex_t_sptr& file_name_regex,
>-				   const regex_t_sptr& file_name_not_regex)
>-  : priv_(new priv(label,
>-		   file_name_regex,
>-		   file_name_not_regex))
>-{
>-}
>-
> /// Tests if the current suppression specification is to avoid adding
> /// the matched ABI artifact to the internal representation or not.
> ///
>@@ -453,32 +431,9 @@ read_suppressions(const string& file_path,
>
> // <type_suppression stuff>
>
>-/// Constructor for @ref type_suppression.
>-///
>-/// @param label the label of the suppression.  This is just a free
>-/// form comment explaining what the suppression is about.
>-///
>-/// @param type_name_regexp the regular expression describing the
>-/// types about which diff reports should be suppressed.  If it's a
>-/// null shared pointer, the parameter is ignored.
>-///
>-/// @param type_name the name of the type about which diff reports
>-/// should be suppressed.  If it's an empty string, the parameter is
>-/// ignored.
>-///
>-/// Note that parameter @p type_name_regexp and @p type_name_regexp
>-/// should not necessarily be populated.  It usually is either one or
>-/// the other that the user wants.
>-type_suppression::type_suppression(const string& label,
>-				   const regex_t_sptr& type_name_regexp,
>-				   const string& type_name)
>-  : suppression_base(label),
>-    priv_(new priv(type_name_regexp,
>-		   type_name,
>-		   /*consider_type_kind=*/false,
>-		   /*type_kind=*/CLASS_TYPE_KIND,
>-		   /*consider_reach_kind=*/false,
>-		   /*reach_kind=*/DIRECT_REACH_KIND))
>+/// Default constructor for @ref type_suppression.
>+type_suppression::type_suppression()
>+  : suppression_base(), priv_(new priv)
> {}
>
> type_suppression::~type_suppression()
>@@ -1912,7 +1867,10 @@ read_type_suppression(const ini::config::section& section)
> 	changed_enumerator_names.push_back(p->get_value()->as_string());
>     }
>
>-  result.reset(new type_suppression(label_str, name_regex, name_str));
>+  result.reset(new type_suppression());
>+  result->set_label(label_str);
>+  result->set_type_name_regex(name_regex);
>+  result->set_type_name(name_str);
>
>   if (consider_type_kind)
>     {
>@@ -2049,77 +2007,7 @@ function_suppression::parameter_spec::set_parameter_type_name_regex
> /// specified by using the various accessors of the @ref
> /// function_suppression type.
> function_suppression::function_suppression()
>-  :  suppression_base(/*label=*/""), priv_(new priv)
>-{}
>-
>-/// Constructor for the @ref function_suppression type.
>-///
>-/// @param label an informative text string that the evalution code
>-/// might use to designate this function suppression specification in
>-/// error messages.  This parameter might be empty, in which case it's
>-/// ignored at evaluation time.
>-///
>-/// @param the name of the function the user wants the current
>-/// specification to designate.  This parameter might be empty, in
>-/// which case it's ignored at evaluation time.
>-///
>-/// @param nr if @p name is empty this parameter is a regular
>-/// expression for a family of names of functions the user wants the
>-/// current specification to designate.  If @p name is not empty, this
>-/// parameter is ignored at specification evaluation time.  This
>-/// parameter might be empty, in which case it's ignored at evaluation
>-/// time.
>-///
>-/// @param ret_tn the name of the return type of the function the user
>-/// wants this specification to designate.  This parameter might be
>-/// empty, in which case it's ignored at evaluation time.
>-///
>-/// @param ret_tr if @p ret_tn is empty, then this is a regular
>-/// expression for a family of return type names for functions the
>-/// user wants the current specification to designate.  If @p ret_tn
>-/// is not empty, then this parameter is ignored at specification
>-/// evaluation time.  This parameter might be empty, in which case
>-/// it's ignored at evaluation time.
>-///
>-/// @param ps a vector of parameter specifications to specify
>-/// properties of the parameters of the functions the user wants this
>-/// specification to designate.  This parameter might be empty, in
>-/// which case it's ignored at evaluation time.
>-///
>-/// @param sym_n the name of symbol of the function the user wants
>-/// this specification to designate.  This parameter might be empty,
>-/// in which case it's ignored at evaluation time.
>-///
>-/// @param sym_nr if the parameter @p sym_n is empty, then this
>-/// parameter is a regular expression for a family of names of symbols
>-/// of functions the user wants this specification to designate.  If
>-/// the parameter @p sym_n is not empty, then this parameter is
>-/// ignored at specification evaluation time.  This parameter might be
>-/// empty, in which case it's ignored at evaluation time.
>-///
>-/// @param sym_v the name of the version of the symbol of the function
>-/// the user wants this specification to designate.  This parameter
>-/// might be empty, in which case it's ignored at evaluation time.
>-///
>-/// @param sym_vr if the parameter @p sym_v is empty, then this
>-/// parameter is a regular expression for a family of versions of
>-/// symbols of functions the user wants the current specification to
>-/// designate.  If the parameter @p sym_v is non empty, then this
>-/// parameter is ignored.  This parameter might be empty, in which
>-/// case it's ignored at evaluation time.
>-function_suppression::function_suppression(const string&		label,
>-					   const string&		name,
>-					   const regex_t_sptr&		nr,
>-					   const string&		ret_tn,
>-					   const regex_t_sptr&		ret_tr,
>-					   parameter_specs_type&	ps,
>-					   const string&		sym_n,
>-					   const regex_t_sptr&		sym_nr,
>-					   const string&		sym_v,
>-					   const regex_t_sptr&		sym_vr)
>-  : suppression_base(label),
>-    priv_(new priv(name, nr, ret_tn, ret_tr, ps,
>-		   sym_n, sym_nr, sym_v, sym_vr))
>+  : suppression_base(), priv_(new priv)
> {}
>
> function_suppression::~function_suppression()
>@@ -3257,16 +3145,17 @@ read_function_suppression(const ini::config::section& section)
> 	  parms.push_back(parm);
>       }
>
>-  result.reset(new function_suppression(label_str,
>-					name,
>-					name_regex,
>-					return_type_name,
>-					return_type_regex,
>-					parms,
>-					sym_name,
>-					sym_name_regex,
>-					sym_version,
>-					sym_ver_regex));
>+  result.reset(new function_suppression());
>+  result->set_label(label_str);
>+  result->set_name(name);
>+  result->set_name_regex(name_regex);
>+  result->set_return_type_name(return_type_name);
>+  result->set_return_type_regex(return_type_regex);
>+  result->set_parameter_specs(parms);
>+  result->set_symbol_name(sym_name);
>+  result->set_symbol_name_regex(sym_name_regex);
>+  result->set_symbol_version(sym_version);
>+  result->set_symbol_version_regex(sym_ver_regex);
>
>   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
>       && (!name.empty()
>@@ -3310,71 +3199,13 @@ read_function_suppression(const ini::config::section& section)
>
> // <variable_suppression stuff>
>
>-/// Constructor for the @ref variable_suppression type.
>-///
>-/// @param label an informative text string that the evalution code
>-/// might use to designate this variable suppression specification in
>-/// error messages.  This parameter might be empty, in which case it's
>-/// ignored at evaluation time.
>-///
>-/// @param name the name of the variable the user wants the current
>-/// specification to designate.  This parameter might be empty, in
>-/// which case it's ignored at evaluation time.
>-///
>-/// @param name_regex if @p name is empty, this parameter is a
>-/// regular expression for a family of names of variables the user
>-/// wants the current specification to designate.  If @p name is not
>-/// empty, then this parameter is ignored at evaluation time.  This
>-/// parameter might be empty, in which case it's ignored at evaluation
>-/// time.
>-///
>-/// @param symbol_name the name of the symbol of the variable the user
>-/// wants the current specification to designate.  This parameter
>-/// might be empty, in which case it's ignored at evaluation time.
>-///
>-/// @param symbol_name_str if @p symbol_name is empty, this parameter
>-/// is a regular expression for a family of names of symbols of
>-/// variables the user wants the current specification to designate.
>-/// If @p symbol_name is not empty, then this parameter is ignored at
>-/// evaluation time.  This parameter might be empty, in which case
>-/// it's ignored at evaluation time.
>-///
>-/// @param symbol_version the version of the symbol of the variable
>-/// the user wants the current specification to designate.  This
>-/// parameter might be empty, in which case it's ignored at evaluation
>-/// time.
>-///
>-/// @param symbol_version_regex if @p symbol_version is empty, then
>-/// this parameter is a regular expression for a family of versions of
>-/// symbol for the variables the user wants the current specification
>-/// to designate.  If @p symbol_version is not empty, then this
>-/// parameter is ignored at evaluation time.  This parameter might be
>-/// empty, in which case it's ignored at evaluation time.
>-///
>-/// @param type_name the name of the type of the variable the user
>-/// wants the current specification to designate.  This parameter
>-/// might be empty, in which case it's ignored at evaluation time.
>+/// Default constructor for the @ref variable_suppression type.
> ///
>-/// @param type_name_regex if @p type_name is empty, then this
>-/// parameter is a regular expression for a family of type names of
>-/// variables the user wants the current specification to designate.
>-/// If @p type_name is not empty, then this parameter is ignored at
>-/// evluation time.  This parameter might be empty, in which case it's
>-/// ignored at evaluation time.
>-variable_suppression::variable_suppression(const string& label,
>-					   const string& name,
>-					   const regex_t_sptr& name_regex,
>-					   const string& symbol_name,
>-					   const regex_t_sptr& symbol_name_regex,
>-					   const string& symbol_version,
>-					   const regex_t_sptr& symbol_version_regex,
>-					   const string& type_name,
>-					   const regex_t_sptr& type_name_regex)
>-  : suppression_base(label),
>-    priv_(new priv(name, name_regex,
>-		   symbol_name, symbol_name_regex,
>-		   symbol_version, symbol_version_regex,
>-		   type_name, type_name_regex))
>+/// It defines no suppression for now.  Suppressions have to be
>+/// specified by using the various accessors of the @ref
>+/// variable_suppression type.
>+variable_suppression::variable_suppression()
>+  : suppression_base(), priv_(new priv)
> {}
>
> /// Virtual destructor for the @erf variable_suppression type.
>@@ -4031,15 +3862,16 @@ read_variable_suppression(const ini::config::section& section)
>   regex_t_sptr type_name_regex;
>   maybe_get_regex_prop(section, "type_name_regexp", type_name_regex);
>
>-  result.reset(new variable_suppression(label_str,
>-					name_str,
>-					name_regex,
>-					symbol_name,
>-					symbol_name_regex,
>-					symbol_version,
>-					symbol_version_regex,
>-					type_name_str,
>-					type_name_regex));
>+  result.reset(new variable_suppression);
>+  result->set_label(label_str);
>+  result->set_name(name_str);
>+  result->set_name_regex(name_regex);
>+  result->set_symbol_name(symbol_name);
>+  result->set_symbol_name_regex(symbol_name_regex);
>+  result->set_symbol_version(symbol_version);
>+  result->set_symbol_version_regex(symbol_version_regex);
>+  result->set_type_name(type_name_str);
>+  result->set_type_name_regex(type_name_regex);
>
>   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
>       && (!name_str.empty()
>@@ -4079,25 +3911,8 @@ read_variable_suppression(const ini::config::section& section)
>
> // <file_suppression stuff>
>
>-/// Constructor for the the @ref file_suppression type.
>-///
>-/// @param label the label of the suppression directive.
>-///
>-/// @param fname_regex the regular expression that
>-/// designates the file name that instances of @ref file_suppression
>-/// should match.
>-///
>-/// @param fname_not_regex the regular expression that
>-/// designates the file name that instances of @ref file_suppression
>-/// shoult *NOT* match.  In other words, this file_suppression should
>-/// be activated if its file name does not match the regular
>-/// expression @p fname_not_regex.
>-file_suppression::file_suppression(const string& label,
>-				   const regex_t_sptr& fname_regex,
>-				   const regex_t_sptr& fname_not_regex)
>-  : suppression_base(label,
>-		     fname_regex,
>-		     fname_not_regex)
>+/// Default constructor for the the @ref file_suppression type.
>+file_suppression::file_suppression()
> {}
>
> /// Test if instances of this @ref file_suppression suppresses a
>@@ -4184,9 +3999,10 @@ read_file_suppression(const ini::config::section& section)
>   regex_t_sptr soname_not_regex;
>   maybe_get_regex_prop(section, "soname_not_regexp", soname_not_regex);
>
>-  result.reset(new file_suppression(label_str,
>-				    file_name_regex,
>-				    file_name_not_regex));
>+  result.reset(new file_suppression);
>+  result->set_label(label_str);
>+  result->set_file_name_regex(file_name_regex);
>+  result->set_file_name_not_regex(file_name_not_regex);
>
>   if (soname_regex)
>     {
>diff --git a/src/abg-tools-utils.cc b/src/abg-tools-utils.cc
>index 3af9fc49..4cef400d 100644
>--- a/src/abg-tools-utils.cc
>+++ b/src/abg-tools-utils.cc
>@@ -1810,11 +1810,8 @@ handle_file_entry(const string& file_path,
> {
>   if (!suppr)
>     {
>-      suppr.reset(
>-	new type_suppression(get_private_types_suppr_spec_label(),
>-			     /*type_name_regexp=*/regex::regex_t_sptr(),
>-			     /*type_name=*/""));
>-
>+      suppr.reset(new type_suppression());
>+      suppr->set_label(get_private_types_suppr_spec_label());
>       // Types that are defined in system headers are usually
>       // OK to be considered as public types.
>       regex::regex_t_sptr headers_regex = regex::compile("^/usr/include/");
>-- 
>2.26.2.303.gf8c07b1a785-goog
>

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 21/21] Remove unused suppression type priv constructors.
  2020-04-24  9:21   ` [PATCH v3 21/21] Remove unused suppression type priv constructors Giuliano Procida
@ 2020-04-27 15:41     ` Matthias Maennich
  0 siblings, 0 replies; 120+ messages in thread
From: Matthias Maennich @ 2020-04-27 15:41 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, dodji, kernel-team

On Fri, Apr 24, 2020 at 10:21:32AM +0100, Giuliano Procida wrote:
>Following on from the previous commit, many constructors for the
>various priv types are now unused. This patch drops them.
>
>There are no behavioural changes.
>
>	* src/abg-suppression-priv.h (suppression_base::priv) Drop all
>	but default constructor.
>	(function_suppression::parameter_spec::priv): Drop all but
>	3-argument constructor. (function_suppression::priv): Drop all
>	but default constructor. (type_suppression::priv): Drop all
>	but default constructor.
>
>Signed-off-by: Giuliano Procida <gprocida@google.com>

Reviewed-by: Matthias Maennich <maennich@google.com>

Cheers,
Matthias

>---
> src/abg-suppression-priv.h | 60 --------------------------------------
> 1 file changed, 60 deletions(-)
>
>diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
>index 7f98fb08..97c163fe 100644
>--- a/src/abg-suppression-priv.h
>+++ b/src/abg-suppression-priv.h
>@@ -58,22 +58,6 @@ public:
>       drops_artifact_()
>   {}
>
>-  priv(const string& label)
>-    : is_artificial_(),
>-      drops_artifact_(),
>-      label_(label)
>-  {}
>-
>-  priv(const string& label,
>-       const regex::regex_t_sptr& file_name_regex,
>-       const regex::regex_t_sptr& file_name_not_regex)
>-    : is_artificial_(),
>-      drops_artifact_(),
>-      label_(label),
>-      file_name_regex_(file_name_regex),
>-      file_name_not_regex_(file_name_not_regex)
>-  {}
>-
>   friend class suppression_base;
> }; // end class suppression_base::priv
>
>@@ -90,14 +74,6 @@ class function_suppression::parameter_spec::priv
>   string				type_name_;
>   regex::regex_t_sptr			type_name_regex_;
>
>-  priv()
>-    : index_()
>-  {}
>-
>-  priv(size_t i, const string& tn)
>-    : index_(i), type_name_(tn)
>-  {}
>-
>   priv(size_t i, const string& tn, const regex::regex_t_sptr& tn_regex)
>     : index_(i), type_name_(tn), type_name_regex_(tn_regex)
>   {}
>@@ -128,28 +104,6 @@ struct function_suppression::priv
>     change_kind_(ALL_CHANGE_KIND),
>     allow_other_aliases_(true)
>   {}
>-
>-  priv(const string&			name,
>-       const regex::regex_t_sptr&	name_regex,
>-       const string&			return_type_name,
>-       const regex::regex_t_sptr&	return_type_regex,
>-       const parameter_specs_type&	parm_specs,
>-       const string&			symbol_name,
>-       const regex::regex_t_sptr&	symbol_name_regex,
>-       const string&			symbol_version,
>-       const regex::regex_t_sptr&	symbol_version_regex)
>-    : change_kind_(ALL_CHANGE_KIND),
>-      name_(name),
>-      name_regex_(name_regex),
>-      return_type_name_(return_type_name),
>-      return_type_regex_(return_type_regex),
>-      parm_specs_(parm_specs),
>-      symbol_name_(symbol_name),
>-      symbol_name_regex_(symbol_name_regex),
>-      symbol_version_(symbol_version),
>-      symbol_version_regex_(symbol_version_regex),
>-      allow_other_aliases_(true)
>-  {}
> }; // end class function_suppression::priv
>
> bool
>@@ -293,20 +247,6 @@ public:
>       reach_kind_(DIRECT_REACH_KIND)
>   {}
>
>-  priv(const regex::regex_t_sptr&	type_name_regexp,
>-       const string&			type_name,
>-       bool				consider_type_kind,
>-       type_suppression::type_kind	type_kind,
>-       bool				consider_reach_kind,
>-       type_suppression::reach_kind	reach_kind)
>-    : type_name_regex_(type_name_regexp),
>-      type_name_(type_name),
>-      consider_type_kind_(consider_type_kind),
>-      type_kind_(type_kind),
>-      consider_reach_kind_(consider_reach_kind),
>-      reach_kind_(reach_kind)
>-  {}
>-
>   friend class type_suppression;
> }; // class type_suppression::priv
>
>-- 
>2.26.2.303.gf8c07b1a785-goog
>

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 08/21] Use regex::compile wrapper instead of regcomp.
  2020-04-27 11:34     ` Matthias Maennich
@ 2020-04-27 16:01       ` Giuliano Procida
  0 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-27 16:01 UTC (permalink / raw)
  To: Matthias Maennich; +Cc: libabigail, Dodji Seketeli, kernel-team

Hi.

On Mon, 27 Apr 2020 at 12:34, Matthias Maennich <maennich@google.com> wrote:
>
> On Fri, Apr 24, 2020 at 10:21:19AM +0100, Giuliano Procida wrote:
> >This patch eliminates all calls to regcomp except that by
> >regex::compile itself.
> >
> >       * src/abg-corpus-priv.h: Mechanically substitute use of
> >       regcomp with regex::compile wrapper.
> >       * src/abg-suppression-priv.h: Ditto.
> >
> >There are no behavioural changes.
> >
> >Signed-off-by: Giuliano Procida <gprocida@google.com>
> >---
> > src/abg-corpus-priv.h      |  16 +--
> > src/abg-suppression-priv.h | 198 ++++++-------------------------------
> > 2 files changed, 38 insertions(+), 176 deletions(-)
> >
> >diff --git a/src/abg-corpus-priv.h b/src/abg-corpus-priv.h
> >index e65f7c8f..544fac54 100644
> >--- a/src/abg-corpus-priv.h
> >+++ b/src/abg-corpus-priv.h
> >@@ -123,8 +123,8 @@ public:
> >            i != fns_suppress_regexps_.end();
> >            ++i)
> >         {
> >-          regex_t_sptr r = sptr_utils::build_sptr(new regex_t);
> >-          if (regcomp(r.get(), i->c_str(), REG_EXTENDED) == 0)
> >+          regex_t_sptr r = regex::compile(*i);
> >+          if (r)
> >             compiled_fns_suppress_regexp_.push_back(r);
> >         }
> >       }
> >@@ -145,8 +145,8 @@ public:
> >            i != fns_keep_regexps_.end();
> >            ++i)
> >         {
> >-          regex_t_sptr r = sptr_utils::build_sptr(new regex_t);
> >-          if (regcomp(r.get(), i->c_str(), REG_EXTENDED) == 0)
> >+          regex_t_sptr r = regex::compile(*i);
> >+          if (r)
> >             compiled_fns_keep_regexps_.push_back(r);
> >         }
> >       }
> >@@ -167,8 +167,8 @@ public:
> >            i != vars_suppress_regexps_.end();
> >            ++i)
> >         {
> >-          regex_t_sptr r = sptr_utils::build_sptr(new regex_t);
> >-          if (regcomp(r.get(), i->c_str(), REG_EXTENDED) == 0)
> >+          regex_t_sptr r = regex::compile(*i);
> >+          if (r)
> >             compiled_vars_suppress_regexp_.push_back(r);
> >         }
> >       }
> >@@ -189,8 +189,8 @@ public:
> >            i != vars_keep_regexps_.end();
> >            ++i)
> >         {
> >-          regex_t_sptr r = sptr_utils::build_sptr(new regex_t);
> >-          if (regcomp(r.get(), i->c_str(), REG_EXTENDED) == 0)
> >+          regex_t_sptr r = regex::compile(*i);
> >+          if (r)
> >             compiled_vars_keep_regexps_.push_back(r);
> >         }
> >       }
> >diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
> >index c37ceff6..4959cdbb 100644
> >--- a/src/abg-suppression-priv.h
> >+++ b/src/abg-suppression-priv.h
> >@@ -91,17 +91,8 @@ public:
> >   const regex::regex_t_sptr&
> >   get_file_name_regex() const
> >   {
> >-    if (!file_name_regex_)
> >-      {
> >-      if (!file_name_regex_str_.empty())
> >-        {
> >-          regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> >-          if (regcomp(r.get(),
> >-                      file_name_regex_str_.c_str(),
> >-                      REG_EXTENDED) == 0)
> >-            file_name_regex_ = r;
> >-        }
> >-      }
> >+    if (!file_name_regex_ && !file_name_regex_str_.empty())
>
> Those made me thinkg whether regex::compile should return NULL for empty
> regex strings? Not necessarily something to address in this change.

This code changes again in later patches. We get to the point where we
could distinguish empty regexes from missing regexes.

If I were doing this from scratch, I'd make empty regexes consistently
mean "match all strings". At the moment they always mean "regex
absent" due to the way the parsing works, probably. There is no error
handling at the moment, but we could explicitly choose to make empty
regexes a parse error later.

> Reviewed-by: Matthias Maennich <maennich@google.com>
>
> Cheers,
> Matthias
>
> >+      file_name_regex_ = regex::compile(file_name_regex_str_);
> >     return file_name_regex_;
> >   }
> >
> >@@ -116,17 +107,8 @@ public:
> >   const regex::regex_t_sptr&
> >   get_file_name_not_regex() const
> >   {
> >-    if (!file_name_not_regex_)
> >-      {
> >-      if (!file_name_not_regex_str_.empty())
> >-        {
> >-          regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> >-          if (regcomp(r.get(),
> >-                      file_name_not_regex_str_.c_str(),
> >-                      REG_EXTENDED) == 0)
> >-            file_name_not_regex_ = r;
> >-        }
> >-      }
> >+    if (!file_name_not_regex_ && !file_name_not_regex_str_.empty())
> >+      file_name_not_regex_ = regex::compile(file_name_not_regex_str_);
> >     return file_name_not_regex_;
> >   }
> >
> >@@ -141,17 +123,8 @@ public:
> >   const regex::regex_t_sptr&
> >   get_soname_regex() const
> >   {
> >-    if (!soname_regex_)
> >-      {
> >-      if (!soname_regex_str_.empty())
> >-        {
> >-          regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> >-          if (regcomp(r.get(),
> >-                      soname_regex_str_.c_str(),
> >-                      REG_EXTENDED) == 0)
> >-            soname_regex_ = r;
> >-        }
> >-      }
> >+    if (!soname_regex_ && !soname_regex_str_.empty())
> >+      soname_regex_ = regex::compile(soname_regex_str_);
> >     return soname_regex_;
> >   }
> >
> >@@ -166,17 +139,8 @@ public:
> >   const regex::regex_t_sptr&
> >   get_soname_not_regex() const
> >   {
> >-    if (!soname_not_regex_)
> >-      {
> >-      if (!soname_not_regex_str_.empty())
> >-        {
> >-          regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> >-          if (regcomp(r.get(),
> >-                      soname_not_regex_str_.c_str(),
> >-                      REG_EXTENDED) == 0)
> >-            soname_not_regex_ = r;
> >-        }
> >-      }
> >+    if (!soname_not_regex_ && !soname_not_regex_str_.empty())
> >+      soname_not_regex_ = regex::compile(soname_not_regex_str_);
> >     return soname_not_regex_;
> >   }
> >
> >@@ -282,13 +246,7 @@ class function_suppression::parameter_spec::priv
> >   get_type_name_regex() const
> >   {
> >     if (!type_name_regex_ && !type_name_regex_str_.empty())
> >-      {
> >-      regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> >-      if (regcomp(r.get(),
> >-                  type_name_regex_str_.c_str(),
> >-                  REG_EXTENDED) == 0)
> >-        type_name_regex_ = r;
> >-      }
> >+      type_name_regex_ = regex::compile(type_name_regex_str_);
> >     return type_name_regex_;
> >   }
> > }; // end class function_suppression::parameter_spec::priv
> >@@ -361,13 +319,7 @@ struct function_suppression::priv
> >   get_name_regex() const
> >   {
> >     if (!name_regex_ && !name_regex_str_.empty())
> >-      {
> >-      regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> >-      if (regcomp(r.get(),
> >-                  name_regex_str_.c_str(),
> >-                  REG_EXTENDED) == 0)
> >-        name_regex_ = r;
> >-      }
> >+      name_regex_ = regex::compile(name_regex_str_);
> >     return name_regex_;
> >   }
> >
> >@@ -384,13 +336,7 @@ struct function_suppression::priv
> >   get_name_not_regex() const
> >   {
> >     if (!name_not_regex_ && !name_not_regex_str_.empty())
> >-      {
> >-      regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> >-      if (regcomp(r.get(),
> >-                  name_not_regex_str_.c_str(),
> >-                  REG_EXTENDED) == 0)
> >-        name_not_regex_ = r;
> >-      }
> >+      name_not_regex_ = regex::compile(name_not_regex_str_);
> >     return name_not_regex_;
> >   }
> >
> >@@ -407,13 +353,7 @@ struct function_suppression::priv
> >   get_return_type_regex() const
> >   {
> >     if (!return_type_regex_ && !return_type_regex_str_.empty())
> >-      {
> >-      regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> >-      if (regcomp(r.get(),
> >-                  return_type_regex_str_.c_str(),
> >-                  REG_EXTENDED) == 0)
> >-        return_type_regex_ = r;
> >-      }
> >+      return_type_regex_ = regex::compile(return_type_regex_str_);
> >     return return_type_regex_;
> >   }
> >
> >@@ -430,13 +370,7 @@ struct function_suppression::priv
> >   get_symbol_name_regex() const
> >   {
> >     if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
> >-      {
> >-      regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> >-      if (regcomp(r.get(),
> >-                  symbol_name_regex_str_.c_str(),
> >-                  REG_EXTENDED) == 0)
> >-        symbol_name_regex_ = r;
> >-      }
> >+      symbol_name_regex_ = regex::compile(symbol_name_regex_str_);
> >     return symbol_name_regex_;
> >   }
> >
> >@@ -453,13 +387,7 @@ struct function_suppression::priv
> >   get_symbol_name_not_regex() const
> >   {
> >     if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
> >-      {
> >-      regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> >-      if (regcomp(r.get(),
> >-                  symbol_name_not_regex_str_.c_str(),
> >-                  REG_EXTENDED) == 0)
> >-        symbol_name_not_regex_ = r;
> >-      }
> >+      symbol_name_not_regex_ = regex::compile(symbol_name_not_regex_str_);
> >     return symbol_name_not_regex_;
> >   }
> >
> >@@ -475,14 +403,8 @@ struct function_suppression::priv
> >   const regex::regex_t_sptr
> >   get_symbol_version_regex() const
> >   {
> >-    if (!symbol_version_regex_ && ! symbol_version_regex_str_.empty())
> >-      {
> >-      regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> >-      if (regcomp(r.get(),
> >-                  symbol_version_regex_str_.c_str(),
> >-                  REG_EXTENDED) == 0)
> >-        symbol_version_regex_ = r;
> >-      }
> >+    if (!symbol_version_regex_ && !symbol_version_regex_str_.empty())
> >+      symbol_version_regex_ = regex::compile(symbol_version_regex_str_);
> >     return symbol_version_regex_;
> >   }
> > }; // end class function_suppression::priv
> >@@ -609,13 +531,7 @@ struct variable_suppression::priv
> >   get_name_regex() const
> >   {
> >     if (!name_regex_ && !name_regex_str_.empty())
> >-      {
> >-      regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> >-      if (regcomp(r.get(),
> >-                  name_regex_str_.c_str(),
> >-                  REG_EXTENDED) == 0)
> >-        name_regex_ = r;
> >-      }
> >+      name_regex_ = regex::compile(name_regex_str_);
> >     return name_regex_;
> >   }
> >
> >@@ -632,13 +548,7 @@ struct variable_suppression::priv
> >   get_name_not_regex() const
> >   {
> >     if (!name_not_regex_ && !name_not_regex_str_.empty())
> >-      {
> >-      regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> >-      if (regcomp(r.get(),
> >-                  name_not_regex_str_.c_str(),
> >-                  REG_EXTENDED) == 0)
> >-        name_not_regex_ = r;
> >-      }
> >+      name_not_regex_ = regex::compile(name_not_regex_str_);
> >     return name_not_regex_;
> >   }
> >
> >@@ -655,13 +565,7 @@ struct variable_suppression::priv
> >   get_symbol_name_regex() const
> >   {
> >     if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
> >-      {
> >-      regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> >-      if (regcomp(r.get(),
> >-                  symbol_name_regex_str_.c_str(),
> >-                  REG_EXTENDED) == 0)
> >-        symbol_name_regex_ = r;
> >-      }
> >+      symbol_name_regex_ = regex::compile(symbol_name_regex_str_);
> >     return symbol_name_regex_;
> >   }
> >
> >@@ -678,12 +582,7 @@ struct variable_suppression::priv
> >   get_symbol_name_not_regex() const
> >   {
> >     if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
> >-      {
> >-      regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> >-      if (regcomp(r.get(), symbol_name_not_regex_str_.c_str(),
> >-                  REG_EXTENDED) == 0)
> >-        symbol_name_not_regex_ = r;
> >-      }
> >+      symbol_name_not_regex_ = regex::compile(symbol_name_not_regex_str_);
> >     return symbol_name_not_regex_;
> >   }
> >
> >@@ -700,13 +599,7 @@ struct variable_suppression::priv
> >   get_symbol_version_regex()  const
> >   {
> >     if (!symbol_version_regex_ && !symbol_version_regex_str_.empty())
> >-      {
> >-      regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> >-      if (regcomp(r.get(),
> >-                  symbol_version_regex_str_.c_str(),
> >-                  REG_EXTENDED) == 0)
> >-        symbol_version_regex_ = r;
> >-      }
> >+      symbol_version_regex_ = regex::compile(symbol_version_regex_str_);
> >     return symbol_version_regex_;
> >   }
> >
> >@@ -723,13 +616,7 @@ struct variable_suppression::priv
> >   get_type_name_regex() const
> >   {
> >     if (!type_name_regex_ && !type_name_regex_str_.empty())
> >-      {
> >-      regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> >-      if (regcomp(r.get(),
> >-                  type_name_regex_str_.c_str(),
> >-                  REG_EXTENDED) == 0)
> >-        type_name_regex_ = r;
> >-      }
> >+      type_name_regex_ = regex::compile(type_name_regex_str_);
> >     return type_name_regex_;
> >   }
> > };// end class variable_supppression::priv
> >@@ -809,17 +696,8 @@ public:
> >   const regex::regex_t_sptr
> >   get_type_name_regex() const
> >   {
> >-    if (!type_name_regex_)
> >-      {
> >-      if (!type_name_regex_str_.empty())
> >-        {
> >-          regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> >-          if (regcomp(r.get(),
> >-                      type_name_regex_str_.c_str(),
> >-                      REG_EXTENDED) == 0)
> >-            type_name_regex_ = r;
> >-        }
> >-      }
> >+    if (!type_name_regex_ && !type_name_regex_str_.empty())
> >+      type_name_regex_ = regex::compile(type_name_regex_str_);
> >     return type_name_regex_;
> >   }
> >
> >@@ -841,17 +719,8 @@ public:
> >   const regex::regex_t_sptr
> >   get_type_name_not_regex() const
> >   {
> >-    if (!type_name_not_regex_)
> >-      {
> >-      if (!type_name_not_regex_str_.empty())
> >-        {
> >-          regex::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;
> >-        }
> >-      }
> >+    if (!type_name_not_regex_ && !type_name_not_regex_str_.empty())
> >+      type_name_not_regex_ = regex::compile(type_name_not_regex_str_);
> >     return type_name_not_regex_;
> >   }
> >
> >@@ -886,17 +755,10 @@ public:
> >   const regex::regex_t_sptr
> >   get_source_location_to_keep_regex() const
> >   {
> >-    if (!source_location_to_keep_regex_)
> >-      {
> >-      if (!source_location_to_keep_regex_str_.empty())
> >-        {
> >-          regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
> >-          if (regcomp(r.get(),
> >-                      source_location_to_keep_regex_str_.c_str(),
> >-                      REG_EXTENDED) == 0)
> >-            source_location_to_keep_regex_ = r;
> >-        }
> >-      }
> >+    if (!source_location_to_keep_regex_
> >+      && !source_location_to_keep_regex_str_.empty())
> >+      source_location_to_keep_regex_ =
> >+        regex::compile(source_location_to_keep_regex_str_);
> >     return source_location_to_keep_regex_;
> >   }
> >
> >--
> >2.26.2.303.gf8c07b1a785-goog
> >

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 15/21] abg-suppression.cc: More consistent regex matching.
  2020-04-27 12:07     ` Matthias Maennich
@ 2020-04-27 16:18       ` Giuliano Procida
  0 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-27 16:18 UTC (permalink / raw)
  To: Matthias Maennich; +Cc: libabigail, Dodji Seketeli, kernel-team

Hi.

On Mon, 27 Apr 2020 at 13:07, Matthias Maennich <maennich@google.com> wrote:
>
> On Fri, Apr 24, 2020 at 10:21:26AM +0100, Giuliano Procida wrote:
> >Following previous patches, various minor inconsistencies in the
> >suppression regex matching code were more readily apparent.
> >
> >- regex_t_sptr values are fetched both by reference and by
> >  value (which has a reference count mutation cost)
> >- there's a mixture of code styles for testing regex presence
> >    - regex = ...; if (regex && ...)
> >    - if (regex = ...) if (...)
> >  the latter has the advantage that the variable has a smaller scope
> >  and can be given a shorter name
> >- in some cases there are redundant tests (always true due to previous
> >  conditional logic)
> >
> >This patch ensures all shared pointers to compiled regexes are fetched
> >by const reference and that the code uses the nested if style of
> >presence checking where possible. It simplifies some logic where
> >there's redundancy.
> >
> >There are no behavioural changes. There may be performance
> >improvements.
> >
> >       * src/abg-suppression.cc (suppression_matches_type_name): Get
> >       regexes by const reference.
> >       (suppression_matches_type_location): Get regexes by const
> >       reference. (function_suppression::suppresses_function): Get
> >       regexes by const reference; use nested if checks; simplify
> >       logic around symbol version checks.
> >       (function_suppression::suppresses_function_symbol): Get
> >       regexes by const reference; use nested if checks; remove
> >       redundant regex presence checks.
> >       (suppression_matches_function_name): Get regexes by const
> >       reference. (suppression_matches_function_sym_name): Get
> >       regexes by const reference.
> >       (suppression_matches_variable_name): Get regexes by const
> >       reference. (suppression_matches_variable_sym_name): Get
> >       regexes by const reference. (suppression_matches_type): Get
> >       regexes by const reference.
> >       (variable_suppression::suppresses_variable): Get regexes by
> >       const reference; use nested if checks; remove redundant
> >       type_name empty check.
> >       (variable_suppression::suppresses_variable_symbol): Get
> >       regexes by const reference; use nested if checks.
> >
> >Signed-off-by: Giuliano Procida <gprocida@google.com>
> >---
> > src/abg-suppression.cc | 167 +++++++++++++++++++----------------------
> > 1 file changed, 76 insertions(+), 91 deletions(-)
> >
> >diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
> >index 331995bf..7d411caf 100644
> >--- a/src/abg-suppression.cc
> >+++ b/src/abg-suppression.cc
> >@@ -1053,15 +1053,14 @@ 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.
> >-        if (const regex_t_sptr& type_name_regex =
> >-            s.get_type_name_regex())
> >+        if (const regex_t_sptr& type_name_regex = s.get_type_name_regex())
> >           {
> >             if (!regex::match(type_name_regex, type_name))
> >               return false;
> >           }
> >
> >-        if (const regex_t_sptr type_name_not_regex =
> >-            s.get_type_name_not_regex())
> >+        if (const regex_t_sptr& type_name_not_regex =
> >+              s.get_type_name_not_regex())
> >           {
> >             if (regex::match(type_name_not_regex, type_name))
> >               return false;
> >@@ -1109,7 +1108,7 @@ suppression_matches_type_location(const type_suppression&        s,
> >       unsigned loc_line = 0, loc_column = 0;
> >       loc.expand(loc_path, loc_line, loc_column);
> >
> >-      if (regex_t_sptr regexp = s.get_source_location_to_keep_regex())
> >+      if (const regex_t_sptr& regexp = s.get_source_location_to_keep_regex())
> >       if (regex::match(regexp, loc_path))
> >         return false;
> >
> >@@ -2549,7 +2548,7 @@ function_suppression::suppresses_function(const function_decl* fn,
> >     }
> >
> >   // check if the "name_regexp" property matches.
> >-  const regex_t_sptr name_regex = get_name_regex();
> >+  const regex_t_sptr& name_regex = get_name_regex();
> >   if (name_regex)
> >     {
> >       if (!regex::match(name_regex, fname))
> >@@ -2580,7 +2579,7 @@ function_suppression::suppresses_function(const function_decl* fn,
> >     }
> >
> >   // check if the "name_not_regexp" property matches.
> >-  const regex_t_sptr name_not_regex = get_name_not_regex();
> >+  const regex_t_sptr& name_not_regex = get_name_not_regex();
> >   if (name_not_regex)
> >     {
> >       if (regex::match(name_not_regex, fname))
> >@@ -2624,11 +2623,9 @@ function_suppression::suppresses_function(const function_decl* fn,
> >       if (fn_return_type_name != get_return_type_name())
> >       return false;
> >     }
> >-  else
> >+  else if (const regex_t_sptr& regex = get_return_type_regex())
> >     {
> >-      const regex_t_sptr return_type_regex = get_return_type_regex();
> >-      if (return_type_regex
> >-        && !regex::match(return_type_regex, fn_return_type_name))
> >+      if (!regex::match(regex, fn_return_type_name))
>
> Not sure, but maybe.
>
> else if (const regex_t_sptr& regex = get_return_type_regex()
>           && (!regex::match(regex, fn_return_type_name)))
>           return false;
>
> I am not too much for this, but this pattern seems to repeat throughout
> the whole patch. So, for consistency sake, we could always do:
>    if (regex = get_regex() && regex::match(...))

That is not the syntax you are looking for...

If we want to declare regex within the conditional bracket, we can.
If we want to && within the conditional bracket, we can.
If we do both, we are initialising a regex with a boolean. I know,
b'cos I tried. :-)
Unless we use different C++17 syntax:

if (const regex_t_sptr& regex = get_regex(); regex::match(...))

> >       return false;
> >     }
> >
> >@@ -2664,14 +2661,15 @@ function_suppression::suppresses_function(const function_decl* fn,
> >     }
> >   else if (sym)
> >     {
> >-      const regex_t_sptr symbol_name_regex = get_symbol_name_regex();
> >-      if (symbol_name_regex && !regex::match(symbol_name_regex, fn_sym_name))
> >-      return false;
> >+      const regex_t_sptr& symbol_name_regex = get_symbol_name_regex();
> >+      const regex_t_sptr& symbol_name_not_regex = get_symbol_name_not_regex();
> >
> >-      const regex_t_sptr symbol_name_not_regex = get_symbol_name_not_regex();
> >-      if (symbol_name_not_regex
> >-        && regex::match(symbol_name_not_regex, fn_sym_name))
> >-      return false;
> >+      if (symbol_name_regex)
> >+      if (!regex::match(symbol_name_regex, fn_sym_name))
>
> if (symbol_name_regex && !regex::match(symbol_name_regex, fn_sym_name))
>    return false;
>
> More examples of this further down.

This is what I meant by "code uses the nested if style of presence
checking where possible". These are the only cases where the regex
isn't initialised inside the if, because we can reuse a variable. I
kept to the nested if just for consistency with all the other cases.

I'm happy to change it or discuss further.

Thanks,
Giuliano.

> Other than that:
>
> Reviewed-by: Matthias Maennich <maennich@google.com>
>
> Cheers,
> Matthias
>
> >+        return false;
> >+      if (symbol_name_not_regex)
> >+      if (regex::match(symbol_name_not_regex, fn_sym_name))
> >+        return false;
> >
> >       if (get_allow_other_aliases())
> >       {
> >@@ -2684,13 +2682,13 @@ function_suppression::suppresses_function(const function_decl* fn,
> >                  a && !a->is_main_symbol();
> >                  a = a->get_next_alias())
> >               {
> >-                if (symbol_name_regex
> >-                    && !regex::match(symbol_name_regex, a->get_name()))
> >-                  return false;
> >-
> >-                if (symbol_name_not_regex
> >-                    && regex::match(symbol_name_not_regex, a->get_name()))
> >-                  return false;
> >+                const std::string& alias_name = a->get_name();
> >+                if (symbol_name_regex)
> >+                  if (!regex::match(symbol_name_regex, alias_name))
> >+                    return false;
> >+                if (symbol_name_not_regex)
> >+                  if (regex::match(symbol_name_not_regex, alias_name))
> >+                    return false;
> >               }
> >           }
> >       }
> >@@ -2698,17 +2696,19 @@ function_suppression::suppresses_function(const function_decl* fn,
> >
> >   // Check if the "symbol_version" and "symbol_version_regexp"
> >   // properties match.
> >-  if (sym && !get_symbol_version().empty())
> >-    {
> >-      if (fn_sym_version != get_symbol_version())
> >-      return false;
> >-    }
> >-  else if (sym)
> >+  if (sym)
> >     {
> >-      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
> >-      if (symbol_version_regex
> >-        && !regex::match(symbol_version_regex, fn_sym_version))
> >-      return false;
> >+      if (!get_symbol_version().empty())
> >+      {
> >+        if (fn_sym_version != get_symbol_version())
> >+          return false;
> >+      }
> >+      else
> >+      {
> >+        if (const regex_t_sptr& regex = get_symbol_version_regex())
> >+          if (!regex::match(regex, fn_sym_version))
> >+            return false;
> >+      }
> >     }
> >
> >   // Check the 'parameter' property.
> >@@ -2742,16 +2742,11 @@ function_suppression::suppresses_function(const function_decl* fn,
> >             if (tn != fn_parm_type_qualified_name)
> >               return false;
> >           }
> >-        else
> >+        else if (const regex_t_sptr& regex =
> >+                   (*p)->get_parameter_type_name_regex())
> >           {
> >-            const regex_t_sptr parm_type_name_regex =
> >-              (*p)->get_parameter_type_name_regex();
> >-            if (parm_type_name_regex)
> >-              {
> >-                if (!regex::match(parm_type_name_regex,
> >-                                  fn_parm_type_qualified_name))
> >-                  return false;
> >-              }
> >+            if (!regex::match(regex, fn_parm_type_qualified_name))
> >+              return false;
> >           }
> >       }
> >     }
> >@@ -2834,10 +2829,9 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
> >       if (sym_name != get_symbol_name())
> >       return false;
> >     }
> >-  else if (get_symbol_name_regex())
> >+  else if (const regex_t_sptr& regex = get_symbol_name_regex())
> >     {
> >-      const regex_t_sptr symbol_name_regex = get_symbol_name_regex();
> >-      if (symbol_name_regex && !regex::match(symbol_name_regex, sym_name))
> >+      if (!regex::match(regex, sym_name))
> >       return false;
> >     }
> >   else
> >@@ -2849,11 +2843,9 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
> >       if (sym_version != get_symbol_version())
> >       return false;
> >     }
> >-  else if (get_symbol_version_regex())
> >+  else if (const regex_t_sptr& regex = get_symbol_version_regex())
> >     {
> >-      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
> >-      if (symbol_version_regex
> >-        && !regex::match(symbol_version_regex, sym_version))
> >+      if (!regex::match(regex, sym_version))
> >       return false;
> >     }
> >   else
> >@@ -2943,12 +2935,12 @@ bool
> > suppression_matches_function_name(const suppr::function_suppression& s,
> >                                 const string& fn_name)
> > {
> >-  if (regex_t_sptr regexp = s.get_name_regex())
> >+  if (const regex_t_sptr& regexp = s.get_name_regex())
> >     {
> >       if (!regex::match(regexp, fn_name))
> >       return false;
> >     }
> >-  else if (regex_t_sptr regexp = s.get_name_not_regex())
> >+  else if (const regex_t_sptr& regexp = s.get_name_not_regex())
> >     {
> >       if (regex::match(regexp, fn_name))
> >       return false;
> >@@ -2979,12 +2971,12 @@ bool
> > suppression_matches_function_sym_name(const suppr::function_suppression& s,
> >                                     const string& fn_linkage_name)
> > {
> >-  if (regex_t_sptr regexp = s.get_symbol_name_regex())
> >+  if (const regex_t_sptr& regexp = s.get_symbol_name_regex())
> >     {
> >       if (!regex::match(regexp, fn_linkage_name))
> >       return false;
> >     }
> >-  else if (regex_t_sptr regexp = s.get_symbol_name_not_regex())
> >+  else if (const regex_t_sptr& regexp = s.get_symbol_name_not_regex())
> >     {
> >       if (regex::match(regexp, fn_linkage_name))
> >       return false;
> >@@ -3012,12 +3004,12 @@ bool
> > suppression_matches_variable_name(const suppr::variable_suppression& s,
> >                                 const string& var_name)
> > {
> >-  if (regex_t_sptr regexp = s.get_name_regex())
> >+  if (const regex_t_sptr& regexp = s.get_name_regex())
> >     {
> >       if (!regex::match(regexp, var_name))
> >       return false;
> >     }
> >-  else if (regex_t_sptr regexp = s.get_name_not_regex())
> >+  else if (const regex_t_sptr& regexp = s.get_name_not_regex())
> >     {
> >       if (regex::match(regexp, var_name))
> >       return false;
> >@@ -3046,12 +3038,12 @@ bool
> > suppression_matches_variable_sym_name(const suppr::variable_suppression& s,
> >                                     const string& var_linkage_name)
> > {
> >-  if (regex_t_sptr regexp = s.get_symbol_name_regex())
> >+  if (const regex_t_sptr& regexp = s.get_symbol_name_regex())
> >     {
> >       if (!regex::match(regexp, var_linkage_name))
> >       return false;
> >     }
> >-  else if (regex_t_sptr regexp = s.get_symbol_name_not_regex())
> >+  else if (const regex_t_sptr& regexp = s.get_symbol_name_not_regex())
> >     {
> >       if (regex::match(regexp, var_linkage_name))
> >       return false;
> >@@ -3080,7 +3072,7 @@ bool
> > suppression_matches_type(const suppr::type_suppression& s,
> >                        const string& type_name)
> > {
> >-  if (regex_t_sptr regexp = s.get_type_name_regex())
> >+  if (const regex_t_sptr& regexp = s.get_type_name_regex())
> >     {
> >       if (!regex::match(regexp, type_name))
> >       return false;
> >@@ -3789,13 +3781,13 @@ variable_suppression::suppresses_variable(const var_decl* var,
> >       // "name_regex" and "name_not_regex" properties match
> >       if (get_name().empty())
> >       {
> >-        const regex_t_sptr name_regex = get_name_regex();
> >-        if (name_regex && !regex::match(name_regex, var_name))
> >-          return false;
> >+        if (const regex_t_sptr& regex = get_name_regex())
> >+          if (!regex::match(regex, var_name))
> >+            return false;
> >
> >-        const regex_t_sptr name_not_regex = get_name_not_regex();
> >-        if (name_not_regex && regex::match(name_not_regex, var_name))
> >-          return false;
> >+        if (const regex_t_sptr& regex = get_name_not_regex())
> >+          if (regex::match(regex, var_name))
> >+            return false;
> >       }
> >     }
> >
> >@@ -3809,13 +3801,13 @@ variable_suppression::suppresses_variable(const var_decl* var,
> >     }
> >   else
> >     {
> >-      const regex_t_sptr sym_name_regex = get_symbol_name_regex();
> >-      if (sym_name_regex && !regex::match(sym_name_regex, var_sym_name))
> >-      return false;
> >+      if (const regex_t_sptr& regex = get_symbol_name_regex())
> >+      if (!regex::match(regex, var_sym_name))
> >+        return false;
> >
> >-      const regex_t_sptr sym_name_not_regex = get_symbol_name_not_regex();
> >-      if (sym_name_not_regex && regex::match(sym_name_not_regex, var_sym_name))
> >-      return false;
> >+      if (const regex_t_sptr& regex = get_symbol_name_not_regex())
> >+      if (regex::match(regex, var_sym_name))
> >+        return false;
> >     }
> >
> >   // Check for symbol_version and symbol_version_regexp property match
> >@@ -3828,10 +3820,9 @@ variable_suppression::suppresses_variable(const var_decl* var,
> >     }
> >   else
> >     {
> >-      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
> >-      if (symbol_version_regex
> >-        && !regex::match(symbol_version_regex, var_sym_version))
> >-      return false;
> >+      if (const regex_t_sptr& regex = get_symbol_version_regex())
> >+      if (!regex::match(regex, var_sym_version))
> >+        return false;
> >     }
> >
> >   // Check for the "type_name" and type_name_regex properties match.
> >@@ -3845,12 +3836,9 @@ variable_suppression::suppresses_variable(const var_decl* var,
> >     }
> >   else
> >     {
> >-      if (get_type_name().empty())
> >-      {
> >-        const regex_t_sptr type_name_regex = get_type_name_regex();
> >-        if (type_name_regex && !regex::match(type_name_regex, var_type_name))
> >-          return false;
> >-      }
> >+      if (const regex_t_sptr& regex = get_type_name_regex())
> >+      if (!regex::match(regex, var_type_name))
> >+        return false;
> >     }
> >
> >   return true;
> >@@ -3936,10 +3924,9 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
> >       if (get_symbol_name() != sym_name)
> >       return false;
> >     }
> >-  else if (get_symbol_name_regex())
> >+  else if (const regex_t_sptr& regex = get_symbol_name_regex())
> >     {
> >-      const regex_t_sptr sym_name_regex = get_symbol_name_regex();
> >-      if (sym_name_regex && !regex::match(sym_name_regex, sym_name))
> >+      if (!regex::match(regex, sym_name))
> >       return false;
> >     }
> >   else
> >@@ -3952,11 +3939,9 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
> >       if (get_symbol_version() != sym_version)
> >       return false;
> >     }
> >-  else if (get_symbol_version_regex())
> >+  else if (const regex_t_sptr& regex = get_symbol_version_regex())
> >     {
> >-      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
> >-      if (symbol_version_regex
> >-        && !regex::match(symbol_version_regex, sym_version))
> >+      if (!regex::match(regex, sym_version))
> >       return false;
> >     }
> >   else
> >@@ -4257,14 +4242,14 @@ file_suppression::suppresses_file(const string& file_path)
> >
> >   bool has_regexp = false;
> >
> >-  if (regex_t_sptr regexp = get_file_name_regex())
> >+  if (const regex_t_sptr& regexp = get_file_name_regex())
> >     {
> >       has_regexp = true;
> >       if (!regex::match(regexp, fname))
> >       return false;
> >     }
> >
> >-  if (regex_t_sptr regexp = get_file_name_not_regex())
> >+  if (const regex_t_sptr& regexp = get_file_name_not_regex())
> >     {
> >       has_regexp = true;
> >       if (regex::match(regexp, fname))
> >--
> >2.26.2.303.gf8c07b1a785-goog
> >

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 16/21] abg-tools-utils.cc: Assert generated regexes OK.
  2020-04-27 12:08     ` Matthias Maennich
@ 2020-04-27 16:21       ` Giuliano Procida
  0 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-27 16:21 UTC (permalink / raw)
  To: Matthias Maennich; +Cc: libabigail, Dodji Seketeli, kernel-team

Hi.

On Mon, 27 Apr 2020 at 13:08, Matthias Maennich <maennich@google.com> wrote:
>
> On Fri, Apr 24, 2020 at 10:21:27AM +0100, Giuliano Procida wrote:
> >There are a couple of places where regexes are generated interally.
>                                                               ^^^ typo

Fixed.

Thank you!

> >Assert they compile OK.
> >
> >This is just paranoia. There should be no behavioural changes.
> >
> >       * src/abg-tools-utils.cc (handle_file_entry): Assert
> >       internally-generated regex compiles.
> >       (gen_suppr_spec_from_kernel_abi_whitelists): Assert
> >       internally-generated regex compiles.
> >
> >Signed-off-by: Giuliano Procida <gprocida@google.com>
>
> Reviewed-by: Matthias Maennich <maennich@google.com>
>
> Cheers,
> Matthias
>
> >---
> > src/abg-tools-utils.cc | 2 ++
> > 1 file changed, 2 insertions(+)
> >
> >diff --git a/src/abg-tools-utils.cc b/src/abg-tools-utils.cc
> >index fe0de750..3af9fc49 100644
> >--- a/src/abg-tools-utils.cc
> >+++ b/src/abg-tools-utils.cc
> >@@ -1818,6 +1818,7 @@ handle_file_entry(const string& file_path,
> >       // Types that are defined in system headers are usually
> >       // OK to be considered as public types.
> >       regex::regex_t_sptr headers_regex = regex::compile("^/usr/include/");
> >+      ABG_ASSERT(headers_regex);
> >       suppr->set_source_location_to_keep_regex(headers_regex);
> >       suppr->set_is_artificial(true);
> >     }
> >@@ -2008,6 +2009,7 @@ gen_suppr_spec_from_kernel_abi_whitelists
> >       // the function and variable names expressed in the white list.
> >       regex::regex_t_sptr regex =
> >       regex::compile(regex::generate_from_strings(whitelisted_names));
> >+      ABG_ASSERT(regex);
> >
> >       // Build a suppression specification which *keeps* functions
> >       // whose ELF symbols match the regular expression contained
> >--
> >2.26.2.303.gf8c07b1a785-goog
> >

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 17/21] Refactor suppression property string parsing.
  2020-04-27 12:17     ` Matthias Maennich
@ 2020-04-27 16:42       ` Giuliano Procida
  0 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-27 16:42 UTC (permalink / raw)
  To: Matthias Maennich; +Cc: libabigail, Dodji Seketeli, kernel-team

Hi.

On Mon, 27 Apr 2020 at 13:17, Matthias Maennich <maennich@google.com> wrote:
>
> On Fri, Apr 24, 2020 at 10:21:28AM +0100, Giuliano Procida wrote:
> >This patch introduces a helper function to look up a key in an ini
> >configuration section and get a string value. All string look-ups now
> >use this.
> >
> >There are no behavioural changes.
> >
> >Signed-off-by: Giuliano Procida <gprocida@google.com>
> >---
> > src/abg-suppression.cc | 198 ++++++++++++++++-------------------------
> > 1 file changed, 78 insertions(+), 120 deletions(-)
> >
> >diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
> >index 7d411caf..84c9b78f 100644
> >--- a/src/abg-suppression.cc
> >+++ b/src/abg-suppression.cc
> >@@ -1594,6 +1594,31 @@ read_suppression_reach_kind(const string& input)
> >     return type_suppression::DIRECT_REACH_KIND;
> > }
> >
> >+/// Maybe fetch a property to a string.
> >+///
> >+/// Attempt to find a simple property in an ini section and copy it
> >+/// to a string
> >+///
> >+/// @param section the ini section to look in
> >+///
> >+/// @param prop the property name
> >+///
> >+/// @param str the string to compile into
> >+///
> >+/// @return whether the property was found
> >+static bool
> >+maybe_get_string_prop(const ini::config::section& section,
> >+                      const std::string& name,
> >+                      std::string& str)
>
> I would prefer a signature like
>
> std::string get_string_prop(... section, ... name, std::string default = "");
>
> In fact, this could be also
>
>    template<typename T>
>    T get_prop(... section, ... name, T default);
>
> if prop->get_value() would be changed accordingly.
>
> This does not play nicely with several keys to lookup though ...

maybe_get_string_prop and maybe_get_regex_prop were the obvious code
refactoring to do as there was a lot of repetition. From the
perspective of M commits later, they are the wrong choice.

In hindsight (!) I should have made a different choice as to how I
ordered my various changes. Something like this:

(this is for strings, something more involved for other types)

1. replace the code above with either

a) if a value is needed unconditionally (as a constructor argument)

string foo_str;
if (prop foo_prop = section.find_property("foo"))
  read_string(foo_prop, foo_str);

b) or conditionally:

if (prop prop = section.find_property("foo")) {
  string str;
  if (read_string(prop, str))
    suppression.set_foo(str);
}

also replacing code like this at the same time:

if (!foo_str.empty())
  suppression.set_foo(str);

2. Make the suppression constructors all default

This would mean switching all the code using pattern a) above to pattern b).

Default values are set by the default constructor, rather than being
scattered about the code.

...
...

N. Replace the find_property calls (and the special scan for
"parameter" properties) with something table-driven.

I can rework the patch series from this point along these lines.
Before I launch into it, let me know what you think! Thanks.

Giuliano.

> Cheers,
> Matthias
>
> >+{
> >+  ini::simple_property_sptr prop =
> >+    is_simple_property(section.find_property(name));
> >+  if (!prop)
> >+    return false;
> >+  str = prop->get_value()->as_string();
> >+  return true;
> >+}
> >+
> > /// Read a type suppression from an instance of ini::config::section
> > /// and build a @ref type_suppression as a result.
> > ///
> >@@ -1609,18 +1634,12 @@ read_type_suppression(const ini::config::section& section)
> >   if (section.get_name() != "suppress_type")
> >     return result;
> >
> >-  ini::simple_property_sptr drop_artifact =
> >-    is_simple_property(section.find_property("drop_artifact"));
> >-  if (!drop_artifact)
> >-    drop_artifact = is_simple_property(section.find_property("drop"));
> >-
> >-  string drop_artifact_str = drop_artifact
> >-    ? drop_artifact->get_value()->as_string()
> >-    : "";
> >+  string drop_artifact_str;
> >+  maybe_get_string_prop(section, "drop_artifact", drop_artifact_str)
> >+    || maybe_get_string_prop(section, "drop", drop_artifact_str);
> >
> >-  ini::simple_property_sptr label =
> >-    is_simple_property(section.find_property("label"));
> >-  string label_str = label ? label->get_value()->as_string() : "";
> >+  string label_str;
> >+  maybe_get_string_prop(section, "label", label_str);
> >
> >   ini::simple_property_sptr file_name_regex_prop =
> >     is_simple_property(section.find_property("file_name_regexp"));
> >@@ -1662,11 +1681,8 @@ read_type_suppression(const ini::config::section& section)
> >     name_not_regex =
> >       regex::compile(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
> >-    ? name_prop->get_value()->as_string()
> >-    : "";
> >+  string name_str;
> >+  maybe_get_string_prop(section, "name", name_str);
> >
> >   ini::property_sptr srcloc_not_in_prop =
> >     section.find_property("source_location_not_in");
> >@@ -1697,25 +1713,19 @@ read_type_suppression(const ini::config::section& section)
> >     srcloc_not_regex =
> >       regex::compile(srcloc_not_regexp_prop->get_value()->as_string());
> >
> >-  bool consider_type_kind = false;
> >-  type_suppression::type_kind type_kind = type_suppression::UNKNOWN_TYPE_KIND;
> >-  if (ini::simple_property_sptr type_kind_prop =
> >-      is_simple_property(section.find_property("type_kind")))
> >-    {
> >-      consider_type_kind = true;
> >-      type_kind =
> >-      read_type_kind_string(type_kind_prop->get_value()->as_string());
> >-    }
> >+  std::string type_kind_str;
> >+  bool consider_type_kind =
> >+    maybe_get_string_prop(section, "type_kind", type_kind_str);
> >+  type_suppression::type_kind type_kind = consider_type_kind
> >+    ? read_type_kind_string(type_kind_str)
> >+    : type_suppression::UNKNOWN_TYPE_KIND;
> >
> >-  bool consider_reach_kind = false;
> >-  type_suppression::reach_kind reach_kind = type_suppression::DIRECT_REACH_KIND;
> >-  if (ini::simple_property_sptr reach_kind_prop =
> >-      is_simple_property(section.find_property("accessed_through")))
> >-    {
> >-      consider_reach_kind = true;
> >-      reach_kind =
> >-      read_suppression_reach_kind(reach_kind_prop->get_value()->as_string());
> >-    }
> >+  std::string reach_kind_str;
> >+  bool consider_reach_kind =
> >+      maybe_get_string_prop(section, "accessed_through", reach_kind_str);
> >+  type_suppression::reach_kind reach_kind = consider_reach_kind
> >+    ? read_suppression_reach_kind(reach_kind_str)
> >+    : type_suppression::DIRECT_REACH_KIND;
> >
> >   // Support has_data_member_inserted_at
> >   vector<type_suppression::insertion_range_sptr> insert_ranges;
> >@@ -3175,26 +3185,15 @@ read_function_suppression(const ini::config::section& section)
> >   if (section.get_name() != "suppress_function")
> >     return result;
> >
> >-  ini::simple_property_sptr drop_artifact =
> >-    is_simple_property(section.find_property("drop_artifact"));
> >-  if (!drop_artifact)
> >-    drop_artifact = is_simple_property(section.find_property("drop"));
> >-
> >-  string drop_artifact_str = drop_artifact
> >-    ? drop_artifact->get_value()->as_string()
> >-    : "";
> >+  string drop_artifact_str;
> >+  maybe_get_string_prop(section, "drop_artifact", drop_artifact_str)
> >+    || maybe_get_string_prop(section, "drop", drop_artifact_str);
> >
> >-  ini::simple_property_sptr change_kind_prop =
> >-    is_simple_property(section.find_property("change_kind"));
> >-  string change_kind_str = change_kind_prop
> >-    ? change_kind_prop->get_value()->as_string()
> >-    : "";
> >+  string change_kind_str;
> >+  maybe_get_string_prop(section, "change_kind", change_kind_str);
> >
> >-  ini::simple_property_sptr label_prop =
> >-    is_simple_property(section.find_property("label"));
> >-  string label_str = label_prop
> >-    ? label_prop->get_value()->as_string()
> >-    : "";
> >+  string label_str;
> >+  maybe_get_string_prop(section, "label", label_str);
> >
> >   ini::simple_property_sptr file_name_regex_prop =
> >     is_simple_property(section.find_property("file_name_regexp"));
> >@@ -3223,11 +3222,8 @@ read_function_suppression(const ini::config::section& section)
> >     soname_not_regex =
> >       regex::compile(soname_not_regex_prop->get_value()->as_string());
> >
> >-  ini::simple_property_sptr name_prop =
> >-    is_simple_property(section.find_property("name"));
> >-  string name = name_prop
> >-    ? name_prop->get_value()->as_string()
> >-    : "";
> >+  string name;
> >+  maybe_get_string_prop(section, "name", name);
> >
> >   ini::simple_property_sptr name_regex_prop =
> >     is_simple_property(section.find_property("name_regexp"));
> >@@ -3242,11 +3238,8 @@ read_function_suppression(const ini::config::section& section)
> >     name_not_regex =
> >       regex::compile(name_not_regex_prop->get_value()->as_string());
> >
> >-  ini::simple_property_sptr return_type_name_prop =
> >-    is_simple_property(section.find_property("return_type_name"));
> >-  string return_type_name = return_type_name_prop
> >-    ? return_type_name_prop->get_value()->as_string()
> >-    : "";
> >+  string return_type_name;
> >+  maybe_get_string_prop(section, "return_type_name", return_type_name);
> >
> >   ini::simple_property_sptr return_type_regex_prop =
> >     is_simple_property(section.find_property("return_type_regexp"));
> >@@ -3255,11 +3248,8 @@ read_function_suppression(const ini::config::section& section)
> >     return_type_regex =
> >       regex::compile(return_type_regex_prop->get_value()->as_string());
> >
> >-  ini::simple_property_sptr sym_name_prop =
> >-    is_simple_property(section.find_property("symbol_name"));
> >-  string sym_name = sym_name_prop
> >-    ? sym_name_prop->get_value()->as_string()
> >-    : "";
> >+  string sym_name;
> >+  maybe_get_string_prop(section, "symbol_name", sym_name);
> >
> >   ini::simple_property_sptr sym_name_regex_prop =
> >     is_simple_property(section.find_property("symbol_name_regexp"));
> >@@ -3275,11 +3265,8 @@ read_function_suppression(const ini::config::section& section)
> >     sym_name_not_regex =
> >       regex::compile(sym_name_not_regex_prop->get_value()->as_string());
> >
> >-  ini::simple_property_sptr sym_ver_prop =
> >-    is_simple_property(section.find_property("symbol_version"));
> >-  string sym_version = sym_ver_prop
> >-    ? sym_ver_prop->get_value()->as_string()
> >-    : "";
> >+  string sym_version;
> >+  maybe_get_string_prop(section, "symbol_version", sym_version);
> >
> >   ini::simple_property_sptr sym_ver_regex_prop =
> >     is_simple_property(section.find_property("symbol_version_regexp"));
> >@@ -3288,11 +3275,8 @@ read_function_suppression(const ini::config::section& section)
> >     sym_ver_regex =
> >       regex::compile(sym_ver_regex_prop->get_value()->as_string());
> >
> >-  ini::simple_property_sptr allow_other_aliases_prop =
> >-    is_simple_property(section.find_property("allow_other_aliases"));
> >-  string allow_other_aliases = allow_other_aliases_prop
> >-    ? allow_other_aliases_prop->get_value()->as_string()
> >-    : "";
> >+  string allow_other_aliases;
> >+  maybe_get_string_prop(section, "allow_other_aliases", allow_other_aliases);
> >
> >   function_suppression::parameter_spec_sptr parm;
> >   function_suppression::parameter_specs_type parms;
> >@@ -4031,26 +4015,15 @@ read_variable_suppression(const ini::config::section& section)
> >   if (section.get_name() != "suppress_variable")
> >     return result;
> >
> >-  ini::simple_property_sptr drop_artifact =
> >-    is_simple_property(section.find_property("drop_artifact"));
> >-  if (!drop_artifact)
> >-    drop_artifact = is_simple_property(section.find_property("drop"));
> >-
> >-  string drop_artifact_str = drop_artifact
> >-    ? drop_artifact->get_value()->as_string()
> >-    : "";
> >+  string drop_artifact_str;
> >+  maybe_get_string_prop(section, "drop_artifact", drop_artifact_str)
> >+    || maybe_get_string_prop(section, "drop", drop_artifact_str);
> >
> >-  ini::simple_property_sptr change_kind_prop =
> >-    is_simple_property(section.find_property("change_kind"));
> >-  string change_kind_str = change_kind_prop
> >-    ? change_kind_prop->get_value()->as_string()
> >-    : "";
> >+  string change_kind_str;
> >+  maybe_get_string_prop(section, "change_kind", change_kind_str);
> >
> >-  ini::simple_property_sptr label_prop =
> >-    is_simple_property(section.find_property("label"));
> >-  string label_str = (label_prop
> >-                    ? label_prop->get_value()->as_string()
> >-                    : "");
> >+  string label_str;
> >+  maybe_get_string_prop(section, "label", label_str);
> >
> >   ini::simple_property_sptr file_name_regex_prop =
> >     is_simple_property(section.find_property("file_name_regexp"));
> >@@ -4079,11 +4052,8 @@ read_variable_suppression(const ini::config::section& section)
> >     soname_not_regex =
> >       regex::compile(soname_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
> >-                   ? name_prop->get_value()->as_string()
> >-                   : "");
> >+  string name_str;
> >+  maybe_get_string_prop(section, "name", name_str);
> >
> >   ini::simple_property_sptr name_regex_prop =
> >     is_simple_property(section.find_property("name_regexp"));
> >@@ -4098,11 +4068,8 @@ read_variable_suppression(const ini::config::section& section)
> >     name_not_regex =
> >       regex::compile(name_not_regex_prop->get_value()->as_string());
> >
> >-  ini::simple_property_sptr sym_name_prop =
> >-    is_simple_property(section.find_property("symbol_name"));
> >-  string symbol_name = (sym_name_prop
> >-                      ? sym_name_prop->get_value()->as_string()
> >-                      : "");
> >+  string symbol_name;
> >+  maybe_get_string_prop(section, "symbol_name", symbol_name);
> >
> >   ini::simple_property_sptr sym_name_regex_prop =
> >     is_simple_property(section.find_property("symbol_name_regexp"));
> >@@ -4118,11 +4085,8 @@ read_variable_suppression(const ini::config::section& section)
> >     symbol_name_not_regex =
> >       regex::compile(sym_name_not_regex_prop->get_value()->as_string());
> >
> >-  ini::simple_property_sptr sym_version_prop =
> >-    is_simple_property(section.find_property("symbol_version"));
> >-  string symbol_version = sym_version_prop
> >-    ? sym_version_prop->get_value()->as_string()
> >-    : "";
> >+  string symbol_version;
> >+  maybe_get_string_prop(section, "symbol_version", symbol_version);
> >
> >   ini::simple_property_sptr sym_version_regex_prop =
> >     is_simple_property(section.find_property("symbol_version_regexp"));
> >@@ -4131,11 +4095,8 @@ read_variable_suppression(const ini::config::section& section)
> >     symbol_version_regex =
> >       regex::compile(sym_version_regex_prop->get_value()->as_string());
> >
> >-  ini::simple_property_sptr type_name_prop =
> >-    is_simple_property(section.find_property("type_name"));
> >-  string type_name_str = type_name_prop
> >-    ? type_name_prop->get_value()->as_string()
> >-    : "";
> >+  string type_name_str;
> >+  maybe_get_string_prop(section, "type_name", type_name_str);
> >
> >   ini::simple_property_sptr type_name_regex_prop =
> >     is_simple_property(section.find_property("type_name_regexp"));
> >@@ -4282,11 +4243,8 @@ read_file_suppression(const ini::config::section& section)
> >   if (section.get_name() != "suppress_file")
> >     return result;
> >
> >-  ini::simple_property_sptr label_prop =
> >-    is_simple_property(section.find_property("label"));
> >-  string label_str = (label_prop
> >-                    ? label_prop->get_value()->as_string()
> >-                    : "");
> >+  string label_str;
> >+  maybe_get_string_prop(section, "label", label_str);
> >
> >   ini::simple_property_sptr file_name_regex_prop =
> >     is_simple_property(section.find_property("file_name_regexp"));
> >--
> >2.26.2.303.gf8c07b1a785-goog
> >

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 18/21] Refactor suppression property regex parsing.
  2020-04-27 14:55     ` Matthias Maennich
@ 2020-04-27 16:59       ` Giuliano Procida
  0 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-27 16:59 UTC (permalink / raw)
  To: Matthias Maennich; +Cc: libabigail, Dodji Seketeli, kernel-team

Hi.

On Mon, 27 Apr 2020 at 15:55, Matthias Maennich <maennich@google.com> wrote:
>
> On Fri, Apr 24, 2020 at 10:21:29AM +0100, Giuliano Procida wrote:
> >This patch introduces a helper function to look up a key in an ini
> >configuration section and get a compiled regex value. All regex
> >look-ups now use this.
> >
> >There are no behavioural changes.
> >
>
> That is an awesome simplification!
>
> I basically have the same comment as before: Getting different data
> types from the ini asks (in my opinion) for a bit generic code.

The generic code comes a bit later. We cannot do everything on a
purely type-driven basis (complications around
has_data_member_inserted* properties), but we can get quite close.

As I note in my comment for 17/21, this is the wrong refactoring. What
the code should look like is (once error handling is there as well):

if (prop prop = section.find_property("foo_regex")) {
  regex r;
  if (!read_regex(prop, r))
    return false;
  result.set_foo_regex(r);
}

or

if (prop prop = section.find_property("foo_regex"))
  if (!type_driven_magic(prop, &bar_suppression::set_foo_regex))
    return false;

for the general case we need (adapter can be "call" in almost all cases):

if (prop prop = section.find_property("foo_regex"))
  if (!type_driven_magic(prop, adapter(&bar_suppression::set_foo_regex)))
    return false;

And once it's table-driven, it's just:

bar_suppression_table = {
  { "foo_regex", { adapter(&bar_suppression::set_foo_regex), ... } },
  ...
};

I'm undecided as to whether the type-driven magic (calling the right
function to extract a type from a property) should be with template
specialisation or plain overloading.

> But I am also ok with this version.
>
> Reviewed-by: Matthias Maennich <maennich@google.com>

I'll hold off until further feedback on 17/21 and this one.

Thanks,
Giuliano.

> Cheers,
> Matthias
>
> >Signed-off-by: Giuliano Procida <gprocida@google.com>
> >---
> > src/abg-suppression.cc | 215 ++++++++++++-----------------------------
> > 1 file changed, 61 insertions(+), 154 deletions(-)
> >
> >diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
> >index 84c9b78f..8b3631fd 100644
> >--- a/src/abg-suppression.cc
> >+++ b/src/abg-suppression.cc
> >@@ -1619,6 +1619,30 @@ maybe_get_string_prop(const ini::config::section& section,
> >   return true;
> > }
> >
> >+/// Maybe compile a property to a regex.
> >+///
> >+/// Attempt to find a simple property in an ini section and compile it
> >+/// to a regex.
> >+///
> >+/// @param section the ini section to look in
> >+///
> >+/// @param prop the property name
> >+///
> >+/// @param r the regex to compile into
> >+///
> >+/// @return whether the property was found
> >+static bool
> >+maybe_get_regex_prop(const ini::config::section& section,
> >+                     const std::string& name,
> >+                     regex_t_sptr& regex)
> >+{
> >+  string str;
> >+  if (!maybe_get_string_prop(section, name, str))
> >+    return false;
> >+  regex = regex::compile(str);
> >+  return true;
> >+}
> >+
> > /// Read a type suppression from an instance of ini::config::section
> > /// and build a @ref type_suppression as a result.
> > ///
> >@@ -1641,45 +1665,23 @@ read_type_suppression(const ini::config::section& section)
> >   string label_str;
> >   maybe_get_string_prop(section, "label", label_str);
> >
> >-  ini::simple_property_sptr file_name_regex_prop =
> >-    is_simple_property(section.find_property("file_name_regexp"));
> >   regex_t_sptr file_name_regex;
> >-  if (file_name_regex_prop)
> >-    file_name_regex =
> >-      regex::compile(file_name_regex_prop->get_value()->as_string());
> >+  maybe_get_regex_prop(section, "file_name_regexp", file_name_regex);
> >
> >-  ini::simple_property_sptr file_name_not_regex_prop =
> >-    is_simple_property(section.find_property("file_name_not_regexp"));
> >   regex_t_sptr file_name_not_regex;
> >-  if (file_name_not_regex_prop)
> >-    file_name_not_regex =
> >-      regex::compile(file_name_not_regex_prop->get_value()->as_string());
> >+  maybe_get_regex_prop(section, "file_name_not_regexp", file_name_not_regex);
> >
> >-  ini::simple_property_sptr soname_regex_prop =
> >-    is_simple_property(section.find_property("soname_regexp"));
> >   regex_t_sptr soname_regex;
> >-  if (soname_regex_prop)
> >-    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
> >+  maybe_get_regex_prop(section, "soname_regexp", soname_regex);
> >
> >-  ini::simple_property_sptr soname_not_regex_prop =
> >-    is_simple_property(section.find_property("soname_not_regexp"));
> >   regex_t_sptr soname_not_regex;
> >-  if (soname_not_regex_prop)
> >-    soname_not_regex =
> >-      regex::compile(soname_not_regex_prop->get_value()->as_string());
> >+  maybe_get_regex_prop(section, "soname_not_regexp", soname_not_regex);
> >
> >-  ini::simple_property_sptr name_regex_prop =
> >-    is_simple_property(section.find_property("name_regexp"));
> >   regex_t_sptr name_regex;
> >-  if (name_regex_prop)
> >-    name_regex = regex::compile(name_regex_prop->get_value()->as_string());
> >+  maybe_get_regex_prop(section, "name_regexp", name_regex);
> >
> >-  ini::simple_property_sptr name_not_regex_prop =
> >-    is_simple_property(section.find_property("name_not_regexp"));
> >   regex_t_sptr name_not_regex;
> >-  if (name_not_regex_prop)
> >-    name_not_regex =
> >-      regex::compile(name_not_regex_prop->get_value()->as_string());
> >+  maybe_get_regex_prop(section, "name_not_regexp", name_not_regex);
> >
> >   string name_str;
> >   maybe_get_string_prop(section, "name", name_str);
> >@@ -1706,12 +1708,8 @@ read_type_suppression(const ini::config::section& section)
> >       }
> >     }
> >
> >-  ini::simple_property_sptr srcloc_not_regexp_prop =
> >-    is_simple_property(section.find_property("source_location_not_regexp"));
> >   regex_t_sptr srcloc_not_regex;
> >-  if (srcloc_not_regexp_prop)
> >-    srcloc_not_regex =
> >-      regex::compile(srcloc_not_regexp_prop->get_value()->as_string());
> >+  maybe_get_regex_prop(section, "source_location_not_regexp", srcloc_not_regex);
> >
> >   std::string type_kind_str;
> >   bool consider_type_kind =
> >@@ -3195,85 +3193,47 @@ read_function_suppression(const ini::config::section& section)
> >   string label_str;
> >   maybe_get_string_prop(section, "label", label_str);
> >
> >-  ini::simple_property_sptr file_name_regex_prop =
> >-    is_simple_property(section.find_property("file_name_regexp"));
> >   regex_t_sptr file_name_regex;
> >-  if (file_name_regex_prop)
> >-    file_name_regex =
> >-      regex::compile(file_name_regex_prop->get_value()->as_string());
> >+  maybe_get_regex_prop(section, "file_name_regexp", file_name_regex);
> >
> >-  ini::simple_property_sptr file_name_not_regex_prop =
> >-    is_simple_property(section.find_property("file_name_not_regexp"));
> >   regex_t_sptr file_name_not_regex;
> >-  if (file_name_not_regex_prop)
> >-    file_name_not_regex =
> >-      regex::compile(file_name_not_regex_prop->get_value()->as_string());
> >+  maybe_get_regex_prop(section, "file_name_not_regexp", file_name_not_regex);
> >
> >-  ini::simple_property_sptr soname_regex_prop =
> >-    is_simple_property(section.find_property("soname_regexp"));
> >   regex_t_sptr soname_regex;
> >-  if (soname_regex_prop)
> >-    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
> >+  maybe_get_regex_prop(section, "soname_regexp", soname_regex);
> >
> >-  ini::simple_property_sptr soname_not_regex_prop =
> >-    is_simple_property(section.find_property("soname_not_regexp"));
> >   regex_t_sptr soname_not_regex;
> >-  if (soname_not_regex_prop)
> >-    soname_not_regex =
> >-      regex::compile(soname_not_regex_prop->get_value()->as_string());
> >+  maybe_get_regex_prop(section, "soname_not_regexp", soname_not_regex);
> >
> >   string name;
> >   maybe_get_string_prop(section, "name", name);
> >
> >-  ini::simple_property_sptr name_regex_prop =
> >-    is_simple_property(section.find_property("name_regexp"));
> >   regex_t_sptr name_regex;
> >-  if (name_regex_prop)
> >-    name_regex = regex::compile(name_regex_prop->get_value()->as_string());
> >+  maybe_get_regex_prop(section, "name_regexp", name_regex);
> >
> >-  ini::simple_property_sptr name_not_regex_prop =
> >-    is_simple_property(section.find_property("name_not_regexp"));
> >   regex_t_sptr name_not_regex;
> >-  if (name_not_regex_prop)
> >-    name_not_regex =
> >-      regex::compile(name_not_regex_prop->get_value()->as_string());
> >+  maybe_get_regex_prop(section, "name_not_regexp", name_not_regex);
> >
> >   string return_type_name;
> >   maybe_get_string_prop(section, "return_type_name", return_type_name);
> >
> >-  ini::simple_property_sptr return_type_regex_prop =
> >-    is_simple_property(section.find_property("return_type_regexp"));
> >   regex_t_sptr return_type_regex;
> >-  if (return_type_regex_prop)
> >-    return_type_regex =
> >-      regex::compile(return_type_regex_prop->get_value()->as_string());
> >+  maybe_get_regex_prop(section, "return_type_regexp", return_type_regex);
> >
> >   string sym_name;
> >   maybe_get_string_prop(section, "symbol_name", sym_name);
> >
> >-  ini::simple_property_sptr sym_name_regex_prop =
> >-    is_simple_property(section.find_property("symbol_name_regexp"));
> >   regex_t_sptr sym_name_regex;
> >-  if (sym_name_regex_prop)
> >-    sym_name_regex =
> >-      regex::compile(sym_name_regex_prop->get_value()->as_string());
> >+  maybe_get_regex_prop(section, "symbol_name_regexp", sym_name_regex);
> >
> >-  ini::simple_property_sptr sym_name_not_regex_prop =
> >-    is_simple_property(section.find_property("symbol_name_not_regexp"));
> >   regex_t_sptr sym_name_not_regex;
> >-  if (sym_name_not_regex_prop)
> >-    sym_name_not_regex =
> >-      regex::compile(sym_name_not_regex_prop->get_value()->as_string());
> >+  maybe_get_regex_prop(section, "symbol_name_not_regexp", sym_name_not_regex);
> >
> >   string sym_version;
> >   maybe_get_string_prop(section, "symbol_version", sym_version);
> >
> >-  ini::simple_property_sptr sym_ver_regex_prop =
> >-    is_simple_property(section.find_property("symbol_version_regexp"));
> >   regex_t_sptr sym_ver_regex;
> >-  if (sym_ver_regex_prop)
> >-    sym_ver_regex =
> >-      regex::compile(sym_ver_regex_prop->get_value()->as_string());
> >+  maybe_get_regex_prop(section, "symbol_version_regexp", sym_ver_regex);
> >
> >   string allow_other_aliases;
> >   maybe_get_string_prop(section, "allow_other_aliases", allow_other_aliases);
> >@@ -4025,85 +3985,47 @@ read_variable_suppression(const ini::config::section& section)
> >   string label_str;
> >   maybe_get_string_prop(section, "label", label_str);
> >
> >-  ini::simple_property_sptr file_name_regex_prop =
> >-    is_simple_property(section.find_property("file_name_regexp"));
> >   regex_t_sptr file_name_regex;
> >-  if (file_name_regex_prop)
> >-    file_name_regex =
> >-      regex::compile(file_name_regex_prop->get_value()->as_string());
> >-
> >- ini::simple_property_sptr file_name_not_regex_prop =
> >-  is_simple_property(section.find_property("file_name_not_regexp"));
> >- regex_t_sptr file_name_not_regex;
> >- if (file_name_not_regex_prop)
> >-   file_name_not_regex =
> >-     regex::compile(file_name_not_regex_prop->get_value()->as_string());
> >-
> >-  ini::simple_property_sptr soname_regex_prop =
> >-    is_simple_property(section.find_property("soname_regexp"));
> >+  maybe_get_regex_prop(section, "file_name_regexp", file_name_regex);
> >+
> >+  regex_t_sptr file_name_not_regex;
> >+  maybe_get_regex_prop(section, "file_name_not_regexp", file_name_not_regex);
> >+
> >   regex_t_sptr soname_regex;
> >-  if (soname_regex_prop)
> >-    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
> >+  maybe_get_regex_prop(section, "soname_regexp", soname_regex);
> >
> >-  ini::simple_property_sptr soname_not_regex_prop =
> >-    is_simple_property(section.find_property("soname_not_regexp"));
> >   regex_t_sptr soname_not_regex;
> >-  if (soname_not_regex_prop)
> >-    soname_not_regex =
> >-      regex::compile(soname_not_regex_prop->get_value()->as_string());
> >+  maybe_get_regex_prop(section, "soname_not_regexp", soname_not_regex);
> >
> >   string name_str;
> >   maybe_get_string_prop(section, "name", name_str);
> >
> >-  ini::simple_property_sptr name_regex_prop =
> >-    is_simple_property(section.find_property("name_regexp"));
> >   regex_t_sptr name_regex;
> >-  if (name_regex_prop)
> >-    name_regex = regex::compile(name_regex_prop->get_value()->as_string());
> >+  maybe_get_regex_prop(section, "name_regexp", name_regex);
> >
> >-  ini::simple_property_sptr name_not_regex_prop =
> >-    is_simple_property(section.find_property("name_not_regexp"));
> >   regex_t_sptr name_not_regex;
> >-  if (name_not_regex_prop)
> >-    name_not_regex =
> >-      regex::compile(name_not_regex_prop->get_value()->as_string());
> >+  maybe_get_regex_prop(section, "name_not_regexp", name_not_regex);
> >
> >   string symbol_name;
> >   maybe_get_string_prop(section, "symbol_name", symbol_name);
> >
> >-  ini::simple_property_sptr sym_name_regex_prop =
> >-    is_simple_property(section.find_property("symbol_name_regexp"));
> >   regex_t_sptr symbol_name_regex;
> >-  if (sym_name_regex_prop)
> >-    symbol_name_regex =
> >-      regex::compile(sym_name_regex_prop->get_value()->as_string());
> >+  maybe_get_regex_prop(section, "symbol_name_regexp", symbol_name_regex);
> >
> >-  ini::simple_property_sptr sym_name_not_regex_prop =
> >-    is_simple_property(section.find_property("symbol_name_not_regexp"));
> >   regex_t_sptr symbol_name_not_regex;
> >-  if (sym_name_not_regex_prop)
> >-    symbol_name_not_regex =
> >-      regex::compile(sym_name_not_regex_prop->get_value()->as_string());
> >+  maybe_get_regex_prop(section, "symbol_name_not_regexp", symbol_name_not_regex);
> >
> >   string symbol_version;
> >   maybe_get_string_prop(section, "symbol_version", symbol_version);
> >
> >-  ini::simple_property_sptr sym_version_regex_prop =
> >-    is_simple_property(section.find_property("symbol_version_regexp"));
> >   regex_t_sptr symbol_version_regex;
> >-  if (sym_version_regex_prop)
> >-    symbol_version_regex =
> >-      regex::compile(sym_version_regex_prop->get_value()->as_string());
> >+  maybe_get_regex_prop(section, "symbol_version_regexp", symbol_version_regex);
> >
> >   string type_name_str;
> >   maybe_get_string_prop(section, "type_name", type_name_str);
> >
> >-  ini::simple_property_sptr type_name_regex_prop =
> >-    is_simple_property(section.find_property("type_name_regexp"));
> >   regex_t_sptr type_name_regex;
> >-  if (type_name_regex_prop)
> >-    type_name_regex =
> >-      regex::compile(type_name_regex_prop->get_value()->as_string());
> >+  maybe_get_regex_prop(section, "type_name_regexp", type_name_regex);
> >
> >   result.reset(new variable_suppression(label_str,
> >                                       name_str,
> >@@ -4246,32 +4168,17 @@ read_file_suppression(const ini::config::section& section)
> >   string label_str;
> >   maybe_get_string_prop(section, "label", label_str);
> >
> >-  ini::simple_property_sptr file_name_regex_prop =
> >-    is_simple_property(section.find_property("file_name_regexp"));
> >   regex_t_sptr file_name_regex;
> >-  if (file_name_regex_prop)
> >-    file_name_regex =
> >-      regex::compile(file_name_regex_prop->get_value()->as_string());
> >-
> >- ini::simple_property_sptr file_name_not_regex_prop =
> >-    is_simple_property(section.find_property("file_name_not_regexp"));
> >- regex_t_sptr file_name_not_regex;
> >- if (file_name_not_regex_prop)
> >-   file_name_not_regex =
> >-     regex::compile(file_name_not_regex_prop->get_value()->as_string());
> >-
> >-  ini::simple_property_sptr soname_regex_prop =
> >-    is_simple_property(section.find_property("soname_regexp"));
> >+  maybe_get_regex_prop(section, "file_name_regexp", file_name_regex);
> >+
> >+  regex_t_sptr file_name_not_regex;
> >+  maybe_get_regex_prop(section, "file_name_not_regexp", file_name_not_regex);
> >+
> >   regex_t_sptr soname_regex;
> >-  if (soname_regex_prop)
> >-    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
> >+  maybe_get_regex_prop(section, "soname_regexp", soname_regex);
> >
> >-  ini::simple_property_sptr soname_not_regex_prop =
> >-    is_simple_property(section.find_property("soname_not_regexp"));
> >   regex_t_sptr soname_not_regex;
> >-  if (soname_not_regex_prop)
> >-    soname_not_regex =
> >-      regex::compile(soname_not_regex_prop->get_value()->as_string());
> >+  maybe_get_regex_prop(section, "soname_not_regexp", soname_not_regex);
> >
> >   result.reset(new file_suppression(label_str,
> >                                   file_name_regex,
> >--
> >2.26.2.303.gf8c07b1a785-goog
> >

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 01/21] Move regex definitions to own files.
  2020-04-27 10:52     ` Matthias Maennich
@ 2020-04-29 14:19       ` Dodji Seketeli
  2020-04-29 14:35         ` Giuliano Procida
  0 siblings, 1 reply; 120+ messages in thread
From: Dodji Seketeli @ 2020-04-29 14:19 UTC (permalink / raw)
  To: Matthias Maennich; +Cc: Giuliano Procida, libabigail, kernel-team

Hello Giuliano, Matthias,

Matthias Maennich <maennich@google.com> a écrit:

[...]

>>diff --git a/src/abg-corpus-priv.h b/src/abg-corpus-priv.h

[...]

>> #include "abg-sptr-utils.h"
>>+#include "abg-regex.h"
>> #include "abg-internal.h"
>
> While it was not before, please sort those includes.
>

Thanks Matthias, for the review, btw.

[...]

>>rename from src/abg-sptr-utils.cc
>>rename to src/abg-regex.cc

[...]

>> #include "abg-sptr-utils.h"
>>+#include "abg-regex.h"
>
> Sort.
>

[...]

>>--- a/src/abg-suppression-priv.h
>>+++ b/src/abg-suppression-priv.h
>>@@ -31,6 +31,7 @@
>> #include "abg-fwd.h"
>> #include "abg-suppression.h"
>> #include "abg-sptr-utils.h"
>>+#include "abg-regex.h"
>
> Sort includes alphabetical.
>
> With the above fixed:
> Reviewed-by: Matthias Maennich <maennich@google.com>

This looks good to me with the above.  It should go in with the changes
Matthias proposed.

I can apply your updated patch if you want.

Thanks a lot!

Cheers,

-- 
		Dodji

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 02/21] Move libxml bits out of abg-sptr-utils.h.
  2020-04-24  9:21   ` [PATCH v3 02/21] Move libxml bits out of abg-sptr-utils.h Giuliano Procida
  2020-04-27 10:53     ` Matthias Maennich
@ 2020-04-29 14:30     ` Dodji Seketeli
  2020-05-04  9:20     ` Dodji Seketeli
  2 siblings, 0 replies; 120+ messages in thread
From: Dodji Seketeli @ 2020-04-29 14:30 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, kernel-team, maennich

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

> The header file abg-sptr-utils.h contains generic things relating to
> shared pointers. It also contains shared pointer typedefs (in the
> sptr_utils namespace) and template specialisations for XML types.
>
> The last of these more naturally belong in abg-libxml-utils.h (and in
> the xml namespace). This patch moves them.
>
> There are no behavioural changes.
>
> 	* include/abg-sptr-utils.h: Remove reader_sptr and
> 	xml_char_sptr typedefs, from namespace
> 	sptr_utils. (build_sptr): Remove corresponding template
> 	function specialisations for these types.
> 	* include/abg-libxml-utils.h: Add reader_sptr and
> 	xml_char_sptr typedefs, to namespace xml. (build_sptr): Add
> 	corresponding template function specialisations for these
> 	types.

This looks good to me, and should go in after its previous one in the
series.

Thanks!

Cheers,


-- 
		Dodji

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 01/21] Move regex definitions to own files.
  2020-04-29 14:19       ` Dodji Seketeli
@ 2020-04-29 14:35         ` Giuliano Procida
  0 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-04-29 14:35 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Matthias Maennich, libabigail, kernel-team

Hi.

The v3 series should be good up to 16/21 (from my perspective). I'm
reworking 17+

Matthias hasn't change-approved everything from 1 to 16, I've included
his Reviewed-by in v3 when he had done so.

I'll look out for further review comments.

Thanks again.

Giuliano.

On Wed, 29 Apr 2020 at 15:19, Dodji Seketeli <dodji@seketeli.org> wrote:
>
> Hello Giuliano, Matthias,
>
> Matthias Maennich <maennich@google.com> a écrit:
>
> [...]
>
> >>diff --git a/src/abg-corpus-priv.h b/src/abg-corpus-priv.h
>
> [...]
>
> >> #include "abg-sptr-utils.h"
> >>+#include "abg-regex.h"
> >> #include "abg-internal.h"
> >
> > While it was not before, please sort those includes.
> >
>
> Thanks Matthias, for the review, btw.
>
> [...]
>
> >>rename from src/abg-sptr-utils.cc
> >>rename to src/abg-regex.cc
>
> [...]
>
> >> #include "abg-sptr-utils.h"
> >>+#include "abg-regex.h"
> >
> > Sort.
> >
>
> [...]
>
> >>--- a/src/abg-suppression-priv.h
> >>+++ b/src/abg-suppression-priv.h
> >>@@ -31,6 +31,7 @@
> >> #include "abg-fwd.h"
> >> #include "abg-suppression.h"
> >> #include "abg-sptr-utils.h"
> >>+#include "abg-regex.h"
> >
> > Sort includes alphabetical.
> >
> > With the above fixed:
> > Reviewed-by: Matthias Maennich <maennich@google.com>
>
> This looks good to me with the above.  It should go in with the changes
> Matthias proposed.
>
> I can apply your updated patch if you want.
>
> Thanks a lot!
>
> Cheers,
>
> --
>                 Dodji

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 19/21] Warn if user-supplied regexes fail to compile.
  2020-04-27 15:36     ` Matthias Maennich
@ 2020-05-01  8:49       ` Giuliano Procida
  0 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-05-01  8:49 UTC (permalink / raw)
  To: Matthias Maennich; +Cc: libabigail, Dodji Seketeli, kernel-team

Hi.

On Mon, 27 Apr 2020 at 16:36, Matthias Maennich <maennich@google.com> wrote:
>
> On Fri, Apr 24, 2020 at 10:21:30AM +0100, Giuliano Procida wrote:
> >There are not many calls to regex::compile in the code base. Two of
> >these pass internally-generated regexes and are followed by assertions
> >that the regexes compile.
> >
> >The remaining cases deal with user-supplied regexes. If these fail to
> >compile they are currently silently ignored.
> >
> >This patch makes sure failures now result in warning messages on
> >stderr, but otherwise does not change program behaviour.
> >
> >       * src/abg-corpus-priv.h
> >       (corpus::exported_decls_builder::priv::compiled_regex_fns_suppress):
> >       Emit a warning message if regex::compile fails.
> >       (corpus::exported_decls_builder::priv::compiled_regex_fns_keep):
> >       Ditto.
> >       (corpus::exported_decls_builder::priv::compiled_regex_vars_suppress):
> >       Ditto.
> >       (corpus::exported_decls_builder::priv::compiled_regex_vars_keep):
> >       Ditto.
> >       * src/abg-suppression.cc (maybe_get_string_prop): Ditto.
> >       (read_parameter_spec_from_string): Ditto.
>
> Is there an option to fail and terminate if such a configuration issue
> is detected?

That is definitely an option (and one I'd personally prefer). However,
we should be mindful of making breaking changes. We could have all
parsing/regex compilation etc. problems cause error messages in the
next major release of libabigail and make the errors terminate the
tool in the one after, for example.

Giuliano.


> But reporting the regex is already great as such!
>
> Reviewed-by: Matthias Maennich <maennich@google.com>
>
> Cheers,
> Matthias
>
> >
> >Signed-off-by: Giuliano Procida <gprocida@google.com>
> >---
> > src/abg-corpus-priv.h  | 10 ++++++++++
> > src/abg-suppression.cc |  4 ++++
> > 2 files changed, 14 insertions(+)
> >
> >diff --git a/src/abg-corpus-priv.h b/src/abg-corpus-priv.h
> >index 2618e2d0..a06a1a23 100644
> >--- a/src/abg-corpus-priv.h
> >+++ b/src/abg-corpus-priv.h
> >@@ -29,6 +29,8 @@
> > #ifndef __ABG_CORPUS_PRIV_H__
> > #define __ABG_CORPUS_PRIV_H__
> >
> >+#include <iostream>
> >+
> > #include "abg-sptr-utils.h"
> > #include "abg-regex.h"
> > #include "abg-internal.h"
> >@@ -126,6 +128,8 @@ public:
> >           regex_t_sptr r = regex::compile(*i);
> >           if (r)
> >             compiled_fns_suppress_regexp_.push_back(r);
> >+          else
> >+            std::cerr << "warning: bad regex '" << *i << "'\n";
> >         }
> >       }
> >     return compiled_fns_suppress_regexp_;
> >@@ -148,6 +152,8 @@ public:
> >           regex_t_sptr r = regex::compile(*i);
> >           if (r)
> >             compiled_fns_keep_regexps_.push_back(r);
> >+          else
> >+            std::cerr << "warning: bad regex '" << *i << "'\n";
> >         }
> >       }
> >     return compiled_fns_keep_regexps_;
> >@@ -170,6 +176,8 @@ public:
> >           regex_t_sptr r = regex::compile(*i);
> >           if (r)
> >             compiled_vars_suppress_regexp_.push_back(r);
> >+          else
> >+            std::cerr << "warning: bad regex '" << *i << "'\n";
> >         }
> >       }
> >     return compiled_vars_suppress_regexp_;
> >@@ -192,6 +200,8 @@ public:
> >           regex_t_sptr r = regex::compile(*i);
> >           if (r)
> >             compiled_vars_keep_regexps_.push_back(r);
> >+          else
> >+            std::cerr << "warning: bad regex '" << *i << "'\n";
> >         }
> >       }
> >     return compiled_vars_keep_regexps_;
> >diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
> >index 8b3631fd..e4b6554c 100644
> >--- a/src/abg-suppression.cc
> >+++ b/src/abg-suppression.cc
> >@@ -1640,6 +1640,8 @@ maybe_get_regex_prop(const ini::config::section& section,
> >   if (!maybe_get_string_prop(section, name, str))
> >     return false;
> >   regex = regex::compile(str);
> >+  if (!regex)
> >+    std::cerr << "warning: bad regex '" << str << "'\n";
> >   return true;
> > }
> >
> >@@ -3157,6 +3159,8 @@ read_parameter_spec_from_string(const string& str)
> >       if (is_regex)
> >       {
> >         type_name_regex = regex::compile(type_name);
> >+        if (!type_name_regex)
> >+          std::cerr << "warning: bad regex '" << type_name << "'\n";
> >         type_name.clear();
> >       }
> >       function_suppression::parameter_spec* p =
> >--
> >2.26.2.303.gf8c07b1a785-goog
> >

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 01/21] Move regex definitions to own files.
  2020-04-24  9:21   ` [PATCH v3 01/21] Move regex definitions to own files Giuliano Procida
  2020-04-27 10:52     ` Matthias Maennich
@ 2020-05-04  9:19     ` Dodji Seketeli
  1 sibling, 0 replies; 120+ messages in thread
From: Dodji Seketeli @ 2020-05-04  9:19 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, kernel-team, maennich

Hello Giuliano,

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

> As a prelude to adding wrapper and helper functions for regex
> functionality, it makes sense to move the existing regex code (the
> shared pointer type and its specialised deleter) to their own files.
>
> This patch does this and also moves various entities into a new
> namespace, abigail::regex. It removes the file abg-sptr-utils.cc which
> only contained regex things.
>
> There are no behavioural changes.
>
> 	* include/Makefile.am: Add abg-regex.h.
> 	* src/Makefile.am: Remove abg-sptr-utils.h, add abg-regex.cc
> 	* include/abg-sptr-utils.h (regex_t_sptr): Remove this
> 	typedef, from namespace abigail::sptr_utils.
> 	(regex_t_deleter): Remove this struct, from namespace
> 	abigail::sptr_utils. (build_sptr): Remove these template
> 	specialisations, in duplicate, for regex_t_sptr.
> 	* include/abg-regex.h: New file, introduces namespace
> 	abigail::regex. (regex_t_sptr): Add this typedef, to namespace
> 	abigail::regex. (regex_t_deleter): Add this struct, to
> 	namespace abigail::regex. (build_sptr): Add these template
> 	specialisations for regex_t_sptr
> 	* src/abg-sptr-utils.cc: Remove this file.
> 	* src/abg-regex.cc: Add new file with contents effectively
> 	the same as abg-sptr-utils.cc.
> 	* src/abg-corpus-priv.h: Update regex_t_sptr namespace
> 	qualification.
> 	* src/abg-corpus.cc: Ditto.
> 	* src/abg-suppression-priv.h: Ditto.
> 	* src/abg-suppression.cc: Ditto.

Applied to master.

Thanks!

-- 
		Dodji

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 02/21] Move libxml bits out of abg-sptr-utils.h.
  2020-04-24  9:21   ` [PATCH v3 02/21] Move libxml bits out of abg-sptr-utils.h Giuliano Procida
  2020-04-27 10:53     ` Matthias Maennich
  2020-04-29 14:30     ` Dodji Seketeli
@ 2020-05-04  9:20     ` Dodji Seketeli
  2 siblings, 0 replies; 120+ messages in thread
From: Dodji Seketeli @ 2020-05-04  9:20 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, kernel-team, maennich

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

> The header file abg-sptr-utils.h contains generic things relating to
> shared pointers. It also contains shared pointer typedefs (in the
> sptr_utils namespace) and template specialisations for XML types.
>
> The last of these more naturally belong in abg-libxml-utils.h (and in
> the xml namespace). This patch moves them.
>
> There are no behavioural changes.
>
> 	* include/abg-sptr-utils.h: Remove reader_sptr and
> 	xml_char_sptr typedefs, from namespace
> 	sptr_utils. (build_sptr): Remove corresponding template
> 	function specialisations for these types.
> 	* include/abg-libxml-utils.h: Add reader_sptr and
> 	xml_char_sptr typedefs, to namespace xml. (build_sptr): Add
> 	corresponding template function specialisations for these
> 	types.

Applied to master, thanks!

Cheers,

-- 
		Dodji

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v3 03/21] Simplify generation of symbol whitelist regex.
  2020-04-24  9:21   ` [PATCH v3 03/21] Simplify generation of symbol whitelist regex Giuliano Procida
  2020-04-27 11:01     ` Matthias Maennich
@ 2020-05-04  9:20     ` Dodji Seketeli
  1 sibling, 0 replies; 120+ messages in thread
From: Dodji Seketeli @ 2020-05-04  9:20 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, kernel-team, maennich

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

> The code to build the symbol whitelist regex uses things like seekp
> and tellp to generate regexes like "^foo$|^bar$".
>
> This patch simplifies the code, for further enhancement, resulting in
> generated regexes like "^(foo|bar)$".
>
> There should be no change in behaviour, unless whitelisted symbol
> names contain special regex characters.
>
> 	* include/abg-regex.h (generate_from_strings): Declare new
> 	function to build a regex from some strings, representing a
> 	membership test.
> 	* src/abg-regex.cc (generate_from_strings): Implement new
> 	function to build a regex from some strings, representing a
> 	membership test, in a straightfoward fashion.
> 	* src/abg-tools-utils.cc
> 	(gen_suppr_spec_from_kernel_abi_whitelists): Replace
> 	regex-building code with a call to generate_from_strings.
> 	* tests/test-kmi-whitelist.cc: Update regexes in test.

Applied to master, thanks!

Cheers,

-- 
		Dodji

^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v4 00/15] Simplify regex and suppression parsing.
  2020-04-24  9:21 ` [PATCH v3 00/21]Simplify " Giuliano Procida
                     ` (20 preceding siblings ...)
  2020-04-24  9:21   ` [PATCH v3 21/21] Remove unused suppression type priv constructors Giuliano Procida
@ 2020-05-04 12:34   ` Giuliano Procida
  2020-05-04 12:34     ` [PATCH v4 01/15] Tidy #includes in a few files Giuliano Procida
                       ` (14 more replies)
  21 siblings, 15 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-05-04 12:34 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

Patches 01/15 and 02/15 reflect review comments from patches 01/21 and
03/21 of the original series, respectively.

Patches 03/15 to 15/15 correspond to 04/21 to 16/21 of the original
series.

Patches 17/21 to 21/21 of the original series have been dropped as the
refactoring wasn't ideal. They have been reworked and will be reposted
as part of a new series.

Regards,
Giuliano.

Giuliano Procida (15):
  Tidy #includes in a few files.
  Document ^_^ regex in generate_from_strings.
  Escape names used in symbol whitelisting regex.
  abg-suppression.cc: More uniform variable naming.
  diff suppression: Fix handling of change kinds.
  Add POSIX regex wrapper functions.
  Use regex::compile wrapper instead of regcomp.
  Use regex::match wrapper instead of regexec.
  Refactor read_parameter_spec_from_string logic.
  Compile suppression regexes earlier.
  Reduce direct access to suppression priv_ members.
  Move match methods from priv to suppression_base.
  Remove suppression type priv class methods.
  abg-suppression.cc: More consistent regex matching.
  abg-tools-utils.cc: Assert generated regexes OK.

 include/abg-regex.h                           |   16 +
 include/abg-suppression.h                     |  180 +--
 src/abg-corpus-priv.h                         |   28 +-
 src/abg-corpus.cc                             |   12 +-
 src/abg-dwarf-reader.cc                       |    4 +-
 src/abg-reader.cc                             |    4 +-
 src/abg-regex.cc                              |   72 +-
 src/abg-suppression-priv.h                    |  684 +---------
 src/abg-suppression.cc                        | 1187 ++++++++---------
 src/abg-tools-utils.cc                        |   19 +-
 .../test15-suppr-added-fn-report-5.txt        |    6 +-
 .../test16-suppr-removed-fn-report-5.txt      |   15 +-
 .../test17-suppr-added-var-report-5.txt       |   15 +-
 .../test18-suppr-removed-var-report-5.txt     |   15 +-
 tests/test-kmi-whitelist.cc                   |   60 +-
 15 files changed, 897 insertions(+), 1420 deletions(-)

-- 
2.26.2.526.g744177e7f7-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v4 01/15] Tidy #includes in a few files.
  2020-05-04 12:34   ` [PATCH v4 00/15] Simplify regex and suppression parsing Giuliano Procida
@ 2020-05-04 12:34     ` Giuliano Procida
  2020-05-04 12:49       ` Matthias Maennich
  2020-05-11 13:24       ` Dodji Seketeli
  2020-05-04 12:34     ` [PATCH v4 02/15] Document ^_^ regex in generate_from_strings Giuliano Procida
                       ` (13 subsequent siblings)
  14 siblings, 2 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-05-04 12:34 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

Following review of a recent change to move regex definitions into
their own files, this commit ensures that #include directives are
separated into categories and sorted alphabetically within the
categories, subject to known ordering constraints (such as "config.h"
first, "abg-internal.h" before visibility directives etc.).

There are no behavioural changes.

	* src/abg-corpus-priv.h: Separate and sort #include
	directives.
	* src/abg-corpus.cc: Ditto.
	* src/abg-regex.cc: Ditto.
	* src/abg-suppression-priv.h: Ditto.
	* src/abg-suppression.cc: Ditto.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-corpus-priv.h      |  4 ++--
 src/abg-corpus.cc          | 12 +++++++-----
 src/abg-regex.cc           |  3 ++-
 src/abg-suppression-priv.h |  4 ++--
 src/abg-suppression.cc     |  1 +
 5 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/src/abg-corpus-priv.h b/src/abg-corpus-priv.h
index e65f7c8f..2b42007b 100644
--- a/src/abg-corpus-priv.h
+++ b/src/abg-corpus-priv.h
@@ -29,9 +29,9 @@
 #ifndef __ABG_CORPUS_PRIV_H__
 #define __ABG_CORPUS_PRIV_H__
 
-#include "abg-sptr-utils.h"
-#include "abg-regex.h"
 #include "abg-internal.h"
+#include "abg-regex.h"
+#include "abg-sptr-utils.h"
 
 namespace abigail
 {
diff --git a/src/abg-corpus.cc b/src/abg-corpus.cc
index 2dcc0ac7..7f763d56 100644
--- a/src/abg-corpus.cc
+++ b/src/abg-corpus.cc
@@ -21,23 +21,25 @@
 /// @file
 
 #include "config.h"
+
+#include <algorithm>
+#include <cassert>
 #include <cstdio>
 #include <cstring>
-#include <cassert>
 #include <stdexcept>
-#include <algorithm>
 
 #include "abg-cxx-compat.h"
 #include "abg-internal.h"
+
 // <headers defining libabigail's API go under here>
 ABG_BEGIN_EXPORT_DECLARATIONS
 
-#include "abg-sptr-utils.h"
-#include "abg-ir.h"
 #include "abg-corpus.h"
+#include "abg-ir.h"
 #include "abg-reader.h"
-#include "abg-writer.h"
+#include "abg-sptr-utils.h"
 #include "abg-tools-utils.h"
+#include "abg-writer.h"
 
 #if WITH_ZIP_ARCHIVE
 #include "abg-libzip-utils.h"
diff --git a/src/abg-regex.cc b/src/abg-regex.cc
index 79a89033..cf0663a2 100644
--- a/src/abg-regex.cc
+++ b/src/abg-regex.cc
@@ -24,8 +24,9 @@
 ///
 
 #include <sstream>
-#include "abg-sptr-utils.h"
+
 #include "abg-regex.h"
+#include "abg-sptr-utils.h"
 
 namespace abigail
 {
diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
index c37ceff6..0ccfde05 100644
--- a/src/abg-suppression-priv.h
+++ b/src/abg-suppression-priv.h
@@ -29,9 +29,9 @@
 #define __ABG_SUPPRESSION_PRIV_H__
 
 #include "abg-fwd.h"
-#include "abg-suppression.h"
-#include "abg-sptr-utils.h"
 #include "abg-regex.h"
+#include "abg-sptr-utils.h"
+#include "abg-suppression.h"
 
 namespace abigail
 {
diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 34eb9616..8b5712fb 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -26,6 +26,7 @@
 /// libabigail.
 
 #include <algorithm>
+
 #include "abg-cxx-compat.h"
 #include "abg-internal.h"
 
-- 
2.26.2.526.g744177e7f7-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v4 02/15] Document ^_^ regex in generate_from_strings.
  2020-05-04 12:34   ` [PATCH v4 00/15] Simplify regex and suppression parsing Giuliano Procida
  2020-05-04 12:34     ` [PATCH v4 01/15] Tidy #includes in a few files Giuliano Procida
@ 2020-05-04 12:34     ` Giuliano Procida
  2020-05-04 12:49       ` Matthias Maennich
  2020-05-11 13:32       ` Dodji Seketeli
  2020-05-04 12:34     ` [PATCH v4 03/15] Escape names used in symbol whitelisting regex Giuliano Procida
                       ` (12 subsequent siblings)
  14 siblings, 2 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-05-04 12:34 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

Following review of the change to simplify generation of symbol
whitelist regexes, this commit clarifies the purpose of the ^_^ regex
as one which will not match any string.

	* src/abg-regex.cc (generate_from_strings): Document ^_^
	regex.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-regex.cc | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/abg-regex.cc b/src/abg-regex.cc
index cf0663a2..0451d111 100644
--- a/src/abg-regex.cc
+++ b/src/abg-regex.cc
@@ -69,6 +69,7 @@ std::string
 generate_from_strings(const std::vector<std::string>& strs)
 {
   if (strs.empty())
+    // This cute-looking regex does not match any string.
     return "^_^";
   std::ostringstream os;
   std::vector<std::string>::const_iterator i = strs.begin();
-- 
2.26.2.526.g744177e7f7-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v4 03/15] Escape names used in symbol whitelisting regex.
  2020-05-04 12:34   ` [PATCH v4 00/15] Simplify regex and suppression parsing Giuliano Procida
  2020-05-04 12:34     ` [PATCH v4 01/15] Tidy #includes in a few files Giuliano Procida
  2020-05-04 12:34     ` [PATCH v4 02/15] Document ^_^ regex in generate_from_strings Giuliano Procida
@ 2020-05-04 12:34     ` Giuliano Procida
  2020-05-04 12:57       ` Matthias Maennich
  2020-05-04 12:34     ` [PATCH v4 04/15] abg-suppression.cc: More uniform variable naming Giuliano Procida
                       ` (11 subsequent siblings)
  14 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-05-04 12:34 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

There is the theoretical possibility that symbols may contain special
regex characters like '.' and '$'. This patch ensures all such
characters in symbol names are escaped before they are added to the
whitelisting regex.

	* include/regex.h (escape): New string reference holder
	class. (operator<<): Declaration of std::ostream,
	regex::escape overload.
	* include/regex.cc (operator<<): New std::ostream,
	regex::escape overload that outputs regex-escaped strings.
	* src/abg-tools-utils.cc
	(gen_suppr_spec_from_kernel_abi_whitelists): Make sure any
	special regex characters in symbol names are escaped.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 include/abg-regex.h | 10 ++++++++++
 src/abg-regex.cc    | 28 ++++++++++++++++++++++++++--
 2 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/include/abg-regex.h b/include/abg-regex.h
index d39ada46..164083cc 100644
--- a/include/abg-regex.h
+++ b/include/abg-regex.h
@@ -58,6 +58,16 @@ struct regex_t_deleter
   }
 };//end struct regex_deleter
 
+/// A class to hold a reference to a string to regex escape.
+struct escape
+{
+  escape(const std::string& str) : ref(str) { }
+  const std::string& ref;
+};
+
+std::ostream&
+operator<<(std::ostream& os, const escape& esc);
+
 std::string
 generate_from_strings(const std::vector<std::string>& strs);
 
diff --git a/src/abg-regex.cc b/src/abg-regex.cc
index 0451d111..a12ecc88 100644
--- a/src/abg-regex.cc
+++ b/src/abg-regex.cc
@@ -24,6 +24,7 @@
 ///
 
 #include <sstream>
+#include <ostream>
 
 #include "abg-regex.h"
 #include "abg-sptr-utils.h"
@@ -57,6 +58,29 @@ sptr_utils::build_sptr<regex_t>()
 namespace regex
 {
 
+/// Escape regex special charaters in input string.
+///
+/// @param os the output stream being written to.
+///
+/// @param esc the regex_escape object holding a reference to the string
+/// needing to be escaped.
+///
+/// @return the output stream.
+std::ostream&
+operator<<(std::ostream& os, const escape& esc)
+{
+  // ']' and '}' are only conditionally special, so could be removed.
+  static const std::string specials = "^.[]$()|*+?{}\\";
+  const std::string str = esc.ref;
+  for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
+    {
+      if (specials.find(*i) != std::string::npos)
+	os << '\\';
+      os << *i;
+    }
+  return os;
+}
+
 /// Generate a regex pattern equivalent to testing set membership.
 ///
 /// A string will match the resulting pattern regex, if and only if it
@@ -73,9 +97,9 @@ generate_from_strings(const std::vector<std::string>& strs)
     return "^_^";
   std::ostringstream os;
   std::vector<std::string>::const_iterator i = strs.begin();
-  os << "^(" << *i++;
+  os << "^(" << escape(*i++);
   while (i != strs.end())
-    os << "|" << *i++;
+    os << "|" << escape(*i++);
   os << ")$";
   return os.str();
 }
-- 
2.26.2.526.g744177e7f7-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v4 04/15] abg-suppression.cc: More uniform variable naming.
  2020-05-04 12:34   ` [PATCH v4 00/15] Simplify regex and suppression parsing Giuliano Procida
                       ` (2 preceding siblings ...)
  2020-05-04 12:34     ` [PATCH v4 03/15] Escape names used in symbol whitelisting regex Giuliano Procida
@ 2020-05-04 12:34     ` Giuliano Procida
  2020-05-11 14:04       ` Dodji Seketeli
  2020-05-04 12:34     ` [PATCH v4 05/15] diff suppression: Fix handling of change kinds Giuliano Procida
                       ` (10 subsequent siblings)
  14 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-05-04 12:34 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

In abg-suppression.cc most of the read_*_suppression functions
populate and return a single variable "result". Others vary a little
from this, having variables "nil" or "suppr".

This patch makes all the functions use a single variable "result".
This will make the next patches a bit simpler.

There are no behavioural changes.

	* src/abg-suppression.cc (read_type_suppression): Rename "nil"
	variable to "result" and reset it instead of introducing
	"suppr" later on. (read_function_suppression): Rename "nil"
	variable to "result" and reset it instead of introducing
	"result" later on.

Reviewed-by: Matthias Maennich <maennich@google.com>
Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-suppression.cc | 64 +++++++++++++++++++++---------------------
 1 file changed, 32 insertions(+), 32 deletions(-)

diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 8b5712fb..217ec5e9 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -1542,10 +1542,10 @@ read_suppression_reach_kind(const string& input)
 static type_suppression_sptr
 read_type_suppression(const ini::config::section& section)
 {
-  type_suppression_sptr nil;
+  type_suppression_sptr result;
 
   if (section.get_name() != "suppress_type")
-    return nil;
+    return result;
 
   ini::simple_property_sptr drop_artifact =
     is_simple_property(section.find_property("drop_artifact"));
@@ -1669,7 +1669,7 @@ read_type_suppression(const ini::config::section& section)
 	       type_suppression::insertion_range::create_fn_call_expr_boundary(ini::read_function_call_expr(ins_point)))
 	begin = expr;
       else
-	return nil;
+	return result;
 
       end = type_suppression::insertion_range::create_integer_boundary(-1);
       type_suppression::insertion_range_sptr insert_range
@@ -1712,7 +1712,7 @@ read_type_suppression(const ini::config::section& section)
 		   type_suppression::insertion_range::create_fn_call_expr_boundary(ini::read_function_call_expr(str)))
 	    begin = expr;
 	  else
-	    return nil;
+	    return result;
 
 	  str = val->get_content()[1];
 	  if (str == "end")
@@ -1725,7 +1725,7 @@ read_type_suppression(const ini::config::section& section)
 		   type_suppression::insertion_range::create_fn_call_expr_boundary(ini::read_function_call_expr(str)))
 	    end = expr;
 	  else
-	    return nil;
+	    return result;
 
 	  type_suppression::insertion_range_sptr insert_range
 	    (new type_suppression::insertion_range(begin, end));
@@ -1736,7 +1736,7 @@ read_type_suppression(const ini::config::section& section)
 	// the 'has_data_member_inserted_between' property has a wrong
 	// value type, so let's discard the endire [suppress_type]
 	// section.
-	return nil;
+	return result;
     }
 
   // Support has_data_members_inserted_between
@@ -1787,7 +1787,7 @@ read_type_suppression(const ini::config::section& section)
 		   type_suppression::insertion_range::create_fn_call_expr_boundary(ini::read_function_call_expr(str)))
 	    begin = expr;
 	  else
-	    return nil;
+	    return result;
 
 	  str = list_value->get_content()[1];
 	  if (str == "end")
@@ -1800,7 +1800,7 @@ read_type_suppression(const ini::config::section& section)
 		   type_suppression::insertion_range::create_fn_call_expr_boundary(ini::read_function_call_expr(str)))
 	    end = expr;
 	  else
-	    return nil;
+	    return result;
 
 	  type_suppression::insertion_range_sptr insert_range
 	    (new type_suppression::insertion_range(begin, end));
@@ -1808,7 +1808,7 @@ read_type_suppression(const ini::config::section& section)
 	  consider_data_member_insertion = true;
 	}
       if (!is_well_formed)
-	return nil;
+	return result;
     }
 
   /// Support 'changed_enumerators = foo, bar, baz'
@@ -1846,59 +1846,58 @@ read_type_suppression(const ini::config::section& section)
       && !consider_type_kind
       && srcloc_not_regexp_str.empty()
       && srcloc_not_in.empty())
-    return nil;
+    return result;
+
+  result.reset(new type_suppression(label_str, name_regex_str, name_str));
 
-  type_suppression_sptr suppr(new type_suppression(label_str,
-						   name_regex_str,
-						   name_str));
   if (consider_type_kind)
     {
-      suppr->set_consider_type_kind(true);
-      suppr->set_type_kind(type_kind);
+      result->set_consider_type_kind(true);
+      result->set_type_kind(type_kind);
     }
 
   if (consider_reach_kind)
     {
-      suppr->set_consider_reach_kind(true);
-      suppr->set_reach_kind(reach_kind);
+      result->set_consider_reach_kind(true);
+      result->set_reach_kind(reach_kind);
     }
 
   if (consider_data_member_insertion)
-    suppr->set_data_member_insertion_ranges(insert_ranges);
+    result->set_data_member_insertion_ranges(insert_ranges);
 
   if (!name_not_regex_str.empty())
-    suppr->set_type_name_not_regex_str(name_not_regex_str);
+    result->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);
+    result->set_file_name_regex_str(file_name_regex_str);
 
   if (!file_name_not_regex_str.empty())
-    suppr->set_file_name_not_regex_str(file_name_not_regex_str);
+    result->set_file_name_not_regex_str(file_name_not_regex_str);
 
   if (!soname_regex_str.empty())
-    suppr->set_soname_regex_str(soname_regex_str);
+    result->set_soname_regex_str(soname_regex_str);
 
   if (!soname_not_regex_str.empty())
-    suppr->set_soname_not_regex_str(soname_not_regex_str);
+    result->set_soname_not_regex_str(soname_not_regex_str);
 
   if (!srcloc_not_in.empty())
-    suppr->set_source_locations_to_keep(srcloc_not_in);
+    result->set_source_locations_to_keep(srcloc_not_in);
 
   if (!srcloc_not_regexp_str.empty())
-    suppr->set_source_location_to_keep_regex_str(srcloc_not_regexp_str);
+    result->set_source_location_to_keep_regex_str(srcloc_not_regexp_str);
 
   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
       && ((!name_regex_str.empty()
 	   || !name_str.empty()
 	   || !srcloc_not_regexp_str.empty()
 	   || !srcloc_not_in.empty())))
-    suppr->set_drops_artifact_from_ir(true);
+    result->set_drops_artifact_from_ir(true);
 
-  if (suppr->get_type_kind() == type_suppression::ENUM_TYPE_KIND
+  if (result->get_type_kind() == type_suppression::ENUM_TYPE_KIND
       && !changed_enumerator_names.empty())
-    suppr->set_changed_enumerator_names(changed_enumerator_names);
+    result->set_changed_enumerator_names(changed_enumerator_names);
 
-  return suppr;
+  return result;
 }
 
 // <function_suppression stuff>
@@ -3153,10 +3152,10 @@ read_parameter_spec_from_string(const string& str)
 static function_suppression_sptr
 read_function_suppression(const ini::config::section& section)
 {
-  function_suppression_sptr nil;
+  function_suppression_sptr result;
 
   if (section.get_name() != "suppress_function")
-    return nil;
+    return result;
 
   ini::simple_property_sptr drop_artifact =
     is_simple_property(section.find_property("drop_artifact"));
@@ -3284,7 +3283,6 @@ read_function_suppression(const ini::config::section& section)
 	  parms.push_back(parm);
       }
 
-  function_suppression_sptr result;
   if (!label_str.empty()
       || !name.empty()
       || !name_regex_str.empty()
@@ -3301,6 +3299,7 @@ read_function_suppression(const ini::config::section& section)
       || !sym_version.empty()
       || !sym_ver_regex_str.empty()
       || !parms.empty())
+
     result.reset(new function_suppression(label_str, name,
 					  name_regex_str,
 					  return_type_name,
@@ -4337,6 +4336,7 @@ read_file_suppression(const ini::config::section& section)
       && soname_regex_str.empty()
       && soname_not_regex_str.empty())
     return result;
+
   result.reset(new file_suppression(label_str,
 				    file_name_regex_str,
 				    file_name_not_regex_str));
-- 
2.26.2.526.g744177e7f7-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v4 05/15] diff suppression: Fix handling of change kinds.
  2020-05-04 12:34   ` [PATCH v4 00/15] Simplify regex and suppression parsing Giuliano Procida
                       ` (3 preceding siblings ...)
  2020-05-04 12:34     ` [PATCH v4 04/15] abg-suppression.cc: More uniform variable naming Giuliano Procida
@ 2020-05-04 12:34     ` Giuliano Procida
  2020-05-04 13:04       ` Matthias Maennich
  2020-05-11 14:15       ` Dodji Seketeli
  2020-05-04 12:34     ` [PATCH v4 06/15] Add POSIX regex wrapper functions Giuliano Procida
                       ` (9 subsequent siblings)
  14 siblings, 2 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-05-04 12:34 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

When parsing suppression specifications, libabigail attempts to detect
and ignore suppressions that are empty and so would match everything
in their category by default.

Unfortunately, with the way the parser currently works, these checks
have to be against an exhaustive list of fields that matter, rather
than by listing the fields that don't (like label). They are fragile
in the face of changes that add new fields.

Two of the short-cut checks are in fact buggy, missing out the
change_kind field. One of the checks also risks a null pointer
dereference as it doesn't actually trigger a return from the function.

This patch eliminates (rather than fixes up) this short-cutting on the
grounds that it is a maintenance burden and inconsistent behaviour.
Users should be able to do this:

[suppress_variable]
  label = Suppress all changes to variables

We could reinstate the logic when the code has global knowledge of
which fields are present and which have no suppression (restriction)
semantics, or perhaps just emit a warning message to the user if they
have supplied a completely empty (no label even) specification.

The patch also corrects 4 affected test cases to reflect that
suppression is actually happening (according to change_kind).

	* src/abg-suppression.cc (read_type_suppression): Remove
	short-circuiting of useless suppressions.
	(read_function_suppression): Ditto.
	(read_variable_suppression: Ditto.
	(read_file_suppression): Ditto.
	tests/data/test-diff-suppr/test15-suppr-added-fn-report-5.txt:
	Fix test - something is actually suppressed.
	* tests/data/test-diff-suppr/test16-suppr-removed-fn-report-5.txt:
	Ditto.
	* tests/data/test-diff-suppr/test17-suppr-added-var-report-5.txt:
	Ditto.
	* tests/data/test-diff-suppr/test18-suppr-removed-var-report-5.txt:
	Ditto.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-suppression.cc                        | 91 +++++--------------
 .../test15-suppr-added-fn-report-5.txt        |  6 +-
 .../test16-suppr-removed-fn-report-5.txt      | 15 +--
 .../test17-suppr-added-var-report-5.txt       | 15 +--
 .../test18-suppr-removed-var-report-5.txt     | 15 +--
 5 files changed, 26 insertions(+), 116 deletions(-)

diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 217ec5e9..51885cf2 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -1835,19 +1835,6 @@ read_type_suppression(const ini::config::section& section)
 	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()
-      && 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()
-      && srcloc_not_in.empty())
-    return result;
-
   result.reset(new type_suppression(label_str, name_regex_str, name_str));
 
   if (consider_type_kind)
@@ -3283,32 +3270,16 @@ read_function_suppression(const ini::config::section& section)
 	  parms.push_back(parm);
       }
 
-  if (!label_str.empty()
-      || !name.empty()
-      || !name_regex_str.empty()
-      || !name_not_regex_str.empty()
-      || !file_name_regex_str.empty()
-      || !file_name_not_regex_str.empty()
-      || !soname_regex_str.empty()
-      || !soname_not_regex_str.empty()
-      || !return_type_name.empty()
-      || !return_type_regex_str.empty()
-      || !sym_name.empty()
-      || !sym_name_regex_str.empty()
-      || !sym_name_not_regex_str.empty()
-      || !sym_version.empty()
-      || !sym_ver_regex_str.empty()
-      || !parms.empty())
-
-    result.reset(new function_suppression(label_str, name,
-					  name_regex_str,
-					  return_type_name,
-					  return_type_regex_str,
-					  parms,
-					  sym_name,
-					  sym_name_regex_str,
-					  sym_version,
-					  sym_ver_regex_str));
+  result.reset(new function_suppression(label_str,
+					name,
+					name_regex_str,
+					return_type_name,
+					return_type_regex_str,
+					parms,
+					sym_name,
+					sym_name_regex_str,
+					sym_version,
+					sym_ver_regex_str));
 
   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
       && (!name.empty()
@@ -3319,11 +3290,11 @@ read_function_suppression(const ini::config::section& section)
 	  || !sym_name_not_regex_str.empty()))
     result->set_drops_artifact_from_ir(true);
 
-  if (result && !change_kind_str.empty())
+  if (!change_kind_str.empty())
     result->set_change_kind
       (function_suppression::parse_change_kind(change_kind_str));
 
-  if (result && !allow_other_aliases.empty())
+  if (!allow_other_aliases.empty())
     result->set_allow_other_aliases(allow_other_aliases == "yes"
 				    || allow_other_aliases == "true");
 
@@ -4151,27 +4122,15 @@ read_variable_suppression(const ini::config::section& section)
     ? type_name_regex_prop->get_value()->as_string()
      : "";
 
-  if (label_str.empty()
-      && name_str.empty()
-      && name_regex_str.empty()
-      && name_not_regex_str.empty()
-      && file_name_regex_str.empty()
-      && file_name_not_regex_str.empty()
-      && soname_regex_str.empty()
-      && soname_not_regex_str.empty()
-      && symbol_name.empty()
-      && symbol_name_regex_str.empty()
-      && symbol_name_not_regex_str.empty()
-      && symbol_version.empty()
-      && symbol_version_regex_str.empty()
-      && type_name_str.empty()
-      && type_name_regex_str.empty())
-    return result;
-
-  result.reset(new variable_suppression(label_str, name_str, name_regex_str,
-					symbol_name, symbol_name_regex_str,
-					symbol_version, symbol_version_regex_str,
-					type_name_str, type_name_regex_str));
+  result.reset(new variable_suppression(label_str,
+					name_str,
+					name_regex_str,
+					symbol_name,
+					symbol_name_regex_str,
+					symbol_version,
+					symbol_version_regex_str,
+					type_name_str,
+					type_name_regex_str));
 
   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
       && (!name_str.empty()
@@ -4188,7 +4147,7 @@ read_variable_suppression(const ini::config::section& section)
   if (!symbol_name_not_regex_str.empty())
     result->set_symbol_name_not_regex_str(symbol_name_not_regex_str);
 
-  if (result && !change_kind_str.empty())
+  if (!change_kind_str.empty())
     result->set_change_kind
       (variable_suppression::parse_change_kind(change_kind_str));
 
@@ -4331,12 +4290,6 @@ read_file_suppression(const ini::config::section& section)
     ? soname_not_regex_prop->get_value()->as_string()
     : "";
 
-  if (file_name_regex_str.empty()
-      && file_name_not_regex_str.empty()
-      && soname_regex_str.empty()
-      && soname_not_regex_str.empty())
-    return result;
-
   result.reset(new file_suppression(label_str,
 				    file_name_regex_str,
 				    file_name_not_regex_str));
diff --git a/tests/data/test-diff-suppr/test15-suppr-added-fn-report-5.txt b/tests/data/test-diff-suppr/test15-suppr-added-fn-report-5.txt
index 4eaba5b7..83dfe326 100644
--- a/tests/data/test-diff-suppr/test15-suppr-added-fn-report-5.txt
+++ b/tests/data/test-diff-suppr/test15-suppr-added-fn-report-5.txt
@@ -1,10 +1,6 @@
-Functions changes summary: 0 Removed, 1 Changed, 1 Added functions
+Functions changes summary: 0 Removed, 1 Changed, 0 Added (1 filtered out) functions
 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 
-1 Added function:
-
-  [A] 'function void bar()'    {_Z3barv}
-
 1 function with some indirect sub-type change:
 
   [C] 'function void bar(S&)' has some indirect sub-type changes:
diff --git a/tests/data/test-diff-suppr/test16-suppr-removed-fn-report-5.txt b/tests/data/test-diff-suppr/test16-suppr-removed-fn-report-5.txt
index b28fbd16..851f7728 100644
--- a/tests/data/test-diff-suppr/test16-suppr-removed-fn-report-5.txt
+++ b/tests/data/test-diff-suppr/test16-suppr-removed-fn-report-5.txt
@@ -1,16 +1,3 @@
-Functions changes summary: 1 Removed, 1 Changed, 0 Added functions
+Functions changes summary: 0 Removed (1 filtered out), 0 Changed (1 filtered out), 0 Added functions
 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 
-1 Removed function:
-
-  [D] 'function void bar()'    {_Z3barv}
-
-1 function with some indirect sub-type change:
-
-  [C] 'function void bar(S*)' has some indirect sub-type changes:
-    parameter 1 of type 'S*' has sub-type changes:
-      in pointed to type 'struct S':
-        type size changed from 32 to 64 (in bits)
-        1 data member insertion:
-          'unsigned int S::bar', at offset 32 (in bits)
-
diff --git a/tests/data/test-diff-suppr/test17-suppr-added-var-report-5.txt b/tests/data/test-diff-suppr/test17-suppr-added-var-report-5.txt
index 6965a151..f4e0aa29 100644
--- a/tests/data/test-diff-suppr/test17-suppr-added-var-report-5.txt
+++ b/tests/data/test-diff-suppr/test17-suppr-added-var-report-5.txt
@@ -1,16 +1,3 @@
 Functions changes summary: 0 Removed, 0 Changed, 0 Added function
-Variables changes summary: 0 Removed, 1 Changed, 1 Added variables
-
-1 Added variable:
-
-  [A] 'int var1'    {var1}
-
-1 Changed variable:
-
-  [C] 'S* var0' was changed:
-    type of variable changed:
-      in pointed to type 'struct S':
-        type size changed from 32 to 64 (in bits)
-        1 data member insertion:
-          'char S::m1', at offset 32 (in bits)
+Variables changes summary: 0 Removed, 0 Changed (1 filtered out), 0 Added (1 filtered out) variables
 
diff --git a/tests/data/test-diff-suppr/test18-suppr-removed-var-report-5.txt b/tests/data/test-diff-suppr/test18-suppr-removed-var-report-5.txt
index 3edf2bd1..ac380a4a 100644
--- a/tests/data/test-diff-suppr/test18-suppr-removed-var-report-5.txt
+++ b/tests/data/test-diff-suppr/test18-suppr-removed-var-report-5.txt
@@ -1,16 +1,3 @@
 Functions changes summary: 0 Removed, 0 Changed, 0 Added function
-Variables changes summary: 1 Removed, 1 Changed, 0 Added variables
-
-1 Removed variable:
-
-  [D] 'int var1'    {var1}
-
-1 Changed variable:
-
-  [C] 'S* var0' was changed:
-    type of variable changed:
-      in pointed to type 'struct S':
-        type size changed from 32 to 64 (in bits)
-        1 data member insertion:
-          'char S::m1', at offset 32 (in bits)
+Variables changes summary: 0 Removed (1 filtered out), 0 Changed (1 filtered out), 0 Added variables
 
-- 
2.26.2.526.g744177e7f7-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v4 06/15] Add POSIX regex wrapper functions.
  2020-05-04 12:34   ` [PATCH v4 00/15] Simplify regex and suppression parsing Giuliano Procida
                       ` (4 preceding siblings ...)
  2020-05-04 12:34     ` [PATCH v4 05/15] diff suppression: Fix handling of change kinds Giuliano Procida
@ 2020-05-04 12:34     ` Giuliano Procida
  2020-05-11 16:37       ` Dodji Seketeli
  2020-05-04 12:34     ` [PATCH v4 07/15] Use regex::compile wrapper instead of regcomp Giuliano Procida
                       ` (8 subsequent siblings)
  14 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-05-04 12:34 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

libabigail code uses the POSIX regex library consistently:

    - compile std::string to regex, with the flag REG_EXTENDED
    - store regex using a shared pointer wrapper
    - check match of regex against std::string

All the C string / std::string logic and so on is repeated at every
call site. This patch introduces wrapper functions to take care of
this logic.

There are no behavioural changes.

	* include/abg-regex.h (compile): Declare new function.
	(match): Declare new function.
	* src/abg-regex.cc (compile): Add new function wrapping
	regcomp. (match): Add new function wrapping regexec.

Reviewed-by: Matthias Maennich <maennich@google.com>
Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 include/abg-regex.h |  6 ++++++
 src/abg-regex.cc    | 40 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+)

diff --git a/include/abg-regex.h b/include/abg-regex.h
index 164083cc..7ab9fc08 100644
--- a/include/abg-regex.h
+++ b/include/abg-regex.h
@@ -71,6 +71,12 @@ operator<<(std::ostream& os, const escape& esc);
 std::string
 generate_from_strings(const std::vector<std::string>& strs);
 
+regex_t_sptr
+compile(const std::string& str);
+
+bool
+match(const regex_t_sptr& r, const std::string& str);
+
 }// end namespace regex
 
 namespace sptr_utils
diff --git a/src/abg-regex.cc b/src/abg-regex.cc
index a12ecc88..cd7c41ce 100644
--- a/src/abg-regex.cc
+++ b/src/abg-regex.cc
@@ -23,12 +23,22 @@
 /// Some specialization for shared pointer utility templates.
 ///
 
+#include "config.h"
+
 #include <sstream>
 #include <ostream>
 
+#include "abg-internal.h"
+
+// <headers defining libabigail's API go under here>
+ABG_BEGIN_EXPORT_DECLARATIONS
+
 #include "abg-regex.h"
 #include "abg-sptr-utils.h"
 
+ABG_END_EXPORT_DECLARATIONS
+// </headers defining libabigail's API>
+
 namespace abigail
 {
 
@@ -104,6 +114,36 @@ generate_from_strings(const std::vector<std::string>& strs)
   return os.str();
 }
 
+/// Compile a regex from a string.
+///
+/// The result is held in a shared pointer. This will be null if regex
+/// compilation fails.
+///
+/// @param str the string representation of the regex.
+///
+/// @return shared pointer holder of a compiled regex object.
+regex_t_sptr
+compile(const std::string& str)
+{
+  regex_t_sptr r = sptr_utils::build_sptr(new regex_t);
+  if (regcomp(r.get(), str.c_str(), REG_EXTENDED))
+    r.reset();
+  return r;
+}
+
+/// See if a string matches a regex.
+///
+/// @param r a shared pointer holder of a compiled regex object.
+///
+/// @param str a string.
+///
+/// @return whether there was a match.
+bool
+match(const regex_t_sptr& r, const std::string& str)
+{
+  return !regexec(r.get(), str.c_str(), 0, NULL, 0);
+}
+
 }//end namespace regex
 
 }//end namespace abigail
-- 
2.26.2.526.g744177e7f7-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v4 07/15] Use regex::compile wrapper instead of regcomp.
  2020-05-04 12:34   ` [PATCH v4 00/15] Simplify regex and suppression parsing Giuliano Procida
                       ` (5 preceding siblings ...)
  2020-05-04 12:34     ` [PATCH v4 06/15] Add POSIX regex wrapper functions Giuliano Procida
@ 2020-05-04 12:34     ` Giuliano Procida
  2020-05-11 16:38       ` Dodji Seketeli
  2020-05-04 12:34     ` [PATCH v4 08/15] Use regex::match wrapper instead of regexec Giuliano Procida
                       ` (7 subsequent siblings)
  14 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-05-04 12:34 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

This patch eliminates all calls to regcomp except that by
regex::compile itself.

	* src/abg-corpus-priv.h: Mechanically substitute use of
	regcomp with regex::compile wrapper.
	* src/abg-suppression-priv.h: Ditto.

There are no behavioural changes.

Reviewed-by: Matthias Maennich <maennich@google.com>
Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-corpus-priv.h      |  16 +--
 src/abg-suppression-priv.h | 198 ++++++-------------------------------
 2 files changed, 38 insertions(+), 176 deletions(-)

diff --git a/src/abg-corpus-priv.h b/src/abg-corpus-priv.h
index 2b42007b..f408e453 100644
--- a/src/abg-corpus-priv.h
+++ b/src/abg-corpus-priv.h
@@ -123,8 +123,8 @@ public:
 	     i != fns_suppress_regexps_.end();
 	     ++i)
 	  {
-	    regex_t_sptr r = sptr_utils::build_sptr(new regex_t);
-	    if (regcomp(r.get(), i->c_str(), REG_EXTENDED) == 0)
+	    regex_t_sptr r = regex::compile(*i);
+	    if (r)
 	      compiled_fns_suppress_regexp_.push_back(r);
 	  }
       }
@@ -145,8 +145,8 @@ public:
 	     i != fns_keep_regexps_.end();
 	     ++i)
 	  {
-	    regex_t_sptr r = sptr_utils::build_sptr(new regex_t);
-	    if (regcomp(r.get(), i->c_str(), REG_EXTENDED) == 0)
+	    regex_t_sptr r = regex::compile(*i);
+	    if (r)
 	      compiled_fns_keep_regexps_.push_back(r);
 	  }
       }
@@ -167,8 +167,8 @@ public:
 	     i != vars_suppress_regexps_.end();
 	     ++i)
 	  {
-	    regex_t_sptr r = sptr_utils::build_sptr(new regex_t);
-	    if (regcomp(r.get(), i->c_str(), REG_EXTENDED) == 0)
+	    regex_t_sptr r = regex::compile(*i);
+	    if (r)
 	      compiled_vars_suppress_regexp_.push_back(r);
 	  }
       }
@@ -189,8 +189,8 @@ public:
 	     i != vars_keep_regexps_.end();
 	     ++i)
 	  {
-	    regex_t_sptr r = sptr_utils::build_sptr(new regex_t);
-	    if (regcomp(r.get(), i->c_str(), REG_EXTENDED) == 0)
+	    regex_t_sptr r = regex::compile(*i);
+	    if (r)
 	      compiled_vars_keep_regexps_.push_back(r);
 	  }
       }
diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
index 0ccfde05..65d919a8 100644
--- a/src/abg-suppression-priv.h
+++ b/src/abg-suppression-priv.h
@@ -91,17 +91,8 @@ public:
   const regex::regex_t_sptr&
   get_file_name_regex() const
   {
-    if (!file_name_regex_)
-      {
-	if (!file_name_regex_str_.empty())
-	  {
-	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	    if (regcomp(r.get(),
-			file_name_regex_str_.c_str(),
-			REG_EXTENDED) == 0)
-	      file_name_regex_ = r;
-	  }
-      }
+    if (!file_name_regex_ && !file_name_regex_str_.empty())
+      file_name_regex_ = regex::compile(file_name_regex_str_);
     return file_name_regex_;
   }
 
@@ -116,17 +107,8 @@ public:
   const regex::regex_t_sptr&
   get_file_name_not_regex() const
   {
-    if (!file_name_not_regex_)
-      {
-	if (!file_name_not_regex_str_.empty())
-	  {
-	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	    if (regcomp(r.get(),
-			file_name_not_regex_str_.c_str(),
-			REG_EXTENDED) == 0)
-	      file_name_not_regex_ = r;
-	  }
-      }
+    if (!file_name_not_regex_ && !file_name_not_regex_str_.empty())
+      file_name_not_regex_ = regex::compile(file_name_not_regex_str_);
     return file_name_not_regex_;
   }
 
@@ -141,17 +123,8 @@ public:
   const regex::regex_t_sptr&
   get_soname_regex() const
   {
-    if (!soname_regex_)
-      {
-	if (!soname_regex_str_.empty())
-	  {
-	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	    if (regcomp(r.get(),
-			soname_regex_str_.c_str(),
-			REG_EXTENDED) == 0)
-	      soname_regex_ = r;
-	  }
-      }
+    if (!soname_regex_ && !soname_regex_str_.empty())
+      soname_regex_ = regex::compile(soname_regex_str_);
     return soname_regex_;
   }
 
@@ -166,17 +139,8 @@ public:
   const regex::regex_t_sptr&
   get_soname_not_regex() const
   {
-    if (!soname_not_regex_)
-      {
-	if (!soname_not_regex_str_.empty())
-	  {
-	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	    if (regcomp(r.get(),
-			soname_not_regex_str_.c_str(),
-			REG_EXTENDED) == 0)
-	      soname_not_regex_ = r;
-	  }
-      }
+    if (!soname_not_regex_ && !soname_not_regex_str_.empty())
+      soname_not_regex_ = regex::compile(soname_not_regex_str_);
     return soname_not_regex_;
   }
 
@@ -282,13 +246,7 @@ class function_suppression::parameter_spec::priv
   get_type_name_regex() const
   {
     if (!type_name_regex_ && !type_name_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    type_name_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  type_name_regex_ = r;
-      }
+      type_name_regex_ = regex::compile(type_name_regex_str_);
     return type_name_regex_;
   }
 }; // end class function_suppression::parameter_spec::priv
@@ -361,13 +319,7 @@ struct function_suppression::priv
   get_name_regex() const
   {
     if (!name_regex_ && !name_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    name_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  name_regex_ = r;
-      }
+      name_regex_ = regex::compile(name_regex_str_);
     return name_regex_;
   }
 
@@ -384,13 +336,7 @@ struct function_suppression::priv
   get_name_not_regex() const
   {
     if (!name_not_regex_ && !name_not_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    name_not_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  name_not_regex_ = r;
-      }
+      name_not_regex_ = regex::compile(name_not_regex_str_);
     return name_not_regex_;
   }
 
@@ -407,13 +353,7 @@ struct function_suppression::priv
   get_return_type_regex() const
   {
     if (!return_type_regex_ && !return_type_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    return_type_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  return_type_regex_ = r;
-      }
+      return_type_regex_ = regex::compile(return_type_regex_str_);
     return return_type_regex_;
   }
 
@@ -430,13 +370,7 @@ struct function_suppression::priv
   get_symbol_name_regex() const
   {
     if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    symbol_name_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  symbol_name_regex_ = r;
-      }
+      symbol_name_regex_ = regex::compile(symbol_name_regex_str_);
     return symbol_name_regex_;
   }
 
@@ -453,13 +387,7 @@ struct function_suppression::priv
   get_symbol_name_not_regex() const
   {
     if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    symbol_name_not_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  symbol_name_not_regex_ = r;
-      }
+      symbol_name_not_regex_ = regex::compile(symbol_name_not_regex_str_);
     return symbol_name_not_regex_;
   }
 
@@ -475,14 +403,8 @@ struct function_suppression::priv
   const regex::regex_t_sptr
   get_symbol_version_regex() const
   {
-    if (!symbol_version_regex_ && ! symbol_version_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    symbol_version_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  symbol_version_regex_ = r;
-      }
+    if (!symbol_version_regex_ && !symbol_version_regex_str_.empty())
+      symbol_version_regex_ = regex::compile(symbol_version_regex_str_);
     return symbol_version_regex_;
   }
 }; // end class function_suppression::priv
@@ -609,13 +531,7 @@ struct variable_suppression::priv
   get_name_regex() const
   {
     if (!name_regex_ && !name_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    name_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  name_regex_ = r;
-      }
+      name_regex_ = regex::compile(name_regex_str_);
     return name_regex_;
   }
 
@@ -632,13 +548,7 @@ struct variable_suppression::priv
   get_name_not_regex() const
   {
     if (!name_not_regex_ && !name_not_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    name_not_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  name_not_regex_ = r;
-      }
+      name_not_regex_ = regex::compile(name_not_regex_str_);
     return name_not_regex_;
   }
 
@@ -655,13 +565,7 @@ struct variable_suppression::priv
   get_symbol_name_regex() const
   {
     if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    symbol_name_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  symbol_name_regex_ = r;
-      }
+      symbol_name_regex_ = regex::compile(symbol_name_regex_str_);
     return symbol_name_regex_;
   }
 
@@ -678,12 +582,7 @@ struct variable_suppression::priv
   get_symbol_name_not_regex() const
   {
     if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(), symbol_name_not_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  symbol_name_not_regex_ = r;
-      }
+      symbol_name_not_regex_ = regex::compile(symbol_name_not_regex_str_);
     return symbol_name_not_regex_;
   }
 
@@ -700,13 +599,7 @@ struct variable_suppression::priv
   get_symbol_version_regex()  const
   {
     if (!symbol_version_regex_ && !symbol_version_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    symbol_version_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  symbol_version_regex_ = r;
-      }
+      symbol_version_regex_ = regex::compile(symbol_version_regex_str_);
     return symbol_version_regex_;
   }
 
@@ -723,13 +616,7 @@ struct variable_suppression::priv
   get_type_name_regex() const
   {
     if (!type_name_regex_ && !type_name_regex_str_.empty())
-      {
-	regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	if (regcomp(r.get(),
-		    type_name_regex_str_.c_str(),
-		    REG_EXTENDED) == 0)
-	  type_name_regex_ = r;
-      }
+      type_name_regex_ = regex::compile(type_name_regex_str_);
     return type_name_regex_;
   }
 };// end class variable_supppression::priv
@@ -809,17 +696,8 @@ public:
   const regex::regex_t_sptr
   get_type_name_regex() const
   {
-    if (!type_name_regex_)
-      {
-	if (!type_name_regex_str_.empty())
-	  {
-	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	    if (regcomp(r.get(),
-			type_name_regex_str_.c_str(),
-			REG_EXTENDED) == 0)
-	      type_name_regex_ = r;
-	  }
-      }
+    if (!type_name_regex_ && !type_name_regex_str_.empty())
+      type_name_regex_ = regex::compile(type_name_regex_str_);
     return type_name_regex_;
   }
 
@@ -841,17 +719,8 @@ public:
   const regex::regex_t_sptr
   get_type_name_not_regex() const
   {
-    if (!type_name_not_regex_)
-      {
-	if (!type_name_not_regex_str_.empty())
-	  {
-	    regex::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;
-	  }
-      }
+    if (!type_name_not_regex_ && !type_name_not_regex_str_.empty())
+      type_name_not_regex_ = regex::compile(type_name_not_regex_str_);
     return type_name_not_regex_;
   }
 
@@ -886,17 +755,10 @@ public:
   const regex::regex_t_sptr
   get_source_location_to_keep_regex() const
   {
-    if (!source_location_to_keep_regex_)
-      {
-	if (!source_location_to_keep_regex_str_.empty())
-	  {
-	    regex::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
-	    if (regcomp(r.get(),
-			source_location_to_keep_regex_str_.c_str(),
-			REG_EXTENDED) == 0)
-	      source_location_to_keep_regex_ = r;
-	  }
-      }
+    if (!source_location_to_keep_regex_
+	&& !source_location_to_keep_regex_str_.empty())
+      source_location_to_keep_regex_ =
+	  regex::compile(source_location_to_keep_regex_str_);
     return source_location_to_keep_regex_;
   }
 
-- 
2.26.2.526.g744177e7f7-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v4 08/15] Use regex::match wrapper instead of regexec.
  2020-05-04 12:34   ` [PATCH v4 00/15] Simplify regex and suppression parsing Giuliano Procida
                       ` (6 preceding siblings ...)
  2020-05-04 12:34     ` [PATCH v4 07/15] Use regex::compile wrapper instead of regcomp Giuliano Procida
@ 2020-05-04 12:34     ` Giuliano Procida
  2020-05-12 16:35       ` Dodji Seketeli
  2020-05-04 12:34     ` [PATCH v4 09/15] Refactor read_parameter_spec_from_string logic Giuliano Procida
                       ` (6 subsequent siblings)
  14 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-05-04 12:34 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

This patch eliminates all calls to regexec except that by regex::match
itself.

There are no behavioural changes.

	* src/abg-corpus-priv.h: Mechanically substitute use of
	regexec with regex::match wrapper.
	* src/abg-suppression-priv.h: Ditto.
	* src/abg-suppression.cc: Ditto.

Reviewed-by: Matthias Maennich <maennich@google.com>
Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-corpus-priv.h      |   8 +--
 src/abg-suppression-priv.h |  10 ++--
 src/abg-suppression.cc     | 119 +++++++++++--------------------------
 3 files changed, 44 insertions(+), 93 deletions(-)

diff --git a/src/abg-corpus-priv.h b/src/abg-corpus-priv.h
index f408e453..ee8c8239 100644
--- a/src/abg-corpus-priv.h
+++ b/src/abg-corpus-priv.h
@@ -521,7 +521,7 @@ public:
 	   compiled_regex_fns_suppress().begin();
 	 i != compiled_regex_fns_suppress().end();
 	 ++i)
-      if (regexec(i->get(), frep.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(*i, frep))
 	{
 	  keep = false;
 	  break;
@@ -554,7 +554,7 @@ public:
 	     compiled_regex_fns_keep().begin();
 	   i != compiled_regex_fns_keep().end();
 	   ++i)
-	if (regexec(i->get(), frep.c_str(), 0, NULL, 0) == 0)
+	if (regex::match(*i, frep))
 	  {
 	    keep = true;
 	    break;
@@ -628,7 +628,7 @@ public:
 	   compiled_regex_vars_suppress().begin();
 	 i != compiled_regex_vars_suppress().end();
 	 ++i)
-      if (regexec(i->get(), frep.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(*i, frep))
 	{
 	  keep = false;
 	  break;
@@ -662,7 +662,7 @@ public:
 	       compiled_regex_vars_keep().begin();
 	     i != compiled_regex_vars_keep().end();
 	     ++i)
-	  if (regexec(i->get(), frep.c_str(), 0, NULL, 0) == 0)
+	  if (regex::match(*i, frep))
 	    {
 	      keep = true;
 	      break;
diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
index 65d919a8..deb08269 100644
--- a/src/abg-suppression-priv.h
+++ b/src/abg-suppression-priv.h
@@ -160,14 +160,14 @@ public:
     if (regex::regex_t_sptr regexp = get_soname_regex())
       {
 	has_regexp = true;
-	if (regexec(regexp.get(), soname.c_str(), 0, NULL, 0) != 0)
+	if (!regex::match(regexp, soname))
 	  return false;
       }
 
     if (regex::regex_t_sptr regexp = get_soname_not_regex())
       {
 	has_regexp = true;
-	if (regexec(regexp.get(), soname.c_str(), 0, NULL, 0) == 0)
+	if (regex::match(regexp, soname))
 	  return false;
       }
 
@@ -195,16 +195,14 @@ public:
     if (regex::regex_t_sptr regexp = get_file_name_regex())
       {
 	has_regexp = true;
-	if (regexec(regexp.get(), binary_name.c_str(),
-	  0, NULL, 0) != 0)
+	if (!regex::match(regexp, binary_name))
 	  return false;
       }
 
     if (regex::regex_t_sptr regexp = get_file_name_not_regex())
       {
 	has_regexp = true;
-	if (regexec(regexp.get(), binary_name.c_str(),
-	  0, NULL, 0) == 0)
+	if (regex::match(regexp, binary_name))
 	  return false;
       }
 
diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 51885cf2..c89201b6 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -990,18 +990,14 @@ suppression_matches_type_name(const type_suppression&	s,
 	  if (const 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)
+	      if (!regex::match(type_name_regex, type_name))
 		return false;
 	    }
 
 	  if (const 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)
+	      if (regex::match(type_name_not_regex, type_name))
 		return false;
 	    }
 	}
@@ -1048,7 +1044,7 @@ suppression_matches_type_location(const type_suppression&	s,
       loc.expand(loc_path, loc_line, loc_column);
 
       if (regex_t_sptr regexp = s.priv_->get_source_location_to_keep_regex())
-	if (regexec(regexp.get(), loc_path.c_str(), 0, NULL, 0) == 0)
+	if (regex::match(regexp, loc_path))
 	  return false;
 
       tools_utils::base_name(loc_path, loc_path_base);
@@ -2484,9 +2480,7 @@ function_suppression::suppresses_function(const function_decl* fn,
   const regex_t_sptr name_regex = priv_->get_name_regex();
   if (name_regex)
     {
-      if (regexec(name_regex.get(),
-		  fname.c_str(),
-		  0, NULL, 0) != 0)
+      if (!regex::match(name_regex, fname))
 	return false;
 
       if (get_allow_other_aliases()
@@ -2507,9 +2501,7 @@ function_suppression::suppresses_function(const function_decl* fn,
 	      for (elf_symbol_sptr a = sym->get_next_alias();
 		   a && !a->is_main_symbol();
 		   a = a->get_next_alias())
-		if (regexec(name_regex.get(),
-			    a->get_name().c_str(),
-			    0, NULL, 0) != 0)
+		if (!regex::match(name_regex, a->get_name()))
 		  return false;
 	    }
 	}
@@ -2519,9 +2511,7 @@ function_suppression::suppresses_function(const function_decl* fn,
   const regex_t_sptr name_not_regex = priv_->get_name_not_regex();
   if (name_not_regex)
     {
-      if (regexec(name_not_regex.get(),
-		  fname.c_str(),
-		  0, NULL, 0) == 0)
+      if (regex::match(name_not_regex, fname))
 	return false;
 
       if (get_allow_other_aliases()
@@ -2542,9 +2532,7 @@ function_suppression::suppresses_function(const function_decl* fn,
 	      for (elf_symbol_sptr a = sym->get_next_alias();
 		   a && !a->is_main_symbol();
 		   a = a->get_next_alias())
-		if (regexec(name_regex.get(),
-			    a->get_name().c_str(),
-			    0, NULL, 0) == 0)
+		if (regex::match(name_regex, a->get_name()))
 		  return false;
 	    }
 	}
@@ -2568,9 +2556,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     {
       const regex_t_sptr return_type_regex = priv_->get_return_type_regex();
       if (return_type_regex
-	  && (regexec(return_type_regex.get(),
-		      fn_return_type_name.c_str(),
-		      0, NULL, 0) != 0))
+	  && !regex::match(return_type_regex, fn_return_type_name))
 	return false;
     }
 
@@ -2607,18 +2593,13 @@ function_suppression::suppresses_function(const function_decl* fn,
   else if (sym)
     {
       const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
-      if (symbol_name_regex
-	  && (regexec(symbol_name_regex.get(),
-		      fn_sym_name.c_str(),
-		      0, NULL, 0) != 0))
+      if (symbol_name_regex && !regex::match(symbol_name_regex, fn_sym_name))
 	return false;
 
       const regex_t_sptr symbol_name_not_regex =
 	priv_->get_symbol_name_not_regex();
       if (symbol_name_not_regex
-	  && (regexec(symbol_name_not_regex.get(),
-		      fn_sym_name.c_str(),
-		      0, NULL, 0) == 0))
+	  && regex::match(symbol_name_not_regex, fn_sym_name))
 	return false;
 
       if (get_allow_other_aliases())
@@ -2633,15 +2614,11 @@ function_suppression::suppresses_function(const function_decl* fn,
 		   a = a->get_next_alias())
 		{
 		  if (symbol_name_regex
-		      && (regexec(symbol_name_regex.get(),
-				  a->get_name().c_str(),
-				  0, NULL, 0) != 0))
+		      && !regex::match(symbol_name_regex, a->get_name()))
 		    return false;
 
 		  if (symbol_name_not_regex
-		      && (regexec(symbol_name_not_regex.get(),
-				  a->get_name().c_str(),
-				  0, NULL, 0) == 0))
+		      && regex::match(symbol_name_not_regex, a->get_name()))
 		    return false;
 		}
 	    }
@@ -2660,9 +2637,7 @@ function_suppression::suppresses_function(const function_decl* fn,
       const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
       if (symbol_version_regex
-	  && (regexec(symbol_version_regex.get(),
-		      fn_sym_version.c_str(),
-		      0, NULL, 0) != 0))
+	  && !regex::match(symbol_version_regex, fn_sym_version))
 	return false;
     }
 
@@ -2703,9 +2678,8 @@ function_suppression::suppresses_function(const function_decl* fn,
 		(*p)->priv_->get_type_name_regex();
 	      if (parm_type_name_regex)
 		{
-		  if ((regexec(parm_type_name_regex.get(),
-			       fn_parm_type_qualified_name.c_str(),
-			       0, NULL, 0) != 0))
+		  if (!regex::match(parm_type_name_regex,
+				    fn_parm_type_qualified_name))
 		    return false;
 		}
 	    }
@@ -2793,10 +2767,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
   else if (!get_symbol_name_regex_str().empty())
     {
       const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
-      if (symbol_name_regex
-	  && (regexec(symbol_name_regex.get(),
-		      sym_name.c_str(),
-		      0, NULL, 0) != 0))
+      if (symbol_name_regex && !regex::match(symbol_name_regex, sym_name))
 	return false;
     }
   else
@@ -2813,9 +2784,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
       const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
       if (symbol_version_regex
-	  && (regexec(symbol_version_regex.get(),
-		      sym_version.c_str(),
-		      0, NULL, 0) != 0))
+	  && !regex::match(symbol_version_regex, sym_version))
 	return false;
     }
   else
@@ -2907,12 +2876,12 @@ suppression_matches_function_name(const suppr::function_suppression& s,
 {
   if (regex_t_sptr regexp = s.priv_->get_name_regex())
     {
-      if (regexec(regexp.get(), fn_name.c_str(), 0, NULL, 0) != 0)
+      if (!regex::match(regexp, fn_name))
 	return false;
     }
   else if (regex_t_sptr regexp = s.priv_->get_name_not_regex())
     {
-      if (regexec(regexp.get(), fn_name.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(regexp, fn_name))
 	return false;
     }
   else if (s.priv_->name_.empty())
@@ -2943,12 +2912,12 @@ suppression_matches_function_sym_name(const suppr::function_suppression& s,
 {
   if (regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
     {
-      if (regexec(regexp.get(), fn_linkage_name.c_str(), 0, NULL, 0) != 0)
+      if (!regex::match(regexp, fn_linkage_name))
 	return false;
     }
   else if (regex_t_sptr regexp = s.priv_->get_symbol_name_not_regex())
     {
-      if (regexec(regexp.get(), fn_linkage_name.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(regexp, fn_linkage_name))
 	return false;
     }
   else if (s.priv_->symbol_name_.empty())
@@ -2976,12 +2945,12 @@ suppression_matches_variable_name(const suppr::variable_suppression& s,
 {
   if (regex_t_sptr regexp = s.priv_->get_name_regex())
     {
-      if (regexec(regexp.get(), var_name.c_str(), 0, NULL, 0) != 0)
+      if (!regex::match(regexp, var_name))
 	return false;
     }
   else if (regex_t_sptr regexp = s.priv_->get_name_not_regex())
     {
-      if (regexec(regexp.get(), var_name.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(regexp, var_name))
 	return false;
     }
   else if (s.priv_->name_.empty())
@@ -3010,13 +2979,13 @@ suppression_matches_variable_sym_name(const suppr::variable_suppression& s,
 {
   if (regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
     {
-      if (regexec(regexp.get(), var_linkage_name.c_str(), 0, NULL, 0) != 0)
+      if (!regex::match(regexp, var_linkage_name))
 	return false;
     }
   else if (regex_t_sptr regexp =
 	   s.priv_->get_symbol_name_not_regex())
     {
-      if (regexec(regexp.get(), var_linkage_name.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(regexp, var_linkage_name))
 	return false;
     }
   else if (s.priv_->symbol_name_.empty())
@@ -3045,7 +3014,7 @@ suppression_matches_type(const suppr::type_suppression& s,
 {
   if (regex_t_sptr regexp = s.priv_->get_type_name_regex())
     {
-      if (regexec(regexp.get(), type_name.c_str(), 0, NULL, 0) != 0)
+      if (!regex::match(regexp, type_name))
 	return false;
     }
   else if (!s.get_type_name().empty())
@@ -3743,15 +3712,11 @@ variable_suppression::suppresses_variable(const var_decl* var,
       if (get_name().empty())
 	{
 	  const regex_t_sptr name_regex = priv_->get_name_regex();
-	  if (name_regex
-	      && (regexec(name_regex.get(), var_name.c_str(),
-			  0, NULL, 0) != 0))
+	  if (name_regex && !regex::match(name_regex, var_name))
 	    return false;
 
 	  const regex_t_sptr name_not_regex = priv_->get_name_not_regex();
-	  if (name_not_regex
-	      && (regexec(name_not_regex.get(), var_name.c_str(),
-			  0, NULL, 0) == 0))
+	  if (name_not_regex && regex::match(name_not_regex, var_name))
 	    return false;
 	}
     }
@@ -3767,16 +3732,12 @@ variable_suppression::suppresses_variable(const var_decl* var,
   else
     {
       const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
-      if (sym_name_regex
-	  && (regexec(sym_name_regex.get(), var_sym_name.c_str(),
-		      0, NULL, 0) != 0))
+      if (sym_name_regex && !regex::match(sym_name_regex, var_sym_name))
 	return false;
 
       const regex_t_sptr sym_name_not_regex =
 	priv_->get_symbol_name_not_regex();
-      if (sym_name_not_regex
-	  && (regexec(sym_name_not_regex.get(), var_sym_name.c_str(),
-		      0, NULL, 0) == 0))
+      if (sym_name_not_regex && regex::match(sym_name_not_regex, var_sym_name))
 	return false;
     }
 
@@ -3793,9 +3754,7 @@ variable_suppression::suppresses_variable(const var_decl* var,
       const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
       if (symbol_version_regex
-	  && (regexec(symbol_version_regex.get(),
-		      var_sym_version.c_str(),
-		      0, NULL, 0) != 0))
+	  && !regex::match(symbol_version_regex, var_sym_version))
 	return false;
     }
 
@@ -3813,9 +3772,7 @@ variable_suppression::suppresses_variable(const var_decl* var,
       if (get_type_name().empty())
 	{
 	  const regex_t_sptr type_name_regex = priv_->get_type_name_regex();
-	  if (type_name_regex
-	      && (regexec(type_name_regex.get(), var_type_name.c_str(),
-			  0, NULL, 0) != 0))
+	  if (type_name_regex && !regex::match(type_name_regex, var_type_name))
 	    return false;
 	}
     }
@@ -3906,9 +3863,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
   else if (!get_symbol_name_regex_str().empty())
     {
       const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
-      if (sym_name_regex
-	  && (regexec(sym_name_regex.get(), sym_name.c_str(),
-		      0, NULL, 0) != 0))
+      if (sym_name_regex && !regex::match(sym_name_regex, sym_name))
 	return false;
     }
   else
@@ -3925,9 +3880,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
       const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
       if (symbol_version_regex
-	  && (regexec(symbol_version_regex.get(),
-		      sym_version.c_str(),
-		      0, NULL, 0) != 0))
+	  && !regex::match(symbol_version_regex, sym_version))
 	return false;
     }
   else
@@ -4223,14 +4176,14 @@ file_suppression::suppresses_file(const string& file_path)
   if (regex_t_sptr regexp = suppression_base::priv_->get_file_name_regex())
     {
       has_regexp = true;
-      if (regexec(regexp.get(), fname.c_str(), 0, NULL, 0) != 0)
+      if (!regex::match(regexp, fname))
 	return false;
     }
 
   if (regex_t_sptr regexp = suppression_base::priv_->get_file_name_not_regex())
     {
       has_regexp = true;
-      if (regexec(regexp.get(), fname.c_str(), 0, NULL, 0) == 0)
+      if (regex::match(regexp, fname))
 	return false;
     }
 
-- 
2.26.2.526.g744177e7f7-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v4 09/15] Refactor read_parameter_spec_from_string logic.
  2020-05-04 12:34   ` [PATCH v4 00/15] Simplify regex and suppression parsing Giuliano Procida
                       ` (7 preceding siblings ...)
  2020-05-04 12:34     ` [PATCH v4 08/15] Use regex::match wrapper instead of regexec Giuliano Procida
@ 2020-05-04 12:34     ` Giuliano Procida
  2020-05-13  7:51       ` Dodji Seketeli
  2020-05-04 12:34     ` [PATCH v4 10/15] Compile suppression regexes earlier Giuliano Procida
                       ` (5 subsequent siblings)
  14 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-05-04 12:34 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

This function extracts either a string or a regex from the same input.
This patch simplifies the string vs regex conditional logic, in order
to make following patches simpler.

There are no behavioural changes.

	* src/abg-suppression.cc (read_parameter_spec_from_string):
	Use separate string and regex variables to simplify the
	creation of returned parameter specification.

Reviewed-by: Matthias Maennich <maennich@google.com>
Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-suppression.cc | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index c89201b6..4014ff06 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -3085,13 +3085,15 @@ read_parameter_spec_from_string(const string& str)
 
   if (!index_str.empty() || !type_name.empty())
     {
-      function_suppression::parameter_spec* p;
+      std::string type_name_regex;
       if (is_regex)
-	p = new function_suppression::parameter_spec(atoi(index_str.c_str()),
-						     "", type_name);
-      else
-	p = new function_suppression::parameter_spec(atoi(index_str.c_str()),
-						     type_name, "");
+	{
+	  type_name_regex = type_name;
+	  type_name.clear();
+	}
+      function_suppression::parameter_spec* p =
+	new function_suppression::parameter_spec(atoi(index_str.c_str()),
+						 type_name, type_name_regex);
       result.reset(p);
     }
 
-- 
2.26.2.526.g744177e7f7-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v4 10/15] Compile suppression regexes earlier.
  2020-05-04 12:34   ` [PATCH v4 00/15] Simplify regex and suppression parsing Giuliano Procida
                       ` (8 preceding siblings ...)
  2020-05-04 12:34     ` [PATCH v4 09/15] Refactor read_parameter_spec_from_string logic Giuliano Procida
@ 2020-05-04 12:34     ` Giuliano Procida
  2020-05-04 13:14       ` Matthias Maennich
  2020-05-13  8:07       ` Dodji Seketeli
  2020-05-04 12:34     ` [PATCH v4 11/15] Reduce direct access to suppression priv_ members Giuliano Procida
                       ` (4 subsequent siblings)
  14 siblings, 2 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-05-04 12:34 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

Regexes are used in suppression specifications for various things.
They are currently compiled on first use, rather than on construction
of the specifications.

This patches changes the suppression specification types to hold
compiled regexes directly which is a significant simplification and is
a prerequisite for early error reporting.

There are no behavioural changes.

	* include/abg-suppression.h (suppression_base): In
	constructor, take regex arguments as regex_t_sptr. Replace all
	set_*_regex_str and get_*_regex_str methods with set_*_regex
	and get_*_regex methods.
	(type_suppression): In constructor, take regex arguments as
	regex_t_sptr. Replace all set_*_regex_str and get_*_regex_str
	methods with set_*_regex and get_*_regex methods.
	(function_suppression): In constructor, take regex arguments
	as regex_t_sptr. Replace all set_*_regex_str and
	get_*_regex_str methods with set_*_regex and get_*_regex
	methods.
	(function_suppression::parameter_spec): In constructor, take
	regex arguments as regex_t_sptr. Replace all set_*_regex_str and
	get_*_regex_str methods with set_*_regex and get_*_regex
	methods.
	(variable_suppression): In constructor, take regex arguments
	as regex_t_sptr. Replace all set_*_regex_str and get_*_regex_str
	methods with set_*_regex and get_*_regex methods.
	(file_suppression): In constructor, take regex arguments
	as regex_t_sptr.
	* src/abg-suppression-priv.h (suppression_base::priv): Drop
	all *_regex_str_ members. Drop mutable qualifier on
	all *_regex_ members. In constructor, take regexes instead of
	strings for regex arguments. Update all get_*_regex methods to
	remove regex compilation and update comments.
	(function_suppression::parameter_spec::priv): Drop
	all *_regex_str_ members. Drop mutable qualifier on
	all *_regex_ members. In constructor, take regexes instead of
	strings for regex arguments. Update get_*_regex methods to
	remove regex compilation and update comments.
	(function_suppression::priv): Drop all *_regex_str_ members.
	Drop mutable qualifier on all *_regex_ members. In constructor,
	take regexes instead of strings for regex arguments. Update
	all get_*_regex methods to remove regex compilation and
	update comments.
	(variable_suppression::priv): Drop all *_regex_str_ members.
	Drop mutable qualifier on all *_regex_ members. In
	constructor, take regexes instead of strings for regex
	arguments. Update all get_*_regex methods to remove
	regex compilation and update comments.
	(type_suppression::priv): Drop all *_regex_str_ members.
	Drop mutable qualifier on all *_regex_ members. In constructor,
	take regexes instead of strings for regex arguments. Update
	all get_*_regex methods to remove regex compilation and
	update comments. Drop set_type_name_regex_str and
	get_type_name_regex_str methods.
	* src/abg-suppression.cc (suppression_base): In constructor,
	take regexes instead of strings for regex arguments. Replace
	all set_*_regex_str and get_*_regex_str methods with
	set_*_regex and get_*_regex methods. Update
	has_file_name_related_property and has_soname_related_property
	methods.
	(type_suppression): In constructor, take regexes instead of
	strings for regex arguments. Replace all set_*_regex_str and
	get_*_regex_str methods with set_*_regex and get_*_regex
	methods. Update has_file_name_related_property and
	has_soname_related_property methods.
	(read_type_suppression): Compile regexes instead of keeping
	them as strings. Pass them to type_suppression constructor and
	setters.
	(function_suppression::parameter_spec): In constructor, take
	regexes instead of strings for regex arguments. Replace all
	set_*_regex_str and get_*_regex_str methods with set_*_regex and
	get_*_regex methods.
	(function_suppression): In constructor, take regexes instead
	of strings for regex arguments. Replace all set_*_regex_str
	and get_*_regex_str methods with set_*_regex and get_*_regex
	methods. Update suppresses_function_symbol method.
	(read_parameter_spec_from_string): Change type of
	type_name_regex from string to regex and compile when needed.
	(read_function_suppression): Compile regexes instead of
	keeping them as strings. Pass them to function_suppression
	constructor and setters.
	(variable_suppression): In constructor, take regexes instead
	of strings for regex arguments. Replace all set_*_regex_str
	and get_*_regex_str methods with set_*_regex and get_*_regex
	methods.
	(file_suppression): In constructor, take regexes instead of
	strings for regex arguments. Replace all set_*_regex_str and
	get_*_regex_str methods with set_*_regex and get_*_regex
	methods.
	* src/abg-tools-utils.cc (handle_file_entry): Compile and
	check regex for /usr/include.
	(gen_suppr_spec_from_kernel_abi_whitelists):
	Compile and check whitelisting regex.
	* tests/test-kmi-whitelist.cc (random_symbols) Add array of
	symbols. (test_suppressions_are_consistent): Rework to test by
	matching regexes against symbols, now that uncompiled regex
	strings are no longer available.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 include/abg-suppression.h   | 165 ++++-----
 src/abg-suppression-priv.h  | 357 ++++---------------
 src/abg-suppression.cc      | 694 ++++++++++++++++++------------------
 src/abg-tools-utils.cc      |  17 +-
 tests/test-kmi-whitelist.cc |  60 +++-
 5 files changed, 583 insertions(+), 710 deletions(-)

diff --git a/include/abg-suppression.h b/include/abg-suppression.h
index 6383b932..8256f9b8 100644
--- a/include/abg-suppression.h
+++ b/include/abg-suppression.h
@@ -26,6 +26,7 @@
 #include "abg-cxx-compat.h"
 #include "abg-ini.h"
 #include "abg-comparison.h"
+#include "abg-regex.h"
 
 namespace abigail
 {
@@ -64,8 +65,8 @@ public:
   suppression_base(const string& label);
 
   suppression_base(const string& label,
-		   const string& file_name_regex_str,
-		   const string& file_name_not_regex_str);
+		   const regex::regex_t_sptr& file_name_regex,
+		   const regex::regex_t_sptr& file_name_not_regex);
 
   bool
   get_drops_artifact_from_ir() const;
@@ -86,31 +87,31 @@ public:
   set_label(const string&);
 
   void
-  set_file_name_regex_str(const string& regexp);
+  set_file_name_regex(const regex::regex_t_sptr& regexp);
 
-  const string&
-  get_file_name_regex_str() const;
+  const regex::regex_t_sptr&
+  get_file_name_regex() const;
 
   void
-  set_file_name_not_regex_str(const string& regexp);
+  set_file_name_not_regex(const regex::regex_t_sptr& regexp);
 
-  const string&
-  get_file_name_not_regex_str() const;
+  const regex::regex_t_sptr&
+  get_file_name_not_regex() const;
 
   bool
   has_file_name_related_property() const;
 
   void
-  set_soname_regex_str(const string& regexp);
+  set_soname_regex(const regex::regex_t_sptr& regexp);
 
-  const string&
-  get_soname_regex_str() const;
+  const regex::regex_t_sptr&
+  get_soname_regex() const;
 
   void
-  set_soname_not_regex_str(const string& regexp);
+  set_soname_not_regex(const regex::regex_t_sptr& regexp);
 
-  const string&
-  get_soname_not_regex_str() const;
+  const regex::regex_t_sptr&
+  get_soname_not_regex() const;
 
   bool
   has_soname_related_property() const;
@@ -204,22 +205,22 @@ public:
   typedef vector<insertion_range_sptr> insertion_ranges;
 
   type_suppression(const string& label,
-		   const string& type_name_regexp,
+		   const regex::regex_t_sptr& type_name_regexp,
 		   const string& type_name);
 
   virtual ~type_suppression();
 
   void
-  set_type_name_regex_str(const string& name_regex_str);
+  set_type_name_regex(const regex::regex_t_sptr& name_regex);
 
-  const string&
-  get_type_name_regex_str() const;
+  const regex::regex_t_sptr&
+  get_type_name_regex() const;
 
   void
-  set_type_name_not_regex_str(const string& name_regex_str);
+  set_type_name_not_regex(const regex::regex_t_sptr& name_regex);
 
-  const string&
-  get_type_name_not_regex_str() const;
+  const regex::regex_t_sptr&
+  get_type_name_not_regex() const;
 
   void
   set_type_name(const string& name);
@@ -269,11 +270,11 @@ public:
   void
   set_source_locations_to_keep(const unordered_set<string>&);
 
-  const string&
-  get_source_location_to_keep_regex_str() const;
+  const regex::regex_t_sptr&
+  get_source_location_to_keep_regex() const;
 
   void
-  set_source_location_to_keep_regex_str(const string&);
+  set_source_location_to_keep_regex(const regex::regex_t_sptr&);
 
   const vector<string>&
   get_changed_enumerator_names() const;
@@ -460,16 +461,16 @@ public:
 
   function_suppression();
 
-  function_suppression(const string&		label,
-		       const string&		name,
-		       const string&		name_regex,
-		       const string&		return_type_name,
-		       const string&		return_type_regex,
-		       parameter_specs_type&	parm_specs,
-		       const string&		symbol_name,
-		       const string&		symbol_name_regex,
-		       const string&		symbol_version,
-		       const string&		symbol_version_regex_str);
+  function_suppression(const string&			label,
+		       const string&			name,
+		       const regex::regex_t_sptr&	name_regex,
+		       const string&			return_type_name,
+		       const regex::regex_t_sptr&	return_type_regex,
+		       parameter_specs_type&		parm_specs,
+		       const string&			symbol_name,
+		       const regex::regex_t_sptr&	symbol_name_regex,
+		       const string&			symbol_version,
+		       const regex::regex_t_sptr&	symbol_version_regex);
 
   virtual ~function_suppression();
 
@@ -488,17 +489,17 @@ public:
   void
   set_name(const string&);
 
-  const string&
-  get_name_regex_str() const;
+  const regex::regex_t_sptr&
+  get_name_regex() const;
 
   void
-  set_name_regex_str(const string&);
+  set_name_regex(const regex::regex_t_sptr&);
 
-  const string&
-  get_name_not_regex_str() const;
+  const regex::regex_t_sptr&
+  get_name_not_regex() const;
 
   void
-  set_name_not_regex_str(const string&);
+  set_name_not_regex(const regex::regex_t_sptr&);
 
   const string&
   get_return_type_name() const;
@@ -506,11 +507,11 @@ public:
   void
   set_return_type_name(const string&);
 
-  const string&
-  get_return_type_regex_str() const;
+  const regex::regex_t_sptr&
+  get_return_type_regex() const;
 
   void
-  set_return_type_regex_str(const string& r);
+  set_return_type_regex(const regex::regex_t_sptr& r);
 
   const parameter_specs_type&
   get_parameter_specs() const;
@@ -527,17 +528,17 @@ public:
   void
   set_symbol_name(const string& n);
 
-  const string&
-  get_symbol_name_regex_str() const;
+  const regex::regex_t_sptr&
+  get_symbol_name_regex() const;
 
   void
-  set_symbol_name_regex_str(const string&);
+  set_symbol_name_regex(const regex::regex_t_sptr&);
 
-  const string&
-  get_symbol_name_not_regex_str() const;
+  const regex::regex_t_sptr&
+  get_symbol_name_not_regex() const;
 
   void
-  set_symbol_name_not_regex_str(const string&);
+  set_symbol_name_not_regex(const regex::regex_t_sptr&);
 
   const string&
   get_symbol_version() const;
@@ -545,11 +546,11 @@ public:
   void
   set_symbol_version(const string&);
 
-  const string&
-  get_symbol_version_regex_str() const;
+  const regex::regex_t_sptr&
+  get_symbol_version_regex() const;
 
   void
-  set_symbol_version_regex_str(const string&);
+  set_symbol_version_regex(const regex::regex_t_sptr&);
 
   bool
   get_allow_other_aliases() const;
@@ -609,7 +610,7 @@ class function_suppression::parameter_spec
 public:
   parameter_spec(size_t index,
 		 const string& type_name,
-		 const string& type_name_regex);
+		 const regex::regex_t_sptr& type_name_regex);
 
   size_t
   get_index() const;
@@ -623,11 +624,11 @@ public:
   void
   set_parameter_type_name(const string&);
 
-  const string&
-  get_parameter_type_name_regex_str() const;
+  const regex::regex_t_sptr&
+  get_parameter_type_name_regex() const;
 
   void
-  set_parameter_type_name_regex_str(const string&);
+  set_parameter_type_name_regex(const regex::regex_t_sptr&);
 };// end class function_suppression::parameter_spec
 
 class variable_suppression;
@@ -679,13 +680,17 @@ public:
 
   variable_suppression(const string& label = "",
 		       const string& name = "",
-		       const string& name_regex_str = "",
+		       const regex::regex_t_sptr& name_regex =
+			 regex::regex_t_sptr(),
 		       const string& symbol_name = "",
-		       const string& symbol_name_regex_str = "",
+		       const regex::regex_t_sptr& symbol_name_regex =
+			 regex::regex_t_sptr(),
 		       const string& symbol_version = "",
-		       const string& symbol_version_regex_str = "",
+		       const regex::regex_t_sptr& symbol_version_regex =
+			 regex::regex_t_sptr(),
 		       const string& type_name = "",
-		       const string& type_name_regex_str = "");
+		       const regex::regex_t_sptr& type_name_regex =
+			 regex::regex_t_sptr());
 
   virtual ~variable_suppression();
 
@@ -704,17 +709,17 @@ public:
   void
   set_name(const string&);
 
-  const string&
-  get_name_regex_str() const;
+  const regex::regex_t_sptr&
+  get_name_regex() const;
 
   void
-  set_name_regex_str(const string&);
+  set_name_regex(const regex::regex_t_sptr&);
 
-  const string&
-  get_name_not_regex_str() const;
+  const regex::regex_t_sptr&
+  get_name_not_regex() const;
 
   void
-  set_name_not_regex_str(const string&);
+  set_name_not_regex(const regex::regex_t_sptr&);
 
   const string&
   get_symbol_name() const;
@@ -722,17 +727,17 @@ public:
   void
   set_symbol_name(const string&);
 
-  const string&
-  get_symbol_name_regex_str() const;
+  const regex::regex_t_sptr&
+  get_symbol_name_regex() const;
 
   void
-  set_symbol_name_regex_str(const string&);
+  set_symbol_name_regex(const regex::regex_t_sptr&);
 
-  const string&
-  get_symbol_name_not_regex_str() const;
+  const regex::regex_t_sptr&
+  get_symbol_name_not_regex() const;
 
   void
-  set_symbol_name_not_regex_str(const string&);
+  set_symbol_name_not_regex(const regex::regex_t_sptr&);
 
   const string&
   get_symbol_version() const;
@@ -740,11 +745,11 @@ public:
   void
   set_symbol_version(const string&);
 
-  const string&
-  get_symbol_version_regex_str() const;
+  const regex::regex_t_sptr&
+  get_symbol_version_regex() const;
 
   void
-  set_symbol_version_regex_str(const string&);
+  set_symbol_version_regex(const regex::regex_t_sptr&);
 
   const string&
   get_type_name() const;
@@ -752,11 +757,11 @@ public:
   void
   set_type_name(const string&);
 
-  const string&
-  get_type_name_regex_str() const;
+  const regex::regex_t_sptr&
+  get_type_name_regex() const;
 
   void
-  set_type_name_regex_str(const string&);
+  set_type_name_regex(const regex::regex_t_sptr&);
 
   bool
   suppresses_diff(const diff* d) const;
@@ -816,8 +821,8 @@ class file_suppression: public suppression_base
 public:
 
   file_suppression(const string& label,
-		   const string& file_name_regex,
-		   const string& file_name_not_regex);
+		   const regex::regex_t_sptr& file_name_regex,
+		   const regex::regex_t_sptr& file_name_not_regex);
 
   virtual bool
   suppresses_diff(const diff* diff) const;
diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
index deb08269..c5f99c15 100644
--- a/src/abg-suppression-priv.h
+++ b/src/abg-suppression-priv.h
@@ -47,14 +47,10 @@ class suppression_base::priv
   bool					is_artificial_;
   bool					drops_artifact_;
   string				label_;
-  string				file_name_regex_str_;
-  mutable regex::regex_t_sptr		file_name_regex_;
-  string				file_name_not_regex_str_;
-  mutable regex::regex_t_sptr		file_name_not_regex_;
-  string				soname_regex_str_;
-  mutable regex::regex_t_sptr		soname_regex_;
-  string				soname_not_regex_str_;
-  mutable regex::regex_t_sptr		soname_not_regex_;
+  regex::regex_t_sptr			file_name_regex_;
+  regex::regex_t_sptr			file_name_not_regex_;
+  regex::regex_t_sptr			soname_regex_;
+  regex::regex_t_sptr			soname_not_regex_;
 
 public:
   priv()
@@ -69,78 +65,46 @@ public:
   {}
 
   priv(const string& label,
-       const string& file_name_regex_str,
-       const string& file_name_not_regex_str)
+       const regex::regex_t_sptr& file_name_regex,
+       const regex::regex_t_sptr& file_name_not_regex)
     : is_artificial_(),
       drops_artifact_(),
       label_(label),
-      file_name_regex_str_(file_name_regex_str),
-      file_name_not_regex_str_(file_name_not_regex_str)
+      file_name_regex_(file_name_regex),
+      file_name_not_regex_(file_name_not_regex)
   {}
 
   friend class suppression_base;
 
-  /// Get the regular expression object associated to the 'file_name_regex'
-  /// property of @ref suppression_base.
-  ///
-  /// If the regular expression object is not created, this method
-  /// creates it and returns it.
-  ///
-  /// If the 'file_name_regex' property of @ref suppression_base is
-  /// empty then this method returns nil.
+  /// Get the regular expression object associated to the
+  /// 'file_name_regex' property of @ref suppression_base.
   const regex::regex_t_sptr&
   get_file_name_regex() const
   {
-    if (!file_name_regex_ && !file_name_regex_str_.empty())
-      file_name_regex_ = regex::compile(file_name_regex_str_);
     return file_name_regex_;
   }
 
   /// Get the regular expression object associated to the
   /// 'file_name_not_regex' property of @ref suppression_base.
-  ///
-  /// If the regular expression object is not created, this method
-  /// creates it and returns it.
-  ///
-  /// If the 'file_name_not_regex' property of @ref suppression_base
-  /// is empty then this method returns nil.
   const regex::regex_t_sptr&
   get_file_name_not_regex() const
   {
-    if (!file_name_not_regex_ && !file_name_not_regex_str_.empty())
-      file_name_not_regex_ = regex::compile(file_name_not_regex_str_);
     return file_name_not_regex_;
   }
 
-  /// Get the regular expression object associated to the
-  /// 'soname_regex' property of @ref suppression_base.
-  ///
-  /// If the regular expression object is not created, this method
-  /// creates it and returns it.
-  ///
-  /// If the 'soname_regex' property of @ref suppression_base is empty
-  /// then this method returns nil.
+  /// Get the regular expression object associated to the 'soname_regex'
+  /// property of @ref suppression_base.
   const regex::regex_t_sptr&
   get_soname_regex() const
   {
-    if (!soname_regex_ && !soname_regex_str_.empty())
-      soname_regex_ = regex::compile(soname_regex_str_);
     return soname_regex_;
   }
 
   /// Get the regular expression object associated to the
   /// 'soname_not_regex' property of @ref suppression_base.
-  ///
-  /// If the regular expression object is not created, this method
-  /// creates it and returns it.
-  ///
-  /// If the 'soname_not_regex' property of @ref suppression_base is
-  /// empty then this method returns nil.
   const regex::regex_t_sptr&
   get_soname_not_regex() const
   {
-    if (!soname_not_regex_ && !soname_not_regex_str_.empty())
-      soname_not_regex_ = regex::compile(soname_not_regex_str_);
     return soname_not_regex_;
   }
 
@@ -225,8 +189,7 @@ class function_suppression::parameter_spec::priv
 
   size_t				index_;
   string				type_name_;
-  string				type_name_regex_str_;
-  mutable regex::regex_t_sptr		type_name_regex_;
+  regex::regex_t_sptr			type_name_regex_;
 
   priv()
     : index_()
@@ -236,15 +199,16 @@ class function_suppression::parameter_spec::priv
     : index_(i), type_name_(tn)
   {}
 
-  priv(size_t i, const string& tn, const string& tn_regex)
-    : index_(i), type_name_(tn), type_name_regex_str_(tn_regex)
+  priv(size_t i, const string& tn, const regex::regex_t_sptr& tn_regex)
+    : index_(i), type_name_(tn), type_name_regex_(tn_regex)
   {}
 
+  /// Get the regular expression object associated to the
+  /// 'type_name_regex' property of @ref
+  /// function_suppression::parameter_spec.
   const regex::regex_t_sptr
   get_type_name_regex() const
   {
-    if (!type_name_regex_ && !type_name_regex_str_.empty())
-      type_name_regex_ = regex::compile(type_name_regex_str_);
     return type_name_regex_;
   }
 }; // end class function_suppression::parameter_spec::priv
@@ -258,22 +222,16 @@ struct function_suppression::priv
 
   change_kind				change_kind_;
   string				name_;
-  string				name_regex_str_;
-  mutable regex::regex_t_sptr		name_regex_;
-  string				name_not_regex_str_;
-  mutable regex::regex_t_sptr		name_not_regex_;
+  regex::regex_t_sptr			name_regex_;
+  regex::regex_t_sptr			name_not_regex_;
   string				return_type_name_;
-  string				return_type_regex_str_;
-  mutable regex::regex_t_sptr		return_type_regex_;
+  regex::regex_t_sptr			return_type_regex_;
   parameter_specs_type			parm_specs_;
   string				symbol_name_;
-  string				symbol_name_regex_str_;
-  mutable regex::regex_t_sptr		symbol_name_regex_;
-  string				symbol_name_not_regex_str_;
-  mutable regex::regex_t_sptr		symbol_name_not_regex_;
+  regex::regex_t_sptr			symbol_name_regex_;
+  regex::regex_t_sptr			symbol_name_not_regex_;
   string				symbol_version_;
-  string				symbol_version_regex_str_;
-  mutable regex::regex_t_sptr		symbol_version_regex_;
+  regex::regex_t_sptr			symbol_version_regex_;
   bool					allow_other_aliases_;
 
   priv():
@@ -282,127 +240,72 @@ struct function_suppression::priv
   {}
 
   priv(const string&			name,
-       const string&			name_regex_str,
+       const regex::regex_t_sptr&	name_regex,
        const string&			return_type_name,
-       const string&			return_type_regex_str,
+       const regex::regex_t_sptr&	return_type_regex,
        const parameter_specs_type&	parm_specs,
        const string&			symbol_name,
-       const string&			symbol_name_regex_str,
+       const regex::regex_t_sptr&	symbol_name_regex,
        const string&			symbol_version,
-       const string&			symbol_version_regex_str)
+       const regex::regex_t_sptr&	symbol_version_regex)
     : change_kind_(ALL_CHANGE_KIND),
       name_(name),
-      name_regex_str_(name_regex_str),
+      name_regex_(name_regex),
       return_type_name_(return_type_name),
-      return_type_regex_str_(return_type_regex_str),
+      return_type_regex_(return_type_regex),
       parm_specs_(parm_specs),
       symbol_name_(symbol_name),
-      symbol_name_regex_str_(symbol_name_regex_str),
+      symbol_name_regex_(symbol_name_regex),
       symbol_version_(symbol_version),
-      symbol_version_regex_str_(symbol_version_regex_str),
+      symbol_version_regex_(symbol_version_regex),
       allow_other_aliases_(true)
   {}
 
-
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// function_suppression::priv::name_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// function_suppression::priv::name_regex_str_..
+  /// Get the regular expression object associated to the 'name_regex'
+  /// property of @ref function_suppression.
   const regex::regex_t_sptr
   get_name_regex() const
   {
-    if (!name_regex_ && !name_regex_str_.empty())
-      name_regex_ = regex::compile(name_regex_str_);
     return name_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// function_suppression::priv::name_not_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// function_suppression::priv::name_not_regex_str_..
+  /// Get the regular expression object associated to the
+  /// 'name_not_regex' property of @ref function_suppression.
   const regex::regex_t_sptr
   get_name_not_regex() const
   {
-    if (!name_not_regex_ && !name_not_regex_str_.empty())
-      name_not_regex_ = regex::compile(name_not_regex_str_);
     return name_not_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// function_suppression::priv::return_type_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// function_suppression::priv::return_type_regex_str_.
+  /// Get the regular expression object associated to the
+  /// 'return_type_regex' property of @ref function_suppression.
   const regex::regex_t_sptr
   get_return_type_regex() const
   {
-    if (!return_type_regex_ && !return_type_regex_str_.empty())
-      return_type_regex_ = regex::compile(return_type_regex_str_);
     return return_type_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// function_suppression::priv::symbol_name_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// function_suppression::priv::symbol_name_regex_str_.
+  /// Get the regular expression object associated to the
+  /// 'symbol_name_regex' property of @ref function_suppression.
   const regex::regex_t_sptr
   get_symbol_name_regex() const
   {
-    if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
-      symbol_name_regex_ = regex::compile(symbol_name_regex_str_);
     return symbol_name_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// function_suppression::priv::symbol_name_not_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// function_suppression::priv::symbol_name_not_regex_str_.
+  /// Get the regular expression object associated to the
+  /// 'symbol_name_not_regex' property of @ref function_suppression.
   const regex::regex_t_sptr
   get_symbol_name_not_regex() const
   {
-    if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
-      symbol_name_not_regex_ = regex::compile(symbol_name_not_regex_str_);
     return symbol_name_not_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// function_suppression::priv::symbol_version_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// function_suppression::priv::symbol_version_regex_str_.
+  /// Get the regular expression object associated to the
+  /// 'symbol_version_regex' property of @ref function_suppression.
   const regex::regex_t_sptr
   get_symbol_version_regex() const
   {
-    if (!symbol_version_regex_ && !symbol_version_regex_str_.empty())
-      symbol_version_regex_ = regex::compile(symbol_version_regex_str_);
     return symbol_version_regex_;
   }
 }; // end class function_suppression::priv
@@ -481,140 +384,80 @@ struct variable_suppression::priv
 
   change_kind				change_kind_;
   string				name_;
-  string				name_regex_str_;
-  mutable regex::regex_t_sptr		name_regex_;
-  string				name_not_regex_str_;
-  mutable regex::regex_t_sptr		name_not_regex_;
+  regex::regex_t_sptr			name_regex_;
+  regex::regex_t_sptr			name_not_regex_;
   string				symbol_name_;
-  string				symbol_name_regex_str_;
-  mutable regex::regex_t_sptr		symbol_name_regex_;
-  string				symbol_name_not_regex_str_;
-  mutable regex::regex_t_sptr		symbol_name_not_regex_;
+  regex::regex_t_sptr			symbol_name_regex_;
+  regex::regex_t_sptr			symbol_name_not_regex_;
   string				symbol_version_;
-  string				symbol_version_regex_str_;
-  mutable regex::regex_t_sptr		symbol_version_regex_;
+  regex::regex_t_sptr			symbol_version_regex_;
   string				type_name_;
-  string				type_name_regex_str_;
-  mutable regex::regex_t_sptr		type_name_regex_;
+  regex::regex_t_sptr			type_name_regex_;
 
   priv(const string& name,
-       const string& name_regex_str,
+       const regex::regex_t_sptr& name_regex,
        const string& symbol_name,
-       const string& symbol_name_regex_str,
+       const regex::regex_t_sptr& symbol_name_regex,
        const string& symbol_version,
-       const string& symbol_version_regex_str,
+       const regex::regex_t_sptr& symbol_version_regex,
        const string& type_name,
-       const string& type_name_regex_str)
+       const regex::regex_t_sptr& type_name_regex)
     : change_kind_(ALL_CHANGE_KIND),
       name_(name),
-      name_regex_str_(name_regex_str),
+      name_regex_(name_regex),
       symbol_name_(symbol_name),
-      symbol_name_regex_str_(symbol_name_regex_str),
+      symbol_name_regex_(symbol_name_regex),
       symbol_version_(symbol_version),
-      symbol_version_regex_str_(symbol_version_regex_str),
+      symbol_version_regex_(symbol_version_regex),
       type_name_(type_name),
-      type_name_regex_str_(type_name_regex_str)
+      type_name_regex_(type_name_regex)
   {}
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// variable_suppression::priv::name_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// variable_suppression::priv::name_regex_str_.
+  /// Get the regular expression object associated to the 'name_regex'
+  /// property of @ref variable_suppression.
   const regex::regex_t_sptr
   get_name_regex() const
   {
-    if (!name_regex_ && !name_regex_str_.empty())
-      name_regex_ = regex::compile(name_regex_str_);
     return name_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// variable_suppression::priv::name_not_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// variable_suppression::priv::name_not_regex_str_..
+  /// Get the regular expression object associated to the
+  /// 'name_not_regex' property of @ref variable_suppression.
   const regex::regex_t_sptr
   get_name_not_regex() const
   {
-    if (!name_not_regex_ && !name_not_regex_str_.empty())
-      name_not_regex_ = regex::compile(name_not_regex_str_);
     return name_not_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// variable_suppression::priv::symbol_name_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// variable_suppression::priv::symbol_name_regex_str_.
+  /// Get the regular expression object associated to the
+  /// 'symbol_name_regex' property of @ref variable_suppression.
   const regex::regex_t_sptr
   get_symbol_name_regex() const
   {
-    if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
-      symbol_name_regex_ = regex::compile(symbol_name_regex_str_);
     return symbol_name_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// variable_suppression::priv::symbol_name_not_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// variable_suppression::priv::symbol_name_not_regex_str_.
+  /// Get the regular expression object associated to the
+  /// 'symbol_name_not_regex' property of @ref variable_suppression.
   const regex::regex_t_sptr
   get_symbol_name_not_regex() const
   {
-    if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
-      symbol_name_not_regex_ = regex::compile(symbol_name_not_regex_str_);
     return symbol_name_not_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// variable_suppression::priv::symbol_version_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// variable_suppression::priv::symbol_version_regex_str_.
+  /// Get the regular expression object associated to the
+  /// 'symbol_version_regex' property of @ref variable_suppression.
   const regex::regex_t_sptr
   get_symbol_version_regex()  const
   {
-    if (!symbol_version_regex_ && !symbol_version_regex_str_.empty())
-      symbol_version_regex_ = regex::compile(symbol_version_regex_str_);
     return symbol_version_regex_;
   }
 
-  /// Getter for a pointer to a regular expression object built from
-  /// the regular expression string
-  /// variable_suppression::priv::type_name_regex_str_.
-  ///
-  /// If that string is empty, then an empty regular expression object
-  /// pointer is returned.
-  ///
-  /// @return a pointer to the regular expression object of
-  /// variable_suppression::priv::type_name_regex_str_.
+  /// Get the regular expression object associated to the
+  /// 'type_name_regex' property of @ref variable_suppression.
   const regex::regex_t_sptr
   get_type_name_regex() const
   {
-    if (!type_name_regex_ && !type_name_regex_str_.empty())
-      type_name_regex_ = regex::compile(type_name_regex_str_);
     return type_name_regex_;
   }
 };// end class variable_supppression::priv
@@ -651,31 +494,28 @@ variable_is_suppressed(const ReadContextType&	ctxt,
 /// The private data for @ref type_suppression.
 class type_suppression::priv
 {
-  string				type_name_regex_str_;
-  mutable regex::regex_t_sptr		type_name_regex_;
+  regex::regex_t_sptr			type_name_regex_;
   string				type_name_;
-  string				type_name_not_regex_str_;
-  mutable regex::regex_t_sptr		type_name_not_regex_;
+  regex::regex_t_sptr			type_name_not_regex_;
   bool					consider_type_kind_;
   type_suppression::type_kind		type_kind_;
   bool					consider_reach_kind_;
   type_suppression::reach_kind		reach_kind_;
   type_suppression::insertion_ranges	insertion_ranges_;
   unordered_set<string>			source_locations_to_keep_;
-  string				source_location_to_keep_regex_str_;
-  mutable regex::regex_t_sptr		source_location_to_keep_regex_;
+  regex::regex_t_sptr			source_location_to_keep_regex_;
   mutable vector<string>		changed_enumerator_names_;
 
   priv();
 
 public:
-  priv(const string&			type_name_regexp,
+  priv(const regex::regex_t_sptr&	type_name_regexp,
        const string&			type_name,
        bool				consider_type_kind,
        type_suppression::type_kind	type_kind,
        bool				consider_reach_kind,
        type_suppression::reach_kind	reach_kind)
-    : type_name_regex_str_(type_name_regexp),
+    : type_name_regex_(type_name_regexp),
       type_name_(type_name),
       consider_type_kind_(consider_type_kind),
       type_kind_(type_kind),
@@ -683,19 +523,11 @@ public:
       reach_kind_(reach_kind)
   {}
 
-  /// Get the regular expression object associated to the 'type_name_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_regex' property of @ref type_suppression is
-  /// empty then this method returns nil.
+  /// Get the regular expression object associated to the
+  /// 'type_name_regex' property of @ref type_suppression.
   const regex::regex_t_sptr
   get_type_name_regex() const
   {
-    if (!type_name_regex_ && !type_name_regex_str_.empty())
-      type_name_regex_ = regex::compile(type_name_regex_str_);
     return type_name_regex_;
   }
 
@@ -708,17 +540,9 @@ public:
 
   /// 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 regex::regex_t_sptr
   get_type_name_not_regex() const
   {
-    if (!type_name_not_regex_ && !type_name_not_regex_str_.empty())
-      type_name_not_regex_ = regex::compile(type_name_not_regex_str_);
     return type_name_not_regex_;
   }
 
@@ -729,34 +553,11 @@ public:
   set_type_name_not_regex(regex::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.
+  /// Get the regular expression object associated to the
+  /// 'source_location_to_keep_regex' property of @ref type_suppression.
   const regex::regex_t_sptr
   get_source_location_to_keep_regex() const
   {
-    if (!source_location_to_keep_regex_
-	&& !source_location_to_keep_regex_str_.empty())
-      source_location_to_keep_regex_ =
-	  regex::compile(source_location_to_keep_regex_str_);
     return source_location_to_keep_regex_;
   }
 
diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 4014ff06..80ac1e9f 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -67,17 +67,17 @@ suppression_base::suppression_base(const string& label)
 /// @param a label for the suppression.  This represents just a
 /// comment.
 ///
-/// @param file_name_regex_str the regular expression that denotes the
+/// @param file_name_regex the regular expression that denotes the
 /// file name to match.
 ///
-/// @param file_name_not_regex_str the regular expression that denotes
+/// @param file_name_not_regex the regular expression that denotes
 /// the file name to *NOT* match.
 suppression_base::suppression_base(const string& label,
-				   const string& file_name_regex_str,
-				   const string& file_name_not_regex_str)
+				   const regex_t_sptr& file_name_regex,
+				   const regex_t_sptr& file_name_not_regex)
   : priv_(new priv(label,
-		   file_name_regex_str,
-		   file_name_not_regex_str))
+		   file_name_regex,
+		   file_name_not_regex))
 {
 }
 
@@ -139,52 +139,50 @@ suppression_base::set_label(const string& label)
 /// Setter for the "file_name_regex" property of the current instance
 /// of @ref suppression_base.
 ///
-/// The "file_name_regex" property is a regular expression string that
+/// The "file_name_regex" property is a regular expression that
 /// designates the file name that contains the ABI artifact this
 /// suppression should apply to.
 ///
-/// @param regexp the new regular expression string.
+/// @param regexp the new regular expression.
 void
-suppression_base::set_file_name_regex_str(const string& regexp)
-{priv_->file_name_regex_str_ = regexp;}
+suppression_base::set_file_name_regex(const regex_t_sptr& regexp)
+{priv_->file_name_regex_ = regexp;}
 
 /// Getter for the "file_name_regex" property of the current instance
 /// of @ref suppression_base.
 ///
-/// The "file_name_regex" property is a regular expression string that
+/// The "file_name_regex" property is a regular expression that
 /// designates the file name that contains the ABI artifacts this
 /// suppression should apply to.
 ///
-/// @return the regular expression string.
-const string&
-suppression_base::get_file_name_regex_str() const
-{return priv_->file_name_regex_str_;}
+/// @return the regular expression.
+const regex_t_sptr&
+suppression_base::get_file_name_regex() const
+{return priv_->file_name_regex_;}
 
 /// Setter for the "file_name_not_regex" property of the current
 /// instance of @ref suppression_base.
 ///
 /// The current suppression specification should apply to ABI
 /// artifacts of a file which name does *NOT* match the regular
-/// expression string designated by the "file_name_not_regex"
-/// property.
+/// expression designated by the "file_name_not_regex" property.
 ///
-/// @param regexp the new regular expression string.
+/// @param regexp the new regular expression.
 void
-suppression_base::set_file_name_not_regex_str(const string& regexp)
-{priv_->file_name_not_regex_str_ = regexp;}
+suppression_base::set_file_name_not_regex(const regex_t_sptr& regexp)
+{priv_->file_name_not_regex_ = regexp;}
 
 /// Getter for the "file_name_not_regex" property of the current
 /// instance of @ref suppression_base.
 ///
 /// The current suppression specification should apply to ABI
 /// artifacts of a file which name does *NOT* match the regular
-/// expression string designated by the "file_name_not_regex"
-/// property.
+/// expression designated by the "file_name_not_regex" property.
 ///
-/// @return the regular expression string.
-const string&
-suppression_base::get_file_name_not_regex_str() const
-{return priv_->file_name_not_regex_str_;}
+/// @return the regular expression.
+const regex_t_sptr&
+suppression_base::get_file_name_not_regex() const
+{return priv_->file_name_not_regex_;}
 
 /// Test if the current suppression has a property related to file
 /// name.
@@ -194,59 +192,56 @@ suppression_base::get_file_name_not_regex_str() const
 bool
 suppression_base::has_file_name_related_property() const
 {
-  return (!(get_file_name_regex_str().empty()
-	    && get_file_name_not_regex_str().empty()));
+  return get_file_name_regex() || get_file_name_not_regex();
 }
 
-/// Setter of the "soname_regex_str property of the current instance
+/// Setter of the "soname_regex" property of the current instance
 /// of @ref suppression_base.
 ///
-/// The "soname_regex_str" is a regular expression string that
-/// designates the soname of the shared library that contains the ABI
-/// artifacts this suppression should apply to.
+/// The "soname_regex" is a regular expression that designates the
+/// soname of the shared library that contains the ABI artifacts this
+/// suppression should apply to.
 ///
-/// @param regexp the new regular expression string.
+/// @param regexp the new regular expression.
 void
-suppression_base::set_soname_regex_str(const string& regexp)
-{priv_->soname_regex_str_ = regexp;}
+suppression_base::set_soname_regex(const regex_t_sptr& regexp)
+{priv_->soname_regex_ = regexp;}
 
-/// Getter of the "soname_regex_str property of the current instance
+/// Getter of the "soname_regex" property of the current instance
 /// of @ref suppression_base.
 ///
-/// The "soname_regex_str" is a regular expression string that
-/// designates the soname of the shared library that contains the ABI
-/// artifacts this suppression should apply to.
+/// The "soname_regex" is a regular expression that designates the
+/// soname of the shared library that contains the ABI artifacts this
+/// suppression should apply to.
 ///
-/// @return the regular expression string.
-const string&
-suppression_base::get_soname_regex_str() const
-{return priv_->soname_regex_str_;}
+/// @return the regular expression.
+const regex_t_sptr&
+suppression_base::get_soname_regex() const
+{return priv_->soname_regex_;}
 
-/// Setter of the "soname_not_regex_str property of the current
+/// Setter of the "soname_not_regex" property of the current
 /// instance of @ref suppression_base.
 ///
 /// The current suppression specification should apply to ABI
 /// artifacts of a shared library which SONAME does *NOT* match the
-/// regular expression string designated by the "soname_not_regex"
-/// property.
+/// regular expression designated by the "soname_not_regex" property.
 ///
-/// @param regexp the new regular expression string.
+/// @param regexp the new regular expression.
 void
-suppression_base::set_soname_not_regex_str(const string& regexp)
-{priv_->soname_not_regex_str_ = regexp;}
+suppression_base::set_soname_not_regex(const regex_t_sptr& regexp)
+{priv_->soname_not_regex_ = regexp;}
 
-/// Getter of the "soname_not_regex_str property of the current
+/// Getter of the "soname_not_regex" property of the current
 /// instance of @ref suppression_base.
 ///
 /// The current suppression specification should apply to ABI
 /// artifacts of a shared library which SONAME does *NOT* match the
-/// regular expression string designated by the "soname_not_regex"
-/// property.
+/// regular expression designated by the "soname_not_regex" property.
 ///
-/// @return the regular expression string.
-const string&
-suppression_base::get_soname_not_regex_str() const
-{return priv_->soname_not_regex_str_;}
+/// @return the regular expression.
+const regex_t_sptr&
+suppression_base::get_soname_not_regex() const
+{return priv_->soname_not_regex_;}
 
 /// Test if the current suppression has a property related to SONAMEs.
 ///
@@ -255,8 +250,7 @@ suppression_base::get_soname_not_regex_str() const
 bool
 suppression_base::has_soname_related_property() const
 {
-  return (!(get_soname_regex_str().empty()
-	    && get_soname_not_regex_str().empty()));
+  return get_soname_regex() || get_soname_not_regex();
 }
 
 /// Check if the SONAMEs of the two binaries being compared match the
@@ -398,8 +392,8 @@ read_suppressions(const string& file_path,
 /// form comment explaining what the suppression is about.
 ///
 /// @param type_name_regexp the regular expression describing the
-/// types about which diff reports should be suppressed.  If it's an
-/// empty string, the parameter is ignored.
+/// types about which diff reports should be suppressed.  If it's a
+/// null shared pointer, the parameter is ignored.
 ///
 /// @param type_name the name of the type about which diff reports
 /// should be suppressed.  If it's an empty string, the parameter is
@@ -409,7 +403,7 @@ read_suppressions(const string& file_path,
 /// should not necessarily be populated.  It usually is either one or
 /// the other that the user wants.
 type_suppression::type_suppression(const string& label,
-				   const string& type_name_regexp,
+				   const regex_t_sptr& type_name_regexp,
 				   const string& type_name)
   : suppression_base(label),
     priv_(new priv(type_name_regexp,
@@ -429,43 +423,43 @@ type_suppression::~type_suppression()
 /// This sets a regular expression that specifies the family of types
 /// about which diff reports should be suppressed.
 ///
-/// @param name_regex_str the new regular expression to set.
+/// @param name_regex the new regular expression to set.
 void
-type_suppression::set_type_name_regex_str(const string& name_regex_str)
-{priv_->type_name_regex_str_ = name_regex_str;}
+type_suppression::set_type_name_regex(const regex_t_sptr& name_regex)
+{priv_->type_name_regex_ = name_regex;}
 
 /// Getter for the "type_name_regex" property of the type suppression
 /// specification.
 ///
-/// This returns a regular expression string that specifies the family
+/// This returns a regular expression that specifies the family
 /// of types about which diff reports should be suppressed.
 ///
-/// @return the regular expression string.
-const string&
-type_suppression::get_type_name_regex_str() const
-{return priv_->type_name_regex_str_;}
+/// @return the regular expression.
+const regex_t_sptr&
+type_suppression::get_type_name_regex() const
+{return priv_->type_name_regex_;}
 
-/// Setter for the "type_name_not_regex_str" property of the type
+/// Setter for the "type_name_not_regex" property of the type
 /// suppression specification.
 ///
-/// This returns a regular expression string that specifies the family
+/// This sets a regular expression 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);}
+type_suppression::set_type_name_not_regex(const regex_t_sptr& r)
+{priv_->set_type_name_not_regex(r);}
 
-/// Getter for the "type_name_not_regex_str" property of the type
+/// Getter for the "type_name_not_regex" property of the type
 /// suppression specification.
 ///
-/// This returns a regular expression string that specifies the family
+/// This returns a regular expression 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();}
+const regex_t_sptr&
+type_suppression::get_type_name_not_regex() const
+{return priv_->type_name_not_regex_;}
 
 /// Setter for the name of the type about which diff reports should be
 /// suppressed.
@@ -612,21 +606,21 @@ type_suppression::set_source_locations_to_keep
 (const unordered_set<string>& l)
 {priv_->source_locations_to_keep_ = l;}
 
-/// Getter of the regular expression string that designates the source
+/// Getter of the regular expression that designates the source
 /// location paths of types that should not be suppressed.
 ///
-/// @return the regular expression string.
-const string&
-type_suppression::get_source_location_to_keep_regex_str() const
-{return priv_->source_location_to_keep_regex_str_;}
+/// @return the regular expression.
+const regex_t_sptr&
+type_suppression::get_source_location_to_keep_regex() const
+{return priv_->source_location_to_keep_regex_;}
 
-/// Setter of the regular expression string that designates the source
+/// Setter of the regular expression that designates the source
 /// location paths of types that should not be suppressed.
 ///
 /// @param r the new regular expression.
 void
-type_suppression::set_source_location_to_keep_regex_str(const string& r)
-{priv_->source_location_to_keep_regex_str_ = r;}
+type_suppression::set_source_location_to_keep_regex(const regex_t_sptr& r)
+{priv_->source_location_to_keep_regex_ = 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
@@ -1558,39 +1552,43 @@ read_type_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr file_name_regex_prop =
     is_simple_property(section.find_property("file_name_regexp"));
-  string file_name_regex_str =
-    file_name_regex_prop ? file_name_regex_prop->get_value()->as_string() : "";
+  regex_t_sptr file_name_regex;
+  if (file_name_regex_prop)
+    file_name_regex =
+      regex::compile(file_name_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr file_name_not_regex_prop =
     is_simple_property(section.find_property("file_name_not_regexp"));
-  string file_name_not_regex_str =
-    file_name_not_regex_prop
-    ? file_name_not_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr file_name_not_regex;
+  if (file_name_not_regex_prop)
+    file_name_not_regex =
+      regex::compile(file_name_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr soname_regex_prop =
     is_simple_property(section.find_property("soname_regexp"));
-  string soname_regex_str =
-    soname_regex_prop ? soname_regex_prop->get_value()->as_string() : "";
+  regex_t_sptr soname_regex;
+  if (soname_regex_prop)
+    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr soname_not_regex_prop =
     is_simple_property(section.find_property("soname_not_regexp"));
-  string soname_not_regex_str =
-    soname_not_regex_prop
-    ? soname_not_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr soname_not_regex;
+  if (soname_not_regex_prop)
+    soname_not_regex =
+      regex::compile(soname_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr name_regex_prop =
     is_simple_property(section.find_property("name_regexp"));
-  string name_regex_str = name_regex_prop
-    ? name_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr name_regex;
+  if (name_regex_prop)
+    name_regex = regex::compile(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()
-    : "";
+  regex_t_sptr name_not_regex;
+  if (name_not_regex_prop)
+    name_not_regex =
+      regex::compile(name_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr name_prop =
     is_simple_property(section.find_property("name"));
@@ -1622,9 +1620,10 @@ read_type_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr srcloc_not_regexp_prop =
     is_simple_property(section.find_property("source_location_not_regexp"));
-  string srcloc_not_regexp_str;
+  regex_t_sptr srcloc_not_regex;
   if (srcloc_not_regexp_prop)
-    srcloc_not_regexp_str = srcloc_not_regexp_prop->get_value()->as_string();
+    srcloc_not_regex =
+      regex::compile(srcloc_not_regexp_prop->get_value()->as_string());
 
   bool consider_type_kind = false;
   type_suppression::type_kind type_kind = type_suppression::UNKNOWN_TYPE_KIND;
@@ -1831,7 +1830,7 @@ read_type_suppression(const ini::config::section& section)
 	changed_enumerator_names.push_back(p->get_value()->as_string());
     }
 
-  result.reset(new type_suppression(label_str, name_regex_str, name_str));
+  result.reset(new type_suppression(label_str, name_regex, name_str));
 
   if (consider_type_kind)
     {
@@ -1848,31 +1847,31 @@ read_type_suppression(const ini::config::section& section)
   if (consider_data_member_insertion)
     result->set_data_member_insertion_ranges(insert_ranges);
 
-  if (!name_not_regex_str.empty())
-    result->set_type_name_not_regex_str(name_not_regex_str);
+  if (name_not_regex)
+    result->set_type_name_not_regex(name_not_regex);
 
-  if (!file_name_regex_str.empty())
-    result->set_file_name_regex_str(file_name_regex_str);
+  if (file_name_regex)
+    result->set_file_name_regex(file_name_regex);
 
-  if (!file_name_not_regex_str.empty())
-    result->set_file_name_not_regex_str(file_name_not_regex_str);
+  if (file_name_not_regex)
+    result->set_file_name_not_regex(file_name_not_regex);
 
-  if (!soname_regex_str.empty())
-    result->set_soname_regex_str(soname_regex_str);
+  if (soname_regex)
+    result->set_soname_regex(soname_regex);
 
-  if (!soname_not_regex_str.empty())
-    result->set_soname_not_regex_str(soname_not_regex_str);
+  if (soname_not_regex)
+    result->set_soname_not_regex(soname_not_regex);
 
   if (!srcloc_not_in.empty())
     result->set_source_locations_to_keep(srcloc_not_in);
 
-  if (!srcloc_not_regexp_str.empty())
-    result->set_source_location_to_keep_regex_str(srcloc_not_regexp_str);
+  if (srcloc_not_regex)
+    result->set_source_location_to_keep_regex(srcloc_not_regex);
 
   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
-      && ((!name_regex_str.empty()
+      && ((name_regex
 	   || !name_str.empty()
-	   || !srcloc_not_regexp_str.empty()
+	   || srcloc_not_regex
 	   || !srcloc_not_in.empty())))
     result->set_drops_artifact_from_ir(true);
 
@@ -1898,7 +1897,7 @@ read_type_suppression(const ini::config::section& section)
 /// account only if the parameter @p tn is empty.
 function_suppression::parameter_spec::parameter_spec(size_t i,
 						     const string& tn,
-						     const string& tn_regex)
+						     const regex_t_sptr& tn_regex)
   : priv_(new priv(i, tn, tn_regex))
 {}
 
@@ -1943,9 +1942,9 @@ function_suppression::parameter_spec::set_parameter_type_name(const string& tn)
 /// empty.
 ///
 /// @return the regular expression or the parameter type name.
-const string&
-function_suppression::parameter_spec::get_parameter_type_name_regex_str() const
-{return priv_->type_name_regex_str_;}
+const regex_t_sptr&
+function_suppression::parameter_spec::get_parameter_type_name_regex() const
+{return priv_->type_name_regex_;}
 
 /// Setter for the regular expression that defines a set of type names
 /// for the parameter designated by this specification.
@@ -1955,12 +1954,12 @@ function_suppression::parameter_spec::get_parameter_type_name_regex_str() const
 /// function_suppression::parameter_spec::get_parameter_type_name() is
 /// empty.
 ///
-/// @param type_name_regex_str the new type name regular expression to
+/// @param type_name_regex the new type name regular expression to
 /// set.
 void
-function_suppression::parameter_spec::set_parameter_type_name_regex_str
-(const string& type_name_regex_str)
-{priv_->type_name_regex_str_ = type_name_regex_str;}
+function_suppression::parameter_spec::set_parameter_type_name_regex
+(const regex_t_sptr& type_name_regex)
+{priv_->type_name_regex_ = type_name_regex;}
 
 /// Default constructor for the @ref function_suppression type.
 ///
@@ -2028,14 +2027,14 @@ function_suppression::function_suppression()
 /// case it's ignored at evaluation time.
 function_suppression::function_suppression(const string&		label,
 					   const string&		name,
-					   const string&		nr,
+					   const regex_t_sptr&		nr,
 					   const string&		ret_tn,
-					   const string&		ret_tr,
+					   const regex_t_sptr&		ret_tr,
 					   parameter_specs_type&	ps,
 					   const string&		sym_n,
-					   const string&		sym_nr,
+					   const regex_t_sptr&		sym_nr,
 					   const string&		sym_v,
-					   const string&		sym_vr)
+					   const regex_t_sptr&		sym_vr)
   : suppression_base(label),
     priv_(new priv(name, nr, ret_tn, ret_tr, ps,
 		   sym_n, sym_nr, sym_v, sym_vr))
@@ -2103,9 +2102,9 @@ function_suppression::set_name(const string& n)
 ///
 /// @return the regular expression for the possible names of the
 /// function(s).
-const string&
-function_suppression::get_name_regex_str() const
-{return priv_->name_regex_str_;}
+const regex_t_sptr&
+function_suppression::get_name_regex() const
+{return priv_->name_regex_;}
 
 /// Setter for a regular expression for a family of names of functions
 /// the user wants the current specification to designate.
@@ -2113,8 +2112,8 @@ function_suppression::get_name_regex_str() const
 /// @param r the new the regular expression for the possible names of
 /// the function(s).
 void
-function_suppression::set_name_regex_str(const string& r)
-{priv_->name_regex_str_ = r;}
+function_suppression::set_name_regex(const regex_t_sptr& r)
+{priv_->name_regex_ = r;}
 
 /// Getter for a regular expression of a family of names of functions
 /// the user wants the current specification to designate the negation
@@ -2122,9 +2121,9 @@ function_suppression::set_name_regex_str(const string& r)
 ///
 /// @return the regular expression for the possible names of the
 /// function(s).
-const string&
-function_suppression::get_name_not_regex_str() const
-{return priv_->name_not_regex_str_;}
+const regex_t_sptr&
+function_suppression::get_name_not_regex() const
+{return priv_->name_not_regex_;}
 
 /// Setter for a regular expression for a family of names of functions
 /// the user wants the current specification to designate the negation
@@ -2133,8 +2132,8 @@ function_suppression::get_name_not_regex_str() const
 /// @param r the new the regular expression for the possible names of
 /// the function(s).
 void
-function_suppression::set_name_not_regex_str(const string& r)
-{priv_->name_not_regex_str_ = r;}
+function_suppression::set_name_not_regex(const regex_t_sptr& r)
+{priv_->name_not_regex_ = r;}
 
 /// Getter for the name of the return type of the function the user
 /// wants this specification to designate.  This property might be
@@ -2166,9 +2165,9 @@ function_suppression::set_return_type_name(const string& tr)
 ///
 /// @return the regular expression for the possible names of the
 /// return types of the function(s).
-const string&
-function_suppression::get_return_type_regex_str() const
-{return priv_->return_type_regex_str_;}
+const regex_t_sptr&
+function_suppression::get_return_type_regex() const
+{return priv_->return_type_regex_;}
 
 /// Setter for a regular expression for a family of return type names
 /// for functions the user wants the current specification to
@@ -2183,8 +2182,8 @@ function_suppression::get_return_type_regex_str() const
 /// @param r the new regular expression for the possible names of the
 /// return types of the function(s) to set.
 void
-function_suppression::set_return_type_regex_str(const string& r)
-{priv_->return_type_regex_str_ = r;}
+function_suppression::set_return_type_regex(const regex_t_sptr& r)
+{priv_->return_type_regex_ = r;}
 
 /// Getter for a vector of parameter specifications to specify
 /// properties of the parameters of the functions the user wants this
@@ -2252,9 +2251,9 @@ function_suppression::set_symbol_name(const string& n)
 ///
 /// @return the regular expression for a family of names of symbols of
 /// functions to designate.
-const string&
-function_suppression::get_symbol_name_regex_str() const
-{return priv_->symbol_name_regex_str_;}
+const regex_t_sptr&
+function_suppression::get_symbol_name_regex() const
+{return priv_->symbol_name_regex_;}
 
 /// Setter for a regular expression for a family of names of symbols
 /// of functions the user wants this specification to designate.
@@ -2269,8 +2268,8 @@ function_suppression::get_symbol_name_regex_str() const
 /// @param r the new regular expression for a family of names of
 /// symbols of functions to set.
 void
-function_suppression::set_symbol_name_regex_str(const string& r)
-{priv_->symbol_name_regex_str_ = r;}
+function_suppression::set_symbol_name_regex(const regex_t_sptr& r)
+{priv_->symbol_name_regex_ = r;}
 
 /// Getter for a regular expression for a family of names of symbols
 /// of functions the user wants this specification to designate.
@@ -2285,11 +2284,11 @@ function_suppression::set_symbol_name_regex_str(const string& r)
 /// This property might be empty, in which case it's ignored at
 /// evaluation time.
 ///
-/// @return the regular expression string for a family of names of
+/// @return the regular expression for a family of names of
 /// symbols that is to be *NOT* suppressed by this suppression specification.
-const string&
-function_suppression::get_symbol_name_not_regex_str() const
-{return priv_->symbol_name_not_regex_str_;}
+const regex_t_sptr&
+function_suppression::get_symbol_name_not_regex() const
+{return priv_->symbol_name_not_regex_;}
 
 /// Setter for a regular expression for a family of names of symbols
 /// of functions the user wants this specification to designate.
@@ -2304,12 +2303,12 @@ function_suppression::get_symbol_name_not_regex_str() const
 /// This property might be empty, in which case it's ignored at
 /// evaluation time.
 ///
-/// @param the new regular expression string for a family of names of
+/// @param the new regular expression for a family of names of
 /// symbols that is to be *NOT* suppressed by this suppression
 /// specification.
 void
-function_suppression::set_symbol_name_not_regex_str(const string& r)
-{priv_->symbol_name_not_regex_str_ = r;}
+function_suppression::set_symbol_name_not_regex(const regex_t_sptr& r)
+{priv_->symbol_name_not_regex_ = r;}
 
 /// Getter for the name of the version of the symbol of the function
 /// the user wants this specification to designate.
@@ -2344,9 +2343,9 @@ function_suppression::set_symbol_version(const string& v)
 ///
 /// @return the regular expression for the versions of symbols of
 /// functions to designate.
-const string&
-function_suppression::get_symbol_version_regex_str() const
-{return priv_->symbol_version_regex_str_;}
+const regex_t_sptr&
+function_suppression::get_symbol_version_regex() const
+{return priv_->symbol_version_regex_;}
 
 /// Setter for a regular expression for a family of versions of
 /// symbols of functions the user wants the current specification to
@@ -2360,8 +2359,8 @@ function_suppression::get_symbol_version_regex_str() const
 /// @param the new regular expression for the versions of symbols of
 /// functions to designate.
 void
-function_suppression::set_symbol_version_regex_str(const string& r)
-{priv_->symbol_version_regex_str_ = r;}
+function_suppression::set_symbol_version_regex(const regex_t_sptr& r)
+{priv_->symbol_version_regex_ = r;}
 
 /// Getter for the "allow_other_aliases" property of the function
 /// suppression specification.
@@ -2764,7 +2763,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
       if (sym_name != get_symbol_name())
 	return false;
     }
-  else if (!get_symbol_name_regex_str().empty())
+  else if (get_symbol_name_regex())
     {
       const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
       if (symbol_name_regex && !regex::match(symbol_name_regex, sym_name))
@@ -2779,7 +2778,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
       if (sym_version != get_symbol_version())
 	return false;
     }
-  else if (!get_symbol_version_regex_str().empty())
+  else if (get_symbol_version_regex())
     {
       const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
@@ -3085,10 +3084,10 @@ read_parameter_spec_from_string(const string& str)
 
   if (!index_str.empty() || !type_name.empty())
     {
-      std::string type_name_regex;
+      regex_t_sptr type_name_regex;
       if (is_regex)
 	{
-	  type_name_regex = type_name;
+	  type_name_regex = regex::compile(type_name);
 	  type_name.clear();
 	}
       function_suppression::parameter_spec* p =
@@ -3138,27 +3137,30 @@ read_function_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr file_name_regex_prop =
     is_simple_property(section.find_property("file_name_regexp"));
-  string file_name_regex_str =
-    file_name_regex_prop ? file_name_regex_prop->get_value()->as_string() : "";
+  regex_t_sptr file_name_regex;
+  if (file_name_regex_prop)
+    file_name_regex =
+      regex::compile(file_name_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr file_name_not_regex_prop =
     is_simple_property(section.find_property("file_name_not_regexp"));
-  string file_name_not_regex_str =
-    file_name_not_regex_prop
-    ? file_name_not_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr file_name_not_regex;
+  if (file_name_not_regex_prop)
+    file_name_not_regex =
+      regex::compile(file_name_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr soname_regex_prop =
     is_simple_property(section.find_property("soname_regexp"));
-  string soname_regex_str =
-    soname_regex_prop ? soname_regex_prop->get_value()->as_string() : "";
+  regex_t_sptr soname_regex;
+  if (soname_regex_prop)
+    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr soname_not_regex_prop =
     is_simple_property(section.find_property("soname_not_regexp"));
-  string soname_not_regex_str =
-    soname_not_regex_prop
-    ? soname_not_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr soname_not_regex;
+  if (soname_not_regex_prop)
+    soname_not_regex =
+      regex::compile(soname_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr name_prop =
     is_simple_property(section.find_property("name"));
@@ -3168,15 +3170,16 @@ read_function_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr name_regex_prop =
     is_simple_property(section.find_property("name_regexp"));
-  string name_regex_str = name_regex_prop
-    ? name_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr name_regex;
+  if (name_regex_prop)
+    name_regex = regex::compile(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()
-    : "";
+  regex_t_sptr name_not_regex;
+  if (name_not_regex_prop)
+    name_not_regex =
+      regex::compile(name_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr return_type_name_prop =
     is_simple_property(section.find_property("return_type_name"));
@@ -3186,9 +3189,10 @@ read_function_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr return_type_regex_prop =
     is_simple_property(section.find_property("return_type_regexp"));
-  string return_type_regex_str = return_type_regex_prop
-    ? return_type_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr return_type_regex;
+  if (return_type_regex_prop)
+    return_type_regex =
+      regex::compile(return_type_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr sym_name_prop =
     is_simple_property(section.find_property("symbol_name"));
@@ -3198,15 +3202,17 @@ read_function_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr sym_name_regex_prop =
     is_simple_property(section.find_property("symbol_name_regexp"));
-  string sym_name_regex_str = sym_name_regex_prop
-    ? sym_name_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr sym_name_regex;
+  if (sym_name_regex_prop)
+    sym_name_regex =
+      regex::compile(sym_name_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr sym_name_not_regex_prop =
     is_simple_property(section.find_property("symbol_name_not_regexp"));
-  string sym_name_not_regex_str = sym_name_not_regex_prop
-    ? sym_name_not_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr sym_name_not_regex;
+  if (sym_name_not_regex_prop)
+    sym_name_not_regex =
+      regex::compile(sym_name_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr sym_ver_prop =
     is_simple_property(section.find_property("symbol_version"));
@@ -3216,9 +3222,10 @@ read_function_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr sym_ver_regex_prop =
     is_simple_property(section.find_property("symbol_version_regexp"));
-  string sym_ver_regex_str = sym_ver_regex_prop
-    ? sym_ver_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr sym_ver_regex;
+  if (sym_ver_regex_prop)
+    sym_ver_regex =
+      regex::compile(sym_ver_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr allow_other_aliases_prop =
     is_simple_property(section.find_property("allow_other_aliases"));
@@ -3243,22 +3250,22 @@ read_function_suppression(const ini::config::section& section)
 
   result.reset(new function_suppression(label_str,
 					name,
-					name_regex_str,
+					name_regex,
 					return_type_name,
-					return_type_regex_str,
+					return_type_regex,
 					parms,
 					sym_name,
-					sym_name_regex_str,
+					sym_name_regex,
 					sym_version,
-					sym_ver_regex_str));
+					sym_ver_regex));
 
   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
       && (!name.empty()
-	  || !name_regex_str.empty()
-	  || !name_not_regex_str.empty()
+	  || name_regex
+	  || name_not_regex
 	  || !sym_name.empty()
-	  || !sym_name_regex_str.empty()
-	  || !sym_name_not_regex_str.empty()))
+	  || sym_name_regex
+	  || sym_name_not_regex))
     result->set_drops_artifact_from_ir(true);
 
   if (!change_kind_str.empty())
@@ -3269,23 +3276,23 @@ read_function_suppression(const ini::config::section& section)
     result->set_allow_other_aliases(allow_other_aliases == "yes"
 				    || allow_other_aliases == "true");
 
-  if (!name_not_regex_str.empty())
-    result->set_name_not_regex_str(name_not_regex_str);
+  if (name_not_regex)
+    result->set_name_not_regex(name_not_regex);
 
-  if (!sym_name_not_regex_str.empty())
-    result->set_symbol_name_not_regex_str(sym_name_not_regex_str);
+  if (sym_name_not_regex)
+    result->set_symbol_name_not_regex(sym_name_not_regex);
 
-  if (!file_name_regex_str.empty())
-    result->set_file_name_regex_str(file_name_regex_str);
+  if (file_name_regex)
+    result->set_file_name_regex(file_name_regex);
 
-  if (!file_name_not_regex_str.empty())
-    result->set_file_name_not_regex_str(file_name_not_regex_str);
+  if (file_name_not_regex)
+    result->set_file_name_not_regex(file_name_not_regex);
 
-  if (!soname_regex_str.empty())
-    result->set_soname_regex_str(soname_regex_str);
+  if (soname_regex)
+    result->set_soname_regex(soname_regex);
 
-  if (!soname_not_regex_str.empty())
-    result->set_soname_not_regex_str(soname_not_regex_str);
+  if (soname_not_regex)
+    result->set_soname_not_regex(soname_not_regex);
 
   return result;
 }
@@ -3305,7 +3312,7 @@ read_function_suppression(const ini::config::section& section)
 /// specification to designate.  This parameter might be empty, in
 /// which case it's ignored at evaluation time.
 ///
-/// @param name_regex_str if @p name is empty, this parameter is a
+/// @param name_regex if @p name is empty, this parameter is a
 /// regular expression for a family of names of variables the user
 /// wants the current specification to designate.  If @p name is not
 /// empty, then this parameter is ignored at evaluation time.  This
@@ -3339,7 +3346,7 @@ read_function_suppression(const ini::config::section& section)
 /// wants the current specification to designate.  This parameter
 /// might be empty, in which case it's ignored at evaluation time.
 ///
-/// @param type_name_regex_str if @p type_name is empty, then this
+/// @param type_name_regex if @p type_name is empty, then this
 /// parameter is a regular expression for a family of type names of
 /// variables the user wants the current specification to designate.
 /// If @p type_name is not empty, then this parameter is ignored at
@@ -3347,18 +3354,18 @@ read_function_suppression(const ini::config::section& section)
 /// ignored at evaluation time.
 variable_suppression::variable_suppression(const string& label,
 					   const string& name,
-					   const string& name_regex_str,
+					   const regex_t_sptr& name_regex,
 					   const string& symbol_name,
-					   const string& symbol_name_regex_str,
+					   const regex_t_sptr& symbol_name_regex,
 					   const string& symbol_version,
-					   const string& symbol_version_regex,
+					   const regex_t_sptr& symbol_version_regex,
 					   const string& type_name,
-					   const string& type_name_regex_str)
+					   const regex_t_sptr& type_name_regex)
   : suppression_base(label),
-    priv_(new priv(name, name_regex_str,
-		   symbol_name, symbol_name_regex_str,
+    priv_(new priv(name, name_regex,
+		   symbol_name, symbol_name_regex,
 		   symbol_version, symbol_version_regex,
-		   type_name, type_name_regex_str))
+		   type_name, type_name_regex))
 {}
 
 /// Virtual destructor for the @erf variable_suppression type.
@@ -3428,9 +3435,9 @@ variable_suppression::set_name(const string& n)
 /// which case it's ignored at evaluation time.
 ///
 /// @return the regular expression for the variable name.
-const string&
-variable_suppression::get_name_regex_str() const
-{return priv_->name_regex_str_;}
+const regex_t_sptr&
+variable_suppression::get_name_regex() const
+{return priv_->name_regex_;}
 
 /// Setter for the regular expression for a family of names of
 /// variables the user wants the current specification to designate.
@@ -3441,22 +3448,22 @@ variable_suppression::get_name_regex_str() const
 ///
 /// @param r the new regular expression for the variable name.
 void
-variable_suppression::set_name_regex_str(const string& r)
-{priv_->name_regex_str_ = r;}
+variable_suppression::set_name_regex(const regex_t_sptr& r)
+{priv_->name_regex_ = r;}
 
 /// Getter for the "name_not_regexp" property of the specification.
 ///
 /// @return the value of the "name_not_regexp" property.
-const string&
-variable_suppression::get_name_not_regex_str() const
-{return priv_->name_not_regex_str_;}
+const regex_t_sptr&
+variable_suppression::get_name_not_regex() const
+{return priv_->name_not_regex_;}
 
 /// Setter for the "name_not_regexp" property of the specification.
 ///
 /// @param r the new value of the "name_not_regexp" property.
 void
-variable_suppression::set_name_not_regex_str(const string& r)
-{priv_->name_not_regex_str_ = r;}
+variable_suppression::set_name_not_regex(const regex_t_sptr& r)
+{priv_->name_not_regex_ = r;}
 
 /// Getter for the name of the symbol of the variable the user wants
 /// the current specification to designate.
@@ -3489,9 +3496,9 @@ variable_suppression::set_symbol_name(const string& n)
 /// empty.
 ///
 /// @return the regular expression for a symbol name of the variable.
-const string&
-variable_suppression::get_symbol_name_regex_str() const
-{return priv_->symbol_name_regex_str_;}
+const regex_t_sptr&
+variable_suppression::get_symbol_name_regex() const
+{return priv_->symbol_name_regex_;}
 
 /// Setter of the regular expression for a family of symbol names of
 /// the variables this specification is about to designate.
@@ -3503,8 +3510,8 @@ variable_suppression::get_symbol_name_regex_str() const
 ///
 /// @param r the regular expression for a symbol name of the variable.
 void
-variable_suppression::set_symbol_name_regex_str(const string& r)
-{priv_->symbol_name_regex_str_ = r;}
+variable_suppression::set_symbol_name_regex(const regex_t_sptr& r)
+{priv_->symbol_name_regex_ = r;}
 
 /// Getter for a regular expression for a family of names of symbols
 /// of variables the user wants this specification to designate.
@@ -3519,11 +3526,11 @@ variable_suppression::set_symbol_name_regex_str(const string& r)
 /// This property might be empty, in which case it's ignored at
 /// evaluation time.
 ///
-/// @return the regular expression string for a family of names of
+/// @return the regular expression for a family of names of
 /// symbols that is to be *NOT* suppressed by this suppression specification.
-const string&
-variable_suppression::get_symbol_name_not_regex_str() const
-{return priv_->symbol_name_not_regex_str_;}
+const regex_t_sptr&
+variable_suppression::get_symbol_name_not_regex() const
+{return priv_->symbol_name_not_regex_;}
 
 /// Setter for a regular expression for a family of names of symbols
 /// of variables the user wants this specification to designate.
@@ -3538,12 +3545,12 @@ variable_suppression::get_symbol_name_not_regex_str() const
 /// This property might be empty, in which case it's ignored at
 /// evaluation time.
 ///
-/// @param the new regular expression string for a family of names of
+/// @param the new regular expression for a family of names of
 /// symbols that is to be *NOT* suppressed by this suppression
 /// specification.
 void
-variable_suppression::set_symbol_name_not_regex_str(const string& r)
-{priv_->symbol_name_not_regex_str_ = r;}
+variable_suppression::set_symbol_name_not_regex(const regex_t_sptr& r)
+{priv_->symbol_name_not_regex_ = r;}
 
 /// Getter for the version of the symbol of the variable the user
 /// wants the current specification to designate.  This property might
@@ -3571,9 +3578,9 @@ variable_suppression::set_symbol_version(const string& v)
 ///
 /// @return the regular expression of the symbol version of the
 /// variable.
-const string&
-variable_suppression::get_symbol_version_regex_str() const
-{return priv_->symbol_version_regex_str_;}
+const regex_t_sptr&
+variable_suppression::get_symbol_version_regex() const
+{return priv_->symbol_version_regex_;}
 
 /// Setter of the regular expression for a family of versions of
 /// symbol for the variables the user wants the current specification
@@ -3584,8 +3591,8 @@ variable_suppression::get_symbol_version_regex_str() const
 /// @param v the new regular expression of the symbol version of the
 /// variable.
 void
-variable_suppression::set_symbol_version_regex_str(const string& r)
-{priv_->symbol_version_regex_str_ = r;}
+variable_suppression::set_symbol_version_regex(const regex_t_sptr& r)
+{priv_->symbol_version_regex_ = r;}
 
 /// Getter for the name of the type of the variable the user wants the
 /// current specification to designate.
@@ -3618,9 +3625,9 @@ variable_suppression::set_type_name(const string& n)
 /// empty, in which case it's ignored at evaluation time.
 ///
 /// @return the regular expression of the variable type name.
-const string&
-variable_suppression::get_type_name_regex_str() const
-{return priv_->type_name_regex_str_;}
+const regex_t_sptr&
+variable_suppression::get_type_name_regex() const
+{return priv_->type_name_regex_;}
 
 /// Setter for the regular expression for a family of type names of
 /// variables the user wants the current specification to designate.
@@ -3632,8 +3639,8 @@ variable_suppression::get_type_name_regex_str() const
 ///
 /// @param r the regular expression of the variable type name.
 void
-variable_suppression::set_type_name_regex_str(const string& r)
-{priv_->type_name_regex_str_ = r;}
+variable_suppression::set_type_name_regex(const regex_t_sptr& r)
+{priv_->type_name_regex_ = r;}
 
 /// Evaluate this suppression specification on a given diff node and
 /// say if the diff node should be suppressed or not.
@@ -3862,7 +3869,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
       if (get_symbol_name() != sym_name)
 	return false;
     }
-  else if (!get_symbol_name_regex_str().empty())
+  else if (get_symbol_name_regex())
     {
       const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
       if (sym_name_regex && !regex::match(sym_name_regex, sym_name))
@@ -3877,7 +3884,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
       if (get_symbol_version() != sym_version)
 	return false;
     }
-  else if (!get_symbol_version_regex_str().empty())
+  else if (get_symbol_version_regex())
     {
       const regex_t_sptr symbol_version_regex =
 	priv_->get_symbol_version_regex();
@@ -3995,27 +4002,30 @@ read_variable_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr file_name_regex_prop =
     is_simple_property(section.find_property("file_name_regexp"));
-  string file_name_regex_str =
-    file_name_regex_prop ? file_name_regex_prop->get_value()->as_string() : "";
+  regex_t_sptr file_name_regex;
+  if (file_name_regex_prop)
+    file_name_regex =
+      regex::compile(file_name_regex_prop->get_value()->as_string());
 
  ini::simple_property_sptr file_name_not_regex_prop =
-    is_simple_property(section.find_property("file_name_not_regexp"));
-  string file_name_not_regex_str =
-    file_name_not_regex_prop
-    ? file_name_not_regex_prop->get_value()->as_string()
-    : "";
+  is_simple_property(section.find_property("file_name_not_regexp"));
+ regex_t_sptr file_name_not_regex;
+ if (file_name_not_regex_prop)
+   file_name_not_regex =
+     regex::compile(file_name_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr soname_regex_prop =
     is_simple_property(section.find_property("soname_regexp"));
-  string soname_regex_str =
-    soname_regex_prop ? soname_regex_prop->get_value()->as_string() : "";
+  regex_t_sptr soname_regex;
+  if (soname_regex_prop)
+    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr soname_not_regex_prop =
     is_simple_property(section.find_property("soname_not_regexp"));
-  string soname_not_regex_str =
-    soname_not_regex_prop
-    ? soname_not_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr soname_not_regex;
+  if (soname_not_regex_prop)
+    soname_not_regex =
+      regex::compile(soname_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr name_prop =
     is_simple_property(section.find_property("name"));
@@ -4025,15 +4035,16 @@ read_variable_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr name_regex_prop =
     is_simple_property(section.find_property("name_regexp"));
-  string name_regex_str = (name_regex_prop
-			   ? name_regex_prop->get_value()->as_string()
-			   : "");
+  regex_t_sptr name_regex;
+  if (name_regex_prop)
+    name_regex = regex::compile(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()
-    : "";
+  regex_t_sptr name_not_regex;
+  if (name_not_regex_prop)
+    name_not_regex =
+      regex::compile(name_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr sym_name_prop =
     is_simple_property(section.find_property("symbol_name"));
@@ -4043,15 +4054,17 @@ read_variable_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr sym_name_regex_prop =
     is_simple_property(section.find_property("symbol_name_regexp"));
-  string symbol_name_regex_str = sym_name_regex_prop
-    ? sym_name_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr symbol_name_regex;
+  if (sym_name_regex_prop)
+    symbol_name_regex =
+      regex::compile(sym_name_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr sym_name_not_regex_prop =
     is_simple_property(section.find_property("symbol_name_not_regexp"));
-  string symbol_name_not_regex_str = sym_name_not_regex_prop
-    ? sym_name_not_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr symbol_name_not_regex;
+  if (sym_name_not_regex_prop)
+    symbol_name_not_regex =
+      regex::compile(sym_name_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr sym_version_prop =
     is_simple_property(section.find_property("symbol_version"));
@@ -4061,9 +4074,10 @@ read_variable_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr sym_version_regex_prop =
     is_simple_property(section.find_property("symbol_version_regexp"));
-  string symbol_version_regex_str = sym_version_regex_prop
-    ? sym_version_regex_prop->get_value()->as_string()
-     : "";
+  regex_t_sptr symbol_version_regex;
+  if (sym_version_regex_prop)
+    symbol_version_regex =
+      regex::compile(sym_version_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr type_name_prop =
     is_simple_property(section.find_property("type_name"));
@@ -4073,50 +4087,51 @@ read_variable_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr type_name_regex_prop =
     is_simple_property(section.find_property("type_name_regexp"));
-  string type_name_regex_str = type_name_regex_prop
-    ? type_name_regex_prop->get_value()->as_string()
-     : "";
+  regex_t_sptr type_name_regex;
+  if (type_name_regex_prop)
+    type_name_regex =
+      regex::compile(type_name_regex_prop->get_value()->as_string());
 
   result.reset(new variable_suppression(label_str,
 					name_str,
-					name_regex_str,
+					name_regex,
 					symbol_name,
-					symbol_name_regex_str,
+					symbol_name_regex,
 					symbol_version,
-					symbol_version_regex_str,
+					symbol_version_regex,
 					type_name_str,
-					type_name_regex_str));
+					type_name_regex));
 
   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
       && (!name_str.empty()
-	  || !name_regex_str.empty()
-	  || !name_not_regex_str.empty()
+	  || name_regex
+	  || name_not_regex
 	  || !symbol_name.empty()
-	  || !symbol_name_regex_str.empty()
-	  || !symbol_name_not_regex_str.empty()))
+	  || symbol_name_regex
+	  || symbol_name_not_regex))
     result->set_drops_artifact_from_ir(true);
 
-  if (!name_not_regex_str.empty())
-    result->set_name_not_regex_str(name_not_regex_str);
+  if (name_not_regex)
+    result->set_name_not_regex(name_not_regex);
 
-  if (!symbol_name_not_regex_str.empty())
-    result->set_symbol_name_not_regex_str(symbol_name_not_regex_str);
+  if (symbol_name_not_regex)
+    result->set_symbol_name_not_regex(symbol_name_not_regex);
 
   if (!change_kind_str.empty())
     result->set_change_kind
       (variable_suppression::parse_change_kind(change_kind_str));
 
-  if (!file_name_regex_str.empty())
-    result->set_file_name_regex_str(file_name_regex_str);
+  if (file_name_regex)
+    result->set_file_name_regex(file_name_regex);
 
-  if (!file_name_not_regex_str.empty())
-    result->set_file_name_not_regex_str(file_name_not_regex_str);
+  if (file_name_not_regex)
+    result->set_file_name_not_regex(file_name_not_regex);
 
-  if (!soname_regex_str.empty())
-    result->set_soname_regex_str(soname_regex_str);
+  if (soname_regex)
+    result->set_soname_regex(soname_regex);
 
-  if (!soname_not_regex_str.empty())
-    result->set_soname_not_regex_str(soname_not_regex_str);
+  if (soname_not_regex)
+    result->set_soname_not_regex(soname_not_regex);
 
   return result;
 }
@@ -4129,21 +4144,21 @@ read_variable_suppression(const ini::config::section& section)
 ///
 /// @param label the label of the suppression directive.
 ///
-/// @param fname_regex_str the regular expression string that
+/// @param fname_regex the regular expression that
 /// designates the file name that instances of @ref file_suppression
 /// should match.
 ///
-/// @param fname_not_regex_str the regular expression string that
+/// @param fname_not_regex the regular expression that
 /// designates the file name that instances of @ref file_suppression
 /// shoult *NOT* match.  In other words, this file_suppression should
 /// be activated if its file name does not match the regular
-/// expression @p fname_not_regex_str.
+/// expression @p fname_not_regex.
 file_suppression::file_suppression(const string& label,
-				   const string& fname_regex_str,
-				   const string& fname_not_regex_str)
+				   const regex_t_sptr& fname_regex,
+				   const regex_t_sptr& fname_not_regex)
   : suppression_base(label,
-		     fname_regex_str,
-		     fname_not_regex_str)
+		     fname_regex,
+		     fname_not_regex)
 {}
 
 /// Test if instances of this @ref file_suppression suppresses a
@@ -4223,41 +4238,44 @@ read_file_suppression(const ini::config::section& section)
 
   ini::simple_property_sptr file_name_regex_prop =
     is_simple_property(section.find_property("file_name_regexp"));
-  string file_name_regex_str =
-    file_name_regex_prop ? file_name_regex_prop->get_value()->as_string() : "";
+  regex_t_sptr file_name_regex;
+  if (file_name_regex_prop)
+    file_name_regex =
+      regex::compile(file_name_regex_prop->get_value()->as_string());
 
  ini::simple_property_sptr file_name_not_regex_prop =
     is_simple_property(section.find_property("file_name_not_regexp"));
-  string file_name_not_regex_str =
-    file_name_not_regex_prop
-    ? file_name_not_regex_prop->get_value()->as_string()
-    : "";
+ regex_t_sptr file_name_not_regex;
+ if (file_name_not_regex_prop)
+   file_name_not_regex =
+     regex::compile(file_name_not_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr soname_regex_prop =
     is_simple_property(section.find_property("soname_regexp"));
-  string soname_regex_str =
-    soname_regex_prop ? soname_regex_prop->get_value()->as_string() : "";
+  regex_t_sptr soname_regex;
+  if (soname_regex_prop)
+    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
 
   ini::simple_property_sptr soname_not_regex_prop =
     is_simple_property(section.find_property("soname_not_regexp"));
-  string soname_not_regex_str =
-    soname_not_regex_prop
-    ? soname_not_regex_prop->get_value()->as_string()
-    : "";
+  regex_t_sptr soname_not_regex;
+  if (soname_not_regex_prop)
+    soname_not_regex =
+      regex::compile(soname_not_regex_prop->get_value()->as_string());
 
   result.reset(new file_suppression(label_str,
-				    file_name_regex_str,
-				    file_name_not_regex_str));
+				    file_name_regex,
+				    file_name_not_regex));
 
-  if (!soname_regex_str.empty())
+  if (soname_regex)
     {
-      result->set_soname_regex_str(soname_regex_str);
+      result->set_soname_regex(soname_regex);
       result->set_drops_artifact_from_ir(true);
     }
 
-  if (!soname_not_regex_str.empty())
+  if (soname_not_regex)
     {
-      result->set_soname_not_regex_str(soname_not_regex_str);
+      result->set_soname_not_regex(soname_not_regex);
       result->set_drops_artifact_from_ir(true);
     }
 
diff --git a/src/abg-tools-utils.cc b/src/abg-tools-utils.cc
index 11486a21..fe0de750 100644
--- a/src/abg-tools-utils.cc
+++ b/src/abg-tools-utils.cc
@@ -1810,13 +1810,15 @@ handle_file_entry(const string& file_path,
 {
   if (!suppr)
     {
-      suppr.reset(new type_suppression(get_private_types_suppr_spec_label(),
-				       /*type_name_regexp=*/"",
-				       /*type_name=*/""));
+      suppr.reset(
+	new type_suppression(get_private_types_suppr_spec_label(),
+			     /*type_name_regexp=*/regex::regex_t_sptr(),
+			     /*type_name=*/""));
 
       // Types that are defined in system headers are usually
       // OK to be considered as public types.
-      suppr->set_source_location_to_keep_regex_str("^/usr/include/");
+      regex::regex_t_sptr headers_regex = regex::compile("^/usr/include/");
+      suppr->set_source_location_to_keep_regex(headers_regex);
       suppr->set_is_artificial(true);
     }
 
@@ -2004,7 +2006,8 @@ gen_suppr_spec_from_kernel_abi_whitelists
 
       // Build a regular expression representing the union of all
       // the function and variable names expressed in the white list.
-      const std::string regex = regex::generate_from_strings(whitelisted_names);
+      regex::regex_t_sptr regex =
+	regex::compile(regex::generate_from_strings(whitelisted_names));
 
       // Build a suppression specification which *keeps* functions
       // whose ELF symbols match the regular expression contained
@@ -2013,7 +2016,7 @@ gen_suppr_spec_from_kernel_abi_whitelists
       // match this regexp.
       function_suppression_sptr fn_suppr(new function_suppression);
       fn_suppr->set_label("whitelist");
-      fn_suppr->set_symbol_name_not_regex_str(regex);
+      fn_suppr->set_symbol_name_not_regex(regex);
       fn_suppr->set_drops_artifact_from_ir(true);
       result.push_back(fn_suppr);
 
@@ -2024,7 +2027,7 @@ gen_suppr_spec_from_kernel_abi_whitelists
       // match this regexp.
       variable_suppression_sptr var_suppr(new variable_suppression);
       var_suppr->set_label("whitelist");
-      var_suppr->set_symbol_name_not_regex_str(regex);
+      var_suppr->set_symbol_name_not_regex(regex);
       var_suppr->set_drops_artifact_from_ir(true);
       result.push_back(var_suppr);
     }
diff --git a/tests/test-kmi-whitelist.cc b/tests/test-kmi-whitelist.cc
index bcc5adee..16cc1861 100644
--- a/tests/test-kmi-whitelist.cc
+++ b/tests/test-kmi-whitelist.cc
@@ -29,10 +29,14 @@
 #include "lib/catch.hpp"
 
 #include "abg-fwd.h"
-#include "abg-suppression.h"
+#include "abg-regex.h"
 #include "abg-tools-utils.h"
+#include "abg-suppression.h"
 #include "test-utils.h"
 
+using abigail::regex::regex_t_sptr;
+using abigail::regex::compile;
+using abigail::regex::match;
 using abigail::tools_utils::gen_suppr_spec_from_kernel_abi_whitelists;
 using abigail::suppr::suppression_sptr;
 using abigail::suppr::suppressions_type;
@@ -57,9 +61,30 @@ const static std::string whitelist_with_duplicate_entry
     = std::string(abigail::tests::get_src_dir())
       + "/tests/data/test-kmi-whitelist/whitelist-with-duplicate-entry";
 
+// These are strings, not regexes, we cannot exhaustively check all
+// strings, but we can do some sampling and match sure we haven't got
+// the regex logic completely wrong.
+static const char* const random_symbols[] =
+{
+  "",
+  ".*",
+  "^$",
+  "test_symbol",
+  "test-symbol",
+  "test symbol",
+  "Test Symbol",
+  "est_symbo",
+  ".*test_symbol.*",
+  "test_symbol ",
+  " test_symbol",
+  " test_symbol ",
+  "test_another_symbol",
+  "$test_another_symbol",
+};
+
 void
 test_suppressions_are_consistent(const suppressions_type& suppr,
-			    const std::string&	     expr)
+				 const std::string&	  expr)
 {
   REQUIRE(suppr.size() == 2);
 
@@ -74,11 +99,32 @@ test_suppressions_are_consistent(const suppressions_type& suppr,
   // same mode
   REQUIRE(left->get_drops_artifact_from_ir()
 	  == right->get_drops_artifact_from_ir());
-  // same regex
-  REQUIRE(left->get_symbol_name_not_regex_str()
-     == right->get_symbol_name_not_regex_str());
-  // regex as expected
-  REQUIRE(left->get_symbol_name_not_regex_str() == expr);
+
+  // these parts of the symbol name matching should be absent
+  REQUIRE(left->get_symbol_name().empty());
+  REQUIRE(!left->get_symbol_name_regex());
+  REQUIRE(right->get_symbol_name().empty());
+  REQUIRE(!right->get_symbol_name_regex());
+
+  regex_t_sptr left_regex = left->get_symbol_name_not_regex();
+  regex_t_sptr right_regex = right->get_symbol_name_not_regex();
+  regex_t_sptr check_regex = compile(expr);
+
+  // all regexes present (compiled)
+  REQUIRE(left_regex);
+  REQUIRE(right_regex);
+  REQUIRE(check_regex);
+
+  // all regexes match or do not match a random symbol
+  for (size_t i = 0; i < sizeof(random_symbols)/sizeof(random_symbols[0]); ++i)
+    {
+      const std::string symbol(random_symbols[i]);
+      bool left_matches = match(left_regex, symbol);
+      bool right_matches = match(right_regex, symbol);
+      bool check_matches = match(check_regex, symbol);
+      REQUIRE(left_matches == right_matches);
+      REQUIRE(left_matches == check_matches);
+    }
 }
 
 TEST_CASE("NoWhitelists", "[whitelists]")
-- 
2.26.2.526.g744177e7f7-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v4 11/15] Reduce direct access to suppression priv_ members.
  2020-05-04 12:34   ` [PATCH v4 00/15] Simplify regex and suppression parsing Giuliano Procida
                       ` (9 preceding siblings ...)
  2020-05-04 12:34     ` [PATCH v4 10/15] Compile suppression regexes earlier Giuliano Procida
@ 2020-05-04 12:34     ` Giuliano Procida
  2020-05-04 12:34     ` [PATCH v4 12/15] Move match methods from priv to suppression_base Giuliano Procida
                       ` (3 subsequent siblings)
  14 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-05-04 12:34 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

Most suppression type functionality is available on the types
themselves via methods, particularly now that there are getters
for all the regex members.

This patch eliminates lots of accesses via priv_ members.

There are no behavioural changes.

	* src/abg-suppression.cc (sonames_of_binaries_match): Use
	suppression_matches_soname helper function.
	(suppression_matches_type_name): Use type_suppression regex getters.
	(suppression_matches_type_location): Use type_suppression
	regex getters.
	(function::suppression::suppresses_function): Use own regex
	getters.
	(function::suppression::suppresses_function_symbol): Use own
	regex getters.
	(suppression_matches_function_name): Use function_suppression
	regex and name getters.
	(suppression_matches_function_sym_name): Use function_suppression
	regex and symbol name getters.
	(suppression_matches_variable_name): Use variable__suppression
	regex and name getters.
	(suppression_matches_variable_sym_name): Use variable_suppression
	regex and symbol name getters.
	(suppression_matches_type): Use type_suppression
	regex getter.
	(variable_suppression::suppresses_variable): Use own regex
	getters.
	(variable_suppression::suppresses_variable_symbol): Use own
	regex getters.
	(type_suppression::suppresses_file): Use own regex getters.
	(suppression_matches_soname_or_filename): Indentation fix, en
	passant.

Reviewed-by: Matthias Maennich <maennich@google.com>
Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-suppression.cc | 107 +++++++++++++++++++----------------------
 1 file changed, 50 insertions(+), 57 deletions(-)

diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 80ac1e9f..4f44b175 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -276,8 +276,8 @@ sonames_of_binaries_match(const suppression_base& suppr,
   if (!suppr.has_soname_related_property())
     return false;
 
-  if (!suppr.priv_->matches_soname(first_soname)
-      && !suppr.priv_->matches_soname(second_soname))
+  if (!suppression_matches_soname(first_soname, suppr)
+      && !suppression_matches_soname(second_soname, suppr))
     return false;
 
   return true;
@@ -965,8 +965,8 @@ suppression_matches_type_name(const type_suppression&	s,
 			      const string&		type_name)
 {
   if (!s.get_type_name().empty()
-      || s.priv_->get_type_name_regex()
-      || s.priv_->get_type_name_not_regex())
+      || s.get_type_name_regex()
+      || s.get_type_name_not_regex())
     {
       // Check if there is an exact type name match.
       if (!s.get_type_name().empty())
@@ -982,14 +982,14 @@ suppression_matches_type_name(const type_suppression&	s,
 	  // the regular expression of the type name, then this
 	  // suppression doesn't apply.
 	  if (const regex_t_sptr& type_name_regex =
-	      s.priv_->get_type_name_regex())
+	      s.get_type_name_regex())
 	    {
 	      if (!regex::match(type_name_regex, type_name))
 		return false;
 	    }
 
 	  if (const regex_t_sptr type_name_not_regex =
-	      s.priv_->get_type_name_not_regex())
+	      s.get_type_name_not_regex())
 	    {
 	      if (regex::match(type_name_not_regex, type_name))
 		return false;
@@ -1037,7 +1037,7 @@ suppression_matches_type_location(const type_suppression&	s,
       unsigned loc_line = 0, loc_column = 0;
       loc.expand(loc_path, loc_line, loc_column);
 
-      if (regex_t_sptr regexp = s.priv_->get_source_location_to_keep_regex())
+      if (regex_t_sptr regexp = s.get_source_location_to_keep_regex())
 	if (regex::match(regexp, loc_path))
 	  return false;
 
@@ -1052,7 +1052,7 @@ suppression_matches_type_location(const type_suppression&	s,
   else
     {
       if (!s.get_source_locations_to_keep().empty()
-	  || s.priv_->get_source_location_to_keep_regex())
+	  || s.get_source_location_to_keep_regex())
 	// The user provided a "source_location_not_regexp" or
 	// a "source_location_not_in" property that was not
 	// triggered.  This means the current type suppression
@@ -1103,7 +1103,7 @@ suppression_matches_type_location(const type_suppression&	s,
 	    }
 	}
       if (!s.get_source_locations_to_keep().empty()
-	  || s.priv_->get_source_location_to_keep_regex())
+	  || s.get_source_location_to_keep_regex())
 	// The user provided a "source_location_not_regexp" or
 	// a "source_location_not_in" property that was not
 	// triggered.  This means the current type suppression
@@ -2476,7 +2476,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
 
   // check if the "name_regexp" property matches.
-  const regex_t_sptr name_regex = priv_->get_name_regex();
+  const regex_t_sptr name_regex = get_name_regex();
   if (name_regex)
     {
       if (!regex::match(name_regex, fname))
@@ -2507,7 +2507,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
 
   // check if the "name_not_regexp" property matches.
-  const regex_t_sptr name_not_regex = priv_->get_name_not_regex();
+  const regex_t_sptr name_not_regex = get_name_not_regex();
   if (name_not_regex)
     {
       if (regex::match(name_not_regex, fname))
@@ -2553,7 +2553,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
   else
     {
-      const regex_t_sptr return_type_regex = priv_->get_return_type_regex();
+      const regex_t_sptr return_type_regex = get_return_type_regex();
       if (return_type_regex
 	  && !regex::match(return_type_regex, fn_return_type_name))
 	return false;
@@ -2591,12 +2591,11 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
   else if (sym)
     {
-      const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
+      const regex_t_sptr symbol_name_regex = get_symbol_name_regex();
       if (symbol_name_regex && !regex::match(symbol_name_regex, fn_sym_name))
 	return false;
 
-      const regex_t_sptr symbol_name_not_regex =
-	priv_->get_symbol_name_not_regex();
+      const regex_t_sptr symbol_name_not_regex = get_symbol_name_not_regex();
       if (symbol_name_not_regex
 	  && regex::match(symbol_name_not_regex, fn_sym_name))
 	return false;
@@ -2633,8 +2632,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
   else if (sym)
     {
-      const regex_t_sptr symbol_version_regex =
-	priv_->get_symbol_version_regex();
+      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
       if (symbol_version_regex
 	  && !regex::match(symbol_version_regex, fn_sym_version))
 	return false;
@@ -2674,7 +2672,7 @@ function_suppression::suppresses_function(const function_decl* fn,
 	  else
 	    {
 	      const regex_t_sptr parm_type_name_regex =
-		(*p)->priv_->get_type_name_regex();
+		(*p)->get_parameter_type_name_regex();
 	      if (parm_type_name_regex)
 		{
 		  if (!regex::match(parm_type_name_regex,
@@ -2765,7 +2763,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
     }
   else if (get_symbol_name_regex())
     {
-      const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
+      const regex_t_sptr symbol_name_regex = get_symbol_name_regex();
       if (symbol_name_regex && !regex::match(symbol_name_regex, sym_name))
 	return false;
     }
@@ -2780,8 +2778,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
     }
   else if (get_symbol_version_regex())
     {
-      const regex_t_sptr symbol_version_regex =
-	priv_->get_symbol_version_regex();
+      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
       if (symbol_version_regex
 	  && !regex::match(symbol_version_regex, sym_version))
 	return false;
@@ -2873,21 +2870,21 @@ bool
 suppression_matches_function_name(const suppr::function_suppression& s,
 				  const string& fn_name)
 {
-  if (regex_t_sptr regexp = s.priv_->get_name_regex())
+  if (regex_t_sptr regexp = s.get_name_regex())
     {
       if (!regex::match(regexp, fn_name))
 	return false;
     }
-  else if (regex_t_sptr regexp = s.priv_->get_name_not_regex())
+  else if (regex_t_sptr regexp = s.get_name_not_regex())
     {
       if (regex::match(regexp, fn_name))
 	return false;
     }
-  else if (s.priv_->name_.empty())
+  else if (s.get_name().empty())
     return false;
-  else // if (!s.priv_->name_.empty())
+  else // if (!s.get_name().empty())
     {
-      if (s.priv_->name_ != fn_name)
+      if (s.get_name() != fn_name)
 	return false;
     }
 
@@ -2909,21 +2906,21 @@ bool
 suppression_matches_function_sym_name(const suppr::function_suppression& s,
 				      const string& fn_linkage_name)
 {
-  if (regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
+  if (regex_t_sptr regexp = s.get_symbol_name_regex())
     {
       if (!regex::match(regexp, fn_linkage_name))
 	return false;
     }
-  else if (regex_t_sptr regexp = s.priv_->get_symbol_name_not_regex())
+  else if (regex_t_sptr regexp = s.get_symbol_name_not_regex())
     {
       if (regex::match(regexp, fn_linkage_name))
 	return false;
     }
-  else if (s.priv_->symbol_name_.empty())
+  else if (s.get_symbol_name().empty())
     return false;
-  else // if (!s.priv_->symbol_name_.empty())
+  else // if (!s.get_symbol_name().empty())
     {
-      if (s.priv_->symbol_name_ != fn_linkage_name)
+      if (s.get_symbol_name() != fn_linkage_name)
 	return false;
     }
 
@@ -2942,21 +2939,21 @@ bool
 suppression_matches_variable_name(const suppr::variable_suppression& s,
 				  const string& var_name)
 {
-  if (regex_t_sptr regexp = s.priv_->get_name_regex())
+  if (regex_t_sptr regexp = s.get_name_regex())
     {
       if (!regex::match(regexp, var_name))
 	return false;
     }
-  else if (regex_t_sptr regexp = s.priv_->get_name_not_regex())
+  else if (regex_t_sptr regexp = s.get_name_not_regex())
     {
       if (regex::match(regexp, var_name))
 	return false;
     }
-  else if (s.priv_->name_.empty())
+  else if (s.get_name().empty())
     return false;
-  else // if (!s.priv_->name_.empty())
+  else // if (!s.get_name().empty())
     {
-      if (s.priv_->name_ != var_name)
+      if (s.get_name() != var_name)
 	return false;
     }
 
@@ -2976,22 +2973,21 @@ bool
 suppression_matches_variable_sym_name(const suppr::variable_suppression& s,
 				      const string& var_linkage_name)
 {
-  if (regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
+  if (regex_t_sptr regexp = s.get_symbol_name_regex())
     {
       if (!regex::match(regexp, var_linkage_name))
 	return false;
     }
-  else if (regex_t_sptr regexp =
-	   s.priv_->get_symbol_name_not_regex())
+  else if (regex_t_sptr regexp = s.get_symbol_name_not_regex())
     {
       if (regex::match(regexp, var_linkage_name))
 	return false;
     }
-  else if (s.priv_->symbol_name_.empty())
+  else if (s.get_symbol_name().empty())
     return false;
-  else // if (!s.priv_->symbol_name_.empty())
+  else // if (!s.get_symbol_name().empty())
     {
-      if (s.priv_->symbol_name_ != var_linkage_name)
+      if (s.get_symbol_name() != var_linkage_name)
 	return false;
     }
 
@@ -3011,7 +3007,7 @@ bool
 suppression_matches_type(const suppr::type_suppression& s,
 			 const string& type_name)
 {
-  if (regex_t_sptr regexp = s.priv_->get_type_name_regex())
+  if (regex_t_sptr regexp = s.get_type_name_regex())
     {
       if (!regex::match(regexp, type_name))
 	return false;
@@ -3720,11 +3716,11 @@ variable_suppression::suppresses_variable(const var_decl* var,
       // "name_regex" and "name_not_regex" properties match
       if (get_name().empty())
 	{
-	  const regex_t_sptr name_regex = priv_->get_name_regex();
+	  const regex_t_sptr name_regex = get_name_regex();
 	  if (name_regex && !regex::match(name_regex, var_name))
 	    return false;
 
-	  const regex_t_sptr name_not_regex = priv_->get_name_not_regex();
+	  const regex_t_sptr name_not_regex = get_name_not_regex();
 	  if (name_not_regex && regex::match(name_not_regex, var_name))
 	    return false;
 	}
@@ -3740,12 +3736,11 @@ variable_suppression::suppresses_variable(const var_decl* var,
     }
   else
     {
-      const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
+      const regex_t_sptr sym_name_regex = get_symbol_name_regex();
       if (sym_name_regex && !regex::match(sym_name_regex, var_sym_name))
 	return false;
 
-      const regex_t_sptr sym_name_not_regex =
-	priv_->get_symbol_name_not_regex();
+      const regex_t_sptr sym_name_not_regex = get_symbol_name_not_regex();
       if (sym_name_not_regex && regex::match(sym_name_not_regex, var_sym_name))
 	return false;
     }
@@ -3760,8 +3755,7 @@ variable_suppression::suppresses_variable(const var_decl* var,
     }
   else
     {
-      const regex_t_sptr symbol_version_regex =
-	priv_->get_symbol_version_regex();
+      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
       if (symbol_version_regex
 	  && !regex::match(symbol_version_regex, var_sym_version))
 	return false;
@@ -3780,7 +3774,7 @@ variable_suppression::suppresses_variable(const var_decl* var,
     {
       if (get_type_name().empty())
 	{
-	  const regex_t_sptr type_name_regex = priv_->get_type_name_regex();
+	  const regex_t_sptr type_name_regex = get_type_name_regex();
 	  if (type_name_regex && !regex::match(type_name_regex, var_type_name))
 	    return false;
 	}
@@ -3871,7 +3865,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
     }
   else if (get_symbol_name_regex())
     {
-      const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
+      const regex_t_sptr sym_name_regex = get_symbol_name_regex();
       if (sym_name_regex && !regex::match(sym_name_regex, sym_name))
 	return false;
     }
@@ -3886,8 +3880,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
     }
   else if (get_symbol_version_regex())
     {
-      const regex_t_sptr symbol_version_regex =
-	priv_->get_symbol_version_regex();
+      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
       if (symbol_version_regex
 	  && !regex::match(symbol_version_regex, sym_version))
 	return false;
@@ -4190,14 +4183,14 @@ file_suppression::suppresses_file(const string& file_path)
 
   bool has_regexp = false;
 
-  if (regex_t_sptr regexp = suppression_base::priv_->get_file_name_regex())
+  if (regex_t_sptr regexp = get_file_name_regex())
     {
       has_regexp = true;
       if (!regex::match(regexp, fname))
 	return false;
     }
 
-  if (regex_t_sptr regexp = suppression_base::priv_->get_file_name_not_regex())
+  if (regex_t_sptr regexp = get_file_name_not_regex())
     {
       has_regexp = true;
       if (regex::match(regexp, fname))
@@ -4350,7 +4343,7 @@ suppression_matches_soname_or_filename(const string& soname,
 				       const suppression_base& suppr)
 {
   return (suppression_matches_soname(soname, suppr)
-	 || suppr.priv_->matches_binary_name(filename));
+	  || suppr.priv_->matches_binary_name(filename));
 }
 
 /// @return the name of the artificial private type suppression
-- 
2.26.2.526.g744177e7f7-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v4 12/15] Move match methods from priv to suppression_base.
  2020-05-04 12:34   ` [PATCH v4 00/15] Simplify regex and suppression parsing Giuliano Procida
                       ` (10 preceding siblings ...)
  2020-05-04 12:34     ` [PATCH v4 11/15] Reduce direct access to suppression priv_ members Giuliano Procida
@ 2020-05-04 12:34     ` Giuliano Procida
  2020-05-04 12:34     ` [PATCH v4 13/15] Remove suppression type priv class methods Giuliano Procida
                       ` (2 subsequent siblings)
  14 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-05-04 12:34 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

The suppression_base::priv methods matches_soname and
matches_binary_name do not require special access to the priv class
and can be moved to the main suppression_base class and use its
getters.

This is a step towards simplifying the suppression type priv classes
to the point they are simple data containers.

There are no behavioural changes.

	* include/abg-suppression.h
	(suppression_base::matches_soname): Add	declaration.
	(suppression_base::matches_binary_name): Add declaration.
	(suppression_base): Remove friend declarations of
	suppression_matches_soname and
	suppression_matches_soname_or_filename.
	* src/abg-dwarf-reader.cc (suppression_can_match): Call
	matches_soname and matches_binary_name on suppression values
	directly.
	* src/abg-reader.cc (suppression_can_match): Call
	matches_soname and matches_binary_name on suppression values
	directly.
	* src/abg-suppression-priv.h
	(suppression_base::priv::matches_soname): Remove method.
	(suppression_base::priv::matches_binary_name): Remove method.
	* src/abg-suppression.cc
	(suppression_base::matches_soname): Add definition.
	(suppression_base::matches_binary_name): Add definition.
	(names_of_binaries_match): Call matches_binary_name on
	suppression values directly. (suppression_matches_soname):
	Call matches_soname on suppression values directly.
	(suppression_matches_soname_or_filename): Call
	matches_binary_name on suppression values directly.

Reviewed-by: Matthias Maennich <maennich@google.com>
Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 include/abg-suppression.h  | 15 +++-----
 src/abg-dwarf-reader.cc    |  4 +-
 src/abg-reader.cc          |  4 +-
 src/abg-suppression-priv.h | 71 +----------------------------------
 src/abg-suppression.cc     | 76 ++++++++++++++++++++++++++++++++++++--
 5 files changed, 83 insertions(+), 87 deletions(-)

diff --git a/include/abg-suppression.h b/include/abg-suppression.h
index 8256f9b8..ed6ca65c 100644
--- a/include/abg-suppression.h
+++ b/include/abg-suppression.h
@@ -116,19 +116,16 @@ public:
   bool
   has_soname_related_property() const;
 
+  bool
+  matches_soname(const std::string& soname) const;
+
+  bool
+  matches_binary_name(const std::string& binary_name) const;
+
   virtual bool
   suppresses_diff(const diff*) const = 0;
 
   virtual ~suppression_base();
-
-  friend bool
-  suppression_matches_soname(const string& soname,
-			     const suppression_base& suppr);
-
-  friend bool
-  suppression_matches_soname_or_filename(const string& soname,
-					 const string& filename,
-					 const suppression_base& suppr);
 }; // end class suppression_base
 
 void
diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
index 63837554..221ebc54 100644
--- a/src/abg-dwarf-reader.cc
+++ b/src/abg-dwarf-reader.cc
@@ -7723,14 +7723,14 @@ public:
   bool
   suppression_can_match(const suppr::suppression_base& s) const
   {
-    if (!s.priv_->matches_soname(dt_soname()))
+    if (!s.matches_soname(dt_soname()))
       if (s.has_soname_related_property())
 	// The suppression has some SONAME related properties, but
 	// none of them match the SONAME of the current binary.  So
 	// the suppression cannot match the current binary.
 	return false;
 
-    if (!s.priv_->matches_binary_name(elf_path()))
+    if (!s.matches_binary_name(elf_path()))
       if (s.has_file_name_related_property())
 	// The suppression has some file_name related properties, but
 	// none of them match the file name of the current binary.  So
diff --git a/src/abg-reader.cc b/src/abg-reader.cc
index 47ac6229..6c429446 100644
--- a/src/abg-reader.cc
+++ b/src/abg-reader.cc
@@ -999,14 +999,14 @@ public:
   {
     corpus_sptr corp = get_corpus();
 
-    if (!s.priv_->matches_soname(corp->get_soname()))
+    if (!s.matches_soname(corp->get_soname()))
       if (s.has_soname_related_property())
 	// The suppression has some SONAME related properties, but
 	// none of them match the SONAME of the current binary.  So
 	// the suppression cannot match the current binary.
 	return false;
 
-    if (!s.priv_->matches_binary_name(corp->get_path()))
+    if (!s.matches_binary_name(corp->get_path()))
       if (s.has_file_name_related_property())
 	// The suppression has some file_name related properties, but
 	// none of them match the file name of the current binary.  So
diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
index c5f99c15..5027571a 100644
--- a/src/abg-suppression-priv.h
+++ b/src/abg-suppression-priv.h
@@ -107,76 +107,7 @@ public:
   {
     return soname_not_regex_;
   }
-
-  /// Test if the current suppression matches a given SONAME.
-  ///
-  /// @param soname the SONAME to consider.
-  ///
-  /// @return true iff the suppression matches the SONAME denoted by
-  /// @p soname.
-  ///
-  /// Note that if the suppression contains no property that is
-  /// related to SONAMEs, the function returns false.
-  bool
-  matches_soname(const string& soname) const
-  {
-    bool has_regexp = false;
-    if (regex::regex_t_sptr regexp = get_soname_regex())
-      {
-	has_regexp = true;
-	if (!regex::match(regexp, soname))
-	  return false;
-      }
-
-    if (regex::regex_t_sptr regexp = get_soname_not_regex())
-      {
-	has_regexp = true;
-	if (regex::match(regexp, soname))
-	  return false;
-      }
-
-      if (!has_regexp)
-	return false;
-
-    return true;
-  }
-
-  /// Test if the current suppression matches the full file path to a
-  /// given binary.
-  ///
-  /// @param binary_name the full path to the binary.
-  ///
-  /// @return true iff the suppression matches the path denoted by @p
-  /// binary_name.
-  ///
-  /// Note that if the suppression contains no property that is
-  /// related to file name, the function returns false.
-  bool
-  matches_binary_name(const string& binary_name) const
-  {
-    bool has_regexp = false;
-
-    if (regex::regex_t_sptr regexp = get_file_name_regex())
-      {
-	has_regexp = true;
-	if (!regex::match(regexp, binary_name))
-	  return false;
-      }
-
-    if (regex::regex_t_sptr regexp = get_file_name_not_regex())
-      {
-	has_regexp = true;
-	if (regex::match(regexp, binary_name))
-	  return false;
-      }
-
-    if (!has_regexp)
-      return false;
-
-    return true;
-  }
-
-}; // end clas suppression_base::priv
+}; // end class suppression_base::priv
 
 // </suppression_base stuff>
 
diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 4f44b175..2618b135 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -253,6 +253,74 @@ suppression_base::has_soname_related_property() const
   return get_soname_regex() || get_soname_not_regex();
 }
 
+/// Test if the current suppression matches a given SONAME.
+///
+/// @param soname the SONAME to consider.
+///
+/// @return true iff the suppression matches the SONAME denoted by
+/// @p soname.
+///
+/// Note that if the suppression contains no property that is
+/// related to SONAMEs, the function returns false.
+bool
+suppression_base::matches_soname(const std::string& soname) const
+{
+  bool has_regexp = false;
+  if (regex_t_sptr regexp = get_soname_regex())
+    {
+      has_regexp = true;
+      if (!regex::match(regexp, soname))
+	return false;
+    }
+
+  if (regex_t_sptr regexp = get_soname_not_regex())
+    {
+      has_regexp = true;
+      if (regex::match(regexp, soname))
+	return false;
+    }
+
+  if (!has_regexp)
+    return false;
+
+  return true;
+}
+
+/// Test if the current suppression matches the full file path to a
+/// given binary.
+///
+/// @param binary_name the full path to the binary.
+///
+/// @return true iff the suppression matches the path denoted by @p
+/// binary_name.
+///
+/// Note that if the suppression contains no property that is
+/// related to file name, the function returns false.
+bool
+suppression_base::matches_binary_name(const std::string& binary_name) const
+{
+  bool has_regexp = false;
+
+  if (regex_t_sptr regexp = get_file_name_regex())
+    {
+      has_regexp = true;
+      if (!regex::match(regexp, binary_name))
+	return false;
+    }
+
+  if (regex_t_sptr regexp = get_file_name_not_regex())
+    {
+      has_regexp = true;
+      if (regex::match(regexp, binary_name))
+	return false;
+    }
+
+  if (!has_regexp)
+    return false;
+
+  return true;
+}
+
 /// Check if the SONAMEs of the two binaries being compared match the
 /// content of the properties "soname_regexp" and "soname_not_regexp"
 /// of the current suppression specification.
@@ -306,8 +374,8 @@ names_of_binaries_match(const suppression_base& suppr,
   if (!suppr.has_file_name_related_property())
     return false;
 
-  if (!suppr.priv_->matches_binary_name(first_binary_path)
-      && !suppr.priv_->matches_binary_name(second_binary_path))
+  if (!suppr.matches_binary_name(first_binary_path)
+      && !suppr.matches_binary_name(second_binary_path))
     return false;
 
   return true;
@@ -4323,7 +4391,7 @@ bool
 suppression_matches_soname(const string& soname,
 			   const suppression_base& suppr)
 {
-  return suppr.priv_->matches_soname(soname);
+  return suppr.matches_soname(soname);
 }
 
 /// Test if a given SONAME or file name is matched by a given
@@ -4343,7 +4411,7 @@ suppression_matches_soname_or_filename(const string& soname,
 				       const suppression_base& suppr)
 {
   return (suppression_matches_soname(soname, suppr)
-	  || suppr.priv_->matches_binary_name(filename));
+	  || suppr.matches_binary_name(filename));
 }
 
 /// @return the name of the artificial private type suppression
-- 
2.26.2.526.g744177e7f7-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v4 13/15] Remove suppression type priv class methods.
  2020-05-04 12:34   ` [PATCH v4 00/15] Simplify regex and suppression parsing Giuliano Procida
                       ` (11 preceding siblings ...)
  2020-05-04 12:34     ` [PATCH v4 12/15] Move match methods from priv to suppression_base Giuliano Procida
@ 2020-05-04 12:34     ` Giuliano Procida
  2020-05-04 12:34     ` [PATCH v4 14/15] abg-suppression.cc: More consistent regex matching Giuliano Procida
  2020-05-04 12:34     ` [PATCH v4 15/15] abg-tools-utils.cc: Assert generated regexes OK Giuliano Procida
  14 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-05-04 12:34 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

The type_suppression::set_type_name_not_regex method is the only
remaining user of all the various suppression_type::priv member
functions. This is easily remedied and all the remaining priv member
functions (regex getters and setters) can be dropped.

This patches leaves all the various suppression priv types as simple
data containers (modulo their constructors).

There are no behavioural changes.

	* src/abg-suppression-priv.h (suppression_base::priv): Drop
	all regex getter methods.
	(function_suppression::parameter_spec::priv): Drop all regex
	getter methods.
	(function_suppression::priv): Drop all regex getter methods.
	(variable_suppression::priv): Drop all regex getter methods.
	(type_suppression::priv): Drop all regex getter and setter
	methods.
	* src/abg-suppression.cc (set_type_name_not_regex): Access
	priv_->type_name_not_regex_ directly.

Reviewed-by: Matthias Maennich <maennich@google.com>
Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-suppression-priv.h | 182 -------------------------------------
 src/abg-suppression.cc     |   2 +-
 2 files changed, 1 insertion(+), 183 deletions(-)

diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
index 5027571a..38adc190 100644
--- a/src/abg-suppression-priv.h
+++ b/src/abg-suppression-priv.h
@@ -75,38 +75,6 @@ public:
   {}
 
   friend class suppression_base;
-
-  /// Get the regular expression object associated to the
-  /// 'file_name_regex' property of @ref suppression_base.
-  const regex::regex_t_sptr&
-  get_file_name_regex() const
-  {
-    return file_name_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'file_name_not_regex' property of @ref suppression_base.
-  const regex::regex_t_sptr&
-  get_file_name_not_regex() const
-  {
-    return file_name_not_regex_;
-  }
-
-  /// Get the regular expression object associated to the 'soname_regex'
-  /// property of @ref suppression_base.
-  const regex::regex_t_sptr&
-  get_soname_regex() const
-  {
-    return soname_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'soname_not_regex' property of @ref suppression_base.
-  const regex::regex_t_sptr&
-  get_soname_not_regex() const
-  {
-    return soname_not_regex_;
-  }
 }; // end class suppression_base::priv
 
 // </suppression_base stuff>
@@ -133,15 +101,6 @@ class function_suppression::parameter_spec::priv
   priv(size_t i, const string& tn, const regex::regex_t_sptr& tn_regex)
     : index_(i), type_name_(tn), type_name_regex_(tn_regex)
   {}
-
-  /// Get the regular expression object associated to the
-  /// 'type_name_regex' property of @ref
-  /// function_suppression::parameter_spec.
-  const regex::regex_t_sptr
-  get_type_name_regex() const
-  {
-    return type_name_regex_;
-  }
 }; // end class function_suppression::parameter_spec::priv
 
 
@@ -191,54 +150,6 @@ struct function_suppression::priv
       symbol_version_regex_(symbol_version_regex),
       allow_other_aliases_(true)
   {}
-
-  /// Get the regular expression object associated to the 'name_regex'
-  /// property of @ref function_suppression.
-  const regex::regex_t_sptr
-  get_name_regex() const
-  {
-    return name_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'name_not_regex' property of @ref function_suppression.
-  const regex::regex_t_sptr
-  get_name_not_regex() const
-  {
-    return name_not_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'return_type_regex' property of @ref function_suppression.
-  const regex::regex_t_sptr
-  get_return_type_regex() const
-  {
-    return return_type_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'symbol_name_regex' property of @ref function_suppression.
-  const regex::regex_t_sptr
-  get_symbol_name_regex() const
-  {
-    return symbol_name_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'symbol_name_not_regex' property of @ref function_suppression.
-  const regex::regex_t_sptr
-  get_symbol_name_not_regex() const
-  {
-    return symbol_name_not_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'symbol_version_regex' property of @ref function_suppression.
-  const regex::regex_t_sptr
-  get_symbol_version_regex() const
-  {
-    return symbol_version_regex_;
-  }
 }; // end class function_suppression::priv
 
 bool
@@ -343,54 +254,6 @@ struct variable_suppression::priv
       type_name_(type_name),
       type_name_regex_(type_name_regex)
   {}
-
-  /// Get the regular expression object associated to the 'name_regex'
-  /// property of @ref variable_suppression.
-  const regex::regex_t_sptr
-  get_name_regex() const
-  {
-    return name_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'name_not_regex' property of @ref variable_suppression.
-  const regex::regex_t_sptr
-  get_name_not_regex() const
-  {
-    return name_not_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'symbol_name_regex' property of @ref variable_suppression.
-  const regex::regex_t_sptr
-  get_symbol_name_regex() const
-  {
-    return symbol_name_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'symbol_name_not_regex' property of @ref variable_suppression.
-  const regex::regex_t_sptr
-  get_symbol_name_not_regex() const
-  {
-    return symbol_name_not_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'symbol_version_regex' property of @ref variable_suppression.
-  const regex::regex_t_sptr
-  get_symbol_version_regex()  const
-  {
-    return symbol_version_regex_;
-  }
-
-  /// Get the regular expression object associated to the
-  /// 'type_name_regex' property of @ref variable_suppression.
-  const regex::regex_t_sptr
-  get_type_name_regex() const
-  {
-    return type_name_regex_;
-  }
 };// end class variable_supppression::priv
 
 template <typename ReadContextType>
@@ -454,51 +317,6 @@ public:
       reach_kind_(reach_kind)
   {}
 
-  /// Get the regular expression object associated to the
-  /// 'type_name_regex' property of @ref type_suppression.
-  const regex::regex_t_sptr
-  get_type_name_regex() const
-  {
-    return type_name_regex_;
-  }
-
-  /// Setter for the type_name_regex object.
-  ///
-  /// @param r the new type_name_regex object.
-  void
-  set_type_name_regex(regex::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.
-  const regex::regex_t_sptr
-  get_type_name_not_regex() const
-  {
-    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(regex::regex_t_sptr r)
-  {type_name_not_regex_ = r;}
-
-  /// Get the regular expression object associated to the
-  /// 'source_location_to_keep_regex' property of @ref type_suppression.
-  const regex::regex_t_sptr
-  get_source_location_to_keep_regex() const
-  {
-    return source_location_to_keep_regex_;
-  }
-
-  /// Setter for the source_location_to_keep_regex object.
-  ///
-  /// @param r the new regex object.
-  void
-  set_source_location_to_keep_regex(regex::regex_t_sptr r)
-  {source_location_to_keep_regex_ = r;}
-
   friend class type_suppression;
 }; // class type_suppression::priv
 
diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 2618b135..4883168d 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -516,7 +516,7 @@ type_suppression::get_type_name_regex() const
 /// @param r the new regexp string.
 void
 type_suppression::set_type_name_not_regex(const regex_t_sptr& r)
-{priv_->set_type_name_not_regex(r);}
+{priv_->type_name_not_regex_ = r;}
 
 /// Getter for the "type_name_not_regex" property of the type
 /// suppression specification.
-- 
2.26.2.526.g744177e7f7-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v4 14/15] abg-suppression.cc: More consistent regex matching.
  2020-05-04 12:34   ` [PATCH v4 00/15] Simplify regex and suppression parsing Giuliano Procida
                       ` (12 preceding siblings ...)
  2020-05-04 12:34     ` [PATCH v4 13/15] Remove suppression type priv class methods Giuliano Procida
@ 2020-05-04 12:34     ` Giuliano Procida
  2020-05-04 13:17       ` Matthias Maennich
  2020-05-04 12:34     ` [PATCH v4 15/15] abg-tools-utils.cc: Assert generated regexes OK Giuliano Procida
  14 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-05-04 12:34 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

Following previous patches, various minor inconsistencies in the
suppression regex matching code were more readily apparent.

- regex_t_sptr values are fetched both by reference and by
  value (which has a reference count mutation cost)
- there's a mixture of code styles for testing regex presence
    - regex = ...; if (regex && ...)
    - if (regex = ...) if (...)
  the latter has the advantage that the variable has a smaller scope
  and can be given a shorter name
- in some cases there are redundant tests (always true due to previous
  conditional logic)

This patch ensures all shared pointers to compiled regexes are fetched
by const reference and that the code uses the nested if style of
presence checking where possible. It simplifies some logic where
there's redundancy.

There are no behavioural changes. There may be performance
improvements.

	* src/abg-suppression.cc (suppression_matches_type_name): Get
	regexes by const reference.
	(suppression_matches_type_location): Get regexes by const
	reference. (function_suppression::suppresses_function): Get
	regexes by const reference; use nested if checks; simplify
	logic around symbol version checks.
	(function_suppression::suppresses_function_symbol): Get
	regexes by const reference; use nested if checks; remove
	redundant regex presence checks.
	(suppression_matches_function_name): Get regexes by const
	reference. (suppression_matches_function_sym_name): Get
	regexes by const reference.
	(suppression_matches_variable_name): Get regexes by const
	reference. (suppression_matches_variable_sym_name): Get
	regexes by const reference. (suppression_matches_type): Get
	regexes by const reference.
	(variable_suppression::suppresses_variable): Get regexes by
	const reference; use nested if checks; remove redundant
	type_name empty check.
	(variable_suppression::suppresses_variable_symbol): Get
	regexes by const reference; use nested if checks.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-suppression.cc | 167 +++++++++++++++++++----------------------
 1 file changed, 76 insertions(+), 91 deletions(-)

diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 4883168d..24f75b9a 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -1049,15 +1049,14 @@ 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.
-	  if (const regex_t_sptr& type_name_regex =
-	      s.get_type_name_regex())
+	  if (const regex_t_sptr& type_name_regex = s.get_type_name_regex())
 	    {
 	      if (!regex::match(type_name_regex, type_name))
 		return false;
 	    }
 
-	  if (const regex_t_sptr type_name_not_regex =
-	      s.get_type_name_not_regex())
+	  if (const regex_t_sptr& type_name_not_regex =
+		s.get_type_name_not_regex())
 	    {
 	      if (regex::match(type_name_not_regex, type_name))
 		return false;
@@ -1105,7 +1104,7 @@ suppression_matches_type_location(const type_suppression&	s,
       unsigned loc_line = 0, loc_column = 0;
       loc.expand(loc_path, loc_line, loc_column);
 
-      if (regex_t_sptr regexp = s.get_source_location_to_keep_regex())
+      if (const regex_t_sptr& regexp = s.get_source_location_to_keep_regex())
 	if (regex::match(regexp, loc_path))
 	  return false;
 
@@ -2544,7 +2543,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
 
   // check if the "name_regexp" property matches.
-  const regex_t_sptr name_regex = get_name_regex();
+  const regex_t_sptr& name_regex = get_name_regex();
   if (name_regex)
     {
       if (!regex::match(name_regex, fname))
@@ -2575,7 +2574,7 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
 
   // check if the "name_not_regexp" property matches.
-  const regex_t_sptr name_not_regex = get_name_not_regex();
+  const regex_t_sptr& name_not_regex = get_name_not_regex();
   if (name_not_regex)
     {
       if (regex::match(name_not_regex, fname))
@@ -2619,11 +2618,9 @@ function_suppression::suppresses_function(const function_decl* fn,
       if (fn_return_type_name != get_return_type_name())
 	return false;
     }
-  else
+  else if (const regex_t_sptr& regex = get_return_type_regex())
     {
-      const regex_t_sptr return_type_regex = get_return_type_regex();
-      if (return_type_regex
-	  && !regex::match(return_type_regex, fn_return_type_name))
+      if (!regex::match(regex, fn_return_type_name))
 	return false;
     }
 
@@ -2659,14 +2656,15 @@ function_suppression::suppresses_function(const function_decl* fn,
     }
   else if (sym)
     {
-      const regex_t_sptr symbol_name_regex = get_symbol_name_regex();
-      if (symbol_name_regex && !regex::match(symbol_name_regex, fn_sym_name))
-	return false;
+      const regex_t_sptr& symbol_name_regex = get_symbol_name_regex();
+      const regex_t_sptr& symbol_name_not_regex = get_symbol_name_not_regex();
 
-      const regex_t_sptr symbol_name_not_regex = get_symbol_name_not_regex();
-      if (symbol_name_not_regex
-	  && regex::match(symbol_name_not_regex, fn_sym_name))
-	return false;
+      if (symbol_name_regex)
+	if (!regex::match(symbol_name_regex, fn_sym_name))
+	  return false;
+      if (symbol_name_not_regex)
+	if (regex::match(symbol_name_not_regex, fn_sym_name))
+	  return false;
 
       if (get_allow_other_aliases())
 	{
@@ -2679,13 +2677,13 @@ function_suppression::suppresses_function(const function_decl* fn,
 		   a && !a->is_main_symbol();
 		   a = a->get_next_alias())
 		{
-		  if (symbol_name_regex
-		      && !regex::match(symbol_name_regex, a->get_name()))
-		    return false;
-
-		  if (symbol_name_not_regex
-		      && regex::match(symbol_name_not_regex, a->get_name()))
-		    return false;
+		  const std::string& alias_name = a->get_name();
+		  if (symbol_name_regex)
+		    if (!regex::match(symbol_name_regex, alias_name))
+		      return false;
+		  if (symbol_name_not_regex)
+		    if (regex::match(symbol_name_not_regex, alias_name))
+		      return false;
 		}
 	    }
 	}
@@ -2693,17 +2691,19 @@ function_suppression::suppresses_function(const function_decl* fn,
 
   // Check if the "symbol_version" and "symbol_version_regexp"
   // properties match.
-  if (sym && !get_symbol_version().empty())
-    {
-      if (fn_sym_version != get_symbol_version())
-	return false;
-    }
-  else if (sym)
+  if (sym)
     {
-      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
-      if (symbol_version_regex
-	  && !regex::match(symbol_version_regex, fn_sym_version))
-	return false;
+      if (!get_symbol_version().empty())
+	{
+	  if (fn_sym_version != get_symbol_version())
+	    return false;
+	}
+      else
+	{
+	  if (const regex_t_sptr& regex = get_symbol_version_regex())
+	    if (!regex::match(regex, fn_sym_version))
+	      return false;
+	}
     }
 
   // Check the 'parameter' property.
@@ -2737,16 +2737,11 @@ function_suppression::suppresses_function(const function_decl* fn,
 	      if (tn != fn_parm_type_qualified_name)
 		return false;
 	    }
-	  else
+	  else if (const regex_t_sptr& regex =
+		     (*p)->get_parameter_type_name_regex())
 	    {
-	      const regex_t_sptr parm_type_name_regex =
-		(*p)->get_parameter_type_name_regex();
-	      if (parm_type_name_regex)
-		{
-		  if (!regex::match(parm_type_name_regex,
-				    fn_parm_type_qualified_name))
-		    return false;
-		}
+	      if (!regex::match(regex, fn_parm_type_qualified_name))
+		return false;
 	    }
 	}
     }
@@ -2829,10 +2824,9 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
       if (sym_name != get_symbol_name())
 	return false;
     }
-  else if (get_symbol_name_regex())
+  else if (const regex_t_sptr& regex = get_symbol_name_regex())
     {
-      const regex_t_sptr symbol_name_regex = get_symbol_name_regex();
-      if (symbol_name_regex && !regex::match(symbol_name_regex, sym_name))
+      if (!regex::match(regex, sym_name))
 	return false;
     }
   else
@@ -2844,11 +2838,9 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
       if (sym_version != get_symbol_version())
 	return false;
     }
-  else if (get_symbol_version_regex())
+  else if (const regex_t_sptr& regex = get_symbol_version_regex())
     {
-      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
-      if (symbol_version_regex
-	  && !regex::match(symbol_version_regex, sym_version))
+      if (!regex::match(regex, sym_version))
 	return false;
     }
   else
@@ -2938,12 +2930,12 @@ bool
 suppression_matches_function_name(const suppr::function_suppression& s,
 				  const string& fn_name)
 {
-  if (regex_t_sptr regexp = s.get_name_regex())
+  if (const regex_t_sptr& regexp = s.get_name_regex())
     {
       if (!regex::match(regexp, fn_name))
 	return false;
     }
-  else if (regex_t_sptr regexp = s.get_name_not_regex())
+  else if (const regex_t_sptr& regexp = s.get_name_not_regex())
     {
       if (regex::match(regexp, fn_name))
 	return false;
@@ -2974,12 +2966,12 @@ bool
 suppression_matches_function_sym_name(const suppr::function_suppression& s,
 				      const string& fn_linkage_name)
 {
-  if (regex_t_sptr regexp = s.get_symbol_name_regex())
+  if (const regex_t_sptr& regexp = s.get_symbol_name_regex())
     {
       if (!regex::match(regexp, fn_linkage_name))
 	return false;
     }
-  else if (regex_t_sptr regexp = s.get_symbol_name_not_regex())
+  else if (const regex_t_sptr& regexp = s.get_symbol_name_not_regex())
     {
       if (regex::match(regexp, fn_linkage_name))
 	return false;
@@ -3007,12 +2999,12 @@ bool
 suppression_matches_variable_name(const suppr::variable_suppression& s,
 				  const string& var_name)
 {
-  if (regex_t_sptr regexp = s.get_name_regex())
+  if (const regex_t_sptr& regexp = s.get_name_regex())
     {
       if (!regex::match(regexp, var_name))
 	return false;
     }
-  else if (regex_t_sptr regexp = s.get_name_not_regex())
+  else if (const regex_t_sptr& regexp = s.get_name_not_regex())
     {
       if (regex::match(regexp, var_name))
 	return false;
@@ -3041,12 +3033,12 @@ bool
 suppression_matches_variable_sym_name(const suppr::variable_suppression& s,
 				      const string& var_linkage_name)
 {
-  if (regex_t_sptr regexp = s.get_symbol_name_regex())
+  if (const regex_t_sptr& regexp = s.get_symbol_name_regex())
     {
       if (!regex::match(regexp, var_linkage_name))
 	return false;
     }
-  else if (regex_t_sptr regexp = s.get_symbol_name_not_regex())
+  else if (const regex_t_sptr& regexp = s.get_symbol_name_not_regex())
     {
       if (regex::match(regexp, var_linkage_name))
 	return false;
@@ -3075,7 +3067,7 @@ bool
 suppression_matches_type(const suppr::type_suppression& s,
 			 const string& type_name)
 {
-  if (regex_t_sptr regexp = s.get_type_name_regex())
+  if (const regex_t_sptr& regexp = s.get_type_name_regex())
     {
       if (!regex::match(regexp, type_name))
 	return false;
@@ -3784,13 +3776,13 @@ variable_suppression::suppresses_variable(const var_decl* var,
       // "name_regex" and "name_not_regex" properties match
       if (get_name().empty())
 	{
-	  const regex_t_sptr name_regex = get_name_regex();
-	  if (name_regex && !regex::match(name_regex, var_name))
-	    return false;
+	  if (const regex_t_sptr& regex = get_name_regex())
+	    if (!regex::match(regex, var_name))
+	      return false;
 
-	  const regex_t_sptr name_not_regex = get_name_not_regex();
-	  if (name_not_regex && regex::match(name_not_regex, var_name))
-	    return false;
+	  if (const regex_t_sptr& regex = get_name_not_regex())
+	    if (regex::match(regex, var_name))
+	      return false;
 	}
     }
 
@@ -3804,13 +3796,13 @@ variable_suppression::suppresses_variable(const var_decl* var,
     }
   else
     {
-      const regex_t_sptr sym_name_regex = get_symbol_name_regex();
-      if (sym_name_regex && !regex::match(sym_name_regex, var_sym_name))
-	return false;
+      if (const regex_t_sptr& regex = get_symbol_name_regex())
+	if (!regex::match(regex, var_sym_name))
+	  return false;
 
-      const regex_t_sptr sym_name_not_regex = get_symbol_name_not_regex();
-      if (sym_name_not_regex && regex::match(sym_name_not_regex, var_sym_name))
-	return false;
+      if (const regex_t_sptr& regex = get_symbol_name_not_regex())
+	if (regex::match(regex, var_sym_name))
+	  return false;
     }
 
   // Check for symbol_version and symbol_version_regexp property match
@@ -3823,10 +3815,9 @@ variable_suppression::suppresses_variable(const var_decl* var,
     }
   else
     {
-      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
-      if (symbol_version_regex
-	  && !regex::match(symbol_version_regex, var_sym_version))
-	return false;
+      if (const regex_t_sptr& regex = get_symbol_version_regex())
+	if (!regex::match(regex, var_sym_version))
+	  return false;
     }
 
   // Check for the "type_name" and type_name_regex properties match.
@@ -3840,12 +3831,9 @@ variable_suppression::suppresses_variable(const var_decl* var,
     }
   else
     {
-      if (get_type_name().empty())
-	{
-	  const regex_t_sptr type_name_regex = get_type_name_regex();
-	  if (type_name_regex && !regex::match(type_name_regex, var_type_name))
-	    return false;
-	}
+      if (const regex_t_sptr& regex = get_type_name_regex())
+	if (!regex::match(regex, var_type_name))
+	  return false;
     }
 
   return true;
@@ -3931,10 +3919,9 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
       if (get_symbol_name() != sym_name)
 	return false;
     }
-  else if (get_symbol_name_regex())
+  else if (const regex_t_sptr& regex = get_symbol_name_regex())
     {
-      const regex_t_sptr sym_name_regex = get_symbol_name_regex();
-      if (sym_name_regex && !regex::match(sym_name_regex, sym_name))
+      if (!regex::match(regex, sym_name))
 	return false;
     }
   else
@@ -3946,11 +3933,9 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
       if (get_symbol_version() != sym_version)
 	return false;
     }
-  else if (get_symbol_version_regex())
+  else if (const regex_t_sptr& regex = get_symbol_version_regex())
     {
-      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
-      if (symbol_version_regex
-	  && !regex::match(symbol_version_regex, sym_version))
+      if (!regex::match(regex, sym_version))
 	return false;
     }
   else
@@ -4251,14 +4236,14 @@ file_suppression::suppresses_file(const string& file_path)
 
   bool has_regexp = false;
 
-  if (regex_t_sptr regexp = get_file_name_regex())
+  if (const regex_t_sptr& regexp = get_file_name_regex())
     {
       has_regexp = true;
       if (!regex::match(regexp, fname))
 	return false;
     }
 
-  if (regex_t_sptr regexp = get_file_name_not_regex())
+  if (const regex_t_sptr& regexp = get_file_name_not_regex())
     {
       has_regexp = true;
       if (regex::match(regexp, fname))
-- 
2.26.2.526.g744177e7f7-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v4 15/15] abg-tools-utils.cc: Assert generated regexes OK.
  2020-05-04 12:34   ` [PATCH v4 00/15] Simplify regex and suppression parsing Giuliano Procida
                       ` (13 preceding siblings ...)
  2020-05-04 12:34     ` [PATCH v4 14/15] abg-suppression.cc: More consistent regex matching Giuliano Procida
@ 2020-05-04 12:34     ` Giuliano Procida
  14 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-05-04 12:34 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, maennich

There are a couple of places where regexes are generated internally.
Assert they compile OK.

This is just paranoia. There should be no behavioural changes.

	* src/abg-tools-utils.cc (handle_file_entry): Assert
	internally-generated regex compiles.
	(gen_suppr_spec_from_kernel_abi_whitelists): Assert
	internally-generated regex compiles.

Reviewed-by: Matthias Maennich <maennich@google.com>
Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-tools-utils.cc | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/abg-tools-utils.cc b/src/abg-tools-utils.cc
index fe0de750..3af9fc49 100644
--- a/src/abg-tools-utils.cc
+++ b/src/abg-tools-utils.cc
@@ -1818,6 +1818,7 @@ handle_file_entry(const string& file_path,
       // Types that are defined in system headers are usually
       // OK to be considered as public types.
       regex::regex_t_sptr headers_regex = regex::compile("^/usr/include/");
+      ABG_ASSERT(headers_regex);
       suppr->set_source_location_to_keep_regex(headers_regex);
       suppr->set_is_artificial(true);
     }
@@ -2008,6 +2009,7 @@ gen_suppr_spec_from_kernel_abi_whitelists
       // the function and variable names expressed in the white list.
       regex::regex_t_sptr regex =
 	regex::compile(regex::generate_from_strings(whitelisted_names));
+      ABG_ASSERT(regex);
 
       // Build a suppression specification which *keeps* functions
       // whose ELF symbols match the regular expression contained
-- 
2.26.2.526.g744177e7f7-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v4 01/15] Tidy #includes in a few files.
  2020-05-04 12:34     ` [PATCH v4 01/15] Tidy #includes in a few files Giuliano Procida
@ 2020-05-04 12:49       ` Matthias Maennich
  2020-05-11 13:24       ` Dodji Seketeli
  1 sibling, 0 replies; 120+ messages in thread
From: Matthias Maennich @ 2020-05-04 12:49 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, dodji, kernel-team

On Mon, May 04, 2020 at 01:34:02PM +0100, Giuliano Procida wrote:
>Following review of a recent change to move regex definitions into
>their own files, this commit ensures that #include directives are
>separated into categories and sorted alphabetically within the
>categories, subject to known ordering constraints (such as "config.h"
>first, "abg-internal.h" before visibility directives etc.).
>
>There are no behavioural changes.
>
>	* src/abg-corpus-priv.h: Separate and sort #include
>	directives.
>	* src/abg-corpus.cc: Ditto.
>	* src/abg-regex.cc: Ditto.
>	* src/abg-suppression-priv.h: Ditto.
>	* src/abg-suppression.cc: Ditto.
>
>Signed-off-by: Giuliano Procida <gprocida@google.com>

Reviewed-by: Matthias Maennich <maennich@google.com>

Cheers,
Matthias

>---
> src/abg-corpus-priv.h      |  4 ++--
> src/abg-corpus.cc          | 12 +++++++-----
> src/abg-regex.cc           |  3 ++-
> src/abg-suppression-priv.h |  4 ++--
> src/abg-suppression.cc     |  1 +
> 5 files changed, 14 insertions(+), 10 deletions(-)
>
>diff --git a/src/abg-corpus-priv.h b/src/abg-corpus-priv.h
>index e65f7c8f..2b42007b 100644
>--- a/src/abg-corpus-priv.h
>+++ b/src/abg-corpus-priv.h
>@@ -29,9 +29,9 @@
> #ifndef __ABG_CORPUS_PRIV_H__
> #define __ABG_CORPUS_PRIV_H__
>
>-#include "abg-sptr-utils.h"
>-#include "abg-regex.h"
> #include "abg-internal.h"
>+#include "abg-regex.h"
>+#include "abg-sptr-utils.h"
>
> namespace abigail
> {
>diff --git a/src/abg-corpus.cc b/src/abg-corpus.cc
>index 2dcc0ac7..7f763d56 100644
>--- a/src/abg-corpus.cc
>+++ b/src/abg-corpus.cc
>@@ -21,23 +21,25 @@
> /// @file
>
> #include "config.h"
>+
>+#include <algorithm>
>+#include <cassert>
> #include <cstdio>
> #include <cstring>
>-#include <cassert>
> #include <stdexcept>
>-#include <algorithm>
>
> #include "abg-cxx-compat.h"
> #include "abg-internal.h"
>+
> // <headers defining libabigail's API go under here>
> ABG_BEGIN_EXPORT_DECLARATIONS
>
>-#include "abg-sptr-utils.h"
>-#include "abg-ir.h"
> #include "abg-corpus.h"
>+#include "abg-ir.h"
> #include "abg-reader.h"
>-#include "abg-writer.h"
>+#include "abg-sptr-utils.h"
> #include "abg-tools-utils.h"
>+#include "abg-writer.h"
>
> #if WITH_ZIP_ARCHIVE
> #include "abg-libzip-utils.h"
>diff --git a/src/abg-regex.cc b/src/abg-regex.cc
>index 79a89033..cf0663a2 100644
>--- a/src/abg-regex.cc
>+++ b/src/abg-regex.cc
>@@ -24,8 +24,9 @@
> ///
>
> #include <sstream>
>-#include "abg-sptr-utils.h"
>+
> #include "abg-regex.h"
>+#include "abg-sptr-utils.h"
>
> namespace abigail
> {
>diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
>index c37ceff6..0ccfde05 100644
>--- a/src/abg-suppression-priv.h
>+++ b/src/abg-suppression-priv.h
>@@ -29,9 +29,9 @@
> #define __ABG_SUPPRESSION_PRIV_H__
>
> #include "abg-fwd.h"
>-#include "abg-suppression.h"
>-#include "abg-sptr-utils.h"
> #include "abg-regex.h"
>+#include "abg-sptr-utils.h"
>+#include "abg-suppression.h"
>
> namespace abigail
> {
>diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
>index 34eb9616..8b5712fb 100644
>--- a/src/abg-suppression.cc
>+++ b/src/abg-suppression.cc
>@@ -26,6 +26,7 @@
> /// libabigail.
>
> #include <algorithm>
>+
> #include "abg-cxx-compat.h"
> #include "abg-internal.h"
>
>-- 
>2.26.2.526.g744177e7f7-goog
>

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v4 02/15] Document ^_^ regex in generate_from_strings.
  2020-05-04 12:34     ` [PATCH v4 02/15] Document ^_^ regex in generate_from_strings Giuliano Procida
@ 2020-05-04 12:49       ` Matthias Maennich
  2020-05-11 13:32       ` Dodji Seketeli
  1 sibling, 0 replies; 120+ messages in thread
From: Matthias Maennich @ 2020-05-04 12:49 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, dodji, kernel-team

On Mon, May 04, 2020 at 01:34:03PM +0100, Giuliano Procida wrote:
>Following review of the change to simplify generation of symbol
>whitelist regexes, this commit clarifies the purpose of the ^_^ regex
>as one which will not match any string.
>
>	* src/abg-regex.cc (generate_from_strings): Document ^_^
>	regex.
>
>Signed-off-by: Giuliano Procida <gprocida@google.com>

Reviewed-by: Matthias Maennich <maennich@google.com>

Cheers,
Matthias

>---
> src/abg-regex.cc | 1 +
> 1 file changed, 1 insertion(+)
>
>diff --git a/src/abg-regex.cc b/src/abg-regex.cc
>index cf0663a2..0451d111 100644
>--- a/src/abg-regex.cc
>+++ b/src/abg-regex.cc
>@@ -69,6 +69,7 @@ std::string
> generate_from_strings(const std::vector<std::string>& strs)
> {
>   if (strs.empty())
>+    // This cute-looking regex does not match any string.
>     return "^_^";
>   std::ostringstream os;
>   std::vector<std::string>::const_iterator i = strs.begin();
>-- 
>2.26.2.526.g744177e7f7-goog
>

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v4 03/15] Escape names used in symbol whitelisting regex.
  2020-05-04 12:34     ` [PATCH v4 03/15] Escape names used in symbol whitelisting regex Giuliano Procida
@ 2020-05-04 12:57       ` Matthias Maennich
  2020-05-04 16:45         ` [PATCH v5 " Giuliano Procida
  0 siblings, 1 reply; 120+ messages in thread
From: Matthias Maennich @ 2020-05-04 12:57 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, dodji, kernel-team

On Mon, May 04, 2020 at 01:34:04PM +0100, Giuliano Procida wrote:
>There is the theoretical possibility that symbols may contain special
>regex characters like '.' and '$'. This patch ensures all such
>characters in symbol names are escaped before they are added to the
>whitelisting regex.
>
>	* include/regex.h (escape): New string reference holder
>	class. (operator<<): Declaration of std::ostream,
>	regex::escape overload.
>	* include/regex.cc (operator<<): New std::ostream,
>	regex::escape overload that outputs regex-escaped strings.
>	* src/abg-tools-utils.cc
>	(gen_suppr_spec_from_kernel_abi_whitelists): Make sure any
>	special regex characters in symbol names are escaped.
>
>Signed-off-by: Giuliano Procida <gprocida@google.com>
>---
> include/abg-regex.h | 10 ++++++++++
> src/abg-regex.cc    | 28 ++++++++++++++++++++++++++--
> 2 files changed, 36 insertions(+), 2 deletions(-)
>
>diff --git a/include/abg-regex.h b/include/abg-regex.h
>index d39ada46..164083cc 100644
>--- a/include/abg-regex.h
>+++ b/include/abg-regex.h
>@@ -58,6 +58,16 @@ struct regex_t_deleter
>   }
> };//end struct regex_deleter
>
>+/// A class to hold a reference to a string to regex escape.
>+struct escape
>+{
>+  escape(const std::string& str) : ref(str) { }
>+  const std::string& ref;
>+};
>+
>+std::ostream&
>+operator<<(std::ostream& os, const escape& esc);
>+
> std::string
> generate_from_strings(const std::vector<std::string>& strs);
>
>diff --git a/src/abg-regex.cc b/src/abg-regex.cc
>index 0451d111..a12ecc88 100644
>--- a/src/abg-regex.cc
>+++ b/src/abg-regex.cc
>@@ -24,6 +24,7 @@
> ///
>
> #include <sstream>
>+#include <ostream>

Sort.

>
> #include "abg-regex.h"
> #include "abg-sptr-utils.h"
>@@ -57,6 +58,29 @@ sptr_utils::build_sptr<regex_t>()
> namespace regex
> {
>
>+/// Escape regex special charaters in input string.
>+///
>+/// @param os the output stream being written to.
>+///
>+/// @param esc the regex_escape object holding a reference to the string
>+/// needing to be escaped.
>+///
>+/// @return the output stream.
>+std::ostream&
>+operator<<(std::ostream& os, const escape& esc)
>+{
>+  // ']' and '}' are only conditionally special, so could be removed.
>+  static const std::string specials = "^.[]$()|*+?{}\\";

Could sort the characters e.g. "[](){}^$.*+?|\\"

>+  const std::string str = esc.ref;

const std::string&

Besides the above
Reviewed-by: Matthias Maennich <maennich@google.com>

Cheers,
Matthias

>+  for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
>+    {
>+      if (specials.find(*i) != std::string::npos)
>+	os << '\\';
>+      os << *i;
>+    }
>+  return os;
>+}
>+
> /// Generate a regex pattern equivalent to testing set membership.
> ///
> /// A string will match the resulting pattern regex, if and only if it
>@@ -73,9 +97,9 @@ generate_from_strings(const std::vector<std::string>& strs)
>     return "^_^";
>   std::ostringstream os;
>   std::vector<std::string>::const_iterator i = strs.begin();
>-  os << "^(" << *i++;
>+  os << "^(" << escape(*i++);
>   while (i != strs.end())
>-    os << "|" << *i++;
>+    os << "|" << escape(*i++);
>   os << ")$";
>   return os.str();
> }
>-- 
>2.26.2.526.g744177e7f7-goog
>

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v4 05/15] diff suppression: Fix handling of change kinds.
  2020-05-04 12:34     ` [PATCH v4 05/15] diff suppression: Fix handling of change kinds Giuliano Procida
@ 2020-05-04 13:04       ` Matthias Maennich
  2020-05-11 14:15       ` Dodji Seketeli
  1 sibling, 0 replies; 120+ messages in thread
From: Matthias Maennich @ 2020-05-04 13:04 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, dodji, kernel-team

On Mon, May 04, 2020 at 01:34:06PM +0100, Giuliano Procida wrote:
>When parsing suppression specifications, libabigail attempts to detect
>and ignore suppressions that are empty and so would match everything
>in their category by default.
>
>Unfortunately, with the way the parser currently works, these checks
>have to be against an exhaustive list of fields that matter, rather
>than by listing the fields that don't (like label). They are fragile
>in the face of changes that add new fields.
>
>Two of the short-cut checks are in fact buggy, missing out the
>change_kind field. One of the checks also risks a null pointer
>dereference as it doesn't actually trigger a return from the function.
>
>This patch eliminates (rather than fixes up) this short-cutting on the
>grounds that it is a maintenance burden and inconsistent behaviour.
>Users should be able to do this:
>
>[suppress_variable]
>  label = Suppress all changes to variables
>
>We could reinstate the logic when the code has global knowledge of
>which fields are present and which have no suppression (restriction)
>semantics, or perhaps just emit a warning message to the user if they
>have supplied a completely empty (no label even) specification.
>
>The patch also corrects 4 affected test cases to reflect that
>suppression is actually happening (according to change_kind).
>
>	* src/abg-suppression.cc (read_type_suppression): Remove
>	short-circuiting of useless suppressions.
>	(read_function_suppression): Ditto.
>	(read_variable_suppression: Ditto.
>	(read_file_suppression): Ditto.
>	tests/data/test-diff-suppr/test15-suppr-added-fn-report-5.txt:
>	Fix test - something is actually suppressed.
>	* tests/data/test-diff-suppr/test16-suppr-removed-fn-report-5.txt:
>	Ditto.
>	* tests/data/test-diff-suppr/test17-suppr-added-var-report-5.txt:
>	Ditto.
>	* tests/data/test-diff-suppr/test18-suppr-removed-var-report-5.txt:
>	Ditto.
>
>Signed-off-by: Giuliano Procida <gprocida@google.com>

Reviewed-by: Matthias Maennich <maennich@google.com>

Cheers,
Matthias

>---
> src/abg-suppression.cc                        | 91 +++++--------------
> .../test15-suppr-added-fn-report-5.txt        |  6 +-
> .../test16-suppr-removed-fn-report-5.txt      | 15 +--
> .../test17-suppr-added-var-report-5.txt       | 15 +--
> .../test18-suppr-removed-var-report-5.txt     | 15 +--
> 5 files changed, 26 insertions(+), 116 deletions(-)
>
>diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
>index 217ec5e9..51885cf2 100644
>--- a/src/abg-suppression.cc
>+++ b/src/abg-suppression.cc
>@@ -1835,19 +1835,6 @@ read_type_suppression(const ini::config::section& section)
> 	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()
>-      && 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()
>-      && srcloc_not_in.empty())
>-    return result;
>-
>   result.reset(new type_suppression(label_str, name_regex_str, name_str));
>
>   if (consider_type_kind)
>@@ -3283,32 +3270,16 @@ read_function_suppression(const ini::config::section& section)
> 	  parms.push_back(parm);
>       }
>
>-  if (!label_str.empty()
>-      || !name.empty()
>-      || !name_regex_str.empty()
>-      || !name_not_regex_str.empty()
>-      || !file_name_regex_str.empty()
>-      || !file_name_not_regex_str.empty()
>-      || !soname_regex_str.empty()
>-      || !soname_not_regex_str.empty()
>-      || !return_type_name.empty()
>-      || !return_type_regex_str.empty()
>-      || !sym_name.empty()
>-      || !sym_name_regex_str.empty()
>-      || !sym_name_not_regex_str.empty()
>-      || !sym_version.empty()
>-      || !sym_ver_regex_str.empty()
>-      || !parms.empty())
>-
>-    result.reset(new function_suppression(label_str, name,
>-					  name_regex_str,
>-					  return_type_name,
>-					  return_type_regex_str,
>-					  parms,
>-					  sym_name,
>-					  sym_name_regex_str,
>-					  sym_version,
>-					  sym_ver_regex_str));
>+  result.reset(new function_suppression(label_str,
>+					name,
>+					name_regex_str,
>+					return_type_name,
>+					return_type_regex_str,
>+					parms,
>+					sym_name,
>+					sym_name_regex_str,
>+					sym_version,
>+					sym_ver_regex_str));
>
>   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
>       && (!name.empty()
>@@ -3319,11 +3290,11 @@ read_function_suppression(const ini::config::section& section)
> 	  || !sym_name_not_regex_str.empty()))
>     result->set_drops_artifact_from_ir(true);
>
>-  if (result && !change_kind_str.empty())
>+  if (!change_kind_str.empty())
>     result->set_change_kind
>       (function_suppression::parse_change_kind(change_kind_str));
>
>-  if (result && !allow_other_aliases.empty())
>+  if (!allow_other_aliases.empty())
>     result->set_allow_other_aliases(allow_other_aliases == "yes"
> 				    || allow_other_aliases == "true");
>
>@@ -4151,27 +4122,15 @@ read_variable_suppression(const ini::config::section& section)
>     ? type_name_regex_prop->get_value()->as_string()
>      : "";
>
>-  if (label_str.empty()
>-      && name_str.empty()
>-      && name_regex_str.empty()
>-      && name_not_regex_str.empty()
>-      && file_name_regex_str.empty()
>-      && file_name_not_regex_str.empty()
>-      && soname_regex_str.empty()
>-      && soname_not_regex_str.empty()
>-      && symbol_name.empty()
>-      && symbol_name_regex_str.empty()
>-      && symbol_name_not_regex_str.empty()
>-      && symbol_version.empty()
>-      && symbol_version_regex_str.empty()
>-      && type_name_str.empty()
>-      && type_name_regex_str.empty())
>-    return result;
>-
>-  result.reset(new variable_suppression(label_str, name_str, name_regex_str,
>-					symbol_name, symbol_name_regex_str,
>-					symbol_version, symbol_version_regex_str,
>-					type_name_str, type_name_regex_str));
>+  result.reset(new variable_suppression(label_str,
>+					name_str,
>+					name_regex_str,
>+					symbol_name,
>+					symbol_name_regex_str,
>+					symbol_version,
>+					symbol_version_regex_str,
>+					type_name_str,
>+					type_name_regex_str));
>
>   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
>       && (!name_str.empty()
>@@ -4188,7 +4147,7 @@ read_variable_suppression(const ini::config::section& section)
>   if (!symbol_name_not_regex_str.empty())
>     result->set_symbol_name_not_regex_str(symbol_name_not_regex_str);
>
>-  if (result && !change_kind_str.empty())
>+  if (!change_kind_str.empty())
>     result->set_change_kind
>       (variable_suppression::parse_change_kind(change_kind_str));
>
>@@ -4331,12 +4290,6 @@ read_file_suppression(const ini::config::section& section)
>     ? soname_not_regex_prop->get_value()->as_string()
>     : "";
>
>-  if (file_name_regex_str.empty()
>-      && file_name_not_regex_str.empty()
>-      && soname_regex_str.empty()
>-      && soname_not_regex_str.empty())
>-    return result;
>-
>   result.reset(new file_suppression(label_str,
> 				    file_name_regex_str,
> 				    file_name_not_regex_str));
>diff --git a/tests/data/test-diff-suppr/test15-suppr-added-fn-report-5.txt b/tests/data/test-diff-suppr/test15-suppr-added-fn-report-5.txt
>index 4eaba5b7..83dfe326 100644
>--- a/tests/data/test-diff-suppr/test15-suppr-added-fn-report-5.txt
>+++ b/tests/data/test-diff-suppr/test15-suppr-added-fn-report-5.txt
>@@ -1,10 +1,6 @@
>-Functions changes summary: 0 Removed, 1 Changed, 1 Added functions
>+Functions changes summary: 0 Removed, 1 Changed, 0 Added (1 filtered out) functions
> Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
>
>-1 Added function:
>-
>-  [A] 'function void bar()'    {_Z3barv}
>-
> 1 function with some indirect sub-type change:
>
>   [C] 'function void bar(S&)' has some indirect sub-type changes:
>diff --git a/tests/data/test-diff-suppr/test16-suppr-removed-fn-report-5.txt b/tests/data/test-diff-suppr/test16-suppr-removed-fn-report-5.txt
>index b28fbd16..851f7728 100644
>--- a/tests/data/test-diff-suppr/test16-suppr-removed-fn-report-5.txt
>+++ b/tests/data/test-diff-suppr/test16-suppr-removed-fn-report-5.txt
>@@ -1,16 +1,3 @@
>-Functions changes summary: 1 Removed, 1 Changed, 0 Added functions
>+Functions changes summary: 0 Removed (1 filtered out), 0 Changed (1 filtered out), 0 Added functions
> Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
>
>-1 Removed function:
>-
>-  [D] 'function void bar()'    {_Z3barv}
>-
>-1 function with some indirect sub-type change:
>-
>-  [C] 'function void bar(S*)' has some indirect sub-type changes:
>-    parameter 1 of type 'S*' has sub-type changes:
>-      in pointed to type 'struct S':
>-        type size changed from 32 to 64 (in bits)
>-        1 data member insertion:
>-          'unsigned int S::bar', at offset 32 (in bits)
>-
>diff --git a/tests/data/test-diff-suppr/test17-suppr-added-var-report-5.txt b/tests/data/test-diff-suppr/test17-suppr-added-var-report-5.txt
>index 6965a151..f4e0aa29 100644
>--- a/tests/data/test-diff-suppr/test17-suppr-added-var-report-5.txt
>+++ b/tests/data/test-diff-suppr/test17-suppr-added-var-report-5.txt
>@@ -1,16 +1,3 @@
> Functions changes summary: 0 Removed, 0 Changed, 0 Added function
>-Variables changes summary: 0 Removed, 1 Changed, 1 Added variables
>-
>-1 Added variable:
>-
>-  [A] 'int var1'    {var1}
>-
>-1 Changed variable:
>-
>-  [C] 'S* var0' was changed:
>-    type of variable changed:
>-      in pointed to type 'struct S':
>-        type size changed from 32 to 64 (in bits)
>-        1 data member insertion:
>-          'char S::m1', at offset 32 (in bits)
>+Variables changes summary: 0 Removed, 0 Changed (1 filtered out), 0 Added (1 filtered out) variables
>
>diff --git a/tests/data/test-diff-suppr/test18-suppr-removed-var-report-5.txt b/tests/data/test-diff-suppr/test18-suppr-removed-var-report-5.txt
>index 3edf2bd1..ac380a4a 100644
>--- a/tests/data/test-diff-suppr/test18-suppr-removed-var-report-5.txt
>+++ b/tests/data/test-diff-suppr/test18-suppr-removed-var-report-5.txt
>@@ -1,16 +1,3 @@
> Functions changes summary: 0 Removed, 0 Changed, 0 Added function
>-Variables changes summary: 1 Removed, 1 Changed, 0 Added variables
>-
>-1 Removed variable:
>-
>-  [D] 'int var1'    {var1}
>-
>-1 Changed variable:
>-
>-  [C] 'S* var0' was changed:
>-    type of variable changed:
>-      in pointed to type 'struct S':
>-        type size changed from 32 to 64 (in bits)
>-        1 data member insertion:
>-          'char S::m1', at offset 32 (in bits)
>+Variables changes summary: 0 Removed (1 filtered out), 0 Changed (1 filtered out), 0 Added variables
>
>-- 
>2.26.2.526.g744177e7f7-goog
>

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v4 10/15] Compile suppression regexes earlier.
  2020-05-04 12:34     ` [PATCH v4 10/15] Compile suppression regexes earlier Giuliano Procida
@ 2020-05-04 13:14       ` Matthias Maennich
  2020-05-13  8:07       ` Dodji Seketeli
  1 sibling, 0 replies; 120+ messages in thread
From: Matthias Maennich @ 2020-05-04 13:14 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, dodji, kernel-team

On Mon, May 04, 2020 at 01:34:11PM +0100, Giuliano Procida wrote:
>Regexes are used in suppression specifications for various things.
>They are currently compiled on first use, rather than on construction
>of the specifications.
>
>This patches changes the suppression specification types to hold
>compiled regexes directly which is a significant simplification and is
>a prerequisite for early error reporting.
>
>There are no behavioural changes.
>
>	* include/abg-suppression.h (suppression_base): In
>	constructor, take regex arguments as regex_t_sptr. Replace all
>	set_*_regex_str and get_*_regex_str methods with set_*_regex
>	and get_*_regex methods.
>	(type_suppression): In constructor, take regex arguments as
>	regex_t_sptr. Replace all set_*_regex_str and get_*_regex_str
>	methods with set_*_regex and get_*_regex methods.
>	(function_suppression): In constructor, take regex arguments
>	as regex_t_sptr. Replace all set_*_regex_str and
>	get_*_regex_str methods with set_*_regex and get_*_regex
>	methods.
>	(function_suppression::parameter_spec): In constructor, take
>	regex arguments as regex_t_sptr. Replace all set_*_regex_str and
>	get_*_regex_str methods with set_*_regex and get_*_regex
>	methods.
>	(variable_suppression): In constructor, take regex arguments
>	as regex_t_sptr. Replace all set_*_regex_str and get_*_regex_str
>	methods with set_*_regex and get_*_regex methods.
>	(file_suppression): In constructor, take regex arguments
>	as regex_t_sptr.
>	* src/abg-suppression-priv.h (suppression_base::priv): Drop
>	all *_regex_str_ members. Drop mutable qualifier on
>	all *_regex_ members. In constructor, take regexes instead of
>	strings for regex arguments. Update all get_*_regex methods to
>	remove regex compilation and update comments.
>	(function_suppression::parameter_spec::priv): Drop
>	all *_regex_str_ members. Drop mutable qualifier on
>	all *_regex_ members. In constructor, take regexes instead of
>	strings for regex arguments. Update get_*_regex methods to
>	remove regex compilation and update comments.
>	(function_suppression::priv): Drop all *_regex_str_ members.
>	Drop mutable qualifier on all *_regex_ members. In constructor,
>	take regexes instead of strings for regex arguments. Update
>	all get_*_regex methods to remove regex compilation and
>	update comments.
>	(variable_suppression::priv): Drop all *_regex_str_ members.
>	Drop mutable qualifier on all *_regex_ members. In
>	constructor, take regexes instead of strings for regex
>	arguments. Update all get_*_regex methods to remove
>	regex compilation and update comments.
>	(type_suppression::priv): Drop all *_regex_str_ members.
>	Drop mutable qualifier on all *_regex_ members. In constructor,
>	take regexes instead of strings for regex arguments. Update
>	all get_*_regex methods to remove regex compilation and
>	update comments. Drop set_type_name_regex_str and
>	get_type_name_regex_str methods.
>	* src/abg-suppression.cc (suppression_base): In constructor,
>	take regexes instead of strings for regex arguments. Replace
>	all set_*_regex_str and get_*_regex_str methods with
>	set_*_regex and get_*_regex methods. Update
>	has_file_name_related_property and has_soname_related_property
>	methods.
>	(type_suppression): In constructor, take regexes instead of
>	strings for regex arguments. Replace all set_*_regex_str and
>	get_*_regex_str methods with set_*_regex and get_*_regex
>	methods. Update has_file_name_related_property and
>	has_soname_related_property methods.
>	(read_type_suppression): Compile regexes instead of keeping
>	them as strings. Pass them to type_suppression constructor and
>	setters.
>	(function_suppression::parameter_spec): In constructor, take
>	regexes instead of strings for regex arguments. Replace all
>	set_*_regex_str and get_*_regex_str methods with set_*_regex and
>	get_*_regex methods.
>	(function_suppression): In constructor, take regexes instead
>	of strings for regex arguments. Replace all set_*_regex_str
>	and get_*_regex_str methods with set_*_regex and get_*_regex
>	methods. Update suppresses_function_symbol method.
>	(read_parameter_spec_from_string): Change type of
>	type_name_regex from string to regex and compile when needed.
>	(read_function_suppression): Compile regexes instead of
>	keeping them as strings. Pass them to function_suppression
>	constructor and setters.
>	(variable_suppression): In constructor, take regexes instead
>	of strings for regex arguments. Replace all set_*_regex_str
>	and get_*_regex_str methods with set_*_regex and get_*_regex
>	methods.
>	(file_suppression): In constructor, take regexes instead of
>	strings for regex arguments. Replace all set_*_regex_str and
>	get_*_regex_str methods with set_*_regex and get_*_regex
>	methods.
>	* src/abg-tools-utils.cc (handle_file_entry): Compile and
>	check regex for /usr/include.
>	(gen_suppr_spec_from_kernel_abi_whitelists):
>	Compile and check whitelisting regex.
>	* tests/test-kmi-whitelist.cc (random_symbols) Add array of
>	symbols. (test_suppressions_are_consistent): Rework to test by
>	matching regexes against symbols, now that uncompiled regex
>	strings are no longer available.
>
>Signed-off-by: Giuliano Procida <gprocida@google.com>

That is indeed a very nice simplification!
I read through the patch, a lot is mechanical replacements. Thus I hope
I did not miss anything, but this likely needs another pair of eyes to
look through.

(Some includes could be sorted.)

Reviewed-by: Matthias Maennich <maennich@google.com>

Cheers,
Matthias
>---
> include/abg-suppression.h   | 165 ++++-----
> src/abg-suppression-priv.h  | 357 ++++---------------
> src/abg-suppression.cc      | 694 ++++++++++++++++++------------------
> src/abg-tools-utils.cc      |  17 +-
> tests/test-kmi-whitelist.cc |  60 +++-
> 5 files changed, 583 insertions(+), 710 deletions(-)
>
>diff --git a/include/abg-suppression.h b/include/abg-suppression.h
>index 6383b932..8256f9b8 100644
>--- a/include/abg-suppression.h
>+++ b/include/abg-suppression.h
>@@ -26,6 +26,7 @@
> #include "abg-cxx-compat.h"
> #include "abg-ini.h"
> #include "abg-comparison.h"
>+#include "abg-regex.h"
>
> namespace abigail
> {
>@@ -64,8 +65,8 @@ public:
>   suppression_base(const string& label);
>
>   suppression_base(const string& label,
>-		   const string& file_name_regex_str,
>-		   const string& file_name_not_regex_str);
>+		   const regex::regex_t_sptr& file_name_regex,
>+		   const regex::regex_t_sptr& file_name_not_regex);
>
>   bool
>   get_drops_artifact_from_ir() const;
>@@ -86,31 +87,31 @@ public:
>   set_label(const string&);
>
>   void
>-  set_file_name_regex_str(const string& regexp);
>+  set_file_name_regex(const regex::regex_t_sptr& regexp);
>
>-  const string&
>-  get_file_name_regex_str() const;
>+  const regex::regex_t_sptr&
>+  get_file_name_regex() const;
>
>   void
>-  set_file_name_not_regex_str(const string& regexp);
>+  set_file_name_not_regex(const regex::regex_t_sptr& regexp);
>
>-  const string&
>-  get_file_name_not_regex_str() const;
>+  const regex::regex_t_sptr&
>+  get_file_name_not_regex() const;
>
>   bool
>   has_file_name_related_property() const;
>
>   void
>-  set_soname_regex_str(const string& regexp);
>+  set_soname_regex(const regex::regex_t_sptr& regexp);
>
>-  const string&
>-  get_soname_regex_str() const;
>+  const regex::regex_t_sptr&
>+  get_soname_regex() const;
>
>   void
>-  set_soname_not_regex_str(const string& regexp);
>+  set_soname_not_regex(const regex::regex_t_sptr& regexp);
>
>-  const string&
>-  get_soname_not_regex_str() const;
>+  const regex::regex_t_sptr&
>+  get_soname_not_regex() const;
>
>   bool
>   has_soname_related_property() const;
>@@ -204,22 +205,22 @@ public:
>   typedef vector<insertion_range_sptr> insertion_ranges;
>
>   type_suppression(const string& label,
>-		   const string& type_name_regexp,
>+		   const regex::regex_t_sptr& type_name_regexp,
> 		   const string& type_name);
>
>   virtual ~type_suppression();
>
>   void
>-  set_type_name_regex_str(const string& name_regex_str);
>+  set_type_name_regex(const regex::regex_t_sptr& name_regex);
>
>-  const string&
>-  get_type_name_regex_str() const;
>+  const regex::regex_t_sptr&
>+  get_type_name_regex() const;
>
>   void
>-  set_type_name_not_regex_str(const string& name_regex_str);
>+  set_type_name_not_regex(const regex::regex_t_sptr& name_regex);
>
>-  const string&
>-  get_type_name_not_regex_str() const;
>+  const regex::regex_t_sptr&
>+  get_type_name_not_regex() const;
>
>   void
>   set_type_name(const string& name);
>@@ -269,11 +270,11 @@ public:
>   void
>   set_source_locations_to_keep(const unordered_set<string>&);
>
>-  const string&
>-  get_source_location_to_keep_regex_str() const;
>+  const regex::regex_t_sptr&
>+  get_source_location_to_keep_regex() const;
>
>   void
>-  set_source_location_to_keep_regex_str(const string&);
>+  set_source_location_to_keep_regex(const regex::regex_t_sptr&);
>
>   const vector<string>&
>   get_changed_enumerator_names() const;
>@@ -460,16 +461,16 @@ public:
>
>   function_suppression();
>
>-  function_suppression(const string&		label,
>-		       const string&		name,
>-		       const string&		name_regex,
>-		       const string&		return_type_name,
>-		       const string&		return_type_regex,
>-		       parameter_specs_type&	parm_specs,
>-		       const string&		symbol_name,
>-		       const string&		symbol_name_regex,
>-		       const string&		symbol_version,
>-		       const string&		symbol_version_regex_str);
>+  function_suppression(const string&			label,
>+		       const string&			name,
>+		       const regex::regex_t_sptr&	name_regex,
>+		       const string&			return_type_name,
>+		       const regex::regex_t_sptr&	return_type_regex,
>+		       parameter_specs_type&		parm_specs,
>+		       const string&			symbol_name,
>+		       const regex::regex_t_sptr&	symbol_name_regex,
>+		       const string&			symbol_version,
>+		       const regex::regex_t_sptr&	symbol_version_regex);
>
>   virtual ~function_suppression();
>
>@@ -488,17 +489,17 @@ public:
>   void
>   set_name(const string&);
>
>-  const string&
>-  get_name_regex_str() const;
>+  const regex::regex_t_sptr&
>+  get_name_regex() const;
>
>   void
>-  set_name_regex_str(const string&);
>+  set_name_regex(const regex::regex_t_sptr&);
>
>-  const string&
>-  get_name_not_regex_str() const;
>+  const regex::regex_t_sptr&
>+  get_name_not_regex() const;
>
>   void
>-  set_name_not_regex_str(const string&);
>+  set_name_not_regex(const regex::regex_t_sptr&);
>
>   const string&
>   get_return_type_name() const;
>@@ -506,11 +507,11 @@ public:
>   void
>   set_return_type_name(const string&);
>
>-  const string&
>-  get_return_type_regex_str() const;
>+  const regex::regex_t_sptr&
>+  get_return_type_regex() const;
>
>   void
>-  set_return_type_regex_str(const string& r);
>+  set_return_type_regex(const regex::regex_t_sptr& r);
>
>   const parameter_specs_type&
>   get_parameter_specs() const;
>@@ -527,17 +528,17 @@ public:
>   void
>   set_symbol_name(const string& n);
>
>-  const string&
>-  get_symbol_name_regex_str() const;
>+  const regex::regex_t_sptr&
>+  get_symbol_name_regex() const;
>
>   void
>-  set_symbol_name_regex_str(const string&);
>+  set_symbol_name_regex(const regex::regex_t_sptr&);
>
>-  const string&
>-  get_symbol_name_not_regex_str() const;
>+  const regex::regex_t_sptr&
>+  get_symbol_name_not_regex() const;
>
>   void
>-  set_symbol_name_not_regex_str(const string&);
>+  set_symbol_name_not_regex(const regex::regex_t_sptr&);
>
>   const string&
>   get_symbol_version() const;
>@@ -545,11 +546,11 @@ public:
>   void
>   set_symbol_version(const string&);
>
>-  const string&
>-  get_symbol_version_regex_str() const;
>+  const regex::regex_t_sptr&
>+  get_symbol_version_regex() const;
>
>   void
>-  set_symbol_version_regex_str(const string&);
>+  set_symbol_version_regex(const regex::regex_t_sptr&);
>
>   bool
>   get_allow_other_aliases() const;
>@@ -609,7 +610,7 @@ class function_suppression::parameter_spec
> public:
>   parameter_spec(size_t index,
> 		 const string& type_name,
>-		 const string& type_name_regex);
>+		 const regex::regex_t_sptr& type_name_regex);
>
>   size_t
>   get_index() const;
>@@ -623,11 +624,11 @@ public:
>   void
>   set_parameter_type_name(const string&);
>
>-  const string&
>-  get_parameter_type_name_regex_str() const;
>+  const regex::regex_t_sptr&
>+  get_parameter_type_name_regex() const;
>
>   void
>-  set_parameter_type_name_regex_str(const string&);
>+  set_parameter_type_name_regex(const regex::regex_t_sptr&);
> };// end class function_suppression::parameter_spec
>
> class variable_suppression;
>@@ -679,13 +680,17 @@ public:
>
>   variable_suppression(const string& label = "",
> 		       const string& name = "",
>-		       const string& name_regex_str = "",
>+		       const regex::regex_t_sptr& name_regex =
>+			 regex::regex_t_sptr(),
> 		       const string& symbol_name = "",
>-		       const string& symbol_name_regex_str = "",
>+		       const regex::regex_t_sptr& symbol_name_regex =
>+			 regex::regex_t_sptr(),
> 		       const string& symbol_version = "",
>-		       const string& symbol_version_regex_str = "",
>+		       const regex::regex_t_sptr& symbol_version_regex =
>+			 regex::regex_t_sptr(),
> 		       const string& type_name = "",
>-		       const string& type_name_regex_str = "");
>+		       const regex::regex_t_sptr& type_name_regex =
>+			 regex::regex_t_sptr());
>
>   virtual ~variable_suppression();
>
>@@ -704,17 +709,17 @@ public:
>   void
>   set_name(const string&);
>
>-  const string&
>-  get_name_regex_str() const;
>+  const regex::regex_t_sptr&
>+  get_name_regex() const;
>
>   void
>-  set_name_regex_str(const string&);
>+  set_name_regex(const regex::regex_t_sptr&);
>
>-  const string&
>-  get_name_not_regex_str() const;
>+  const regex::regex_t_sptr&
>+  get_name_not_regex() const;
>
>   void
>-  set_name_not_regex_str(const string&);
>+  set_name_not_regex(const regex::regex_t_sptr&);
>
>   const string&
>   get_symbol_name() const;
>@@ -722,17 +727,17 @@ public:
>   void
>   set_symbol_name(const string&);
>
>-  const string&
>-  get_symbol_name_regex_str() const;
>+  const regex::regex_t_sptr&
>+  get_symbol_name_regex() const;
>
>   void
>-  set_symbol_name_regex_str(const string&);
>+  set_symbol_name_regex(const regex::regex_t_sptr&);
>
>-  const string&
>-  get_symbol_name_not_regex_str() const;
>+  const regex::regex_t_sptr&
>+  get_symbol_name_not_regex() const;
>
>   void
>-  set_symbol_name_not_regex_str(const string&);
>+  set_symbol_name_not_regex(const regex::regex_t_sptr&);
>
>   const string&
>   get_symbol_version() const;
>@@ -740,11 +745,11 @@ public:
>   void
>   set_symbol_version(const string&);
>
>-  const string&
>-  get_symbol_version_regex_str() const;
>+  const regex::regex_t_sptr&
>+  get_symbol_version_regex() const;
>
>   void
>-  set_symbol_version_regex_str(const string&);
>+  set_symbol_version_regex(const regex::regex_t_sptr&);
>
>   const string&
>   get_type_name() const;
>@@ -752,11 +757,11 @@ public:
>   void
>   set_type_name(const string&);
>
>-  const string&
>-  get_type_name_regex_str() const;
>+  const regex::regex_t_sptr&
>+  get_type_name_regex() const;
>
>   void
>-  set_type_name_regex_str(const string&);
>+  set_type_name_regex(const regex::regex_t_sptr&);
>
>   bool
>   suppresses_diff(const diff* d) const;
>@@ -816,8 +821,8 @@ class file_suppression: public suppression_base
> public:
>
>   file_suppression(const string& label,
>-		   const string& file_name_regex,
>-		   const string& file_name_not_regex);
>+		   const regex::regex_t_sptr& file_name_regex,
>+		   const regex::regex_t_sptr& file_name_not_regex);
>
>   virtual bool
>   suppresses_diff(const diff* diff) const;
>diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h
>index deb08269..c5f99c15 100644
>--- a/src/abg-suppression-priv.h
>+++ b/src/abg-suppression-priv.h
>@@ -47,14 +47,10 @@ class suppression_base::priv
>   bool					is_artificial_;
>   bool					drops_artifact_;
>   string				label_;
>-  string				file_name_regex_str_;
>-  mutable regex::regex_t_sptr		file_name_regex_;
>-  string				file_name_not_regex_str_;
>-  mutable regex::regex_t_sptr		file_name_not_regex_;
>-  string				soname_regex_str_;
>-  mutable regex::regex_t_sptr		soname_regex_;
>-  string				soname_not_regex_str_;
>-  mutable regex::regex_t_sptr		soname_not_regex_;
>+  regex::regex_t_sptr			file_name_regex_;
>+  regex::regex_t_sptr			file_name_not_regex_;
>+  regex::regex_t_sptr			soname_regex_;
>+  regex::regex_t_sptr			soname_not_regex_;
>
> public:
>   priv()
>@@ -69,78 +65,46 @@ public:
>   {}
>
>   priv(const string& label,
>-       const string& file_name_regex_str,
>-       const string& file_name_not_regex_str)
>+       const regex::regex_t_sptr& file_name_regex,
>+       const regex::regex_t_sptr& file_name_not_regex)
>     : is_artificial_(),
>       drops_artifact_(),
>       label_(label),
>-      file_name_regex_str_(file_name_regex_str),
>-      file_name_not_regex_str_(file_name_not_regex_str)
>+      file_name_regex_(file_name_regex),
>+      file_name_not_regex_(file_name_not_regex)
>   {}
>
>   friend class suppression_base;
>
>-  /// Get the regular expression object associated to the 'file_name_regex'
>-  /// property of @ref suppression_base.
>-  ///
>-  /// If the regular expression object is not created, this method
>-  /// creates it and returns it.
>-  ///
>-  /// If the 'file_name_regex' property of @ref suppression_base is
>-  /// empty then this method returns nil.
>+  /// Get the regular expression object associated to the
>+  /// 'file_name_regex' property of @ref suppression_base.
>   const regex::regex_t_sptr&
>   get_file_name_regex() const
>   {
>-    if (!file_name_regex_ && !file_name_regex_str_.empty())
>-      file_name_regex_ = regex::compile(file_name_regex_str_);
>     return file_name_regex_;
>   }
>
>   /// Get the regular expression object associated to the
>   /// 'file_name_not_regex' property of @ref suppression_base.
>-  ///
>-  /// If the regular expression object is not created, this method
>-  /// creates it and returns it.
>-  ///
>-  /// If the 'file_name_not_regex' property of @ref suppression_base
>-  /// is empty then this method returns nil.
>   const regex::regex_t_sptr&
>   get_file_name_not_regex() const
>   {
>-    if (!file_name_not_regex_ && !file_name_not_regex_str_.empty())
>-      file_name_not_regex_ = regex::compile(file_name_not_regex_str_);
>     return file_name_not_regex_;
>   }
>
>-  /// Get the regular expression object associated to the
>-  /// 'soname_regex' property of @ref suppression_base.
>-  ///
>-  /// If the regular expression object is not created, this method
>-  /// creates it and returns it.
>-  ///
>-  /// If the 'soname_regex' property of @ref suppression_base is empty
>-  /// then this method returns nil.
>+  /// Get the regular expression object associated to the 'soname_regex'
>+  /// property of @ref suppression_base.
>   const regex::regex_t_sptr&
>   get_soname_regex() const
>   {
>-    if (!soname_regex_ && !soname_regex_str_.empty())
>-      soname_regex_ = regex::compile(soname_regex_str_);
>     return soname_regex_;
>   }
>
>   /// Get the regular expression object associated to the
>   /// 'soname_not_regex' property of @ref suppression_base.
>-  ///
>-  /// If the regular expression object is not created, this method
>-  /// creates it and returns it.
>-  ///
>-  /// If the 'soname_not_regex' property of @ref suppression_base is
>-  /// empty then this method returns nil.
>   const regex::regex_t_sptr&
>   get_soname_not_regex() const
>   {
>-    if (!soname_not_regex_ && !soname_not_regex_str_.empty())
>-      soname_not_regex_ = regex::compile(soname_not_regex_str_);
>     return soname_not_regex_;
>   }
>
>@@ -225,8 +189,7 @@ class function_suppression::parameter_spec::priv
>
>   size_t				index_;
>   string				type_name_;
>-  string				type_name_regex_str_;
>-  mutable regex::regex_t_sptr		type_name_regex_;
>+  regex::regex_t_sptr			type_name_regex_;
>
>   priv()
>     : index_()
>@@ -236,15 +199,16 @@ class function_suppression::parameter_spec::priv
>     : index_(i), type_name_(tn)
>   {}
>
>-  priv(size_t i, const string& tn, const string& tn_regex)
>-    : index_(i), type_name_(tn), type_name_regex_str_(tn_regex)
>+  priv(size_t i, const string& tn, const regex::regex_t_sptr& tn_regex)
>+    : index_(i), type_name_(tn), type_name_regex_(tn_regex)
>   {}
>
>+  /// Get the regular expression object associated to the
>+  /// 'type_name_regex' property of @ref
>+  /// function_suppression::parameter_spec.
>   const regex::regex_t_sptr
>   get_type_name_regex() const
>   {
>-    if (!type_name_regex_ && !type_name_regex_str_.empty())
>-      type_name_regex_ = regex::compile(type_name_regex_str_);
>     return type_name_regex_;
>   }
> }; // end class function_suppression::parameter_spec::priv
>@@ -258,22 +222,16 @@ struct function_suppression::priv
>
>   change_kind				change_kind_;
>   string				name_;
>-  string				name_regex_str_;
>-  mutable regex::regex_t_sptr		name_regex_;
>-  string				name_not_regex_str_;
>-  mutable regex::regex_t_sptr		name_not_regex_;
>+  regex::regex_t_sptr			name_regex_;
>+  regex::regex_t_sptr			name_not_regex_;
>   string				return_type_name_;
>-  string				return_type_regex_str_;
>-  mutable regex::regex_t_sptr		return_type_regex_;
>+  regex::regex_t_sptr			return_type_regex_;
>   parameter_specs_type			parm_specs_;
>   string				symbol_name_;
>-  string				symbol_name_regex_str_;
>-  mutable regex::regex_t_sptr		symbol_name_regex_;
>-  string				symbol_name_not_regex_str_;
>-  mutable regex::regex_t_sptr		symbol_name_not_regex_;
>+  regex::regex_t_sptr			symbol_name_regex_;
>+  regex::regex_t_sptr			symbol_name_not_regex_;
>   string				symbol_version_;
>-  string				symbol_version_regex_str_;
>-  mutable regex::regex_t_sptr		symbol_version_regex_;
>+  regex::regex_t_sptr			symbol_version_regex_;
>   bool					allow_other_aliases_;
>
>   priv():
>@@ -282,127 +240,72 @@ struct function_suppression::priv
>   {}
>
>   priv(const string&			name,
>-       const string&			name_regex_str,
>+       const regex::regex_t_sptr&	name_regex,
>        const string&			return_type_name,
>-       const string&			return_type_regex_str,
>+       const regex::regex_t_sptr&	return_type_regex,
>        const parameter_specs_type&	parm_specs,
>        const string&			symbol_name,
>-       const string&			symbol_name_regex_str,
>+       const regex::regex_t_sptr&	symbol_name_regex,
>        const string&			symbol_version,
>-       const string&			symbol_version_regex_str)
>+       const regex::regex_t_sptr&	symbol_version_regex)
>     : change_kind_(ALL_CHANGE_KIND),
>       name_(name),
>-      name_regex_str_(name_regex_str),
>+      name_regex_(name_regex),
>       return_type_name_(return_type_name),
>-      return_type_regex_str_(return_type_regex_str),
>+      return_type_regex_(return_type_regex),
>       parm_specs_(parm_specs),
>       symbol_name_(symbol_name),
>-      symbol_name_regex_str_(symbol_name_regex_str),
>+      symbol_name_regex_(symbol_name_regex),
>       symbol_version_(symbol_version),
>-      symbol_version_regex_str_(symbol_version_regex_str),
>+      symbol_version_regex_(symbol_version_regex),
>       allow_other_aliases_(true)
>   {}
>
>-
>-  /// Getter for a pointer to a regular expression object built from
>-  /// the regular expression string
>-  /// function_suppression::priv::name_regex_str_.
>-  ///
>-  /// If that string is empty, then an empty regular expression object
>-  /// pointer is returned.
>-  ///
>-  /// @return a pointer to the regular expression object of
>-  /// function_suppression::priv::name_regex_str_..
>+  /// Get the regular expression object associated to the 'name_regex'
>+  /// property of @ref function_suppression.
>   const regex::regex_t_sptr
>   get_name_regex() const
>   {
>-    if (!name_regex_ && !name_regex_str_.empty())
>-      name_regex_ = regex::compile(name_regex_str_);
>     return name_regex_;
>   }
>
>-  /// Getter for a pointer to a regular expression object built from
>-  /// the regular expression string
>-  /// function_suppression::priv::name_not_regex_str_.
>-  ///
>-  /// If that string is empty, then an empty regular expression object
>-  /// pointer is returned.
>-  ///
>-  /// @return a pointer to the regular expression object of
>-  /// function_suppression::priv::name_not_regex_str_..
>+  /// Get the regular expression object associated to the
>+  /// 'name_not_regex' property of @ref function_suppression.
>   const regex::regex_t_sptr
>   get_name_not_regex() const
>   {
>-    if (!name_not_regex_ && !name_not_regex_str_.empty())
>-      name_not_regex_ = regex::compile(name_not_regex_str_);
>     return name_not_regex_;
>   }
>
>-  /// Getter for a pointer to a regular expression object built from
>-  /// the regular expression string
>-  /// function_suppression::priv::return_type_regex_str_.
>-  ///
>-  /// If that string is empty, then an empty regular expression object
>-  /// pointer is returned.
>-  ///
>-  /// @return a pointer to the regular expression object of
>-  /// function_suppression::priv::return_type_regex_str_.
>+  /// Get the regular expression object associated to the
>+  /// 'return_type_regex' property of @ref function_suppression.
>   const regex::regex_t_sptr
>   get_return_type_regex() const
>   {
>-    if (!return_type_regex_ && !return_type_regex_str_.empty())
>-      return_type_regex_ = regex::compile(return_type_regex_str_);
>     return return_type_regex_;
>   }
>
>-  /// Getter for a pointer to a regular expression object built from
>-  /// the regular expression string
>-  /// function_suppression::priv::symbol_name_regex_str_.
>-  ///
>-  /// If that string is empty, then an empty regular expression object
>-  /// pointer is returned.
>-  ///
>-  /// @return a pointer to the regular expression object of
>-  /// function_suppression::priv::symbol_name_regex_str_.
>+  /// Get the regular expression object associated to the
>+  /// 'symbol_name_regex' property of @ref function_suppression.
>   const regex::regex_t_sptr
>   get_symbol_name_regex() const
>   {
>-    if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
>-      symbol_name_regex_ = regex::compile(symbol_name_regex_str_);
>     return symbol_name_regex_;
>   }
>
>-  /// Getter for a pointer to a regular expression object built from
>-  /// the regular expression string
>-  /// function_suppression::priv::symbol_name_not_regex_str_.
>-  ///
>-  /// If that string is empty, then an empty regular expression object
>-  /// pointer is returned.
>-  ///
>-  /// @return a pointer to the regular expression object of
>-  /// function_suppression::priv::symbol_name_not_regex_str_.
>+  /// Get the regular expression object associated to the
>+  /// 'symbol_name_not_regex' property of @ref function_suppression.
>   const regex::regex_t_sptr
>   get_symbol_name_not_regex() const
>   {
>-    if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
>-      symbol_name_not_regex_ = regex::compile(symbol_name_not_regex_str_);
>     return symbol_name_not_regex_;
>   }
>
>-  /// Getter for a pointer to a regular expression object built from
>-  /// the regular expression string
>-  /// function_suppression::priv::symbol_version_regex_str_.
>-  ///
>-  /// If that string is empty, then an empty regular expression object
>-  /// pointer is returned.
>-  ///
>-  /// @return a pointer to the regular expression object of
>-  /// function_suppression::priv::symbol_version_regex_str_.
>+  /// Get the regular expression object associated to the
>+  /// 'symbol_version_regex' property of @ref function_suppression.
>   const regex::regex_t_sptr
>   get_symbol_version_regex() const
>   {
>-    if (!symbol_version_regex_ && !symbol_version_regex_str_.empty())
>-      symbol_version_regex_ = regex::compile(symbol_version_regex_str_);
>     return symbol_version_regex_;
>   }
> }; // end class function_suppression::priv
>@@ -481,140 +384,80 @@ struct variable_suppression::priv
>
>   change_kind				change_kind_;
>   string				name_;
>-  string				name_regex_str_;
>-  mutable regex::regex_t_sptr		name_regex_;
>-  string				name_not_regex_str_;
>-  mutable regex::regex_t_sptr		name_not_regex_;
>+  regex::regex_t_sptr			name_regex_;
>+  regex::regex_t_sptr			name_not_regex_;
>   string				symbol_name_;
>-  string				symbol_name_regex_str_;
>-  mutable regex::regex_t_sptr		symbol_name_regex_;
>-  string				symbol_name_not_regex_str_;
>-  mutable regex::regex_t_sptr		symbol_name_not_regex_;
>+  regex::regex_t_sptr			symbol_name_regex_;
>+  regex::regex_t_sptr			symbol_name_not_regex_;
>   string				symbol_version_;
>-  string				symbol_version_regex_str_;
>-  mutable regex::regex_t_sptr		symbol_version_regex_;
>+  regex::regex_t_sptr			symbol_version_regex_;
>   string				type_name_;
>-  string				type_name_regex_str_;
>-  mutable regex::regex_t_sptr		type_name_regex_;
>+  regex::regex_t_sptr			type_name_regex_;
>
>   priv(const string& name,
>-       const string& name_regex_str,
>+       const regex::regex_t_sptr& name_regex,
>        const string& symbol_name,
>-       const string& symbol_name_regex_str,
>+       const regex::regex_t_sptr& symbol_name_regex,
>        const string& symbol_version,
>-       const string& symbol_version_regex_str,
>+       const regex::regex_t_sptr& symbol_version_regex,
>        const string& type_name,
>-       const string& type_name_regex_str)
>+       const regex::regex_t_sptr& type_name_regex)
>     : change_kind_(ALL_CHANGE_KIND),
>       name_(name),
>-      name_regex_str_(name_regex_str),
>+      name_regex_(name_regex),
>       symbol_name_(symbol_name),
>-      symbol_name_regex_str_(symbol_name_regex_str),
>+      symbol_name_regex_(symbol_name_regex),
>       symbol_version_(symbol_version),
>-      symbol_version_regex_str_(symbol_version_regex_str),
>+      symbol_version_regex_(symbol_version_regex),
>       type_name_(type_name),
>-      type_name_regex_str_(type_name_regex_str)
>+      type_name_regex_(type_name_regex)
>   {}
>
>-  /// Getter for a pointer to a regular expression object built from
>-  /// the regular expression string
>-  /// variable_suppression::priv::name_regex_str_.
>-  ///
>-  /// If that string is empty, then an empty regular expression object
>-  /// pointer is returned.
>-  ///
>-  /// @return a pointer to the regular expression object of
>-  /// variable_suppression::priv::name_regex_str_.
>+  /// Get the regular expression object associated to the 'name_regex'
>+  /// property of @ref variable_suppression.
>   const regex::regex_t_sptr
>   get_name_regex() const
>   {
>-    if (!name_regex_ && !name_regex_str_.empty())
>-      name_regex_ = regex::compile(name_regex_str_);
>     return name_regex_;
>   }
>
>-  /// Getter for a pointer to a regular expression object built from
>-  /// the regular expression string
>-  /// variable_suppression::priv::name_not_regex_str_.
>-  ///
>-  /// If that string is empty, then an empty regular expression object
>-  /// pointer is returned.
>-  ///
>-  /// @return a pointer to the regular expression object of
>-  /// variable_suppression::priv::name_not_regex_str_..
>+  /// Get the regular expression object associated to the
>+  /// 'name_not_regex' property of @ref variable_suppression.
>   const regex::regex_t_sptr
>   get_name_not_regex() const
>   {
>-    if (!name_not_regex_ && !name_not_regex_str_.empty())
>-      name_not_regex_ = regex::compile(name_not_regex_str_);
>     return name_not_regex_;
>   }
>
>-  /// Getter for a pointer to a regular expression object built from
>-  /// the regular expression string
>-  /// variable_suppression::priv::symbol_name_regex_str_.
>-  ///
>-  /// If that string is empty, then an empty regular expression object
>-  /// pointer is returned.
>-  ///
>-  /// @return a pointer to the regular expression object of
>-  /// variable_suppression::priv::symbol_name_regex_str_.
>+  /// Get the regular expression object associated to the
>+  /// 'symbol_name_regex' property of @ref variable_suppression.
>   const regex::regex_t_sptr
>   get_symbol_name_regex() const
>   {
>-    if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
>-      symbol_name_regex_ = regex::compile(symbol_name_regex_str_);
>     return symbol_name_regex_;
>   }
>
>-  /// Getter for a pointer to a regular expression object built from
>-  /// the regular expression string
>-  /// variable_suppression::priv::symbol_name_not_regex_str_.
>-  ///
>-  /// If that string is empty, then an empty regular expression object
>-  /// pointer is returned.
>-  ///
>-  /// @return a pointer to the regular expression object of
>-  /// variable_suppression::priv::symbol_name_not_regex_str_.
>+  /// Get the regular expression object associated to the
>+  /// 'symbol_name_not_regex' property of @ref variable_suppression.
>   const regex::regex_t_sptr
>   get_symbol_name_not_regex() const
>   {
>-    if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
>-      symbol_name_not_regex_ = regex::compile(symbol_name_not_regex_str_);
>     return symbol_name_not_regex_;
>   }
>
>-  /// Getter for a pointer to a regular expression object built from
>-  /// the regular expression string
>-  /// variable_suppression::priv::symbol_version_regex_str_.
>-  ///
>-  /// If that string is empty, then an empty regular expression object
>-  /// pointer is returned.
>-  ///
>-  /// @return a pointer to the regular expression object of
>-  /// variable_suppression::priv::symbol_version_regex_str_.
>+  /// Get the regular expression object associated to the
>+  /// 'symbol_version_regex' property of @ref variable_suppression.
>   const regex::regex_t_sptr
>   get_symbol_version_regex()  const
>   {
>-    if (!symbol_version_regex_ && !symbol_version_regex_str_.empty())
>-      symbol_version_regex_ = regex::compile(symbol_version_regex_str_);
>     return symbol_version_regex_;
>   }
>
>-  /// Getter for a pointer to a regular expression object built from
>-  /// the regular expression string
>-  /// variable_suppression::priv::type_name_regex_str_.
>-  ///
>-  /// If that string is empty, then an empty regular expression object
>-  /// pointer is returned.
>-  ///
>-  /// @return a pointer to the regular expression object of
>-  /// variable_suppression::priv::type_name_regex_str_.
>+  /// Get the regular expression object associated to the
>+  /// 'type_name_regex' property of @ref variable_suppression.
>   const regex::regex_t_sptr
>   get_type_name_regex() const
>   {
>-    if (!type_name_regex_ && !type_name_regex_str_.empty())
>-      type_name_regex_ = regex::compile(type_name_regex_str_);
>     return type_name_regex_;
>   }
> };// end class variable_supppression::priv
>@@ -651,31 +494,28 @@ variable_is_suppressed(const ReadContextType&	ctxt,
> /// The private data for @ref type_suppression.
> class type_suppression::priv
> {
>-  string				type_name_regex_str_;
>-  mutable regex::regex_t_sptr		type_name_regex_;
>+  regex::regex_t_sptr			type_name_regex_;
>   string				type_name_;
>-  string				type_name_not_regex_str_;
>-  mutable regex::regex_t_sptr		type_name_not_regex_;
>+  regex::regex_t_sptr			type_name_not_regex_;
>   bool					consider_type_kind_;
>   type_suppression::type_kind		type_kind_;
>   bool					consider_reach_kind_;
>   type_suppression::reach_kind		reach_kind_;
>   type_suppression::insertion_ranges	insertion_ranges_;
>   unordered_set<string>			source_locations_to_keep_;
>-  string				source_location_to_keep_regex_str_;
>-  mutable regex::regex_t_sptr		source_location_to_keep_regex_;
>+  regex::regex_t_sptr			source_location_to_keep_regex_;
>   mutable vector<string>		changed_enumerator_names_;
>
>   priv();
>
> public:
>-  priv(const string&			type_name_regexp,
>+  priv(const regex::regex_t_sptr&	type_name_regexp,
>        const string&			type_name,
>        bool				consider_type_kind,
>        type_suppression::type_kind	type_kind,
>        bool				consider_reach_kind,
>        type_suppression::reach_kind	reach_kind)
>-    : type_name_regex_str_(type_name_regexp),
>+    : type_name_regex_(type_name_regexp),
>       type_name_(type_name),
>       consider_type_kind_(consider_type_kind),
>       type_kind_(type_kind),
>@@ -683,19 +523,11 @@ public:
>       reach_kind_(reach_kind)
>   {}
>
>-  /// Get the regular expression object associated to the 'type_name_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_regex' property of @ref type_suppression is
>-  /// empty then this method returns nil.
>+  /// Get the regular expression object associated to the
>+  /// 'type_name_regex' property of @ref type_suppression.
>   const regex::regex_t_sptr
>   get_type_name_regex() const
>   {
>-    if (!type_name_regex_ && !type_name_regex_str_.empty())
>-      type_name_regex_ = regex::compile(type_name_regex_str_);
>     return type_name_regex_;
>   }
>
>@@ -708,17 +540,9 @@ public:
>
>   /// 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 regex::regex_t_sptr
>   get_type_name_not_regex() const
>   {
>-    if (!type_name_not_regex_ && !type_name_not_regex_str_.empty())
>-      type_name_not_regex_ = regex::compile(type_name_not_regex_str_);
>     return type_name_not_regex_;
>   }
>
>@@ -729,34 +553,11 @@ public:
>   set_type_name_not_regex(regex::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.
>+  /// Get the regular expression object associated to the
>+  /// 'source_location_to_keep_regex' property of @ref type_suppression.
>   const regex::regex_t_sptr
>   get_source_location_to_keep_regex() const
>   {
>-    if (!source_location_to_keep_regex_
>-	&& !source_location_to_keep_regex_str_.empty())
>-      source_location_to_keep_regex_ =
>-	  regex::compile(source_location_to_keep_regex_str_);
>     return source_location_to_keep_regex_;
>   }
>
>diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
>index 4014ff06..80ac1e9f 100644
>--- a/src/abg-suppression.cc
>+++ b/src/abg-suppression.cc
>@@ -67,17 +67,17 @@ suppression_base::suppression_base(const string& label)
> /// @param a label for the suppression.  This represents just a
> /// comment.
> ///
>-/// @param file_name_regex_str the regular expression that denotes the
>+/// @param file_name_regex the regular expression that denotes the
> /// file name to match.
> ///
>-/// @param file_name_not_regex_str the regular expression that denotes
>+/// @param file_name_not_regex the regular expression that denotes
> /// the file name to *NOT* match.
> suppression_base::suppression_base(const string& label,
>-				   const string& file_name_regex_str,
>-				   const string& file_name_not_regex_str)
>+				   const regex_t_sptr& file_name_regex,
>+				   const regex_t_sptr& file_name_not_regex)
>   : priv_(new priv(label,
>-		   file_name_regex_str,
>-		   file_name_not_regex_str))
>+		   file_name_regex,
>+		   file_name_not_regex))
> {
> }
>
>@@ -139,52 +139,50 @@ suppression_base::set_label(const string& label)
> /// Setter for the "file_name_regex" property of the current instance
> /// of @ref suppression_base.
> ///
>-/// The "file_name_regex" property is a regular expression string that
>+/// The "file_name_regex" property is a regular expression that
> /// designates the file name that contains the ABI artifact this
> /// suppression should apply to.
> ///
>-/// @param regexp the new regular expression string.
>+/// @param regexp the new regular expression.
> void
>-suppression_base::set_file_name_regex_str(const string& regexp)
>-{priv_->file_name_regex_str_ = regexp;}
>+suppression_base::set_file_name_regex(const regex_t_sptr& regexp)
>+{priv_->file_name_regex_ = regexp;}
>
> /// Getter for the "file_name_regex" property of the current instance
> /// of @ref suppression_base.
> ///
>-/// The "file_name_regex" property is a regular expression string that
>+/// The "file_name_regex" property is a regular expression that
> /// designates the file name that contains the ABI artifacts this
> /// suppression should apply to.
> ///
>-/// @return the regular expression string.
>-const string&
>-suppression_base::get_file_name_regex_str() const
>-{return priv_->file_name_regex_str_;}
>+/// @return the regular expression.
>+const regex_t_sptr&
>+suppression_base::get_file_name_regex() const
>+{return priv_->file_name_regex_;}
>
> /// Setter for the "file_name_not_regex" property of the current
> /// instance of @ref suppression_base.
> ///
> /// The current suppression specification should apply to ABI
> /// artifacts of a file which name does *NOT* match the regular
>-/// expression string designated by the "file_name_not_regex"
>-/// property.
>+/// expression designated by the "file_name_not_regex" property.
> ///
>-/// @param regexp the new regular expression string.
>+/// @param regexp the new regular expression.
> void
>-suppression_base::set_file_name_not_regex_str(const string& regexp)
>-{priv_->file_name_not_regex_str_ = regexp;}
>+suppression_base::set_file_name_not_regex(const regex_t_sptr& regexp)
>+{priv_->file_name_not_regex_ = regexp;}
>
> /// Getter for the "file_name_not_regex" property of the current
> /// instance of @ref suppression_base.
> ///
> /// The current suppression specification should apply to ABI
> /// artifacts of a file which name does *NOT* match the regular
>-/// expression string designated by the "file_name_not_regex"
>-/// property.
>+/// expression designated by the "file_name_not_regex" property.
> ///
>-/// @return the regular expression string.
>-const string&
>-suppression_base::get_file_name_not_regex_str() const
>-{return priv_->file_name_not_regex_str_;}
>+/// @return the regular expression.
>+const regex_t_sptr&
>+suppression_base::get_file_name_not_regex() const
>+{return priv_->file_name_not_regex_;}
>
> /// Test if the current suppression has a property related to file
> /// name.
>@@ -194,59 +192,56 @@ suppression_base::get_file_name_not_regex_str() const
> bool
> suppression_base::has_file_name_related_property() const
> {
>-  return (!(get_file_name_regex_str().empty()
>-	    && get_file_name_not_regex_str().empty()));
>+  return get_file_name_regex() || get_file_name_not_regex();
> }
>
>-/// Setter of the "soname_regex_str property of the current instance
>+/// Setter of the "soname_regex" property of the current instance
> /// of @ref suppression_base.
> ///
>-/// The "soname_regex_str" is a regular expression string that
>-/// designates the soname of the shared library that contains the ABI
>-/// artifacts this suppression should apply to.
>+/// The "soname_regex" is a regular expression that designates the
>+/// soname of the shared library that contains the ABI artifacts this
>+/// suppression should apply to.
> ///
>-/// @param regexp the new regular expression string.
>+/// @param regexp the new regular expression.
> void
>-suppression_base::set_soname_regex_str(const string& regexp)
>-{priv_->soname_regex_str_ = regexp;}
>+suppression_base::set_soname_regex(const regex_t_sptr& regexp)
>+{priv_->soname_regex_ = regexp;}
>
>-/// Getter of the "soname_regex_str property of the current instance
>+/// Getter of the "soname_regex" property of the current instance
> /// of @ref suppression_base.
> ///
>-/// The "soname_regex_str" is a regular expression string that
>-/// designates the soname of the shared library that contains the ABI
>-/// artifacts this suppression should apply to.
>+/// The "soname_regex" is a regular expression that designates the
>+/// soname of the shared library that contains the ABI artifacts this
>+/// suppression should apply to.
> ///
>-/// @return the regular expression string.
>-const string&
>-suppression_base::get_soname_regex_str() const
>-{return priv_->soname_regex_str_;}
>+/// @return the regular expression.
>+const regex_t_sptr&
>+suppression_base::get_soname_regex() const
>+{return priv_->soname_regex_;}
>
>-/// Setter of the "soname_not_regex_str property of the current
>+/// Setter of the "soname_not_regex" property of the current
> /// instance of @ref suppression_base.
> ///
> /// The current suppression specification should apply to ABI
> /// artifacts of a shared library which SONAME does *NOT* match the
>-/// regular expression string designated by the "soname_not_regex"
>-/// property.
>+/// regular expression designated by the "soname_not_regex" property.
> ///
>-/// @param regexp the new regular expression string.
>+/// @param regexp the new regular expression.
> void
>-suppression_base::set_soname_not_regex_str(const string& regexp)
>-{priv_->soname_not_regex_str_ = regexp;}
>+suppression_base::set_soname_not_regex(const regex_t_sptr& regexp)
>+{priv_->soname_not_regex_ = regexp;}
>
>-/// Getter of the "soname_not_regex_str property of the current
>+/// Getter of the "soname_not_regex" property of the current
> /// instance of @ref suppression_base.
> ///
> /// The current suppression specification should apply to ABI
> /// artifacts of a shared library which SONAME does *NOT* match the
>-/// regular expression string designated by the "soname_not_regex"
>-/// property.
>+/// regular expression designated by the "soname_not_regex" property.
> ///
>-/// @return the regular expression string.
>-const string&
>-suppression_base::get_soname_not_regex_str() const
>-{return priv_->soname_not_regex_str_;}
>+/// @return the regular expression.
>+const regex_t_sptr&
>+suppression_base::get_soname_not_regex() const
>+{return priv_->soname_not_regex_;}
>
> /// Test if the current suppression has a property related to SONAMEs.
> ///
>@@ -255,8 +250,7 @@ suppression_base::get_soname_not_regex_str() const
> bool
> suppression_base::has_soname_related_property() const
> {
>-  return (!(get_soname_regex_str().empty()
>-	    && get_soname_not_regex_str().empty()));
>+  return get_soname_regex() || get_soname_not_regex();
> }
>
> /// Check if the SONAMEs of the two binaries being compared match the
>@@ -398,8 +392,8 @@ read_suppressions(const string& file_path,
> /// form comment explaining what the suppression is about.
> ///
> /// @param type_name_regexp the regular expression describing the
>-/// types about which diff reports should be suppressed.  If it's an
>-/// empty string, the parameter is ignored.
>+/// types about which diff reports should be suppressed.  If it's a
>+/// null shared pointer, the parameter is ignored.
> ///
> /// @param type_name the name of the type about which diff reports
> /// should be suppressed.  If it's an empty string, the parameter is
>@@ -409,7 +403,7 @@ read_suppressions(const string& file_path,
> /// should not necessarily be populated.  It usually is either one or
> /// the other that the user wants.
> type_suppression::type_suppression(const string& label,
>-				   const string& type_name_regexp,
>+				   const regex_t_sptr& type_name_regexp,
> 				   const string& type_name)
>   : suppression_base(label),
>     priv_(new priv(type_name_regexp,
>@@ -429,43 +423,43 @@ type_suppression::~type_suppression()
> /// This sets a regular expression that specifies the family of types
> /// about which diff reports should be suppressed.
> ///
>-/// @param name_regex_str the new regular expression to set.
>+/// @param name_regex the new regular expression to set.
> void
>-type_suppression::set_type_name_regex_str(const string& name_regex_str)
>-{priv_->type_name_regex_str_ = name_regex_str;}
>+type_suppression::set_type_name_regex(const regex_t_sptr& name_regex)
>+{priv_->type_name_regex_ = name_regex;}
>
> /// Getter for the "type_name_regex" property of the type suppression
> /// specification.
> ///
>-/// This returns a regular expression string that specifies the family
>+/// This returns a regular expression that specifies the family
> /// of types about which diff reports should be suppressed.
> ///
>-/// @return the regular expression string.
>-const string&
>-type_suppression::get_type_name_regex_str() const
>-{return priv_->type_name_regex_str_;}
>+/// @return the regular expression.
>+const regex_t_sptr&
>+type_suppression::get_type_name_regex() const
>+{return priv_->type_name_regex_;}
>
>-/// Setter for the "type_name_not_regex_str" property of the type
>+/// Setter for the "type_name_not_regex" property of the type
> /// suppression specification.
> ///
>-/// This returns a regular expression string that specifies the family
>+/// This sets a regular expression 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);}
>+type_suppression::set_type_name_not_regex(const regex_t_sptr& r)
>+{priv_->set_type_name_not_regex(r);}
>
>-/// Getter for the "type_name_not_regex_str" property of the type
>+/// Getter for the "type_name_not_regex" property of the type
> /// suppression specification.
> ///
>-/// This returns a regular expression string that specifies the family
>+/// This returns a regular expression 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();}
>+const regex_t_sptr&
>+type_suppression::get_type_name_not_regex() const
>+{return priv_->type_name_not_regex_;}
>
> /// Setter for the name of the type about which diff reports should be
> /// suppressed.
>@@ -612,21 +606,21 @@ type_suppression::set_source_locations_to_keep
> (const unordered_set<string>& l)
> {priv_->source_locations_to_keep_ = l;}
>
>-/// Getter of the regular expression string that designates the source
>+/// Getter of the regular expression that designates the source
> /// location paths of types that should not be suppressed.
> ///
>-/// @return the regular expression string.
>-const string&
>-type_suppression::get_source_location_to_keep_regex_str() const
>-{return priv_->source_location_to_keep_regex_str_;}
>+/// @return the regular expression.
>+const regex_t_sptr&
>+type_suppression::get_source_location_to_keep_regex() const
>+{return priv_->source_location_to_keep_regex_;}
>
>-/// Setter of the regular expression string that designates the source
>+/// Setter of the regular expression that designates the source
> /// location paths of types that should not be suppressed.
> ///
> /// @param r the new regular expression.
> void
>-type_suppression::set_source_location_to_keep_regex_str(const string& r)
>-{priv_->source_location_to_keep_regex_str_ = r;}
>+type_suppression::set_source_location_to_keep_regex(const regex_t_sptr& r)
>+{priv_->source_location_to_keep_regex_ = 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
>@@ -1558,39 +1552,43 @@ read_type_suppression(const ini::config::section& section)
>
>   ini::simple_property_sptr file_name_regex_prop =
>     is_simple_property(section.find_property("file_name_regexp"));
>-  string file_name_regex_str =
>-    file_name_regex_prop ? file_name_regex_prop->get_value()->as_string() : "";
>+  regex_t_sptr file_name_regex;
>+  if (file_name_regex_prop)
>+    file_name_regex =
>+      regex::compile(file_name_regex_prop->get_value()->as_string());
>
>   ini::simple_property_sptr file_name_not_regex_prop =
>     is_simple_property(section.find_property("file_name_not_regexp"));
>-  string file_name_not_regex_str =
>-    file_name_not_regex_prop
>-    ? file_name_not_regex_prop->get_value()->as_string()
>-    : "";
>+  regex_t_sptr file_name_not_regex;
>+  if (file_name_not_regex_prop)
>+    file_name_not_regex =
>+      regex::compile(file_name_not_regex_prop->get_value()->as_string());
>
>   ini::simple_property_sptr soname_regex_prop =
>     is_simple_property(section.find_property("soname_regexp"));
>-  string soname_regex_str =
>-    soname_regex_prop ? soname_regex_prop->get_value()->as_string() : "";
>+  regex_t_sptr soname_regex;
>+  if (soname_regex_prop)
>+    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
>
>   ini::simple_property_sptr soname_not_regex_prop =
>     is_simple_property(section.find_property("soname_not_regexp"));
>-  string soname_not_regex_str =
>-    soname_not_regex_prop
>-    ? soname_not_regex_prop->get_value()->as_string()
>-    : "";
>+  regex_t_sptr soname_not_regex;
>+  if (soname_not_regex_prop)
>+    soname_not_regex =
>+      regex::compile(soname_not_regex_prop->get_value()->as_string());
>
>   ini::simple_property_sptr name_regex_prop =
>     is_simple_property(section.find_property("name_regexp"));
>-  string name_regex_str = name_regex_prop
>-    ? name_regex_prop->get_value()->as_string()
>-    : "";
>+  regex_t_sptr name_regex;
>+  if (name_regex_prop)
>+    name_regex = regex::compile(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()
>-    : "";
>+  regex_t_sptr name_not_regex;
>+  if (name_not_regex_prop)
>+    name_not_regex =
>+      regex::compile(name_not_regex_prop->get_value()->as_string());
>
>   ini::simple_property_sptr name_prop =
>     is_simple_property(section.find_property("name"));
>@@ -1622,9 +1620,10 @@ read_type_suppression(const ini::config::section& section)
>
>   ini::simple_property_sptr srcloc_not_regexp_prop =
>     is_simple_property(section.find_property("source_location_not_regexp"));
>-  string srcloc_not_regexp_str;
>+  regex_t_sptr srcloc_not_regex;
>   if (srcloc_not_regexp_prop)
>-    srcloc_not_regexp_str = srcloc_not_regexp_prop->get_value()->as_string();
>+    srcloc_not_regex =
>+      regex::compile(srcloc_not_regexp_prop->get_value()->as_string());
>
>   bool consider_type_kind = false;
>   type_suppression::type_kind type_kind = type_suppression::UNKNOWN_TYPE_KIND;
>@@ -1831,7 +1830,7 @@ read_type_suppression(const ini::config::section& section)
> 	changed_enumerator_names.push_back(p->get_value()->as_string());
>     }
>
>-  result.reset(new type_suppression(label_str, name_regex_str, name_str));
>+  result.reset(new type_suppression(label_str, name_regex, name_str));
>
>   if (consider_type_kind)
>     {
>@@ -1848,31 +1847,31 @@ read_type_suppression(const ini::config::section& section)
>   if (consider_data_member_insertion)
>     result->set_data_member_insertion_ranges(insert_ranges);
>
>-  if (!name_not_regex_str.empty())
>-    result->set_type_name_not_regex_str(name_not_regex_str);
>+  if (name_not_regex)
>+    result->set_type_name_not_regex(name_not_regex);
>
>-  if (!file_name_regex_str.empty())
>-    result->set_file_name_regex_str(file_name_regex_str);
>+  if (file_name_regex)
>+    result->set_file_name_regex(file_name_regex);
>
>-  if (!file_name_not_regex_str.empty())
>-    result->set_file_name_not_regex_str(file_name_not_regex_str);
>+  if (file_name_not_regex)
>+    result->set_file_name_not_regex(file_name_not_regex);
>
>-  if (!soname_regex_str.empty())
>-    result->set_soname_regex_str(soname_regex_str);
>+  if (soname_regex)
>+    result->set_soname_regex(soname_regex);
>
>-  if (!soname_not_regex_str.empty())
>-    result->set_soname_not_regex_str(soname_not_regex_str);
>+  if (soname_not_regex)
>+    result->set_soname_not_regex(soname_not_regex);
>
>   if (!srcloc_not_in.empty())
>     result->set_source_locations_to_keep(srcloc_not_in);
>
>-  if (!srcloc_not_regexp_str.empty())
>-    result->set_source_location_to_keep_regex_str(srcloc_not_regexp_str);
>+  if (srcloc_not_regex)
>+    result->set_source_location_to_keep_regex(srcloc_not_regex);
>
>   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
>-      && ((!name_regex_str.empty()
>+      && ((name_regex
> 	   || !name_str.empty()
>-	   || !srcloc_not_regexp_str.empty()
>+	   || srcloc_not_regex
> 	   || !srcloc_not_in.empty())))
>     result->set_drops_artifact_from_ir(true);
>
>@@ -1898,7 +1897,7 @@ read_type_suppression(const ini::config::section& section)
> /// account only if the parameter @p tn is empty.
> function_suppression::parameter_spec::parameter_spec(size_t i,
> 						     const string& tn,
>-						     const string& tn_regex)
>+						     const regex_t_sptr& tn_regex)
>   : priv_(new priv(i, tn, tn_regex))
> {}
>
>@@ -1943,9 +1942,9 @@ function_suppression::parameter_spec::set_parameter_type_name(const string& tn)
> /// empty.
> ///
> /// @return the regular expression or the parameter type name.
>-const string&
>-function_suppression::parameter_spec::get_parameter_type_name_regex_str() const
>-{return priv_->type_name_regex_str_;}
>+const regex_t_sptr&
>+function_suppression::parameter_spec::get_parameter_type_name_regex() const
>+{return priv_->type_name_regex_;}
>
> /// Setter for the regular expression that defines a set of type names
> /// for the parameter designated by this specification.
>@@ -1955,12 +1954,12 @@ function_suppression::parameter_spec::get_parameter_type_name_regex_str() const
> /// function_suppression::parameter_spec::get_parameter_type_name() is
> /// empty.
> ///
>-/// @param type_name_regex_str the new type name regular expression to
>+/// @param type_name_regex the new type name regular expression to
> /// set.
> void
>-function_suppression::parameter_spec::set_parameter_type_name_regex_str
>-(const string& type_name_regex_str)
>-{priv_->type_name_regex_str_ = type_name_regex_str;}
>+function_suppression::parameter_spec::set_parameter_type_name_regex
>+(const regex_t_sptr& type_name_regex)
>+{priv_->type_name_regex_ = type_name_regex;}
>
> /// Default constructor for the @ref function_suppression type.
> ///
>@@ -2028,14 +2027,14 @@ function_suppression::function_suppression()
> /// case it's ignored at evaluation time.
> function_suppression::function_suppression(const string&		label,
> 					   const string&		name,
>-					   const string&		nr,
>+					   const regex_t_sptr&		nr,
> 					   const string&		ret_tn,
>-					   const string&		ret_tr,
>+					   const regex_t_sptr&		ret_tr,
> 					   parameter_specs_type&	ps,
> 					   const string&		sym_n,
>-					   const string&		sym_nr,
>+					   const regex_t_sptr&		sym_nr,
> 					   const string&		sym_v,
>-					   const string&		sym_vr)
>+					   const regex_t_sptr&		sym_vr)
>   : suppression_base(label),
>     priv_(new priv(name, nr, ret_tn, ret_tr, ps,
> 		   sym_n, sym_nr, sym_v, sym_vr))
>@@ -2103,9 +2102,9 @@ function_suppression::set_name(const string& n)
> ///
> /// @return the regular expression for the possible names of the
> /// function(s).
>-const string&
>-function_suppression::get_name_regex_str() const
>-{return priv_->name_regex_str_;}
>+const regex_t_sptr&
>+function_suppression::get_name_regex() const
>+{return priv_->name_regex_;}
>
> /// Setter for a regular expression for a family of names of functions
> /// the user wants the current specification to designate.
>@@ -2113,8 +2112,8 @@ function_suppression::get_name_regex_str() const
> /// @param r the new the regular expression for the possible names of
> /// the function(s).
> void
>-function_suppression::set_name_regex_str(const string& r)
>-{priv_->name_regex_str_ = r;}
>+function_suppression::set_name_regex(const regex_t_sptr& r)
>+{priv_->name_regex_ = r;}
>
> /// Getter for a regular expression of a family of names of functions
> /// the user wants the current specification to designate the negation
>@@ -2122,9 +2121,9 @@ function_suppression::set_name_regex_str(const string& r)
> ///
> /// @return the regular expression for the possible names of the
> /// function(s).
>-const string&
>-function_suppression::get_name_not_regex_str() const
>-{return priv_->name_not_regex_str_;}
>+const regex_t_sptr&
>+function_suppression::get_name_not_regex() const
>+{return priv_->name_not_regex_;}
>
> /// Setter for a regular expression for a family of names of functions
> /// the user wants the current specification to designate the negation
>@@ -2133,8 +2132,8 @@ function_suppression::get_name_not_regex_str() const
> /// @param r the new the regular expression for the possible names of
> /// the function(s).
> void
>-function_suppression::set_name_not_regex_str(const string& r)
>-{priv_->name_not_regex_str_ = r;}
>+function_suppression::set_name_not_regex(const regex_t_sptr& r)
>+{priv_->name_not_regex_ = r;}
>
> /// Getter for the name of the return type of the function the user
> /// wants this specification to designate.  This property might be
>@@ -2166,9 +2165,9 @@ function_suppression::set_return_type_name(const string& tr)
> ///
> /// @return the regular expression for the possible names of the
> /// return types of the function(s).
>-const string&
>-function_suppression::get_return_type_regex_str() const
>-{return priv_->return_type_regex_str_;}
>+const regex_t_sptr&
>+function_suppression::get_return_type_regex() const
>+{return priv_->return_type_regex_;}
>
> /// Setter for a regular expression for a family of return type names
> /// for functions the user wants the current specification to
>@@ -2183,8 +2182,8 @@ function_suppression::get_return_type_regex_str() const
> /// @param r the new regular expression for the possible names of the
> /// return types of the function(s) to set.
> void
>-function_suppression::set_return_type_regex_str(const string& r)
>-{priv_->return_type_regex_str_ = r;}
>+function_suppression::set_return_type_regex(const regex_t_sptr& r)
>+{priv_->return_type_regex_ = r;}
>
> /// Getter for a vector of parameter specifications to specify
> /// properties of the parameters of the functions the user wants this
>@@ -2252,9 +2251,9 @@ function_suppression::set_symbol_name(const string& n)
> ///
> /// @return the regular expression for a family of names of symbols of
> /// functions to designate.
>-const string&
>-function_suppression::get_symbol_name_regex_str() const
>-{return priv_->symbol_name_regex_str_;}
>+const regex_t_sptr&
>+function_suppression::get_symbol_name_regex() const
>+{return priv_->symbol_name_regex_;}
>
> /// Setter for a regular expression for a family of names of symbols
> /// of functions the user wants this specification to designate.
>@@ -2269,8 +2268,8 @@ function_suppression::get_symbol_name_regex_str() const
> /// @param r the new regular expression for a family of names of
> /// symbols of functions to set.
> void
>-function_suppression::set_symbol_name_regex_str(const string& r)
>-{priv_->symbol_name_regex_str_ = r;}
>+function_suppression::set_symbol_name_regex(const regex_t_sptr& r)
>+{priv_->symbol_name_regex_ = r;}
>
> /// Getter for a regular expression for a family of names of symbols
> /// of functions the user wants this specification to designate.
>@@ -2285,11 +2284,11 @@ function_suppression::set_symbol_name_regex_str(const string& r)
> /// This property might be empty, in which case it's ignored at
> /// evaluation time.
> ///
>-/// @return the regular expression string for a family of names of
>+/// @return the regular expression for a family of names of
> /// symbols that is to be *NOT* suppressed by this suppression specification.
>-const string&
>-function_suppression::get_symbol_name_not_regex_str() const
>-{return priv_->symbol_name_not_regex_str_;}
>+const regex_t_sptr&
>+function_suppression::get_symbol_name_not_regex() const
>+{return priv_->symbol_name_not_regex_;}
>
> /// Setter for a regular expression for a family of names of symbols
> /// of functions the user wants this specification to designate.
>@@ -2304,12 +2303,12 @@ function_suppression::get_symbol_name_not_regex_str() const
> /// This property might be empty, in which case it's ignored at
> /// evaluation time.
> ///
>-/// @param the new regular expression string for a family of names of
>+/// @param the new regular expression for a family of names of
> /// symbols that is to be *NOT* suppressed by this suppression
> /// specification.
> void
>-function_suppression::set_symbol_name_not_regex_str(const string& r)
>-{priv_->symbol_name_not_regex_str_ = r;}
>+function_suppression::set_symbol_name_not_regex(const regex_t_sptr& r)
>+{priv_->symbol_name_not_regex_ = r;}
>
> /// Getter for the name of the version of the symbol of the function
> /// the user wants this specification to designate.
>@@ -2344,9 +2343,9 @@ function_suppression::set_symbol_version(const string& v)
> ///
> /// @return the regular expression for the versions of symbols of
> /// functions to designate.
>-const string&
>-function_suppression::get_symbol_version_regex_str() const
>-{return priv_->symbol_version_regex_str_;}
>+const regex_t_sptr&
>+function_suppression::get_symbol_version_regex() const
>+{return priv_->symbol_version_regex_;}
>
> /// Setter for a regular expression for a family of versions of
> /// symbols of functions the user wants the current specification to
>@@ -2360,8 +2359,8 @@ function_suppression::get_symbol_version_regex_str() const
> /// @param the new regular expression for the versions of symbols of
> /// functions to designate.
> void
>-function_suppression::set_symbol_version_regex_str(const string& r)
>-{priv_->symbol_version_regex_str_ = r;}
>+function_suppression::set_symbol_version_regex(const regex_t_sptr& r)
>+{priv_->symbol_version_regex_ = r;}
>
> /// Getter for the "allow_other_aliases" property of the function
> /// suppression specification.
>@@ -2764,7 +2763,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
>       if (sym_name != get_symbol_name())
> 	return false;
>     }
>-  else if (!get_symbol_name_regex_str().empty())
>+  else if (get_symbol_name_regex())
>     {
>       const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
>       if (symbol_name_regex && !regex::match(symbol_name_regex, sym_name))
>@@ -2779,7 +2778,7 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
>       if (sym_version != get_symbol_version())
> 	return false;
>     }
>-  else if (!get_symbol_version_regex_str().empty())
>+  else if (get_symbol_version_regex())
>     {
>       const regex_t_sptr symbol_version_regex =
> 	priv_->get_symbol_version_regex();
>@@ -3085,10 +3084,10 @@ read_parameter_spec_from_string(const string& str)
>
>   if (!index_str.empty() || !type_name.empty())
>     {
>-      std::string type_name_regex;
>+      regex_t_sptr type_name_regex;
>       if (is_regex)
> 	{
>-	  type_name_regex = type_name;
>+	  type_name_regex = regex::compile(type_name);
> 	  type_name.clear();
> 	}
>       function_suppression::parameter_spec* p =
>@@ -3138,27 +3137,30 @@ read_function_suppression(const ini::config::section& section)
>
>   ini::simple_property_sptr file_name_regex_prop =
>     is_simple_property(section.find_property("file_name_regexp"));
>-  string file_name_regex_str =
>-    file_name_regex_prop ? file_name_regex_prop->get_value()->as_string() : "";
>+  regex_t_sptr file_name_regex;
>+  if (file_name_regex_prop)
>+    file_name_regex =
>+      regex::compile(file_name_regex_prop->get_value()->as_string());
>
>   ini::simple_property_sptr file_name_not_regex_prop =
>     is_simple_property(section.find_property("file_name_not_regexp"));
>-  string file_name_not_regex_str =
>-    file_name_not_regex_prop
>-    ? file_name_not_regex_prop->get_value()->as_string()
>-    : "";
>+  regex_t_sptr file_name_not_regex;
>+  if (file_name_not_regex_prop)
>+    file_name_not_regex =
>+      regex::compile(file_name_not_regex_prop->get_value()->as_string());
>
>   ini::simple_property_sptr soname_regex_prop =
>     is_simple_property(section.find_property("soname_regexp"));
>-  string soname_regex_str =
>-    soname_regex_prop ? soname_regex_prop->get_value()->as_string() : "";
>+  regex_t_sptr soname_regex;
>+  if (soname_regex_prop)
>+    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
>
>   ini::simple_property_sptr soname_not_regex_prop =
>     is_simple_property(section.find_property("soname_not_regexp"));
>-  string soname_not_regex_str =
>-    soname_not_regex_prop
>-    ? soname_not_regex_prop->get_value()->as_string()
>-    : "";
>+  regex_t_sptr soname_not_regex;
>+  if (soname_not_regex_prop)
>+    soname_not_regex =
>+      regex::compile(soname_not_regex_prop->get_value()->as_string());
>
>   ini::simple_property_sptr name_prop =
>     is_simple_property(section.find_property("name"));
>@@ -3168,15 +3170,16 @@ read_function_suppression(const ini::config::section& section)
>
>   ini::simple_property_sptr name_regex_prop =
>     is_simple_property(section.find_property("name_regexp"));
>-  string name_regex_str = name_regex_prop
>-    ? name_regex_prop->get_value()->as_string()
>-    : "";
>+  regex_t_sptr name_regex;
>+  if (name_regex_prop)
>+    name_regex = regex::compile(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()
>-    : "";
>+  regex_t_sptr name_not_regex;
>+  if (name_not_regex_prop)
>+    name_not_regex =
>+      regex::compile(name_not_regex_prop->get_value()->as_string());
>
>   ini::simple_property_sptr return_type_name_prop =
>     is_simple_property(section.find_property("return_type_name"));
>@@ -3186,9 +3189,10 @@ read_function_suppression(const ini::config::section& section)
>
>   ini::simple_property_sptr return_type_regex_prop =
>     is_simple_property(section.find_property("return_type_regexp"));
>-  string return_type_regex_str = return_type_regex_prop
>-    ? return_type_regex_prop->get_value()->as_string()
>-    : "";
>+  regex_t_sptr return_type_regex;
>+  if (return_type_regex_prop)
>+    return_type_regex =
>+      regex::compile(return_type_regex_prop->get_value()->as_string());
>
>   ini::simple_property_sptr sym_name_prop =
>     is_simple_property(section.find_property("symbol_name"));
>@@ -3198,15 +3202,17 @@ read_function_suppression(const ini::config::section& section)
>
>   ini::simple_property_sptr sym_name_regex_prop =
>     is_simple_property(section.find_property("symbol_name_regexp"));
>-  string sym_name_regex_str = sym_name_regex_prop
>-    ? sym_name_regex_prop->get_value()->as_string()
>-    : "";
>+  regex_t_sptr sym_name_regex;
>+  if (sym_name_regex_prop)
>+    sym_name_regex =
>+      regex::compile(sym_name_regex_prop->get_value()->as_string());
>
>   ini::simple_property_sptr sym_name_not_regex_prop =
>     is_simple_property(section.find_property("symbol_name_not_regexp"));
>-  string sym_name_not_regex_str = sym_name_not_regex_prop
>-    ? sym_name_not_regex_prop->get_value()->as_string()
>-    : "";
>+  regex_t_sptr sym_name_not_regex;
>+  if (sym_name_not_regex_prop)
>+    sym_name_not_regex =
>+      regex::compile(sym_name_not_regex_prop->get_value()->as_string());
>
>   ini::simple_property_sptr sym_ver_prop =
>     is_simple_property(section.find_property("symbol_version"));
>@@ -3216,9 +3222,10 @@ read_function_suppression(const ini::config::section& section)
>
>   ini::simple_property_sptr sym_ver_regex_prop =
>     is_simple_property(section.find_property("symbol_version_regexp"));
>-  string sym_ver_regex_str = sym_ver_regex_prop
>-    ? sym_ver_regex_prop->get_value()->as_string()
>-    : "";
>+  regex_t_sptr sym_ver_regex;
>+  if (sym_ver_regex_prop)
>+    sym_ver_regex =
>+      regex::compile(sym_ver_regex_prop->get_value()->as_string());
>
>   ini::simple_property_sptr allow_other_aliases_prop =
>     is_simple_property(section.find_property("allow_other_aliases"));
>@@ -3243,22 +3250,22 @@ read_function_suppression(const ini::config::section& section)
>
>   result.reset(new function_suppression(label_str,
> 					name,
>-					name_regex_str,
>+					name_regex,
> 					return_type_name,
>-					return_type_regex_str,
>+					return_type_regex,
> 					parms,
> 					sym_name,
>-					sym_name_regex_str,
>+					sym_name_regex,
> 					sym_version,
>-					sym_ver_regex_str));
>+					sym_ver_regex));
>
>   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
>       && (!name.empty()
>-	  || !name_regex_str.empty()
>-	  || !name_not_regex_str.empty()
>+	  || name_regex
>+	  || name_not_regex
> 	  || !sym_name.empty()
>-	  || !sym_name_regex_str.empty()
>-	  || !sym_name_not_regex_str.empty()))
>+	  || sym_name_regex
>+	  || sym_name_not_regex))
>     result->set_drops_artifact_from_ir(true);
>
>   if (!change_kind_str.empty())
>@@ -3269,23 +3276,23 @@ read_function_suppression(const ini::config::section& section)
>     result->set_allow_other_aliases(allow_other_aliases == "yes"
> 				    || allow_other_aliases == "true");
>
>-  if (!name_not_regex_str.empty())
>-    result->set_name_not_regex_str(name_not_regex_str);
>+  if (name_not_regex)
>+    result->set_name_not_regex(name_not_regex);
>
>-  if (!sym_name_not_regex_str.empty())
>-    result->set_symbol_name_not_regex_str(sym_name_not_regex_str);
>+  if (sym_name_not_regex)
>+    result->set_symbol_name_not_regex(sym_name_not_regex);
>
>-  if (!file_name_regex_str.empty())
>-    result->set_file_name_regex_str(file_name_regex_str);
>+  if (file_name_regex)
>+    result->set_file_name_regex(file_name_regex);
>
>-  if (!file_name_not_regex_str.empty())
>-    result->set_file_name_not_regex_str(file_name_not_regex_str);
>+  if (file_name_not_regex)
>+    result->set_file_name_not_regex(file_name_not_regex);
>
>-  if (!soname_regex_str.empty())
>-    result->set_soname_regex_str(soname_regex_str);
>+  if (soname_regex)
>+    result->set_soname_regex(soname_regex);
>
>-  if (!soname_not_regex_str.empty())
>-    result->set_soname_not_regex_str(soname_not_regex_str);
>+  if (soname_not_regex)
>+    result->set_soname_not_regex(soname_not_regex);
>
>   return result;
> }
>@@ -3305,7 +3312,7 @@ read_function_suppression(const ini::config::section& section)
> /// specification to designate.  This parameter might be empty, in
> /// which case it's ignored at evaluation time.
> ///
>-/// @param name_regex_str if @p name is empty, this parameter is a
>+/// @param name_regex if @p name is empty, this parameter is a
> /// regular expression for a family of names of variables the user
> /// wants the current specification to designate.  If @p name is not
> /// empty, then this parameter is ignored at evaluation time.  This
>@@ -3339,7 +3346,7 @@ read_function_suppression(const ini::config::section& section)
> /// wants the current specification to designate.  This parameter
> /// might be empty, in which case it's ignored at evaluation time.
> ///
>-/// @param type_name_regex_str if @p type_name is empty, then this
>+/// @param type_name_regex if @p type_name is empty, then this
> /// parameter is a regular expression for a family of type names of
> /// variables the user wants the current specification to designate.
> /// If @p type_name is not empty, then this parameter is ignored at
>@@ -3347,18 +3354,18 @@ read_function_suppression(const ini::config::section& section)
> /// ignored at evaluation time.
> variable_suppression::variable_suppression(const string& label,
> 					   const string& name,
>-					   const string& name_regex_str,
>+					   const regex_t_sptr& name_regex,
> 					   const string& symbol_name,
>-					   const string& symbol_name_regex_str,
>+					   const regex_t_sptr& symbol_name_regex,
> 					   const string& symbol_version,
>-					   const string& symbol_version_regex,
>+					   const regex_t_sptr& symbol_version_regex,
> 					   const string& type_name,
>-					   const string& type_name_regex_str)
>+					   const regex_t_sptr& type_name_regex)
>   : suppression_base(label),
>-    priv_(new priv(name, name_regex_str,
>-		   symbol_name, symbol_name_regex_str,
>+    priv_(new priv(name, name_regex,
>+		   symbol_name, symbol_name_regex,
> 		   symbol_version, symbol_version_regex,
>-		   type_name, type_name_regex_str))
>+		   type_name, type_name_regex))
> {}
>
> /// Virtual destructor for the @erf variable_suppression type.
>@@ -3428,9 +3435,9 @@ variable_suppression::set_name(const string& n)
> /// which case it's ignored at evaluation time.
> ///
> /// @return the regular expression for the variable name.
>-const string&
>-variable_suppression::get_name_regex_str() const
>-{return priv_->name_regex_str_;}
>+const regex_t_sptr&
>+variable_suppression::get_name_regex() const
>+{return priv_->name_regex_;}
>
> /// Setter for the regular expression for a family of names of
> /// variables the user wants the current specification to designate.
>@@ -3441,22 +3448,22 @@ variable_suppression::get_name_regex_str() const
> ///
> /// @param r the new regular expression for the variable name.
> void
>-variable_suppression::set_name_regex_str(const string& r)
>-{priv_->name_regex_str_ = r;}
>+variable_suppression::set_name_regex(const regex_t_sptr& r)
>+{priv_->name_regex_ = r;}
>
> /// Getter for the "name_not_regexp" property of the specification.
> ///
> /// @return the value of the "name_not_regexp" property.
>-const string&
>-variable_suppression::get_name_not_regex_str() const
>-{return priv_->name_not_regex_str_;}
>+const regex_t_sptr&
>+variable_suppression::get_name_not_regex() const
>+{return priv_->name_not_regex_;}
>
> /// Setter for the "name_not_regexp" property of the specification.
> ///
> /// @param r the new value of the "name_not_regexp" property.
> void
>-variable_suppression::set_name_not_regex_str(const string& r)
>-{priv_->name_not_regex_str_ = r;}
>+variable_suppression::set_name_not_regex(const regex_t_sptr& r)
>+{priv_->name_not_regex_ = r;}
>
> /// Getter for the name of the symbol of the variable the user wants
> /// the current specification to designate.
>@@ -3489,9 +3496,9 @@ variable_suppression::set_symbol_name(const string& n)
> /// empty.
> ///
> /// @return the regular expression for a symbol name of the variable.
>-const string&
>-variable_suppression::get_symbol_name_regex_str() const
>-{return priv_->symbol_name_regex_str_;}
>+const regex_t_sptr&
>+variable_suppression::get_symbol_name_regex() const
>+{return priv_->symbol_name_regex_;}
>
> /// Setter of the regular expression for a family of symbol names of
> /// the variables this specification is about to designate.
>@@ -3503,8 +3510,8 @@ variable_suppression::get_symbol_name_regex_str() const
> ///
> /// @param r the regular expression for a symbol name of the variable.
> void
>-variable_suppression::set_symbol_name_regex_str(const string& r)
>-{priv_->symbol_name_regex_str_ = r;}
>+variable_suppression::set_symbol_name_regex(const regex_t_sptr& r)
>+{priv_->symbol_name_regex_ = r;}
>
> /// Getter for a regular expression for a family of names of symbols
> /// of variables the user wants this specification to designate.
>@@ -3519,11 +3526,11 @@ variable_suppression::set_symbol_name_regex_str(const string& r)
> /// This property might be empty, in which case it's ignored at
> /// evaluation time.
> ///
>-/// @return the regular expression string for a family of names of
>+/// @return the regular expression for a family of names of
> /// symbols that is to be *NOT* suppressed by this suppression specification.
>-const string&
>-variable_suppression::get_symbol_name_not_regex_str() const
>-{return priv_->symbol_name_not_regex_str_;}
>+const regex_t_sptr&
>+variable_suppression::get_symbol_name_not_regex() const
>+{return priv_->symbol_name_not_regex_;}
>
> /// Setter for a regular expression for a family of names of symbols
> /// of variables the user wants this specification to designate.
>@@ -3538,12 +3545,12 @@ variable_suppression::get_symbol_name_not_regex_str() const
> /// This property might be empty, in which case it's ignored at
> /// evaluation time.
> ///
>-/// @param the new regular expression string for a family of names of
>+/// @param the new regular expression for a family of names of
> /// symbols that is to be *NOT* suppressed by this suppression
> /// specification.
> void
>-variable_suppression::set_symbol_name_not_regex_str(const string& r)
>-{priv_->symbol_name_not_regex_str_ = r;}
>+variable_suppression::set_symbol_name_not_regex(const regex_t_sptr& r)
>+{priv_->symbol_name_not_regex_ = r;}
>
> /// Getter for the version of the symbol of the variable the user
> /// wants the current specification to designate.  This property might
>@@ -3571,9 +3578,9 @@ variable_suppression::set_symbol_version(const string& v)
> ///
> /// @return the regular expression of the symbol version of the
> /// variable.
>-const string&
>-variable_suppression::get_symbol_version_regex_str() const
>-{return priv_->symbol_version_regex_str_;}
>+const regex_t_sptr&
>+variable_suppression::get_symbol_version_regex() const
>+{return priv_->symbol_version_regex_;}
>
> /// Setter of the regular expression for a family of versions of
> /// symbol for the variables the user wants the current specification
>@@ -3584,8 +3591,8 @@ variable_suppression::get_symbol_version_regex_str() const
> /// @param v the new regular expression of the symbol version of the
> /// variable.
> void
>-variable_suppression::set_symbol_version_regex_str(const string& r)
>-{priv_->symbol_version_regex_str_ = r;}
>+variable_suppression::set_symbol_version_regex(const regex_t_sptr& r)
>+{priv_->symbol_version_regex_ = r;}
>
> /// Getter for the name of the type of the variable the user wants the
> /// current specification to designate.
>@@ -3618,9 +3625,9 @@ variable_suppression::set_type_name(const string& n)
> /// empty, in which case it's ignored at evaluation time.
> ///
> /// @return the regular expression of the variable type name.
>-const string&
>-variable_suppression::get_type_name_regex_str() const
>-{return priv_->type_name_regex_str_;}
>+const regex_t_sptr&
>+variable_suppression::get_type_name_regex() const
>+{return priv_->type_name_regex_;}
>
> /// Setter for the regular expression for a family of type names of
> /// variables the user wants the current specification to designate.
>@@ -3632,8 +3639,8 @@ variable_suppression::get_type_name_regex_str() const
> ///
> /// @param r the regular expression of the variable type name.
> void
>-variable_suppression::set_type_name_regex_str(const string& r)
>-{priv_->type_name_regex_str_ = r;}
>+variable_suppression::set_type_name_regex(const regex_t_sptr& r)
>+{priv_->type_name_regex_ = r;}
>
> /// Evaluate this suppression specification on a given diff node and
> /// say if the diff node should be suppressed or not.
>@@ -3862,7 +3869,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
>       if (get_symbol_name() != sym_name)
> 	return false;
>     }
>-  else if (!get_symbol_name_regex_str().empty())
>+  else if (get_symbol_name_regex())
>     {
>       const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
>       if (sym_name_regex && !regex::match(sym_name_regex, sym_name))
>@@ -3877,7 +3884,7 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
>       if (get_symbol_version() != sym_version)
> 	return false;
>     }
>-  else if (!get_symbol_version_regex_str().empty())
>+  else if (get_symbol_version_regex())
>     {
>       const regex_t_sptr symbol_version_regex =
> 	priv_->get_symbol_version_regex();
>@@ -3995,27 +4002,30 @@ read_variable_suppression(const ini::config::section& section)
>
>   ini::simple_property_sptr file_name_regex_prop =
>     is_simple_property(section.find_property("file_name_regexp"));
>-  string file_name_regex_str =
>-    file_name_regex_prop ? file_name_regex_prop->get_value()->as_string() : "";
>+  regex_t_sptr file_name_regex;
>+  if (file_name_regex_prop)
>+    file_name_regex =
>+      regex::compile(file_name_regex_prop->get_value()->as_string());
>
>  ini::simple_property_sptr file_name_not_regex_prop =
>-    is_simple_property(section.find_property("file_name_not_regexp"));
>-  string file_name_not_regex_str =
>-    file_name_not_regex_prop
>-    ? file_name_not_regex_prop->get_value()->as_string()
>-    : "";
>+  is_simple_property(section.find_property("file_name_not_regexp"));
>+ regex_t_sptr file_name_not_regex;
>+ if (file_name_not_regex_prop)
>+   file_name_not_regex =
>+     regex::compile(file_name_not_regex_prop->get_value()->as_string());
>
>   ini::simple_property_sptr soname_regex_prop =
>     is_simple_property(section.find_property("soname_regexp"));
>-  string soname_regex_str =
>-    soname_regex_prop ? soname_regex_prop->get_value()->as_string() : "";
>+  regex_t_sptr soname_regex;
>+  if (soname_regex_prop)
>+    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
>
>   ini::simple_property_sptr soname_not_regex_prop =
>     is_simple_property(section.find_property("soname_not_regexp"));
>-  string soname_not_regex_str =
>-    soname_not_regex_prop
>-    ? soname_not_regex_prop->get_value()->as_string()
>-    : "";
>+  regex_t_sptr soname_not_regex;
>+  if (soname_not_regex_prop)
>+    soname_not_regex =
>+      regex::compile(soname_not_regex_prop->get_value()->as_string());
>
>   ini::simple_property_sptr name_prop =
>     is_simple_property(section.find_property("name"));
>@@ -4025,15 +4035,16 @@ read_variable_suppression(const ini::config::section& section)
>
>   ini::simple_property_sptr name_regex_prop =
>     is_simple_property(section.find_property("name_regexp"));
>-  string name_regex_str = (name_regex_prop
>-			   ? name_regex_prop->get_value()->as_string()
>-			   : "");
>+  regex_t_sptr name_regex;
>+  if (name_regex_prop)
>+    name_regex = regex::compile(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()
>-    : "";
>+  regex_t_sptr name_not_regex;
>+  if (name_not_regex_prop)
>+    name_not_regex =
>+      regex::compile(name_not_regex_prop->get_value()->as_string());
>
>   ini::simple_property_sptr sym_name_prop =
>     is_simple_property(section.find_property("symbol_name"));
>@@ -4043,15 +4054,17 @@ read_variable_suppression(const ini::config::section& section)
>
>   ini::simple_property_sptr sym_name_regex_prop =
>     is_simple_property(section.find_property("symbol_name_regexp"));
>-  string symbol_name_regex_str = sym_name_regex_prop
>-    ? sym_name_regex_prop->get_value()->as_string()
>-    : "";
>+  regex_t_sptr symbol_name_regex;
>+  if (sym_name_regex_prop)
>+    symbol_name_regex =
>+      regex::compile(sym_name_regex_prop->get_value()->as_string());
>
>   ini::simple_property_sptr sym_name_not_regex_prop =
>     is_simple_property(section.find_property("symbol_name_not_regexp"));
>-  string symbol_name_not_regex_str = sym_name_not_regex_prop
>-    ? sym_name_not_regex_prop->get_value()->as_string()
>-    : "";
>+  regex_t_sptr symbol_name_not_regex;
>+  if (sym_name_not_regex_prop)
>+    symbol_name_not_regex =
>+      regex::compile(sym_name_not_regex_prop->get_value()->as_string());
>
>   ini::simple_property_sptr sym_version_prop =
>     is_simple_property(section.find_property("symbol_version"));
>@@ -4061,9 +4074,10 @@ read_variable_suppression(const ini::config::section& section)
>
>   ini::simple_property_sptr sym_version_regex_prop =
>     is_simple_property(section.find_property("symbol_version_regexp"));
>-  string symbol_version_regex_str = sym_version_regex_prop
>-    ? sym_version_regex_prop->get_value()->as_string()
>-     : "";
>+  regex_t_sptr symbol_version_regex;
>+  if (sym_version_regex_prop)
>+    symbol_version_regex =
>+      regex::compile(sym_version_regex_prop->get_value()->as_string());
>
>   ini::simple_property_sptr type_name_prop =
>     is_simple_property(section.find_property("type_name"));
>@@ -4073,50 +4087,51 @@ read_variable_suppression(const ini::config::section& section)
>
>   ini::simple_property_sptr type_name_regex_prop =
>     is_simple_property(section.find_property("type_name_regexp"));
>-  string type_name_regex_str = type_name_regex_prop
>-    ? type_name_regex_prop->get_value()->as_string()
>-     : "";
>+  regex_t_sptr type_name_regex;
>+  if (type_name_regex_prop)
>+    type_name_regex =
>+      regex::compile(type_name_regex_prop->get_value()->as_string());
>
>   result.reset(new variable_suppression(label_str,
> 					name_str,
>-					name_regex_str,
>+					name_regex,
> 					symbol_name,
>-					symbol_name_regex_str,
>+					symbol_name_regex,
> 					symbol_version,
>-					symbol_version_regex_str,
>+					symbol_version_regex,
> 					type_name_str,
>-					type_name_regex_str));
>+					type_name_regex));
>
>   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
>       && (!name_str.empty()
>-	  || !name_regex_str.empty()
>-	  || !name_not_regex_str.empty()
>+	  || name_regex
>+	  || name_not_regex
> 	  || !symbol_name.empty()
>-	  || !symbol_name_regex_str.empty()
>-	  || !symbol_name_not_regex_str.empty()))
>+	  || symbol_name_regex
>+	  || symbol_name_not_regex))
>     result->set_drops_artifact_from_ir(true);
>
>-  if (!name_not_regex_str.empty())
>-    result->set_name_not_regex_str(name_not_regex_str);
>+  if (name_not_regex)
>+    result->set_name_not_regex(name_not_regex);
>
>-  if (!symbol_name_not_regex_str.empty())
>-    result->set_symbol_name_not_regex_str(symbol_name_not_regex_str);
>+  if (symbol_name_not_regex)
>+    result->set_symbol_name_not_regex(symbol_name_not_regex);
>
>   if (!change_kind_str.empty())
>     result->set_change_kind
>       (variable_suppression::parse_change_kind(change_kind_str));
>
>-  if (!file_name_regex_str.empty())
>-    result->set_file_name_regex_str(file_name_regex_str);
>+  if (file_name_regex)
>+    result->set_file_name_regex(file_name_regex);
>
>-  if (!file_name_not_regex_str.empty())
>-    result->set_file_name_not_regex_str(file_name_not_regex_str);
>+  if (file_name_not_regex)
>+    result->set_file_name_not_regex(file_name_not_regex);
>
>-  if (!soname_regex_str.empty())
>-    result->set_soname_regex_str(soname_regex_str);
>+  if (soname_regex)
>+    result->set_soname_regex(soname_regex);
>
>-  if (!soname_not_regex_str.empty())
>-    result->set_soname_not_regex_str(soname_not_regex_str);
>+  if (soname_not_regex)
>+    result->set_soname_not_regex(soname_not_regex);
>
>   return result;
> }
>@@ -4129,21 +4144,21 @@ read_variable_suppression(const ini::config::section& section)
> ///
> /// @param label the label of the suppression directive.
> ///
>-/// @param fname_regex_str the regular expression string that
>+/// @param fname_regex the regular expression that
> /// designates the file name that instances of @ref file_suppression
> /// should match.
> ///
>-/// @param fname_not_regex_str the regular expression string that
>+/// @param fname_not_regex the regular expression that
> /// designates the file name that instances of @ref file_suppression
> /// shoult *NOT* match.  In other words, this file_suppression should
> /// be activated if its file name does not match the regular
>-/// expression @p fname_not_regex_str.
>+/// expression @p fname_not_regex.
> file_suppression::file_suppression(const string& label,
>-				   const string& fname_regex_str,
>-				   const string& fname_not_regex_str)
>+				   const regex_t_sptr& fname_regex,
>+				   const regex_t_sptr& fname_not_regex)
>   : suppression_base(label,
>-		     fname_regex_str,
>-		     fname_not_regex_str)
>+		     fname_regex,
>+		     fname_not_regex)
> {}
>
> /// Test if instances of this @ref file_suppression suppresses a
>@@ -4223,41 +4238,44 @@ read_file_suppression(const ini::config::section& section)
>
>   ini::simple_property_sptr file_name_regex_prop =
>     is_simple_property(section.find_property("file_name_regexp"));
>-  string file_name_regex_str =
>-    file_name_regex_prop ? file_name_regex_prop->get_value()->as_string() : "";
>+  regex_t_sptr file_name_regex;
>+  if (file_name_regex_prop)
>+    file_name_regex =
>+      regex::compile(file_name_regex_prop->get_value()->as_string());
>
>  ini::simple_property_sptr file_name_not_regex_prop =
>     is_simple_property(section.find_property("file_name_not_regexp"));
>-  string file_name_not_regex_str =
>-    file_name_not_regex_prop
>-    ? file_name_not_regex_prop->get_value()->as_string()
>-    : "";
>+ regex_t_sptr file_name_not_regex;
>+ if (file_name_not_regex_prop)
>+   file_name_not_regex =
>+     regex::compile(file_name_not_regex_prop->get_value()->as_string());
>
>   ini::simple_property_sptr soname_regex_prop =
>     is_simple_property(section.find_property("soname_regexp"));
>-  string soname_regex_str =
>-    soname_regex_prop ? soname_regex_prop->get_value()->as_string() : "";
>+  regex_t_sptr soname_regex;
>+  if (soname_regex_prop)
>+    soname_regex = regex::compile(soname_regex_prop->get_value()->as_string());
>
>   ini::simple_property_sptr soname_not_regex_prop =
>     is_simple_property(section.find_property("soname_not_regexp"));
>-  string soname_not_regex_str =
>-    soname_not_regex_prop
>-    ? soname_not_regex_prop->get_value()->as_string()
>-    : "";
>+  regex_t_sptr soname_not_regex;
>+  if (soname_not_regex_prop)
>+    soname_not_regex =
>+      regex::compile(soname_not_regex_prop->get_value()->as_string());
>
>   result.reset(new file_suppression(label_str,
>-				    file_name_regex_str,
>-				    file_name_not_regex_str));
>+				    file_name_regex,
>+				    file_name_not_regex));
>
>-  if (!soname_regex_str.empty())
>+  if (soname_regex)
>     {
>-      result->set_soname_regex_str(soname_regex_str);
>+      result->set_soname_regex(soname_regex);
>       result->set_drops_artifact_from_ir(true);
>     }
>
>-  if (!soname_not_regex_str.empty())
>+  if (soname_not_regex)
>     {
>-      result->set_soname_not_regex_str(soname_not_regex_str);
>+      result->set_soname_not_regex(soname_not_regex);
>       result->set_drops_artifact_from_ir(true);
>     }
>
>diff --git a/src/abg-tools-utils.cc b/src/abg-tools-utils.cc
>index 11486a21..fe0de750 100644
>--- a/src/abg-tools-utils.cc
>+++ b/src/abg-tools-utils.cc
>@@ -1810,13 +1810,15 @@ handle_file_entry(const string& file_path,
> {
>   if (!suppr)
>     {
>-      suppr.reset(new type_suppression(get_private_types_suppr_spec_label(),
>-				       /*type_name_regexp=*/"",
>-				       /*type_name=*/""));
>+      suppr.reset(
>+	new type_suppression(get_private_types_suppr_spec_label(),
>+			     /*type_name_regexp=*/regex::regex_t_sptr(),
>+			     /*type_name=*/""));
>
>       // Types that are defined in system headers are usually
>       // OK to be considered as public types.
>-      suppr->set_source_location_to_keep_regex_str("^/usr/include/");
>+      regex::regex_t_sptr headers_regex = regex::compile("^/usr/include/");
>+      suppr->set_source_location_to_keep_regex(headers_regex);
>       suppr->set_is_artificial(true);
>     }
>
>@@ -2004,7 +2006,8 @@ gen_suppr_spec_from_kernel_abi_whitelists
>
>       // Build a regular expression representing the union of all
>       // the function and variable names expressed in the white list.
>-      const std::string regex = regex::generate_from_strings(whitelisted_names);
>+      regex::regex_t_sptr regex =
>+	regex::compile(regex::generate_from_strings(whitelisted_names));
>
>       // Build a suppression specification which *keeps* functions
>       // whose ELF symbols match the regular expression contained
>@@ -2013,7 +2016,7 @@ gen_suppr_spec_from_kernel_abi_whitelists
>       // match this regexp.
>       function_suppression_sptr fn_suppr(new function_suppression);
>       fn_suppr->set_label("whitelist");
>-      fn_suppr->set_symbol_name_not_regex_str(regex);
>+      fn_suppr->set_symbol_name_not_regex(regex);
>       fn_suppr->set_drops_artifact_from_ir(true);
>       result.push_back(fn_suppr);
>
>@@ -2024,7 +2027,7 @@ gen_suppr_spec_from_kernel_abi_whitelists
>       // match this regexp.
>       variable_suppression_sptr var_suppr(new variable_suppression);
>       var_suppr->set_label("whitelist");
>-      var_suppr->set_symbol_name_not_regex_str(regex);
>+      var_suppr->set_symbol_name_not_regex(regex);
>       var_suppr->set_drops_artifact_from_ir(true);
>       result.push_back(var_suppr);
>     }
>diff --git a/tests/test-kmi-whitelist.cc b/tests/test-kmi-whitelist.cc
>index bcc5adee..16cc1861 100644
>--- a/tests/test-kmi-whitelist.cc
>+++ b/tests/test-kmi-whitelist.cc
>@@ -29,10 +29,14 @@
> #include "lib/catch.hpp"
>
> #include "abg-fwd.h"
>-#include "abg-suppression.h"
>+#include "abg-regex.h"
> #include "abg-tools-utils.h"
>+#include "abg-suppression.h"
> #include "test-utils.h"
>
>+using abigail::regex::regex_t_sptr;
>+using abigail::regex::compile;
>+using abigail::regex::match;
> using abigail::tools_utils::gen_suppr_spec_from_kernel_abi_whitelists;
> using abigail::suppr::suppression_sptr;
> using abigail::suppr::suppressions_type;
>@@ -57,9 +61,30 @@ const static std::string whitelist_with_duplicate_entry
>     = std::string(abigail::tests::get_src_dir())
>       + "/tests/data/test-kmi-whitelist/whitelist-with-duplicate-entry";
>
>+// These are strings, not regexes, we cannot exhaustively check all
>+// strings, but we can do some sampling and match sure we haven't got
>+// the regex logic completely wrong.
>+static const char* const random_symbols[] =
>+{
>+  "",
>+  ".*",
>+  "^$",
>+  "test_symbol",
>+  "test-symbol",
>+  "test symbol",
>+  "Test Symbol",
>+  "est_symbo",
>+  ".*test_symbol.*",
>+  "test_symbol ",
>+  " test_symbol",
>+  " test_symbol ",
>+  "test_another_symbol",
>+  "$test_another_symbol",
>+};
>+
> void
> test_suppressions_are_consistent(const suppressions_type& suppr,
>-			    const std::string&	     expr)
>+				 const std::string&	  expr)
> {
>   REQUIRE(suppr.size() == 2);
>
>@@ -74,11 +99,32 @@ test_suppressions_are_consistent(const suppressions_type& suppr,
>   // same mode
>   REQUIRE(left->get_drops_artifact_from_ir()
> 	  == right->get_drops_artifact_from_ir());
>-  // same regex
>-  REQUIRE(left->get_symbol_name_not_regex_str()
>-     == right->get_symbol_name_not_regex_str());
>-  // regex as expected
>-  REQUIRE(left->get_symbol_name_not_regex_str() == expr);
>+
>+  // these parts of the symbol name matching should be absent
>+  REQUIRE(left->get_symbol_name().empty());
>+  REQUIRE(!left->get_symbol_name_regex());
>+  REQUIRE(right->get_symbol_name().empty());
>+  REQUIRE(!right->get_symbol_name_regex());
>+
>+  regex_t_sptr left_regex = left->get_symbol_name_not_regex();
>+  regex_t_sptr right_regex = right->get_symbol_name_not_regex();
>+  regex_t_sptr check_regex = compile(expr);
>+
>+  // all regexes present (compiled)
>+  REQUIRE(left_regex);
>+  REQUIRE(right_regex);
>+  REQUIRE(check_regex);
>+
>+  // all regexes match or do not match a random symbol
>+  for (size_t i = 0; i < sizeof(random_symbols)/sizeof(random_symbols[0]); ++i)
>+    {
>+      const std::string symbol(random_symbols[i]);
>+      bool left_matches = match(left_regex, symbol);
>+      bool right_matches = match(right_regex, symbol);
>+      bool check_matches = match(check_regex, symbol);
>+      REQUIRE(left_matches == right_matches);
>+      REQUIRE(left_matches == check_matches);
>+    }
> }
>
> TEST_CASE("NoWhitelists", "[whitelists]")
>-- 
>2.26.2.526.g744177e7f7-goog
>

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v4 14/15] abg-suppression.cc: More consistent regex matching.
  2020-05-04 12:34     ` [PATCH v4 14/15] abg-suppression.cc: More consistent regex matching Giuliano Procida
@ 2020-05-04 13:17       ` Matthias Maennich
  0 siblings, 0 replies; 120+ messages in thread
From: Matthias Maennich @ 2020-05-04 13:17 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, dodji, kernel-team

On Mon, May 04, 2020 at 01:34:15PM +0100, Giuliano Procida wrote:
>Following previous patches, various minor inconsistencies in the
>suppression regex matching code were more readily apparent.
>
>- regex_t_sptr values are fetched both by reference and by
>  value (which has a reference count mutation cost)
>- there's a mixture of code styles for testing regex presence
>    - regex = ...; if (regex && ...)
>    - if (regex = ...) if (...)
>  the latter has the advantage that the variable has a smaller scope
>  and can be given a shorter name
>- in some cases there are redundant tests (always true due to previous
>  conditional logic)
>
>This patch ensures all shared pointers to compiled regexes are fetched
>by const reference and that the code uses the nested if style of
>presence checking where possible. It simplifies some logic where
>there's redundancy.
>
>There are no behavioural changes. There may be performance
>improvements.
>
>	* src/abg-suppression.cc (suppression_matches_type_name): Get
>	regexes by const reference.
>	(suppression_matches_type_location): Get regexes by const
>	reference. (function_suppression::suppresses_function): Get
>	regexes by const reference; use nested if checks; simplify
>	logic around symbol version checks.
>	(function_suppression::suppresses_function_symbol): Get
>	regexes by const reference; use nested if checks; remove
>	redundant regex presence checks.
>	(suppression_matches_function_name): Get regexes by const
>	reference. (suppression_matches_function_sym_name): Get
>	regexes by const reference.
>	(suppression_matches_variable_name): Get regexes by const
>	reference. (suppression_matches_variable_sym_name): Get
>	regexes by const reference. (suppression_matches_type): Get
>	regexes by const reference.
>	(variable_suppression::suppresses_variable): Get regexes by
>	const reference; use nested if checks; remove redundant
>	type_name empty check.
>	(variable_suppression::suppresses_variable_symbol): Get
>	regexes by const reference; use nested if checks.
>
>Signed-off-by: Giuliano Procida <gprocida@google.com>

Reviewed-by: Matthias Maennich <maennich@google.com>

Cheers,
Matthias
>---
> src/abg-suppression.cc | 167 +++++++++++++++++++----------------------
> 1 file changed, 76 insertions(+), 91 deletions(-)
>
>diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
>index 4883168d..24f75b9a 100644
>--- a/src/abg-suppression.cc
>+++ b/src/abg-suppression.cc
>@@ -1049,15 +1049,14 @@ 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.
>-	  if (const regex_t_sptr& type_name_regex =
>-	      s.get_type_name_regex())
>+	  if (const regex_t_sptr& type_name_regex = s.get_type_name_regex())
> 	    {
> 	      if (!regex::match(type_name_regex, type_name))
> 		return false;
> 	    }
>
>-	  if (const regex_t_sptr type_name_not_regex =
>-	      s.get_type_name_not_regex())
>+	  if (const regex_t_sptr& type_name_not_regex =
>+		s.get_type_name_not_regex())
> 	    {
> 	      if (regex::match(type_name_not_regex, type_name))
> 		return false;
>@@ -1105,7 +1104,7 @@ suppression_matches_type_location(const type_suppression&	s,
>       unsigned loc_line = 0, loc_column = 0;
>       loc.expand(loc_path, loc_line, loc_column);
>
>-      if (regex_t_sptr regexp = s.get_source_location_to_keep_regex())
>+      if (const regex_t_sptr& regexp = s.get_source_location_to_keep_regex())
> 	if (regex::match(regexp, loc_path))
> 	  return false;
>
>@@ -2544,7 +2543,7 @@ function_suppression::suppresses_function(const function_decl* fn,
>     }
>
>   // check if the "name_regexp" property matches.
>-  const regex_t_sptr name_regex = get_name_regex();
>+  const regex_t_sptr& name_regex = get_name_regex();
>   if (name_regex)
>     {
>       if (!regex::match(name_regex, fname))
>@@ -2575,7 +2574,7 @@ function_suppression::suppresses_function(const function_decl* fn,
>     }
>
>   // check if the "name_not_regexp" property matches.
>-  const regex_t_sptr name_not_regex = get_name_not_regex();
>+  const regex_t_sptr& name_not_regex = get_name_not_regex();
>   if (name_not_regex)
>     {
>       if (regex::match(name_not_regex, fname))
>@@ -2619,11 +2618,9 @@ function_suppression::suppresses_function(const function_decl* fn,
>       if (fn_return_type_name != get_return_type_name())
> 	return false;
>     }
>-  else
>+  else if (const regex_t_sptr& regex = get_return_type_regex())
>     {
>-      const regex_t_sptr return_type_regex = get_return_type_regex();
>-      if (return_type_regex
>-	  && !regex::match(return_type_regex, fn_return_type_name))
>+      if (!regex::match(regex, fn_return_type_name))
> 	return false;
>     }
>
>@@ -2659,14 +2656,15 @@ function_suppression::suppresses_function(const function_decl* fn,
>     }
>   else if (sym)
>     {
>-      const regex_t_sptr symbol_name_regex = get_symbol_name_regex();
>-      if (symbol_name_regex && !regex::match(symbol_name_regex, fn_sym_name))
>-	return false;
>+      const regex_t_sptr& symbol_name_regex = get_symbol_name_regex();
>+      const regex_t_sptr& symbol_name_not_regex = get_symbol_name_not_regex();
>
>-      const regex_t_sptr symbol_name_not_regex = get_symbol_name_not_regex();
>-      if (symbol_name_not_regex
>-	  && regex::match(symbol_name_not_regex, fn_sym_name))
>-	return false;
>+      if (symbol_name_regex)
>+	if (!regex::match(symbol_name_regex, fn_sym_name))
>+	  return false;
>+      if (symbol_name_not_regex)
>+	if (regex::match(symbol_name_not_regex, fn_sym_name))
>+	  return false;
>
>       if (get_allow_other_aliases())
> 	{
>@@ -2679,13 +2677,13 @@ function_suppression::suppresses_function(const function_decl* fn,
> 		   a && !a->is_main_symbol();
> 		   a = a->get_next_alias())
> 		{
>-		  if (symbol_name_regex
>-		      && !regex::match(symbol_name_regex, a->get_name()))
>-		    return false;
>-
>-		  if (symbol_name_not_regex
>-		      && regex::match(symbol_name_not_regex, a->get_name()))
>-		    return false;
>+		  const std::string& alias_name = a->get_name();
>+		  if (symbol_name_regex)
>+		    if (!regex::match(symbol_name_regex, alias_name))
>+		      return false;
>+		  if (symbol_name_not_regex)
>+		    if (regex::match(symbol_name_not_regex, alias_name))
>+		      return false;
> 		}
> 	    }
> 	}
>@@ -2693,17 +2691,19 @@ function_suppression::suppresses_function(const function_decl* fn,
>
>   // Check if the "symbol_version" and "symbol_version_regexp"
>   // properties match.
>-  if (sym && !get_symbol_version().empty())
>-    {
>-      if (fn_sym_version != get_symbol_version())
>-	return false;
>-    }
>-  else if (sym)
>+  if (sym)
>     {
>-      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
>-      if (symbol_version_regex
>-	  && !regex::match(symbol_version_regex, fn_sym_version))
>-	return false;
>+      if (!get_symbol_version().empty())
>+	{
>+	  if (fn_sym_version != get_symbol_version())
>+	    return false;
>+	}
>+      else
>+	{
>+	  if (const regex_t_sptr& regex = get_symbol_version_regex())
>+	    if (!regex::match(regex, fn_sym_version))
>+	      return false;
>+	}
>     }
>
>   // Check the 'parameter' property.
>@@ -2737,16 +2737,11 @@ function_suppression::suppresses_function(const function_decl* fn,
> 	      if (tn != fn_parm_type_qualified_name)
> 		return false;
> 	    }
>-	  else
>+	  else if (const regex_t_sptr& regex =
>+		     (*p)->get_parameter_type_name_regex())
> 	    {
>-	      const regex_t_sptr parm_type_name_regex =
>-		(*p)->get_parameter_type_name_regex();
>-	      if (parm_type_name_regex)
>-		{
>-		  if (!regex::match(parm_type_name_regex,
>-				    fn_parm_type_qualified_name))
>-		    return false;
>-		}
>+	      if (!regex::match(regex, fn_parm_type_qualified_name))
>+		return false;
> 	    }
> 	}
>     }
>@@ -2829,10 +2824,9 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
>       if (sym_name != get_symbol_name())
> 	return false;
>     }
>-  else if (get_symbol_name_regex())
>+  else if (const regex_t_sptr& regex = get_symbol_name_regex())
>     {
>-      const regex_t_sptr symbol_name_regex = get_symbol_name_regex();
>-      if (symbol_name_regex && !regex::match(symbol_name_regex, sym_name))
>+      if (!regex::match(regex, sym_name))
> 	return false;
>     }
>   else
>@@ -2844,11 +2838,9 @@ function_suppression::suppresses_function_symbol(const elf_symbol* sym,
>       if (sym_version != get_symbol_version())
> 	return false;
>     }
>-  else if (get_symbol_version_regex())
>+  else if (const regex_t_sptr& regex = get_symbol_version_regex())
>     {
>-      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
>-      if (symbol_version_regex
>-	  && !regex::match(symbol_version_regex, sym_version))
>+      if (!regex::match(regex, sym_version))
> 	return false;
>     }
>   else
>@@ -2938,12 +2930,12 @@ bool
> suppression_matches_function_name(const suppr::function_suppression& s,
> 				  const string& fn_name)
> {
>-  if (regex_t_sptr regexp = s.get_name_regex())
>+  if (const regex_t_sptr& regexp = s.get_name_regex())
>     {
>       if (!regex::match(regexp, fn_name))
> 	return false;
>     }
>-  else if (regex_t_sptr regexp = s.get_name_not_regex())
>+  else if (const regex_t_sptr& regexp = s.get_name_not_regex())
>     {
>       if (regex::match(regexp, fn_name))
> 	return false;
>@@ -2974,12 +2966,12 @@ bool
> suppression_matches_function_sym_name(const suppr::function_suppression& s,
> 				      const string& fn_linkage_name)
> {
>-  if (regex_t_sptr regexp = s.get_symbol_name_regex())
>+  if (const regex_t_sptr& regexp = s.get_symbol_name_regex())
>     {
>       if (!regex::match(regexp, fn_linkage_name))
> 	return false;
>     }
>-  else if (regex_t_sptr regexp = s.get_symbol_name_not_regex())
>+  else if (const regex_t_sptr& regexp = s.get_symbol_name_not_regex())
>     {
>       if (regex::match(regexp, fn_linkage_name))
> 	return false;
>@@ -3007,12 +2999,12 @@ bool
> suppression_matches_variable_name(const suppr::variable_suppression& s,
> 				  const string& var_name)
> {
>-  if (regex_t_sptr regexp = s.get_name_regex())
>+  if (const regex_t_sptr& regexp = s.get_name_regex())
>     {
>       if (!regex::match(regexp, var_name))
> 	return false;
>     }
>-  else if (regex_t_sptr regexp = s.get_name_not_regex())
>+  else if (const regex_t_sptr& regexp = s.get_name_not_regex())
>     {
>       if (regex::match(regexp, var_name))
> 	return false;
>@@ -3041,12 +3033,12 @@ bool
> suppression_matches_variable_sym_name(const suppr::variable_suppression& s,
> 				      const string& var_linkage_name)
> {
>-  if (regex_t_sptr regexp = s.get_symbol_name_regex())
>+  if (const regex_t_sptr& regexp = s.get_symbol_name_regex())
>     {
>       if (!regex::match(regexp, var_linkage_name))
> 	return false;
>     }
>-  else if (regex_t_sptr regexp = s.get_symbol_name_not_regex())
>+  else if (const regex_t_sptr& regexp = s.get_symbol_name_not_regex())
>     {
>       if (regex::match(regexp, var_linkage_name))
> 	return false;
>@@ -3075,7 +3067,7 @@ bool
> suppression_matches_type(const suppr::type_suppression& s,
> 			 const string& type_name)
> {
>-  if (regex_t_sptr regexp = s.get_type_name_regex())
>+  if (const regex_t_sptr& regexp = s.get_type_name_regex())
>     {
>       if (!regex::match(regexp, type_name))
> 	return false;
>@@ -3784,13 +3776,13 @@ variable_suppression::suppresses_variable(const var_decl* var,
>       // "name_regex" and "name_not_regex" properties match
>       if (get_name().empty())
> 	{
>-	  const regex_t_sptr name_regex = get_name_regex();
>-	  if (name_regex && !regex::match(name_regex, var_name))
>-	    return false;
>+	  if (const regex_t_sptr& regex = get_name_regex())
>+	    if (!regex::match(regex, var_name))
>+	      return false;
>
>-	  const regex_t_sptr name_not_regex = get_name_not_regex();
>-	  if (name_not_regex && regex::match(name_not_regex, var_name))
>-	    return false;
>+	  if (const regex_t_sptr& regex = get_name_not_regex())
>+	    if (regex::match(regex, var_name))
>+	      return false;
> 	}
>     }
>
>@@ -3804,13 +3796,13 @@ variable_suppression::suppresses_variable(const var_decl* var,
>     }
>   else
>     {
>-      const regex_t_sptr sym_name_regex = get_symbol_name_regex();
>-      if (sym_name_regex && !regex::match(sym_name_regex, var_sym_name))
>-	return false;
>+      if (const regex_t_sptr& regex = get_symbol_name_regex())
>+	if (!regex::match(regex, var_sym_name))
>+	  return false;
>
>-      const regex_t_sptr sym_name_not_regex = get_symbol_name_not_regex();
>-      if (sym_name_not_regex && regex::match(sym_name_not_regex, var_sym_name))
>-	return false;
>+      if (const regex_t_sptr& regex = get_symbol_name_not_regex())
>+	if (regex::match(regex, var_sym_name))
>+	  return false;
>     }
>
>   // Check for symbol_version and symbol_version_regexp property match
>@@ -3823,10 +3815,9 @@ variable_suppression::suppresses_variable(const var_decl* var,
>     }
>   else
>     {
>-      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
>-      if (symbol_version_regex
>-	  && !regex::match(symbol_version_regex, var_sym_version))
>-	return false;
>+      if (const regex_t_sptr& regex = get_symbol_version_regex())
>+	if (!regex::match(regex, var_sym_version))
>+	  return false;
>     }
>
>   // Check for the "type_name" and type_name_regex properties match.
>@@ -3840,12 +3831,9 @@ variable_suppression::suppresses_variable(const var_decl* var,
>     }
>   else
>     {
>-      if (get_type_name().empty())
>-	{
>-	  const regex_t_sptr type_name_regex = get_type_name_regex();
>-	  if (type_name_regex && !regex::match(type_name_regex, var_type_name))
>-	    return false;
>-	}
>+      if (const regex_t_sptr& regex = get_type_name_regex())
>+	if (!regex::match(regex, var_type_name))
>+	  return false;
>     }
>
>   return true;
>@@ -3931,10 +3919,9 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
>       if (get_symbol_name() != sym_name)
> 	return false;
>     }
>-  else if (get_symbol_name_regex())
>+  else if (const regex_t_sptr& regex = get_symbol_name_regex())
>     {
>-      const regex_t_sptr sym_name_regex = get_symbol_name_regex();
>-      if (sym_name_regex && !regex::match(sym_name_regex, sym_name))
>+      if (!regex::match(regex, sym_name))
> 	return false;
>     }
>   else
>@@ -3946,11 +3933,9 @@ variable_suppression::suppresses_variable_symbol(const elf_symbol* sym,
>       if (get_symbol_version() != sym_version)
> 	return false;
>     }
>-  else if (get_symbol_version_regex())
>+  else if (const regex_t_sptr& regex = get_symbol_version_regex())
>     {
>-      const regex_t_sptr symbol_version_regex = get_symbol_version_regex();
>-      if (symbol_version_regex
>-	  && !regex::match(symbol_version_regex, sym_version))
>+      if (!regex::match(regex, sym_version))
> 	return false;
>     }
>   else
>@@ -4251,14 +4236,14 @@ file_suppression::suppresses_file(const string& file_path)
>
>   bool has_regexp = false;
>
>-  if (regex_t_sptr regexp = get_file_name_regex())
>+  if (const regex_t_sptr& regexp = get_file_name_regex())
>     {
>       has_regexp = true;
>       if (!regex::match(regexp, fname))
> 	return false;
>     }
>
>-  if (regex_t_sptr regexp = get_file_name_not_regex())
>+  if (const regex_t_sptr& regexp = get_file_name_not_regex())
>     {
>       has_regexp = true;
>       if (regex::match(regexp, fname))
>-- 
>2.26.2.526.g744177e7f7-goog
>

^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v5 03/15] Escape names used in symbol whitelisting regex.
  2020-05-04 12:57       ` Matthias Maennich
@ 2020-05-04 16:45         ` Giuliano Procida
  2020-05-11 13:59           ` Dodji Seketeli
  0 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-05-04 16:45 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida, Matthias Maennich

There is the theoretical possibility that symbols may contain special
regex characters like '.' and '$'. This patch ensures all such
characters in symbol names are escaped before they are added to the
whitelisting regex.

	* include/regex.h (escape): New string reference holder
	class. (operator<<): Declaration of std::ostream,
	regex::escape overload.
	* include/regex.cc (operator<<): New std::ostream,
	regex::escape overload that outputs regex-escaped strings.
	* src/abg-tools-utils.cc
	(gen_suppr_spec_from_kernel_abi_whitelists): Make sure any
	special regex characters in symbol names are escaped.

Reviewed-by: Matthias Maennich <maennich@google.com>
Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 include/abg-regex.h | 10 ++++++++++
 src/abg-regex.cc    | 28 ++++++++++++++++++++++++++--
 2 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/include/abg-regex.h b/include/abg-regex.h
index d39ada46..164083cc 100644
--- a/include/abg-regex.h
+++ b/include/abg-regex.h
@@ -58,6 +58,16 @@ struct regex_t_deleter
   }
 };//end struct regex_deleter
 
+/// A class to hold a reference to a string to regex escape.
+struct escape
+{
+  escape(const std::string& str) : ref(str) { }
+  const std::string& ref;
+};
+
+std::ostream&
+operator<<(std::ostream& os, const escape& esc);
+
 std::string
 generate_from_strings(const std::vector<std::string>& strs);
 
diff --git a/src/abg-regex.cc b/src/abg-regex.cc
index 0451d111..59f56deb 100644
--- a/src/abg-regex.cc
+++ b/src/abg-regex.cc
@@ -24,6 +24,7 @@
 ///
 
 #include <sstream>
+#include <ostream>
 
 #include "abg-regex.h"
 #include "abg-sptr-utils.h"
@@ -57,6 +58,29 @@ sptr_utils::build_sptr<regex_t>()
 namespace regex
 {
 
+/// Escape regex special charaters in input string.
+///
+/// @param os the output stream being written to.
+///
+/// @param esc the regex_escape object holding a reference to the string
+/// needing to be escaped.
+///
+/// @return the output stream.
+std::ostream&
+operator<<(std::ostream& os, const escape& esc)
+{
+  // ']' and '}' are only conditionally special, so could be removed.
+  static const std::string specials = "^.[]$()|*+?{}\\";
+  const std::string& str = esc.ref;
+  for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
+    {
+      if (specials.find(*i) != std::string::npos)
+	os << '\\';
+      os << *i;
+    }
+  return os;
+}
+
 /// Generate a regex pattern equivalent to testing set membership.
 ///
 /// A string will match the resulting pattern regex, if and only if it
@@ -73,9 +97,9 @@ generate_from_strings(const std::vector<std::string>& strs)
     return "^_^";
   std::ostringstream os;
   std::vector<std::string>::const_iterator i = strs.begin();
-  os << "^(" << *i++;
+  os << "^(" << escape(*i++);
   while (i != strs.end())
-    os << "|" << *i++;
+    os << "|" << escape(*i++);
   os << ")$";
   return os.str();
 }
-- 
2.26.2.526.g744177e7f7-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v4 01/15] Tidy #includes in a few files.
  2020-05-04 12:34     ` [PATCH v4 01/15] Tidy #includes in a few files Giuliano Procida
  2020-05-04 12:49       ` Matthias Maennich
@ 2020-05-11 13:24       ` Dodji Seketeli
  1 sibling, 0 replies; 120+ messages in thread
From: Dodji Seketeli @ 2020-05-11 13:24 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, kernel-team, maennich

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

> Following review of a recent change to move regex definitions into
> their own files, this commit ensures that #include directives are
> separated into categories and sorted alphabetically within the categories, 

Just as a comment, I don't have a strong opinion about alphabetically
sorting header files.  I don't intend to require that for the project.
I am not rejecting this change however.

> subject to known ordering constraints (such as
> "config.h" first, "abg-internal.h" before visibility directives etc.).

These ordering constraints are however important to respect for obvious
reasons.  So these are the ones I am interested in :-)

Thank you for doing this.

>
> There are no behavioural changes.
>
> 	* src/abg-corpus-priv.h: Separate and sort #include
> 	directives.
> 	* src/abg-corpus.cc: Ditto.
> 	* src/abg-regex.cc: Ditto.
> 	* src/abg-suppression-priv.h: Ditto.
> 	* src/abg-suppression.cc: Ditto.

Applied to master, thanks!

Cheers,

-- 
		Dodji

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v4 02/15] Document ^_^ regex in generate_from_strings.
  2020-05-04 12:34     ` [PATCH v4 02/15] Document ^_^ regex in generate_from_strings Giuliano Procida
  2020-05-04 12:49       ` Matthias Maennich
@ 2020-05-11 13:32       ` Dodji Seketeli
  1 sibling, 0 replies; 120+ messages in thread
From: Dodji Seketeli @ 2020-05-11 13:32 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, kernel-team, maennich

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

[...]

>  generate_from_strings(const std::vector<std::string>& strs)
>  {
>    if (strs.empty())
> +    // This cute-looking regex does not match any string.
>      return "^_^";

Cute-looking, indeed :-)

> Following review of the change to simplify generation of symbol
> whitelist regexes, this commit clarifies the purpose of the ^_^ regex
> as one which will not match any string.
>
> 	* src/abg-regex.cc (generate_from_strings): Document ^_^
> 	regex.

Applied to master, thanks!

Cheers,

-- 
		Dodji

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v5 03/15] Escape names used in symbol whitelisting regex.
  2020-05-04 16:45         ` [PATCH v5 " Giuliano Procida
@ 2020-05-11 13:59           ` Dodji Seketeli
  0 siblings, 0 replies; 120+ messages in thread
From: Dodji Seketeli @ 2020-05-11 13:59 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, kernel-team, Matthias Maennich

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

> There is the theoretical possibility that symbols may contain special
> regex characters like '.' and '$'. This patch ensures all such
> characters in symbol names are escaped before they are added to the
> whitelisting regex.
>
> 	* include/regex.h (escape): New string reference holder
> 	class. (operator<<): Declaration of std::ostream,
> 	regex::escape overload.
> 	* include/regex.cc (operator<<): New std::ostream,
> 	regex::escape overload that outputs regex-escaped strings.
> 	* src/abg-tools-utils.cc
> 	(gen_suppr_spec_from_kernel_abi_whitelists): Make sure any
> 	special regex characters in symbol names are escaped.

Applied to master, thanks!

Cheers,

-- 
		Dodji

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v4 04/15] abg-suppression.cc: More uniform variable naming.
  2020-05-04 12:34     ` [PATCH v4 04/15] abg-suppression.cc: More uniform variable naming Giuliano Procida
@ 2020-05-11 14:04       ` Dodji Seketeli
  0 siblings, 0 replies; 120+ messages in thread
From: Dodji Seketeli @ 2020-05-11 14:04 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, kernel-team, maennich

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

> In abg-suppression.cc most of the read_*_suppression functions
> populate and return a single variable "result". Others vary a little
> from this, having variables "nil" or "suppr".
>
> This patch makes all the functions use a single variable "result".
> This will make the next patches a bit simpler.
>
> There are no behavioural changes.
>
> 	* src/abg-suppression.cc (read_type_suppression): Rename "nil"
> 	variable to "result" and reset it instead of introducing
> 	"suppr" later on. (read_function_suppression): Rename "nil"
> 	variable to "result" and reset it instead of introducing
> 	"result" later on.

Applied to master, thanks!

Cheers,

-- 
		Dodji

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v4 05/15] diff suppression: Fix handling of change kinds.
  2020-05-04 12:34     ` [PATCH v4 05/15] diff suppression: Fix handling of change kinds Giuliano Procida
  2020-05-04 13:04       ` Matthias Maennich
@ 2020-05-11 14:15       ` Dodji Seketeli
  2020-05-11 15:47         ` Giuliano Procida
  1 sibling, 1 reply; 120+ messages in thread
From: Dodji Seketeli @ 2020-05-11 14:15 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, kernel-team, maennich

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

> When parsing suppression specifications, libabigail attempts to detect
> and ignore suppressions that are empty and so would match everything
> in their category by default.

No.  Libabigail doesn't try to detect suppressions that are empty.
Rather, it requires *some* properties to be present in the suppression.

Those mandatory properties are documented for each kind of suppression
at
https://sourceware.org/libabigail/manual/libabigail-concepts.html#suppress-type,
for instance.

The reason why there are mandatory properties is to somehow, to give
incentive to the the writer of the suppression to think and to minimise
the risk of having supprising false negatives due to suppression
specifications that are too "greedy" in a sense.

In other words, when in doubt, we choose to not suppress anything,
rather than suppress too much.

I agree that this is a "balanced" act.

> Unfortunately, with the way the parser currently works, these checks
> have to be against an exhaustive list of fields that matter, rather
> than by listing the fields that don't (like label).

What I said above is the reason why it works against an exhaustive
list.  So that is by design.

> They are fragile in the face of changes that add new fields.

Well, new fields are not a problem because they won't change the set of
mandatory fields that have been chosen already.

> Two of the short-cut checks are in fact buggy, missing out the
> change_kind field.

That's by design.  You don't need to specify the change_kind property
for the suppress_type directive to work because that property it's
considered advanced.

> One of the checks also risks a null pointer
> dereference as it doesn't actually trigger a return from the function.

That ought to be fixed, I guess.

> This patch eliminates (rather than fixes up) this short-cutting on the
> grounds that it is a maintenance burden and inconsistent behaviour.

> Users should be able to do this:
>
> [suppress_variable]
>   label = Suppress all changes to variables

That's precisely what I don't want to allow, by design.

I'd rather have the user specify a regular expression that matches
everything rather than that.

So, in light of my explanations above, I'd prefer that we don't apply
this patch.

Does that make sense?

Cheers,

-- 
		Dodji

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v4 05/15] diff suppression: Fix handling of change kinds.
  2020-05-11 14:15       ` Dodji Seketeli
@ 2020-05-11 15:47         ` Giuliano Procida
  2020-05-11 17:53           ` Dodji Seketeli
  0 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-05-11 15:47 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: libabigail, kernel-team, Matthias Männich

Hi Dodji.

On Mon, 11 May 2020 at 15:15, Dodji Seketeli <dodji@seketeli.org> wrote:
>
> Giuliano Procida <gprocida@google.com> a écrit:
>
> > When parsing suppression specifications, libabigail attempts to detect
> > and ignore suppressions that are empty and so would match everything
> > in their category by default.
>
> No.  Libabigail doesn't try to detect suppressions that are empty.
> Rather, it requires *some* properties to be present in the suppression.
>
> Those mandatory properties are documented for each kind of suppression
> at
>
https://sourceware.org/libabigail/manual/libabigail-concepts.html#suppress-type
,
> for instance.
>
> The reason why there are mandatory properties is to somehow, to give
> incentive to the the writer of the suppression to think and to minimise
> the risk of having supprising false negatives due to suppression
> specifications that are too "greedy" in a sense.
>
> In other words, when in doubt, we choose to not suppress anything,
> rather than suppress too much.
>
> I agree that this is a "balanced" act.

The code and documentation should agree, certainly! If we stick to current
implementation and documentation, I would feel better if the code noisily
ignored rather than silently ignored such suppressions.

> > Unfortunately, with the way the parser currently works, these checks
> > have to be against an exhaustive list of fields that matter, rather
> > than by listing the fields that don't (like label).
>
> What I said above is the reason why it works against an exhaustive
> list.  So that is by design.
>
> > They are fragile in the face of changes that add new fields.
>
> Well, new fields are not a problem because they won't change the set of
> mandatory fields that have been chosen already.

Well, once the dust has settled, it should be very cheap to add
source_location_regexp, for example. But, the way I see the code working,
my fragility argument doesn't stand.

> > Two of the short-cut checks are in fact buggy, missing out the
> > change_kind field.
>
> That's by design.  You don't need to specify the change_kind property
> for the suppress_type directive to work because that property it's
> considered advanced.

It's not that change_kind should be mandatory but that it should be one of
the fields considered sufficient for the specification not to be ignored.

The tests as written are very confusing then. A comment in the .suppr files
that only specify change_kind to say "this suppression will be ignored"
would be useful. It was these tests that led me to believe the code should
have included change_kind as one of the sufficient fields.

> > One of the checks also risks a null pointer
> > dereference as it doesn't actually trigger a return from the function.
>
> That ought to be fixed, I guess.
>
> > This patch eliminates (rather than fixes up) this short-cutting on the
> > grounds that it is a maintenance burden and inconsistent behaviour.
>
> > Users should be able to do this:
> >
> > [suppress_variable]
> >   label = Suppress all changes to variables
>
> That's precisely what I don't want to allow, by design.
>
> I'd rather have the user specify a regular expression that matches
> everything rather than that.

To give you my perspective...

I have no idea what suppression specifications are being used in reality,
so I am looking at things fairly abstractly. I see things through a
mathematical viewpoint: a suppression is simply a predicate (function
returning a truth value) on a type of object.

libabigail supports multiple suppression specifications and ORs them
together. Within each suppression specification, things are (mostly) ANDed
together (and within ANDs there is some support for NOT as well via
_not_regex properties). [c.f. DNF
<https://en.wikipedia.org/wiki/Disjunctive_normal_form>]

So the user can construct certain types of predicates. More generally, the
predicates which always return true or always return false are perfectly
valid mathematically. The always false one (never suppress) is
constructible by supplying an empty OR - no predicates - and the always
true one would logically be constructible by supplying an empty AND - a
predicate with no properties. Treating empty AND as false is what I meant
by "inconsistent".

More practically though, what do we want to happen when the user does
something bad? The current behaviour is to silently ignore.

I think it would be more useful to generate warning messages. Then there is
no surprise to the user if their suppression is either ignored or
suppresses too much. I don't mind so much which behaviour is implemented
so long as there is this coverage. It would be nice if the user didn't have
to do regex matches to implement "true" or "only additions" as predicates,
but that's a smaller issue.

> So, in light of my explanations above, I'd prefer that we don't apply
> this patch.

Understood.

> Does that make sense?

I can preserve the existing behaviours, but I would really want to do both
of:

a) comment the tests that were surprising to me (or allow change_kind as a
sufficient property)
b) emit warnings to the user whenever a suppression is going to be ignored
because it doesn't have one of a list of properties

I'm happy to adapt the code and repost.

> Cheers,
>
> --
>                 Dodji

Regards,
Giuliano.

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v4 06/15] Add POSIX regex wrapper functions.
  2020-05-04 12:34     ` [PATCH v4 06/15] Add POSIX regex wrapper functions Giuliano Procida
@ 2020-05-11 16:37       ` Dodji Seketeli
  0 siblings, 0 replies; 120+ messages in thread
From: Dodji Seketeli @ 2020-05-11 16:37 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, kernel-team, maennich

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

> libabigail code uses the POSIX regex library consistently:
>
>     - compile std::string to regex, with the flag REG_EXTENDED
>     - store regex using a shared pointer wrapper
>     - check match of regex against std::string
>
> All the C string / std::string logic and so on is repeated at every
> call site. This patch introduces wrapper functions to take care of
> this logic.
>
> There are no behavioural changes.
>
> 	* include/abg-regex.h (compile): Declare new function.
> 	(match): Declare new function.
> 	* src/abg-regex.cc (compile): Add new function wrapping
> 	regcomp. (match): Add new function wrapping regexec.

Applied to master, thanks.

-- 
		Dodji

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v4 07/15] Use regex::compile wrapper instead of regcomp.
  2020-05-04 12:34     ` [PATCH v4 07/15] Use regex::compile wrapper instead of regcomp Giuliano Procida
@ 2020-05-11 16:38       ` Dodji Seketeli
  0 siblings, 0 replies; 120+ messages in thread
From: Dodji Seketeli @ 2020-05-11 16:38 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, kernel-team, maennich

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

> This patch eliminates all calls to regcomp except that by
> regex::compile itself.
>
> 	* src/abg-corpus-priv.h: Mechanically substitute use of
> 	regcomp with regex::compile wrapper.
> 	* src/abg-suppression-priv.h: Ditto.

Applied to master, thanks.

-- 
		Dodji

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v4 05/15] diff suppression: Fix handling of change kinds.
  2020-05-11 15:47         ` Giuliano Procida
@ 2020-05-11 17:53           ` Dodji Seketeli
  2020-05-12  9:54             ` Giuliano Procida
  0 siblings, 1 reply; 120+ messages in thread
From: Dodji Seketeli @ 2020-05-11 17:53 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, kernel-team, Matthias Männich

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


> The code and documentation should agree, certainly! If we stick to current
> implementation and documentation, I would feel better if the code noisily
> ignored rather than silently ignored such suppressions.

In general, I chose to avoid emitting user messages unless those are
emitted in well defined places like special "passes" that are meant for
analysis and reporting.

So rather than scathering user messages left and right everywhere, I'd
prefer we properly fix this issue by adding a (set of) pass(es) that
would walk the parsed ini file, analyse it and emit warnings or errors
as necessary.

I understand that you've proposed something in that regard at
https://sourceware.org/pipermail/libabigail/2020q2/002160.html, so I
think the discussion will happen there.

So the more I think about this, the less I am in favour of handling that
here.

[...]

>> > Two of the short-cut checks are in fact buggy, missing out the
>> > change_kind field.
>>
>> That's by design.  You don't need to specify the change_kind property
>> for the suppress_type directive to work because that property it's
>> considered advanced.
>
> It's not that change_kind should be mandatory but that it should be one of
> the fields considered sufficient for the specification not to be
> ignored.

When I was assessing what property should be part of the sufficient set,
it didn't seem to me that change_kind should be in there (because it did
sound too easy to make it match a super-broad set of things to
suppress).  The goal, in my mind is *NOT* to strive for minimalism or
orthogonality.  To the contrary.  I'd rather require some redundancy to
be sure user think about this twice.  Because, again, it's super easy to
come up with false negatives otherwise.

Nevertheless if you think it should, then it's just a discussion to be
held.  As a matter of fact, I am not dead opposed to it.  So in the
grand scheme of things, I don't see this as bug.


> The tests as written are very confusing then. A comment in the .suppr files
> that only specify change_kind to say "this suppression will be ignored"
> would be useful. It was these tests that led me to believe the code should
> have included change_kind as one of the sufficient fields.

Fair enough.

[...]

> To give you my perspective...
>
> I have no idea what suppression specifications are being used in reality,
> so I am looking at things fairly abstractly. I see things through a
> mathematical viewpoint: a suppression is simply a predicate (function
> returning a truth value) on a type of object.
>
> libabigail supports multiple suppression specifications and ORs them
> together. Within each suppression specification, things are (mostly) ANDed
> together (and within ANDs there is some support for NOT as well via
> _not_regex properties). [c.f. DNF
> <https://en.wikipedia.org/wiki/Disjunctive_normal_form>]
>
> So the user can construct certain types of predicates. More generally, the
> predicates which always return true or always return false are perfectly
> valid mathematically. The always false one (never suppress) is
> constructible by supplying an empty OR - no predicates - and the always
> true one would logically be constructible by supplying an empty AND - a
> predicate with no properties. Treating empty AND as false is what I meant
> by "inconsistent".
>
> More practically though, what do we want to happen when the user does
> something bad? The current behaviour is to silently ignore.

Yes.  The "silent" part of the behaviour was not meant to be engraved in
stone forever :-)  I still want to add a semantic pass to handle that
separately.


> I think it would be more useful to generate warning messages.

Agreed.

[...]

>> So, in light of my explanations above, I'd prefer that we don't apply
>> this patch.
>
> Understood.
>
>> Does that make sense?
>
> I can preserve the existing behaviours, but I would really want to do both
> of:
>
> a) comment the tests that were surprising to me (or allow change_kind as a
> sufficient property)

Agreed.

> b) emit warnings to the user whenever a suppression is going to be ignored
> because it doesn't have one of a list of properties

I am not opposed to this, but as I said above, I'd rather see this
happen as part of the separate discussion/project I mentioned earlier.

> I'm happy to adapt the code and repost.

I'd happily accept a patch that does a/ in this context.

I hope this helps.

Cheers,

-- 
		Dodji

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v4 05/15] diff suppression: Fix handling of change kinds.
  2020-05-11 17:53           ` Dodji Seketeli
@ 2020-05-12  9:54             ` Giuliano Procida
  2020-05-12 10:14               ` [PATCH v5 05/15] Tidy checks for sufficient suppression properties Giuliano Procida
  0 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-05-12  9:54 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: libabigail, kernel-team, Matthias Männich

Hi there.

TL;DR: I'll send a separate documentation patch; "label" properties need a
second look; I'll send a revised patch preserving current behaviour and
with a placeholder for emitting a message.

On Mon, 11 May 2020 at 18:53, Dodji Seketeli <dodji@seketeli.org> wrote:

> Giuliano Procida <gprocida@google.com> a écrit:
>
>
> > The code and documentation should agree, certainly! If we stick to
> current
> > implementation and documentation, I would feel better if the code noisily
> > ignored rather than silently ignored such suppressions.
>
> In general, I chose to avoid emitting user messages unless those are
> emitted in well defined places like special "passes" that are meant for
> analysis and reporting.
>
> So rather than scathering user messages left and right everywhere, I'd
> prefer we properly fix this issue by adding a (set of) pass(es) that
> would walk the parsed ini file, analyse it and emit warnings or errors
> as necessary.
>

Putting my programming language hat back on for a minute, error reporting
is naturally part of both the "parser" and the "type checker". Now for
libabigail suppressions, responsibility is shared between the ini parser,
property fetching and checking code and a fair number of helper functions.
Everything funnels through read_suppressions and so long as all the error
reporting exists at or below this, it's within a well-defined "suppression
parsing" scope. It just happens that, so far, there are no such messages.

It's also worth making the distinction between error handling (noticing and
propagating error status) and error reporting (informing the user). It
sounds like you would like to limit the places reporting happens. We could
reduce them to a minimum by only reporting problems at the highest levels -
in read_suppressions and read_*_suppression perhaps - but we'd still need
to pass success/failure status around in some fashion to achieve this. We
should stick to a single mechanism.

The simplest mechanism is: bool parseX(..., X& x);
An alternative is std::optional<X> parseX(...);

More complicated (and much costlier in terms of coding) approaches such as
passing around a reference to an error state object or throwing, catching
and rethrowing exceptions would allow finer control over error reporting,
compared with just emitting messages when problems are noticed. But for a
configuration language, this is really not merited.


> I understand that you've proposed something in that regard at
> https://sourceware.org/pipermail/libabigail/2020q2/002160.html, so I
> think the discussion will happen there.
>

The proposal includes both error handling and reporting, but doesn't
discuss a particular mechanism. It does say that (after refactoring) every
piece of parsing code that can fail should have error handling and
reporting.


> So the more I think about this, the less I am in favour of handling that
> here.
>
> [...]
>
> >> > Two of the short-cut checks are in fact buggy, missing out the
> >> > change_kind field.
> >>
> >> That's by design.  You don't need to specify the change_kind property
> >> for the suppress_type directive to work because that property it's
> >> considered advanced.
> >
> > It's not that change_kind should be mandatory but that it should be one
> of
> > the fields considered sufficient for the specification not to be
> > ignored.
>
> When I was assessing what property should be part of the sufficient set,
> it didn't seem to me that change_kind should be in there (because it did
> sound too easy to make it match a super-broad set of things to
> suppress).  The goal, in my mind is *NOT* to strive for minimalism or
> orthogonality.  To the contrary.  I'd rather require some redundancy to
> be sure user think about this twice.  Because, again, it's super easy to
> come up with false negatives otherwise.
>
> Nevertheless if you think it should, then it's just a discussion to be
> held.  As a matter of fact, I am not dead opposed to it.  So in the
> grand scheme of things, I don't see this as bug.
>

I'm not a user or the designer and unless real users complain about the
(documented or actual) behaviour, there's no pressing need to change it.
Accommodating a set of sufficient fields per suppression type is not much
extra code.

Speaking of documentation... I had a look at the documentation and noticed
some minor discrepancies. I'll send a separate patch for this.

And looking again at the sets I noticed an inconsistency between the
various suppression types. For function and variable suppressions, "label"
is considered sufficient, but for file and type suppression it is not.
What's your preference here?

> The tests as written are very confusing then. A comment in the .suppr
> files
> > that only specify change_kind to say "this suppression will be ignored"
> > would be useful. It was these tests that led me to believe the code
> should
> > have included change_kind as one of the sufficient fields.
>
> Fair enough.

[...]
>
> > To give you my perspective...
> >
> > I have no idea what suppression specifications are being used in reality,
> > so I am looking at things fairly abstractly. I see things through a
> > mathematical viewpoint: a suppression is simply a predicate (function
> > returning a truth value) on a type of object.
> >
> > libabigail supports multiple suppression specifications and ORs them
> > together. Within each suppression specification, things are (mostly)
> ANDed
> > together (and within ANDs there is some support for NOT as well via
> > _not_regex properties). [c.f. DNF
> > <https://en.wikipedia.org/wiki/Disjunctive_normal_form>]
> >
> > So the user can construct certain types of predicates. More generally,
> the
> > predicates which always return true or always return false are perfectly
> > valid mathematically. The always false one (never suppress) is
> > constructible by supplying an empty OR - no predicates - and the always
> > true one would logically be constructible by supplying an empty AND - a
> > predicate with no properties. Treating empty AND as false is what I meant
> > by "inconsistent".
> >
> > More practically though, what do we want to happen when the user does
> > something bad? The current behaviour is to silently ignore.
>
> Yes.  The "silent" part of the behaviour was not meant to be engraved in
> stone forever :-)  I still want to add a semantic pass to handle that
> separately.


I'm not sure what form it will take, but once it has access to propagated
error status and complete specification, it can do whatever extra checking
/ reporting you like.


> > I think it would be more useful to generate warning messages.
>
> Agreed.
>
> [...]
>
> >> So, in light of my explanations above, I'd prefer that we don't apply
> >> this patch.
> >
> > Understood.
> >
> >> Does that make sense?
> >
> > I can preserve the existing behaviours, but I would really want to do
> both
> > of:
> >
> > a) comment the tests that were surprising to me (or allow change_kind as
> a
> > sufficient property)
>
> Agreed.
>
> > b) emit warnings to the user whenever a suppression is going to be
> ignored
> > because it doesn't have one of a list of properties
>
> I am not opposed to this, but as I said above, I'd rather see this
> happen as part of the separate discussion/project I mentioned earlier.
>
> > I'm happy to adapt the code and repost.
>
> I'd happily accept a patch that does a/ in this context.
>

I can do this. It'll be obvious where error messages can be added.


> I hope this helps.
>
> Cheers,
>
> --
>                 Dodji
>

Regards,
Giuliano.


> --
> To unsubscribe from this group and stop receiving emails from it, send an
> email to kernel-team+unsubscribe@android.com.
>
>

^ permalink raw reply	[flat|nested] 120+ messages in thread

* [PATCH v5 05/15] Tidy checks for sufficient suppression properties.
  2020-05-12  9:54             ` Giuliano Procida
@ 2020-05-12 10:14               ` Giuliano Procida
  2020-05-12 16:11                 ` Dodji Seketeli
  0 siblings, 1 reply; 120+ messages in thread
From: Giuliano Procida @ 2020-05-12 10:14 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, kernel-team, gprocida

Each suppression specification must have at least one of a documented
per-suppression type list of properties defined if it is to be
considered at all.

At present:

- suppression specifications which fail the check are silently ignored
- in the function suppression case, the check does not trigger an
  early return and risks a later null pointer dereference.

This commit:

- reimplements the checks using arrays and helper function calls
- adds a helper function to determine if a suppression specification
  is going to be ignored due a lack of properties
- makes the parsing functions return failure early if the check fails

Inconsistencies between suppression types (in particular, the
treatment of the "label" property) remain.

The only behavioural change may be to how present but empty properties
are handled. This is an edge case that may be worth revisiting in a
more general fashion in a later commit.

	* src/abg-suppression.cc (check_sufficient_props): New helper
	function to check for sufficient properties in a section.
	(read_type_suppression): Replace conditional logic with call
	to check_sufficient_props.
	(read_function_suppression): Ditto.
	(read_variable_suppression): Ditto.
	(read_file_suppression): Ditto.
	* tests/data/test-diff-suppr/test15-suppr-added-fn-4.suppr:
	Explain why the suppression will be ignored.
	* tests/data/test-diff-suppr/test16-suppr-removed-fn-4.suppr:
	Ditto.
	* tests/data/test-diff-suppr/test17-suppr-added-var-4.suppr:
	Ditto.
	* tests/data/test-diff-suppr/test18-suppr-removed-var-4.suppr:
	Ditto.

Signed-off-by: Giuliano Procida <gprocida@google.com>
---
 src/abg-suppression.cc                        | 188 +++++++++++-------
 .../test15-suppr-added-fn-4.suppr             |   1 +
 .../test16-suppr-removed-fn-4.suppr           |   1 +
 .../test17-suppr-added-var-4.suppr            |   1 +
 .../test18-suppr-removed-var-4.suppr          |   1 +
 5 files changed, 123 insertions(+), 69 deletions(-)

diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc
index 217ec5e9..4309e255 100644
--- a/src/abg-suppression.cc
+++ b/src/abg-suppression.cc
@@ -52,6 +52,30 @@ namespace suppr
 using abg_compat::dynamic_pointer_cast;
 using regex::regex_t_sptr;
 
+// <parsing stuff>
+
+// section parsing
+
+/// Check if a section has at least one of the given properties.
+///
+/// @param names pointer to the start of an array of names.
+///
+/// @param count number of names in the array.
+///
+/// @return whether at least of one the properties was found.
+bool
+check_sufficient_props(const char *const * names, size_t count,
+		       const ini::config::section& section)
+{
+  for (const char *const * name = names; name < names + count; ++name)
+    if (section.find_property(*name))
+      return true;
+  // TODO: Possibly give reason for failure in a message here.
+  return false;
+}
+
+// </parsing stuff>
+
 // <suppression_base stuff>
 
 /// Constructor for @ref suppression_base
@@ -1547,6 +1571,23 @@ read_type_suppression(const ini::config::section& section)
   if (section.get_name() != "suppress_type")
     return result;
 
+  static const char *const sufficient_props[] = {
+    "file_name_regexp",
+    "file_name_not_regexp",
+    "soname_regexp",
+    "soname_not_regexp",
+    "name",
+    "name_regexp",
+    "name_not_regexp",
+    "type_kind",
+    "source_location_not_in",
+    "source_location_not_regexp",
+  };
+  if (!check_sufficient_props(sufficient_props,
+			      sizeof(sufficient_props)/sizeof(char*),
+			      section))
+    return result;
+
   ini::simple_property_sptr drop_artifact =
     is_simple_property(section.find_property("drop_artifact"));
   if (!drop_artifact)
@@ -1835,19 +1876,6 @@ read_type_suppression(const ini::config::section& section)
 	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()
-      && 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()
-      && srcloc_not_in.empty())
-    return result;
-
   result.reset(new type_suppression(label_str, name_regex_str, name_str));
 
   if (consider_type_kind)
@@ -3157,6 +3185,29 @@ read_function_suppression(const ini::config::section& section)
   if (section.get_name() != "suppress_function")
     return result;
 
+  static const char *const sufficient_props[] = {
+    "label",
+    "file_name_regexp",
+    "file_name_not_regexp",
+    "soname_regexp",
+    "soname_not_regexp",
+    "name",
+    "name_regexp",
+    "name_not_regexp",
+    "parameter",
+    "return_type_name",
+    "return_type_regexp",
+    "symbol_name",
+    "symbol_name_regexp",
+    "symbol_name_not_regexp",
+    "symbol_version",
+    "symbol_version_regexp",
+  };
+  if (!check_sufficient_props(sufficient_props,
+			      sizeof(sufficient_props)/sizeof(char*),
+			      section))
+    return result;
+
   ini::simple_property_sptr drop_artifact =
     is_simple_property(section.find_property("drop_artifact"));
   if (!drop_artifact)
@@ -3283,32 +3334,16 @@ read_function_suppression(const ini::config::section& section)
 	  parms.push_back(parm);
       }
 
-  if (!label_str.empty()
-      || !name.empty()
-      || !name_regex_str.empty()
-      || !name_not_regex_str.empty()
-      || !file_name_regex_str.empty()
-      || !file_name_not_regex_str.empty()
-      || !soname_regex_str.empty()
-      || !soname_not_regex_str.empty()
-      || !return_type_name.empty()
-      || !return_type_regex_str.empty()
-      || !sym_name.empty()
-      || !sym_name_regex_str.empty()
-      || !sym_name_not_regex_str.empty()
-      || !sym_version.empty()
-      || !sym_ver_regex_str.empty()
-      || !parms.empty())
-
-    result.reset(new function_suppression(label_str, name,
-					  name_regex_str,
-					  return_type_name,
-					  return_type_regex_str,
-					  parms,
-					  sym_name,
-					  sym_name_regex_str,
-					  sym_version,
-					  sym_ver_regex_str));
+  result.reset(new function_suppression(label_str,
+					name,
+					name_regex_str,
+					return_type_name,
+					return_type_regex_str,
+					parms,
+					sym_name,
+					sym_name_regex_str,
+					sym_version,
+					sym_ver_regex_str));
 
   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
       && (!name.empty()
@@ -3319,11 +3354,11 @@ read_function_suppression(const ini::config::section& section)
 	  || !sym_name_not_regex_str.empty()))
     result->set_drops_artifact_from_ir(true);
 
-  if (result && !change_kind_str.empty())
+  if (!change_kind_str.empty())
     result->set_change_kind
       (function_suppression::parse_change_kind(change_kind_str));
 
-  if (result && !allow_other_aliases.empty())
+  if (!allow_other_aliases.empty())
     result->set_allow_other_aliases(allow_other_aliases == "yes"
 				    || allow_other_aliases == "true");
 
@@ -4046,6 +4081,28 @@ read_variable_suppression(const ini::config::section& section)
   if (section.get_name() != "suppress_variable")
     return result;
 
+  static const char *const sufficient_props[] = {
+    "label",
+    "file_name_regexp",
+    "file_name_not_regexp",
+    "soname_regexp",
+    "soname_not_regexp",
+    "name",
+    "name_regexp",
+    "name_not_regexp",
+    "symbol_name",
+    "symbol_name_regexp",
+    "symbol_name_not_regexp",
+    "symbol_version",
+    "symbol_version_regexp",
+    "type_name",
+    "type_name_regexp",
+  };
+  if (!check_sufficient_props(sufficient_props,
+			      sizeof(sufficient_props)/sizeof(char*),
+			      section))
+    return result;
+
   ini::simple_property_sptr drop_artifact =
     is_simple_property(section.find_property("drop_artifact"));
   if (!drop_artifact)
@@ -4151,27 +4208,15 @@ read_variable_suppression(const ini::config::section& section)
     ? type_name_regex_prop->get_value()->as_string()
      : "";
 
-  if (label_str.empty()
-      && name_str.empty()
-      && name_regex_str.empty()
-      && name_not_regex_str.empty()
-      && file_name_regex_str.empty()
-      && file_name_not_regex_str.empty()
-      && soname_regex_str.empty()
-      && soname_not_regex_str.empty()
-      && symbol_name.empty()
-      && symbol_name_regex_str.empty()
-      && symbol_name_not_regex_str.empty()
-      && symbol_version.empty()
-      && symbol_version_regex_str.empty()
-      && type_name_str.empty()
-      && type_name_regex_str.empty())
-    return result;
-
-  result.reset(new variable_suppression(label_str, name_str, name_regex_str,
-					symbol_name, symbol_name_regex_str,
-					symbol_version, symbol_version_regex_str,
-					type_name_str, type_name_regex_str));
+  result.reset(new variable_suppression(label_str,
+					name_str,
+					name_regex_str,
+					symbol_name,
+					symbol_name_regex_str,
+					symbol_version,
+					symbol_version_regex_str,
+					type_name_str,
+					type_name_regex_str));
 
   if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
       && (!name_str.empty()
@@ -4188,7 +4233,7 @@ read_variable_suppression(const ini::config::section& section)
   if (!symbol_name_not_regex_str.empty())
     result->set_symbol_name_not_regex_str(symbol_name_not_regex_str);
 
-  if (result && !change_kind_str.empty())
+  if (!change_kind_str.empty())
     result->set_change_kind
       (variable_suppression::parse_change_kind(change_kind_str));
 
@@ -4301,6 +4346,17 @@ read_file_suppression(const ini::config::section& section)
   if (section.get_name() != "suppress_file")
     return result;
 
+  static const char *const sufficient_props[] = {
+    "file_name_regexp",
+    "file_name_not_regexp",
+    "soname_regexp",
+    "soname_not_regexp",
+  };
+  if (!check_sufficient_props(sufficient_props,
+			      sizeof(sufficient_props)/sizeof(char*),
+			      section))
+    return result;
+
   ini::simple_property_sptr label_prop =
     is_simple_property(section.find_property("label"));
   string label_str = (label_prop
@@ -4331,12 +4387,6 @@ read_file_suppression(const ini::config::section& section)
     ? soname_not_regex_prop->get_value()->as_string()
     : "";
 
-  if (file_name_regex_str.empty()
-      && file_name_not_regex_str.empty()
-      && soname_regex_str.empty()
-      && soname_not_regex_str.empty())
-    return result;
-
   result.reset(new file_suppression(label_str,
 				    file_name_regex_str,
 				    file_name_not_regex_str));
diff --git a/tests/data/test-diff-suppr/test15-suppr-added-fn-4.suppr b/tests/data/test-diff-suppr/test15-suppr-added-fn-4.suppr
index 0c9ea2c1..2b148904 100644
--- a/tests/data/test-diff-suppr/test15-suppr-added-fn-4.suppr
+++ b/tests/data/test-diff-suppr/test15-suppr-added-fn-4.suppr
@@ -1,2 +1,3 @@
+# This suppression is ignored as change_kind alone is insufficient.
 [suppress_function]
   change_kind = added-function
diff --git a/tests/data/test-diff-suppr/test16-suppr-removed-fn-4.suppr b/tests/data/test-diff-suppr/test16-suppr-removed-fn-4.suppr
index a04e0e8c..8058ba72 100644
--- a/tests/data/test-diff-suppr/test16-suppr-removed-fn-4.suppr
+++ b/tests/data/test-diff-suppr/test16-suppr-removed-fn-4.suppr
@@ -1,2 +1,3 @@
+# This suppression is ignored as change_kind alone is insufficient.
 [suppress_function]
   change_kind = all
diff --git a/tests/data/test-diff-suppr/test17-suppr-added-var-4.suppr b/tests/data/test-diff-suppr/test17-suppr-added-var-4.suppr
index 05c3bd65..e0dcc904 100644
--- a/tests/data/test-diff-suppr/test17-suppr-added-var-4.suppr
+++ b/tests/data/test-diff-suppr/test17-suppr-added-var-4.suppr
@@ -1,2 +1,3 @@
+# This suppression is ignored as change_kind alone is insufficient.
 [suppress_variable]
   change_kind = all
diff --git a/tests/data/test-diff-suppr/test18-suppr-removed-var-4.suppr b/tests/data/test-diff-suppr/test18-suppr-removed-var-4.suppr
index 05c3bd65..e0dcc904 100644
--- a/tests/data/test-diff-suppr/test18-suppr-removed-var-4.suppr
+++ b/tests/data/test-diff-suppr/test18-suppr-removed-var-4.suppr
@@ -1,2 +1,3 @@
+# This suppression is ignored as change_kind alone is insufficient.
 [suppress_variable]
   change_kind = all
-- 
2.26.2.645.ge9eca65c58-goog


^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v5 05/15] Tidy checks for sufficient suppression properties.
  2020-05-12 10:14               ` [PATCH v5 05/15] Tidy checks for sufficient suppression properties Giuliano Procida
@ 2020-05-12 16:11                 ` Dodji Seketeli
  0 siblings, 0 replies; 120+ messages in thread
From: Dodji Seketeli @ 2020-05-12 16:11 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, kernel-team

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

> Each suppression specification must have at least one of a documented
> per-suppression type list of properties defined if it is to be
> considered at all.
>
> At present:
>
> - suppression specifications which fail the check are silently ignored
> - in the function suppression case, the check does not trigger an
>   early return and risks a later null pointer dereference.
>
> This commit:
>
> - reimplements the checks using arrays and helper function calls
> - adds a helper function to determine if a suppression specification
>   is going to be ignored due a lack of properties
> - makes the parsing functions return failure early if the check fails
>
> Inconsistencies between suppression types (in particular, the
> treatment of the "label" property) remain.
>
> The only behavioural change may be to how present but empty properties
> are handled. This is an edge case that may be worth revisiting in a
> more general fashion in a later commit.
>
> 	* src/abg-suppression.cc (check_sufficient_props): New helper
> 	function to check for sufficient properties in a section.
> 	(read_type_suppression): Replace conditional logic with call
> 	to check_sufficient_props.
> 	(read_function_suppression): Ditto.
> 	(read_variable_suppression): Ditto.
> 	(read_file_suppression): Ditto.
> 	* tests/data/test-diff-suppr/test15-suppr-added-fn-4.suppr:
> 	Explain why the suppression will be ignored.
> 	* tests/data/test-diff-suppr/test16-suppr-removed-fn-4.suppr:
> 	Ditto.
> 	* tests/data/test-diff-suppr/test17-suppr-added-var-4.suppr:
> 	Ditto.
> 	* tests/data/test-diff-suppr/test18-suppr-removed-var-4.suppr:
> 	Ditto.

Applied to master, thanks!

[...]

> Signed-off-by: Giuliano Procida <gprocida@google.com>
  Acked-by: Dodji Seketeli <dodji@seketeli.org>

Cheers,

-- 
		Dodji

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v4 08/15] Use regex::match wrapper instead of regexec.
  2020-05-04 12:34     ` [PATCH v4 08/15] Use regex::match wrapper instead of regexec Giuliano Procida
@ 2020-05-12 16:35       ` Dodji Seketeli
  0 siblings, 0 replies; 120+ messages in thread
From: Dodji Seketeli @ 2020-05-12 16:35 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, kernel-team, maennich

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

> This patch eliminates all calls to regexec except that by regex::match
> itself.
>
> There are no behavioural changes.
>
> 	* src/abg-corpus-priv.h: Mechanically substitute use of
> 	regexec with regex::match wrapper.
> 	* src/abg-suppression-priv.h: Ditto.
> 	* src/abg-suppression.cc: Ditto.

Applied to master, thanks!

> Reviewed-by: Matthias Maennich <maennich@google.com>
> Signed-off-by: Giuliano Procida <gprocida@google.com>
  Acked-by: Dodji Seketeli <dodji@seketeli.org>

[...]

Cheers,

-- 
		Dodji

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v4 09/15] Refactor read_parameter_spec_from_string logic.
  2020-05-04 12:34     ` [PATCH v4 09/15] Refactor read_parameter_spec_from_string logic Giuliano Procida
@ 2020-05-13  7:51       ` Dodji Seketeli
  0 siblings, 0 replies; 120+ messages in thread
From: Dodji Seketeli @ 2020-05-13  7:51 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, kernel-team, maennich

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

> This function extracts either a string or a regex from the same input.
> This patch simplifies the string vs regex conditional logic, in order
> to make following patches simpler.
>
> There are no behavioural changes.
>
> 	* src/abg-suppression.cc (read_parameter_spec_from_string):
> 	Use separate string and regex variables to simplify the
> 	creation of returned parameter specification.

Acked-by: Dodji Seketeli <dodji@seketeli.org>

Applied to master, thanks.

[...]

Cheers,

-- 
		Dodji

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v4 10/15] Compile suppression regexes earlier.
  2020-05-04 12:34     ` [PATCH v4 10/15] Compile suppression regexes earlier Giuliano Procida
  2020-05-04 13:14       ` Matthias Maennich
@ 2020-05-13  8:07       ` Dodji Seketeli
  2020-05-13 15:36         ` Giuliano Procida
  1 sibling, 1 reply; 120+ messages in thread
From: Dodji Seketeli @ 2020-05-13  8:07 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, kernel-team, maennich

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

> Regexes are used in suppression specifications for various things.
> They are currently compiled on first use, rather than on construction
> of the specifications.
>
> This patches changes the suppression specification types to hold
> compiled regexes directly which is a significant simplification and is
> a prerequisite for early error reporting.

[...]

> diff --git a/include/abg-suppression.h b/include/abg-suppression.h
> index 6383b932..8256f9b8 100644
> --- a/include/abg-suppression.h
> +++ b/include/abg-suppression.h
> @@ -26,6 +26,7 @@
>  #include "abg-cxx-compat.h"
>  #include "abg-ini.h"
>  #include "abg-comparison.h"
> +#include "abg-regex.h"
>  
>  namespace abigail
>  {
> @@ -64,8 +65,8 @@ public:
>    suppression_base(const string& label);
>  
>    suppression_base(const string& label,
> -		   const string& file_name_regex_str,
> -		   const string& file_name_not_regex_str);
> +		   const regex::regex_t_sptr& file_name_regex,
> +		   const regex::regex_t_sptr& file_name_not_regex);

I am not against compiling the regular expressions early.

However, I don't like leaking the regex_t type through the suppression
API.  I'd really prefer the compiled regular expression type to stay
internal to the suppression API.

In other words, existing users of the library who created suppressions
just using regular expressions strings (as opposed to compiled regular
expressions) to interact with the API should be able to continue to do
so.  This breaks the API compatibility un-necessarily, IMHO.  I'd like
to avoid that.  And I don't think it's a design flaw to interact with
the API just through strings, as opposed to using it through regex_t,
quite the opposite.  It was a design decision that I tried to stick to
throughout the library.  The reader interface does't leak the underlying
XML library types.  The dwarf reader doesn't leak the types of the
underlying facilities we use, etc.  So I'd like this to stay consistent
accross the library.

I am sorry to tell you this this late.  I could have saved you a lot of
work; I didn't realize in our discussions that this was what you wanted
to do.

Cheers,

-- 
		Dodji

^ permalink raw reply	[flat|nested] 120+ messages in thread

* Re: [PATCH v4 10/15] Compile suppression regexes earlier.
  2020-05-13  8:07       ` Dodji Seketeli
@ 2020-05-13 15:36         ` Giuliano Procida
  0 siblings, 0 replies; 120+ messages in thread
From: Giuliano Procida @ 2020-05-13 15:36 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: libabigail, kernel-team, Matthias Männich

Hi there.

On Wed, 13 May 2020 at 09:07, Dodji Seketeli <dodji@seketeli.org> wrote:

> Giuliano Procida <gprocida@google.com> a écrit:
>
> > Regexes are used in suppression specifications for various things.
> > They are currently compiled on first use, rather than on construction
> > of the specifications.
> >
> > This patches changes the suppression specification types to hold
> > compiled regexes directly which is a significant simplification and is
> > a prerequisite for early error reporting.
>
> [...]
>
> > diff --git a/include/abg-suppression.h b/include/abg-suppression.h
> > index 6383b932..8256f9b8 100644
> > --- a/include/abg-suppression.h
> > +++ b/include/abg-suppression.h
> > @@ -26,6 +26,7 @@
> >  #include "abg-cxx-compat.h"
> >  #include "abg-ini.h"
> >  #include "abg-comparison.h"
> > +#include "abg-regex.h"
> >
> >  namespace abigail
> >  {
> > @@ -64,8 +65,8 @@ public:
> >    suppression_base(const string& label);
> >
> >    suppression_base(const string& label,
> > -                const string& file_name_regex_str,
> > -                const string& file_name_not_regex_str);
> > +                const regex::regex_t_sptr& file_name_regex,
> > +                const regex::regex_t_sptr& file_name_not_regex);
>
> I am not against compiling the regular expressions early.
>
> However, I don't like leaking the regex_t type through the suppression
> API.  I'd really prefer the compiled regular expression type to stay
> internal to the suppression API.
>

Mostly as an aside, I considered whether it would be worth wrapping up
regex_t in a type that was more than just a shared_ptr with a specialised
destructor. While it would be nice to have a copyable value type, this is a
poor fit for regex_t which isn't copyable. The existing regex_t_sptr type
is OK but lacks a way to create new memset-to-0 regex_t objects and there
is no const-protecting version. We should really be looking ahead to when
we can switch to std::basic_regex or similar, wrapped in std::optional
when... optional. std::basic_regex throws an exception on construction if
the regex cannot be compiled. I think it would be reasonable to have this
standard library type as part of the suppression API going forward.

If the suppression API has to remain stable between major releases of
libabigail, then we can never remove things like:

// does not check validity of regexp
void set_file_name_not_regex_str(const string& regexp);
// allows nominally constant insertion ranges to be mutated
const insertion_ranges& get_data_member_insertion_ranges() const;

I do understand we can add always to the interface, but we may end up with
more code than we'd like to maintain.

In other words, existing users of the library who created suppressions
> just using regular expressions strings (as opposed to compiled regular
> expressions) to interact with the API should be able to continue to do
> so.  This breaks the API compatibility un-necessarily, IMHO.  I'd like
> to avoid that.  And I don't think it's a design flaw to interact with
> the API just through strings, as opposed to using it through regex_t,
> quite the opposite.  It was a design decision that I tried to stick to
> throughout the library.  The reader interface does't leak the underlying
> XML library types.  The dwarf reader doesn't leak the types of the
> underlying facilities we use, etc.  So I'd like this to stay consistent
> accross the library.
>

A large surface has been exposed in abg-suppression.h, including plenty of
things that could be considered implementation details. I might have
envisaged exposing a single function or method, something like:

  bool read_suppressions(std::istream& is, ...);

However, what is completely unclear to (Matthias and) me is: what users of
libabigail-as-a-library there are and what they might like to see in the
way of interface change or stability. Can you shed any light on this?

I am sorry to tell you this this late.  I could have saved you a lot of
> work; I didn't realize in our discussions that this was what you wanted
> to do.
>

We did discuss changing the internal representation of regexes (dropping
the string representation) and this implies dropping all the

  const string& get_foo_regex_str() const;

methods from the interface.

I also mentioned perhaps keeping the string representation around for error
reporting. But with early compilation of regexes, that buys very little.
There is one possible use-case: semantic checks on regexes and other
suppression properties.

I've already contributed abg-regex.h to the public interface.

But, never mind. I can look at reworking my patch series to preserve the
existing exposed API in abg-suppression.h. I predict considerable extra
complexity in two areas (regexes and insertion ranges) and some minor extra
complications in others (enums used for change kinds etc.). However, this
will not happen any time soon as I need to focus on bugs and features that
are more relevant to kernel ABI work.

It makes sense to consider the rest of the patches in the series posted to
the list as abandoned, though you might possibly want to adapt
"abg-tools-utils.cc: Assert generated regexes OK."


> Cheers,
>
> --
>                 Dodji
>

Regards,
Giuliano.


> --
> To unsubscribe from this group and stop receiving emails from it, send an
> email to kernel-team+unsubscribe@android.com.
>
>

^ permalink raw reply	[flat|nested] 120+ messages in thread

end of thread, other threads:[~2020-05-13 15:37 UTC | newest]

Thread overview: 120+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-23 15:44 [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
2020-04-23 15:44 ` [PATCH 01/21] Move regex definitions to own files Giuliano Procida
2020-04-23 15:44 ` [PATCH 02/21] Move libxml bits out of abg-sptr-utils.h Giuliano Procida
2020-04-23 15:44 ` [PATCH 03/21] Simplify generation of symbol whitelist regex Giuliano Procida
2020-04-23 15:44 ` [PATCH 04/21] Escape names used in symbol whitelisting regex Giuliano Procida
2020-04-23 15:44 ` [PATCH 05/21] abg-suppression.cc: More uniform variable naming Giuliano Procida
2020-04-23 15:44 ` [PATCH 06/21] diff suppression: Fix handling of change kinds Giuliano Procida
2020-04-23 15:44 ` [PATCH 07/21] Add POSIX regex wrapper functions Giuliano Procida
2020-04-23 18:07   ` [PATCH v2 " Giuliano Procida
2020-04-23 15:44 ` [PATCH 08/21] Use regex::compile wrapper instead of regcomp Giuliano Procida
2020-04-23 15:44 ` [PATCH 09/21] Use regex::match wrapper instead of regexec Giuliano Procida
2020-04-23 18:02   ` [PATCH v2 " Giuliano Procida
2020-04-23 15:44 ` [PATCH 10/21] Refactor read_parameter_spec_from_string logic Giuliano Procida
2020-04-23 15:44 ` [PATCH 11/21] Compile suppression regexes earlier Giuliano Procida
2020-04-23 15:44 ` [PATCH 12/21] Reduce direct access to suppression priv_ members Giuliano Procida
2020-04-23 15:44 ` [PATCH 13/21] Move match methods from priv to suppression_base Giuliano Procida
2020-04-23 15:44 ` [PATCH 14/21] Remove suppression types' priv class methods Giuliano Procida
2020-04-23 15:44 ` [PATCH 15/21] abg-suppression.cc: More consistent regex matching Giuliano Procida
2020-04-23 15:44 ` [PATCH 16/21] abg-tools-utils.cc: Assert generated regexes OK Giuliano Procida
2020-04-23 15:44 ` [PATCH 17/21] Refactor suppression property string parsing Giuliano Procida
2020-04-23 15:44 ` [PATCH 18/21] Refactor suppression property regex parsing Giuliano Procida
2020-04-23 15:44 ` [PATCH 19/21] Warn if user-supplied regexes fail to compile Giuliano Procida
2020-04-23 18:04   ` [PATCH v2 " Giuliano Procida
2020-04-23 15:44 ` [PATCH 20/21] Default construct suppression types Giuliano Procida
2020-04-23 15:44 ` [PATCH 21/21] Remove unused suppression type priv constructors Giuliano Procida
2020-04-23 18:11 ` [PATCH 00/21] Simplify regex and suppression parsing Giuliano Procida
2020-04-24  8:54   ` Giuliano Procida
2020-04-24  9:21 ` [PATCH v3 00/21]Simplify " Giuliano Procida
2020-04-24  9:21   ` [PATCH v3 01/21] Move regex definitions to own files Giuliano Procida
2020-04-27 10:52     ` Matthias Maennich
2020-04-29 14:19       ` Dodji Seketeli
2020-04-29 14:35         ` Giuliano Procida
2020-05-04  9:19     ` Dodji Seketeli
2020-04-24  9:21   ` [PATCH v3 02/21] Move libxml bits out of abg-sptr-utils.h Giuliano Procida
2020-04-27 10:53     ` Matthias Maennich
2020-04-29 14:30     ` Dodji Seketeli
2020-05-04  9:20     ` Dodji Seketeli
2020-04-24  9:21   ` [PATCH v3 03/21] Simplify generation of symbol whitelist regex Giuliano Procida
2020-04-27 11:01     ` Matthias Maennich
2020-04-27 15:31       ` Giuliano Procida
2020-05-04  9:20     ` Dodji Seketeli
2020-04-24  9:21   ` [PATCH v3 04/21] Escape names used in symbol whitelisting regex Giuliano Procida
2020-04-27 11:14     ` Matthias Maennich
2020-04-27 15:37       ` Giuliano Procida
2020-04-24  9:21   ` [PATCH v3 05/21] abg-suppression.cc: More uniform variable naming Giuliano Procida
2020-04-27 11:17     ` Matthias Maennich
2020-04-24  9:21   ` [PATCH v3 06/21] diff suppression: Fix handling of change kinds Giuliano Procida
2020-04-24  9:21   ` [PATCH v3 07/21] Add POSIX regex wrapper functions Giuliano Procida
2020-04-27 11:23     ` Matthias Maennich
2020-04-24  9:21   ` [PATCH v3 08/21] Use regex::compile wrapper instead of regcomp Giuliano Procida
2020-04-27 11:34     ` Matthias Maennich
2020-04-27 16:01       ` Giuliano Procida
2020-04-24  9:21   ` [PATCH v3 09/21] Use regex::match wrapper instead of regexec Giuliano Procida
2020-04-27 11:38     ` Matthias Maennich
2020-04-24  9:21   ` [PATCH v3 10/21] Refactor read_parameter_spec_from_string logic Giuliano Procida
2020-04-24  9:21   ` [PATCH v3 11/21] Compile suppression regexes earlier Giuliano Procida
2020-04-24  9:21   ` [PATCH v3 12/21] Reduce direct access to suppression priv_ members Giuliano Procida
2020-04-27 11:54     ` Matthias Maennich
2020-04-24  9:21   ` [PATCH v3 13/21] Move match methods from priv to suppression_base Giuliano Procida
2020-04-27 11:55     ` Matthias Maennich
2020-04-24  9:21   ` [PATCH v3 14/21] Remove suppression types' priv class methods Giuliano Procida
2020-04-27 11:57     ` Matthias Maennich
2020-04-24  9:21   ` [PATCH v3 15/21] abg-suppression.cc: More consistent regex matching Giuliano Procida
2020-04-27 12:07     ` Matthias Maennich
2020-04-27 16:18       ` Giuliano Procida
2020-04-24  9:21   ` [PATCH v3 16/21] abg-tools-utils.cc: Assert generated regexes OK Giuliano Procida
2020-04-27 12:08     ` Matthias Maennich
2020-04-27 16:21       ` Giuliano Procida
2020-04-24  9:21   ` [PATCH v3 17/21] Refactor suppression property string parsing Giuliano Procida
2020-04-27 12:17     ` Matthias Maennich
2020-04-27 16:42       ` Giuliano Procida
2020-04-24  9:21   ` [PATCH v3 18/21] Refactor suppression property regex parsing Giuliano Procida
2020-04-27 14:55     ` Matthias Maennich
2020-04-27 16:59       ` Giuliano Procida
2020-04-24  9:21   ` [PATCH v3 19/21] Warn if user-supplied regexes fail to compile Giuliano Procida
2020-04-27 15:36     ` Matthias Maennich
2020-05-01  8:49       ` Giuliano Procida
2020-04-24  9:21   ` [PATCH v3 20/21] Default construct suppression types Giuliano Procida
2020-04-27 15:40     ` Matthias Maennich
2020-04-24  9:21   ` [PATCH v3 21/21] Remove unused suppression type priv constructors Giuliano Procida
2020-04-27 15:41     ` Matthias Maennich
2020-05-04 12:34   ` [PATCH v4 00/15] Simplify regex and suppression parsing Giuliano Procida
2020-05-04 12:34     ` [PATCH v4 01/15] Tidy #includes in a few files Giuliano Procida
2020-05-04 12:49       ` Matthias Maennich
2020-05-11 13:24       ` Dodji Seketeli
2020-05-04 12:34     ` [PATCH v4 02/15] Document ^_^ regex in generate_from_strings Giuliano Procida
2020-05-04 12:49       ` Matthias Maennich
2020-05-11 13:32       ` Dodji Seketeli
2020-05-04 12:34     ` [PATCH v4 03/15] Escape names used in symbol whitelisting regex Giuliano Procida
2020-05-04 12:57       ` Matthias Maennich
2020-05-04 16:45         ` [PATCH v5 " Giuliano Procida
2020-05-11 13:59           ` Dodji Seketeli
2020-05-04 12:34     ` [PATCH v4 04/15] abg-suppression.cc: More uniform variable naming Giuliano Procida
2020-05-11 14:04       ` Dodji Seketeli
2020-05-04 12:34     ` [PATCH v4 05/15] diff suppression: Fix handling of change kinds Giuliano Procida
2020-05-04 13:04       ` Matthias Maennich
2020-05-11 14:15       ` Dodji Seketeli
2020-05-11 15:47         ` Giuliano Procida
2020-05-11 17:53           ` Dodji Seketeli
2020-05-12  9:54             ` Giuliano Procida
2020-05-12 10:14               ` [PATCH v5 05/15] Tidy checks for sufficient suppression properties Giuliano Procida
2020-05-12 16:11                 ` Dodji Seketeli
2020-05-04 12:34     ` [PATCH v4 06/15] Add POSIX regex wrapper functions Giuliano Procida
2020-05-11 16:37       ` Dodji Seketeli
2020-05-04 12:34     ` [PATCH v4 07/15] Use regex::compile wrapper instead of regcomp Giuliano Procida
2020-05-11 16:38       ` Dodji Seketeli
2020-05-04 12:34     ` [PATCH v4 08/15] Use regex::match wrapper instead of regexec Giuliano Procida
2020-05-12 16:35       ` Dodji Seketeli
2020-05-04 12:34     ` [PATCH v4 09/15] Refactor read_parameter_spec_from_string logic Giuliano Procida
2020-05-13  7:51       ` Dodji Seketeli
2020-05-04 12:34     ` [PATCH v4 10/15] Compile suppression regexes earlier Giuliano Procida
2020-05-04 13:14       ` Matthias Maennich
2020-05-13  8:07       ` Dodji Seketeli
2020-05-13 15:36         ` Giuliano Procida
2020-05-04 12:34     ` [PATCH v4 11/15] Reduce direct access to suppression priv_ members Giuliano Procida
2020-05-04 12:34     ` [PATCH v4 12/15] Move match methods from priv to suppression_base Giuliano Procida
2020-05-04 12:34     ` [PATCH v4 13/15] Remove suppression type priv class methods Giuliano Procida
2020-05-04 12:34     ` [PATCH v4 14/15] abg-suppression.cc: More consistent regex matching Giuliano Procida
2020-05-04 13:17       ` Matthias Maennich
2020-05-04 12:34     ` [PATCH v4 15/15] abg-tools-utils.cc: Assert generated regexes OK Giuliano Procida

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).