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