[suppress_type]
soname_regexp = libwebkit2?gtk-.*\\.so.*
- name_regexp = (^std::.*|WebCore::.*|WebKit::.*)
+ name_regexp = ^std::.*
+ drop = true
+
+[suppress_type]
+# Transform all C++ types in the WebCore and WebKit namespaces into
+# opaque types. These are essentially internal types of libwebkit2
+# anyway. This greatly reduces the size of the in-memory working set.
+ label = libabigail::OPAQUE_TYPE_LABEL
+ soname_regexp = libwebkit2?gtk-.*\\.so.*
+ name_regexp = (^WebCore::.*|^WebKit::.*)
+ drop = true
+
+[suppress_type]
+# All structs that don't start with either WebKit* or _WebKit are
+# considered internal types and so are transform into opaque types.
+# This helps to reduce the size of the in-memory working set further.
+ label = libabigail::OPAQUE_TYPE_LABEL
+ soname_regexp = libwebkit2?gtk-.*\\.so.*
+ type_kind = struct
+ name_not_regexp = ^_?WebKit.*
drop = true
#######################################################
Define a label for the section. A label is just an informative
string that might be used by the tool to refer to a type suppression
- in error messages.
+ in error messages. There can also be some special label names that
+ make the suppression system behave a certain way.
* ``soname_regexp``
ABI being analyzed. This property makes its enclosing suppression
specification to be applied in the :ref:`early suppression
specification mode <early_suppression_mode_label>`. The net effect
- is that it potentially reduces the memory used to represent the ABI
- being analyzed.
+ is that it potentially reduces the amount of memory used to represent
+ the ABI being analyzed.
+
+ Please note that for ``struct``, ``class`` or``enum`` types matching
+ a suppression specification with this property having a value set to
+ "yes" (or to "true"), if the specification also has a ``label``
+ property with a value set to ``libabigail::OPAQUE_TYPE_LABEL``, then
+ the type is transformed into an opaque type, rather than being just
+ dropped on the floor. That also reduces the amount of memory used to
+ represent the ABI being analyzed, but with potentially less
+ disruption in the resulting ABI representation.
Please note that for this property to be effective, the enclosing
suppression specification must have at least one of the following
``label`` ``=`` <some-value>
- Define a label for the section. A label is just an informative
- string that might be used by a tool to refer to a type suppression in
- error messages.
-
+ Define a label for the section. In general, a label is just an
+ informative string that might be used by a tool to refer to a type
+ suppression in error messages.
+
+ Note however that there are some special label values that can
+ trigger a special kind of behavior. Below are those special label
+ values:
+
+ * ``libabigail::OPAQUE_TYPE_LABEL``: A struct, class or enum type
+ that matches a ``[suppress_type]`` section with this label
+ property value is going to be replaced by an opaque type of the
+ same kind. Note that an opaque type is essentially a
+ declaration-only type, thus with no member. Also note that for a
+ ``[suppress_type]`` section with this label to trigger the
+ transformation of a type into an opaque type, the section must
+ have the ``drop`` property value set to ``yes|true``.
* ``name``
const suppression_base& suppr);
const char*
-get_private_types_suppr_spec_label();
+get_opaque_types_suppr_spec_label();
bool
-is_private_type_suppr_spec(const type_suppression&);
+is_opaque_type_suppr_spec(const type_suppression&);
bool
-is_private_type_suppr_spec(const suppression_sptr& s);
+is_opaque_type_suppr_spec(const suppression_sptr& s);
bool
suppression_can_match(const fe_iface&,
if (d->suppresses_diff(this))
{
do_suppress = true;
- if (is_private_type_suppr_spec(d))
+ if (is_opaque_type_suppr_spec(d))
is_private_type = true;
break;
}
///
/// @param type_die the DIE that designates the type to consider.
///
-/// @param type_is_private out parameter. If this function returns
+/// @param type_is_opaque out parameter. If this function returns
/// true (the type @p type_die is suppressed) and if the type was
-/// suppressed because it's private then this parameter is set to
+/// suppressed because it's opaque then this parameter is set to
/// true.
///
/// @return true iff the type designated by the DIE @p type_die, in
type_is_suppressed(const reader& rdr,
const scope_decl* scope,
Dwarf_Die *type_die,
- bool &type_is_private)
+ bool &type_is_opaque)
{
if (type_die == 0
|| (dwarf_tag(type_die) != DW_TAG_enumeration_type
return suppr::is_type_suppressed(rdr,
qualified_name,
type_location,
- type_is_private,
+ type_is_opaque,
/*require_drop_property=*/true);
}
const scope_decl* scope,
Dwarf_Die *type_die)
{
- bool type_is_private = false;
- return type_is_suppressed(rdr, scope, type_die, type_is_private);
+ bool type_is_opaque = false;
+ return type_is_suppressed(rdr, scope, type_die, type_is_opaque);
}
/// Get the opaque version of a type that was suppressed because it's
string type_name, linkage_name;
location type_location;
die_loc_and_name(rdr, type_die, type_location, type_name, linkage_name);
- if (!type_location)
- return result;
string qualified_name = build_qualified_name(scope, type_name);
case DW_TAG_enumeration_type:
{
- bool type_is_private = false;
+ bool type_is_opaque = false;
bool type_suppressed =
- type_is_suppressed(rdr, scope, die, type_is_private);
- if (type_suppressed && type_is_private)
+ type_is_suppressed(rdr, scope, die, type_is_opaque);
+ if (type_suppressed && type_is_opaque)
{
// The type is suppressed because it's private. If other
// non-suppressed and declaration-only instances of this
case DW_TAG_class_type:
case DW_TAG_structure_type:
{
- bool type_is_private = false;
+ bool type_is_opaque = false;
bool type_suppressed=
- type_is_suppressed(rdr, scope, die, type_is_private);
+ type_is_suppressed(rdr, scope, die, type_is_opaque);
- if (type_suppressed && type_is_private)
+ if (type_suppressed && type_is_opaque)
{
// The type is suppressed because it's private. If other
// non-suppressed and declaration-only instances of this
// public -- depending on, e.g, if the typedef is defined in a
// public header or not. So if we are in the context of a
// private type suppression let's *NOT* peel typedefs away.
- if (!is_private_type_suppr_spec(*this))
+ if (!is_opaque_type_suppr_spec(*this))
{
ft = peel_typedef_type(ft);
st = peel_typedef_type(st);
// the declaration. If we reach this place, it
// means the class has no definition at this point.
ABG_ASSERT(!cl->get_definition_of_declaration());
- if (s.get_label() == get_private_types_suppr_spec_label())
+ if (s.get_label() == get_opaque_types_suppr_spec_label())
// So this looks like what really amounts to an
// opaque type. So it's not defined in the public
// headers. So we want to filter it out.
/// specification that is auto-generated by libabigail to suppress
/// change reports about types that are not defined in public headers.
const char*
-get_private_types_suppr_spec_label()
+get_opaque_types_suppr_spec_label()
{
- static const char *PRIVATE_TYPES_SUPPR_SPEC_NAME =
- "Artificial private types suppression specification";
+ static const char *OPAQUE_TYPES_SUPPR_SPEC_NAME =
+ "libabigail::OPAQUE_TYPE_LABEL";
- return PRIVATE_TYPES_SUPPR_SPEC_NAME;
+ return OPAQUE_TYPES_SUPPR_SPEC_NAME;
}
/// Test if a type suppression specification represents a private type
///
/// @return true iff @p s is a private type suppr spec.
bool
-is_private_type_suppr_spec(const type_suppression& s)
-{return s.get_label() == get_private_types_suppr_spec_label();}
+is_opaque_type_suppr_spec(const type_suppression& s)
+{return s.get_label() == get_opaque_types_suppr_spec_label();}
/// Test if a type suppression specification represents a private type
/// suppression automatically generated by libabigail from the user
///
/// @return true iff @p s is a private type suppr spec.
bool
-is_private_type_suppr_spec(const suppression_sptr& s)
+is_opaque_type_suppr_spec(const suppression_sptr& s)
{
type_suppression_sptr type_suppr = is_type_suppression(s);
return (type_suppr
- && type_suppr->get_label() == get_private_types_suppr_spec_label());
+ && type_suppr->get_label() == get_opaque_types_suppr_spec_label());
}
// </file_suppression stuff>
///
/// @param type_location the source location of the type.
///
-/// @param type_is_private output parameter. This is set to true if
+/// @param type_is_opaque output parameter. This is set to true if
/// the type was matched by one suppression specification, and if the
-/// suppression was for private types.
+/// suppression was for opaque types.
///
/// @param require_drop_property if true, this type requires the
/// suppression specification to contain the "drop" property to match
is_type_suppressed(const fe_iface& fe,
const string& type_name,
const location& type_location,
- bool& type_is_private,
+ bool& type_is_opaque,
bool require_drop_property)
{
for (auto i : fe.suppressions())
type_name,
type_location))
{
- if (is_private_type_suppr_spec(*suppr))
- type_is_private = true;
+ if (is_opaque_type_suppr_spec(*suppr))
+ type_is_opaque = true;
return true;
}
}
- type_is_private = false;
+ type_is_opaque = false;
return false;
}
{
if (!suppr)
{
- suppr.reset(new type_suppression(get_private_types_suppr_spec_label(),
+ suppr.reset(new type_suppression(get_opaque_types_suppr_spec_label(),
/*type_name_regexp=*/"",
/*type_name=*/""));
test-diff-suppr/test-has-data-member-inserted-at-3-v0.o \
test-diff-suppr/test-has-data-member-inserted-at-3-v1.c \
test-diff-suppr/test-has-data-member-inserted-at-3-v1.o \
+test-diff-suppr/PR31646/test-PR31646.2.abignore \
+test-diff-suppr/PR31646/test-PR31646.abignore \
+test-diff-suppr/PR31646/test-PR31646-result-1.txt \
+test-diff-suppr/PR31646/test-PR31646-result-2.txt \
+test-diff-suppr/PR31646/test-PR31646-result-3.txt \
+test-diff-suppr/PR31646/test-PR31646-v0.cc \
+test-diff-suppr/PR31646/test-PR31646-v0.o \
+test-diff-suppr/PR31646/test-PR31646-v1.cc \
+test-diff-suppr/PR31646/test-PR31646-v1.o \
\
test-lookup-syms/test0.cc \
test-lookup-syms/test0.o \
--- /dev/null
+Functions changes summary: 0 Removed, 1 Changed, 0 Added function
+Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+
+1 function with some indirect sub-type change:
+
+ [C] 'function opaque* fun(type&)' at test-PR31646-v0.cc:15:1 has some indirect sub-type changes:
+ return type changed:
+ entity changed from 'opaque*' to 'void'
+ type size changed from 64 to 0 (in bits)
+ parameter 1 of type 'type&' has sub-type changes:
+ in referenced type 'struct type' at test-PR31646-v1.cc:8:1:
+ type size hasn't changed
+ 1 data member change:
+ type of 'opaque* m1' changed:
+ in pointed to type 'struct opaque' at test-PR31646-v1.cc:1:1:
+ type size changed from 64 to 96 (in bits)
+ 1 data member insertion:
+ 'char m_inserted', at offset 32 (in bits) at test-PR31646-v1.cc:4:1
+ 1 data member change:
+ 'int m1' offset changed from 32 to 64 (in bits) (by +32 bits)
+
--- /dev/null
+Functions changes summary: 0 Removed, 1 Changed, 0 Added function
+Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+
+1 function with some indirect sub-type change:
+
+ [C] 'function opaque* fun(type&)' at test-PR31646-v0.cc:15:1 has some indirect sub-type changes:
+ return type changed:
+ entity changed from 'opaque*' to 'void'
+ type size changed from 64 to 0 (in bits)
+
--- /dev/null
+struct opaque
+{
+ int m0;
+ int m1;
+};
+
+struct type
+{
+ int m0;
+ opaque* m1;
+ int m2;
+};
+
+opaque*
+fun(type&)
+{
+}
--- /dev/null
+struct opaque
+{
+ int m0;
+ char m_inserted;
+ int m1;
+};
+
+struct type
+{
+ int m0;
+ opaque* m1;
+ int m2;
+};
+
+void
+fun(type&)
+{
+}
--- /dev/null
+[suppress_type]
+ label = libabigail::OPAQUE_TYPE_LABEL
+ name = opaque
+ drop = yes
\ No newline at end of file
--- /dev/null
+[suppress_type]
+ name = opaque
+ drop = yes
\ No newline at end of file
"data/test-diff-suppr/test-has-strict-flexible-array-data-member-conversion-report-2.txt",
"output/test-diff-suppr/test-has-strict-flexible-array-data-member-conversion-report-2.txt",
},
+ {
+ "data/test-diff-suppr/PR31646/test-PR31646-v0.o",
+ "data/test-diff-suppr/PR31646/test-PR31646-v1.o",
+ "",
+ "",
+ "",
+ "--no-default-suppression ",
+ "data/test-diff-suppr/PR31646/test-PR31646-result-1.txt",
+ "output/test-diff-suppr/PR31646/test-PR31646-result-1.txt",
+ },
+ {
+ "data/test-diff-suppr/PR31646/test-PR31646-v0.o",
+ "data/test-diff-suppr/PR31646/test-PR31646-v1.o",
+ "",
+ "",
+ "data/test-diff-suppr/PR31646/test-PR31646.abignore",
+ "--no-default-suppression ",
+ "data/test-diff-suppr/PR31646/test-PR31646-result-2.txt",
+ "output/test-diff-suppr/PR31646/test-PR31646-result-2.txt",
+ },
+ {
+ "data/test-diff-suppr/PR31646/test-PR31646-v0.o",
+ "data/test-diff-suppr/PR31646/test-PR31646-v1.o",
+ "",
+ "",
+ "data/test-diff-suppr/PR31646/test-PR31646.2.abignore",
+ "--no-default-suppression ",
+ "data/test-diff-suppr/PR31646/test-PR31646-result-3.txt",
+ "output/test-diff-suppr/PR31646/test-PR31646-result-3.txt",
+ },
// This should be the last entry
{NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
};
opts.show_all_types);
ABG_ASSERT(reader);
- reader->add_suppressions(priv_types_supprs1);
+ reader->add_suppressions(supprs);
set_generic_options(*reader, opts);
corpus1 = reader->read_corpus(c1_status);
///
/// @param debug_dir the debug directory of the ELF file.
///
+/// @param priv_types_supprs type suppression specification that
+/// suppress private types.
+///
/// @param opts the options passed the user.
///
/// @param env the environment to use for the comparison.
static abidiff_status
compare_to_self(const elf_file& elf,
const string& debug_dir,
+ const suppressions_type& priv_types_supprs,
const options& opts,
abigail::ir::environment& env,
corpus_diff_sptr& diff,
<< elf.path
<< " ...\n";
+ ctxt.reset(new diff_context);
+ set_diff_context_from_opts(ctxt, opts);
+ suppressions_type& supprs = ctxt->suppressions();
+
+ // Add the opaque type suppressions set to the set of suppressions.
+ for (auto& suppr : priv_types_supprs)
+ supprs.push_back(suppr);
+
corpus_sptr corp;
abigail::elf_based_reader_sptr reader;
{
opts.show_all_types);
ABG_ASSERT(reader);
+ reader->add_suppressions(supprs);
corp = reader->read_corpus(c_status);
if (!(c_status & abigail::fe_iface::STATUS_OK))
abigail::fe_iface::STATUS_UNKNOWN;
status |= compare_to_self(args->elf1, args->debug_dir1,
+ args->private_types_suppr1,
args->opts, env, diff, ctxt, out,
&detailed_status);
if (iter != second_package.path_elf_file_sptr_map().end()
&& (iter->second->type == abigail::elf::ELF_TYPE_DSO
|| iter->second->type == abigail::elf::ELF_TYPE_EXEC
- || iter->second->type == abigail::elf::ELF_TYPE_PI_EXEC
+ || iter->second->type == abigail::elf::ELF_TYPE_PI_EXEC
|| iter->second->type == abigail::elf::ELF_TYPE_RELOCATABLE))
{
if (iter->second->type != abigail::elf::ELF_TYPE_RELOCATABLE)
pkg.debug_info_packages().front()->extracted_dir_path() +
relative_debug_path;
- suppressions_type supprs;
for (map<string, elf_file_sptr>::iterator it =
pkg.path_elf_file_sptr_map().begin();
it != pkg.path_elf_file_sptr_map().end();
if (it != pkg.path_elf_file_sptr_map().end()
&& (it->second->type == abigail::elf::ELF_TYPE_DSO
|| it->second->type == abigail::elf::ELF_TYPE_EXEC
- || it->second->type == abigail::elf::ELF_TYPE_PI_EXEC
+ || it->second->type == abigail::elf::ELF_TYPE_PI_EXEC
|| it->second->type == abigail::elf::ELF_TYPE_RELOCATABLE))
{
if (it->second->type != abigail::elf::ELF_TYPE_RELOCATABLE)
compare_args_sptr args
(new compare_args(*it->second,
debug_dir,
- supprs,
+ create_private_types_suppressions
+ (pkg, opts),
*it->second,
debug_dir,
- supprs,
+ create_private_types_suppressions
+ (pkg, opts),
opts));
self_compare_task_sptr t(new self_compare_task(args));
self_compare_tasks.push_back(t);
abipkgdiff_tool,
'--dso-only' if global_config.dso_only else '',
'--self-check',
+ suppressions,
debuginfo_pkg1,
+ devel_pkg1,
cmp_half1.subject.downloaded_file,
]
else: