defined in header files whose path match the regular expression
provided a value of the property.
+ .. _suppr_has_data_member_label:
+
+* ``has_data_member``
+
+ Usage:
+
+ ``has_data_member`` ``=`` <``list-of-data-member-names``>
+
+Suppresses change reports involving a type which contains data members
+whose names are provided in the list value of this property.
+
+A usage examples of this property would be: ::
+
+ has_data_member = {private_data_member0, private_data_member1}
+
+
+The property above would match any type which contains at least two
+data members whose names are ``private_data_member0`` and
+``private_data_member1``.
+
+Another usage examples of this property would be: ::
+
+ has_data_member = another_private_data_member
+
+The property above would match any type which contains
+a data member which name is ``another_private_data_member0``.
+
+ .. _suppr_has_data_member_regexp_label:
+
+* ``has_data_member_regexp``
+
+ Usage:
+
+ ``has_data_member_regexp`` ``=`` <``a-regular-expression``>
+
+Suppresses change reports involving a type which contains data members
+whose names match the regular expression provided as the value of this
+property.
+
+A usage examples of this property would be: ::
+
+ has_data_member_regexp = ^private_data_member
+
+The property above would match any type which contains data members
+whose names match the regular expression ``^private_data_member``. In
+other words, it would match any type which contains data members whose
+names start with the string "private_data_member".
+
.. _suppr_has_data_member_inserted_at_label:
* ``has_data_member_inserted_at``
#include <string>
#include <typeinfo>
#include <unordered_map>
+#include <unordered_set>
#include <utility> // for std::rel_ops, at least.
#include <vector>
#include "abg-interned-str.h"
using std::unordered_map;
using std::string;
using std::vector;
+using std::unordered_set;
+
+typedef unordered_set<string> string_set_type;
// Pull in relational operators.
using namespace std::rel_ops;
void
set_reach_kind(reach_kind k);
+ const string_set_type&
+ get_potential_data_member_names() const;
+
+ void
+ set_potential_data_member_names(const string_set_type&) const;
+
+ const string&
+ get_potential_data_member_names_regex_str() const;
+
+ void
+ set_potential_data_member_names_regex_str(const string&) const;
+
void
set_data_member_insertion_ranges(const insertion_ranges& r);
type_suppression::type_kind type_kind_;
bool consider_reach_kind_;
type_suppression::reach_kind reach_kind_;
+ // The data members a class needs to have to match this suppression
+ // specification. These might be selected by a regular expression.
+ string_set_type potential_data_members_;
+ // The regular expression string that selects the potential data
+ // members of the class.
+ string potential_data_members_regex_str_;
+ // The compiled regular expression that selects the potential data
+ // members of the class.
+ mutable regex::regex_t_sptr potential_data_members_regex_;
type_suppression::insertion_ranges insertion_ranges_;
unordered_set<string> source_locations_to_keep_;
string source_location_to_keep_regex_str_;
set_source_location_to_keep_regex(regex::regex_t_sptr r)
{source_location_to_keep_regex_ = r;}
+ /// Getter for the "potential_data_member_names_regex" object.
+ ///
+ /// This regex object matches the names of the data members that are
+ /// needed for this suppression specification to select the type.
+ ///
+ /// @return the "potential_data_member_names_regex" object.
+ const regex::regex_t_sptr
+ get_potential_data_member_names_regex() const
+ {
+ if (!potential_data_members_regex_
+ && !potential_data_members_regex_str_.empty())
+ {
+ potential_data_members_regex_ =
+ regex::compile(potential_data_members_regex_str_);
+ }
+ return potential_data_members_regex_;
+ }
+
+ /// Setter for the "potential_data_member_names_regex" object.
+ ///
+ /// This regex object matches the names of the data members that are
+ /// needed for this suppression specification to select the type.
+ ///
+ /// @param r the new "potential_data_member_names_regex" object.
+ void
+ set_potential_data_member_names_regex(regex::regex_t_sptr &r)
+ {potential_data_members_regex_ = r;}
+
friend class type_suppression;
}; // class type_suppression::priv
type_suppression::set_reach_kind(reach_kind k)
{priv_->reach_kind_ = k;}
+/// Getter of the "potential_data_member_names" property.
+///
+/// @return the set of potential data member names of this
+/// suppression.
+const unordered_set<string>&
+type_suppression::get_potential_data_member_names() const
+{return priv_->potential_data_members_;}
+
+/// Setter of the "potential_data_member_names" property.
+///
+/// @param s the new set of potential data member names of this
+/// suppression.
+void
+type_suppression::set_potential_data_member_names
+(const string_set_type& s) const
+{priv_->potential_data_members_ = s;}
+
+/// Getter of the "potential_data_member_names_regex" string.
+///
+/// @return the "potential_data_member_names_regex" string.
+const string&
+type_suppression::get_potential_data_member_names_regex_str() const
+{return priv_->potential_data_members_regex_str_;}
+
+/// Setter of the "potential_data_member_names_regex" string.
+///
+/// @param d the new "potential_data_member_names_regex" string.
+void
+type_suppression::set_potential_data_member_names_regex_str
+(const string& d) const
+{priv_->potential_data_members_regex_str_ = d;}
+
/// Setter for the vector of data member insertion ranges that
/// specifies where a data member is inserted as far as this
/// suppression specification is concerned.
// Now let's consider class diffs in the context of a suppr spec
// that contains properties like "has_data_member_inserted_*".
+ const class_or_union_diff* cou_diff = is_class_or_union_diff(d);
+ if (cou_diff)
+ {
+ class_or_union_sptr f = cou_diff->first_class_or_union();
+ // We are looking at the a class or union diff ...
+ if (!get_potential_data_member_names().empty())
+ {
+ // ... and the suppr spec has a:
+ //
+ // "has_data_member = {foo, bar}" property
+ //
+ for (string var_name : get_potential_data_member_names())
+ if (!f->find_data_member(var_name))
+ return false;
+ }
+
+ if (!get_potential_data_member_names_regex_str().empty())
+ {
+ if (const regex_t_sptr& data_member_name_regex =
+ priv_->get_potential_data_member_names_regex())
+ {
+ bool data_member_matched = false;
+ for (var_decl_sptr dm : f->get_data_members())
+ {
+ if (regex::match(data_member_name_regex, dm->get_name()))
+ {
+ data_member_matched = true;
+ break;
+ }
+ }
+ if (!data_member_matched)
+ return false;
+ }
+ }
+ }
+
+ // Evaluate has_data_member_inserted_*" clauses.
const class_diff* klass_diff = dynamic_cast<const class_diff*>(d);
if (klass_diff)
{
read_suppression_reach_kind(reach_kind_prop->get_value()->as_string());
}
+ // Support has_data_member = {}
+ string_set_type potential_data_member_names;
+ if (ini::property_sptr propertee = section.find_property("has_data_member"))
+ {
+ // This is either has_data_member = {foo, blah} or
+ // has_data_member = foo.
+ ini::tuple_property_value_sptr tv;
+ ini::string_property_value_sptr sv;
+ if (ini::tuple_property_sptr prop = is_tuple_property(propertee))
+ // Value is of the form {foo,blah}
+ tv = prop->get_value();
+ else if (ini::simple_property_sptr prop = is_simple_property(propertee))
+ // Value is of the form foo.
+ sv = prop->get_value();
+
+ // Ensure that the property value has the form {"foo", "blah", ...};
+ // Meaning it's a tuple of one element which is a list or a string.
+ if (tv
+ && tv->get_value_items().size() == 1
+ && (is_list_property_value(tv->get_value_items().front())
+ || is_string_property_value(tv->get_value_items().front())))
+ {
+ ini::list_property_value_sptr val =
+ is_list_property_value(tv->get_value_items().front());
+ if (!val)
+ {
+ // We have just one potential data member name,as a
+ // string_property_value.
+ string name =
+ is_string_property_value(tv->get_value_items().front())
+ ->as_string();
+ potential_data_member_names.insert(name);
+ }
+ else
+ for (const string& name : val->get_content())
+ potential_data_member_names.insert(name);
+ }
+ else if (sv)
+ {
+ string name = sv->as_string();
+ potential_data_member_names.insert(name);
+ }
+ }
+
+ // Support has_data_member_regexp = str
+ string potential_data_member_names_regexp_str;
+ if (ini::simple_property_sptr prop =
+ is_simple_property(section.find_property("has_data_member_regexp")))
+ potential_data_member_names_regexp_str = prop->get_value()->as_string();
+
// Support has_data_member_inserted_at
vector<type_suppression::insertion_range_sptr> insert_ranges;
bool consider_data_member_insertion = false;
result->set_reach_kind(reach_kind);
}
+ if (!potential_data_member_names.empty())
+ result->set_potential_data_member_names(potential_data_member_names);
+
+ if (!potential_data_member_names_regexp_str.empty())
+ result->set_potential_data_member_names_regex_str
+ (potential_data_member_names_regexp_str);
+
if (consider_data_member_insertion)
result->set_data_member_insertion_ranges(insert_ranges);
test-diff-suppr/PR28073/PR28073.before.o.abi \
test-diff-suppr/PR28073/PR28073.c \
test-diff-suppr/PR28073/bitfield.suppr \
+test-diff-suppr/has-data-member-1.suppr \
+test-diff-suppr/has-data-member-2.suppr \
+test-diff-suppr/has-data-member-3.suppr \
+test-diff-suppr/has-data-member-4.suppr \
+test-diff-suppr/has-data-member-5.suppr \
+test-diff-suppr/has-data-member-6.suppr \
+test-diff-suppr/has-data-member-7.suppr \
+test-diff-suppr/test-has-data-member-output-1.txt \
+test-diff-suppr/test-has-data-member-output-2.txt \
+test-diff-suppr/test-has-data-member-v0.cc \
+test-diff-suppr/test-has-data-member-v0.o \
+test-diff-suppr/test-has-data-member-v1.cc \
+test-diff-suppr/test-has-data-member-v1.o \
\
test-diff-dwarf-abixml/test0-pr19026-libvtkIOSQL-6.1.so.1 \
test-diff-dwarf-abixml/test0-pr19026-libvtkIOSQL-6.1.so.1.abi \
--- /dev/null
+[suppress_type]
+ type_kind = struct
+ has_data_member = {private_data_member0, private_data_member1}
--- /dev/null
+[suppress_type]
+ type_kind = struct
+ has_data_member = {private_data_member0}
--- /dev/null
+[suppress_type]
+ type_kind = struct
+ has_data_member = private_data_member1
--- /dev/null
+[suppress_type]
+ type_kind = struct
+ has_data_member = {private_data_member3, private_data_member4}
--- /dev/null
+[suppress_type]
+ type_kind = struct
+ has_data_member = private_data_member5
--- /dev/null
+[suppress_type]
+ type_kind = struct
+ has_data_member_regexp = ^private_data_member
--- /dev/null
+[suppress_type]
+ type_kind = struct
+ has_data_member_regexp = ^private_data_memberWRONG
--- /dev/null
+Functions changes summary: 0 Removed, 2 Changed, 0 Added functions
+Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+
+2 functions with some indirect sub-type change:
+
+ [C] 'function int bar(S1*)' at test-has-data-member-v0.cc:19:1 has some indirect sub-type changes:
+ parameter 1 of type 'S1*' has sub-type changes:
+ in pointed to type 'struct S1' at test-has-data-member-v1.cc:8:1:
+ type size changed from 32 to 64 (in bits)
+ 1 data member insertion:
+ 'char non_suppressed_added_member', at offset 32 (in bits) at test-has-data-member-v1.cc:11:1
+
+ [C] 'function void foo(S0&)' at test-has-data-member-v0.cc:14:1 has some indirect sub-type changes:
+ parameter 1 of type 'S0&' has sub-type changes:
+ in referenced type 'struct S0' at test-has-data-member-v1.cc:1:1:
+ type size changed from 64 to 96 (in bits)
+ 1 data member insertion:
+ 'int suppressed_added_member', at offset 64 (in bits) at test-has-data-member-v1.cc:5:1
+
--- /dev/null
+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 int bar(S1*)' at test-has-data-member-v0.cc:19:1 has some indirect sub-type changes:
+ parameter 1 of type 'S1*' has sub-type changes:
+ in pointed to type 'struct S1' at test-has-data-member-v1.cc:8:1:
+ type size changed from 32 to 64 (in bits)
+ 1 data member insertion:
+ 'char non_suppressed_added_member', at offset 32 (in bits) at test-has-data-member-v1.cc:11:1
+
--- /dev/null
+struct S0
+{
+ int private_data_member0;
+ char private_data_member1;
+};
+
+struct S1
+{
+ int m0;
+};
+
+
+void
+foo(S0&)
+{
+}
+
+int
+bar(S1* s)
+{
+ return s->m0;
+}
--- /dev/null
+struct S0
+{
+ int private_data_member0;
+ char private_data_member1;
+ int suppressed_added_member;
+};
+
+struct S1
+{
+ int m0;
+ char non_suppressed_added_member;
+};
+
+
+void
+foo(S0&)
+{
+}
+
+int
+bar(S1* s)
+{
+ return s->m0;
+}
"data/test-diff-suppr/PR28073/PR28073-output-2.txt",
"output/test-diff-suppr/PR28073/PR28073-output-2.txt"
},
+ {
+ "data/test-diff-suppr/test-has-data-member-v0.o",
+ "data/test-diff-suppr/test-has-data-member-v1.o",
+ "",
+ "",
+ "",
+ "--drop-private-types --no-default-suppression",
+ "data/test-diff-suppr/test-has-data-member-output-1.txt",
+ "output/test-diff-suppr/test-has-data-member-output-1.txt"
+ },
+ {
+ "data/test-diff-suppr/test-has-data-member-v0.o",
+ "data/test-diff-suppr/test-has-data-member-v1.o",
+ "",
+ "",
+ "data/test-diff-suppr/has-data-member-1.suppr",
+ "--drop-private-types --no-default-suppression",
+ "data/test-diff-suppr/test-has-data-member-output-2.txt",
+ "output/test-diff-suppr/test-has-data-member-output-2.1.txt"
+ },
+ {
+ "data/test-diff-suppr/test-has-data-member-v0.o",
+ "data/test-diff-suppr/test-has-data-member-v1.o",
+ "",
+ "",
+ "data/test-diff-suppr/has-data-member-2.suppr",
+ "--drop-private-types --no-default-suppression",
+ "data/test-diff-suppr/test-has-data-member-output-2.txt",
+ "output/test-diff-suppr/test-has-data-member-output-2.2.txt"
+ },
+ {
+ "data/test-diff-suppr/test-has-data-member-v0.o",
+ "data/test-diff-suppr/test-has-data-member-v1.o",
+ "",
+ "",
+ "data/test-diff-suppr/has-data-member-3.suppr",
+ "--drop-private-types --no-default-suppression",
+ "data/test-diff-suppr/test-has-data-member-output-2.txt",
+ "output/test-diff-suppr/test-has-data-member-output-2.3.txt"
+ },
+ {
+ "data/test-diff-suppr/test-has-data-member-v0.o",
+ "data/test-diff-suppr/test-has-data-member-v1.o",
+ "",
+ "",
+ "data/test-diff-suppr/has-data-member-4.suppr",
+ "--drop-private-types --no-default-suppression",
+ "data/test-diff-suppr/test-has-data-member-output-1.txt",
+ "output/test-diff-suppr/test-has-data-member-output-1.2.txt"
+ },
+ {
+ "data/test-diff-suppr/test-has-data-member-v0.o",
+ "data/test-diff-suppr/test-has-data-member-v1.o",
+ "",
+ "",
+ "data/test-diff-suppr/has-data-member-5.suppr",
+ "--drop-private-types --no-default-suppression",
+ "data/test-diff-suppr/test-has-data-member-output-1.txt",
+ "output/test-diff-suppr/test-has-data-member-output-1.3.txt"
+ },
+ {
+ "data/test-diff-suppr/test-has-data-member-v0.o",
+ "data/test-diff-suppr/test-has-data-member-v1.o",
+ "",
+ "",
+ "data/test-diff-suppr/has-data-member-6.suppr",
+ "--drop-private-types --no-default-suppression",
+ "data/test-diff-suppr/test-has-data-member-output-2.txt",
+ "output/test-diff-suppr/test-has-data-member-output-2.4.txt"
+ },
+ {
+ "data/test-diff-suppr/test-has-data-member-v0.o",
+ "data/test-diff-suppr/test-has-data-member-v1.o",
+ "",
+ "",
+ "data/test-diff-suppr/has-data-member-7.suppr",
+ "--drop-private-types --no-default-suppression",
+ "data/test-diff-suppr/test-has-data-member-output-1.txt",
+ "output/test-diff-suppr/test-has-data-member-output-1.4.txt"
+ },
// This should be the last entry
{NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
};