#########
Concepts
#########

.. _abi_artifacts_label:

ABI artifacts
=============

An ABI artifact is a relevant part of the ABI of a shared library or
program.  Examples of ABI artifacts are exported types, variables,
functions, or `ELF`_ symbols exported by a shared library.

The set of ABI artifact for a binary is called an ABI Corpus.

.. _harmfulchangeconcept_label:

Harmful changes
===============

A change in the diff report is considered harmful if it might cause
ABI compatibility issues.  That is, it might prevent an application
dynamically linked against a given version of a library to keep
working with the changed subsequent versions of the same library.

.. _harmlesschangeconcept_label:

Harmless changes
================

A change in the diff report is considered harmless if it will not
cause any ABI compatibility issue.  That is, it will not prevent an
application dynamically linked against given version of a library to
keep working with the changed subsequent versions of the same library.

By default, ``abidiff`` filters harmless changes from the diff report.

.. _suppr_spec_label:

Suppression specifications
==========================


Definition
----------

A suppression specification file is a way for a user to instruct
:ref:`abidiff <abidiff_label>`, :ref:`abipkgdiff <abipkgdiff_label>`
or any other relevant libabigail tool to avoid emitting reports for
changes involving certain :ref:`ABI artifacts<abi_artifacts_label>`.

It contains directives (or specifications) that describe the set of
ABI artifacts to avoid emitting change reports about.

Introductory examples
---------------------

Its syntax is based on a simplified and customized form of `Ini File
Syntax`_.  For instance, to specify that change reports on a type
named FooPrivateType should be suppressed, one could write this
suppression specification: ::

   [suppress_type]
     name = FooPrivateType

If we want to ensure that only change reports about structures named
FooPrivateType should be suppressed, we could write: ::

   [suppress_type]
     type_kind = struct
     name = FooPrivateType

But we could also want to suppress change reports avoid typedefs named
FooPrivateType.  In that case we would write:  ::

   [suppress_type]
     type_kind = typedef
     name = FooPrivateType

Or, we could want to suppress change reports about all struct which
names end with the string "PrivateType": ::

   [suppress_type]
     type_kind = struct
     name_regexp = ^.*PrivateType

Let's now look at the generic syntax of suppression specification
files.

Syntax
------

Properties
^^^^^^^^^^

More generally, the format of suppression lists is organized around
the concept of `property`.  Every property has a name and a value,
delimited by the ``=`` sign.  E.g: ::

	 name = value

Leading and trailing white spaces are ignored around property names
and values.

.. _suppr_regexp_label:

Regular expressions
^^^^^^^^^^^^^^^^^^^

The value of some properties might be a regular expression.  In that
case, they must comply with the syntax of `extended POSIX regular
expressions
<http://www.gnu.org/software/findutils/manual/html_node/find_html/posix_002dextended-regular-expression-syntax.html#posix_002dextended-regular-expression-syntax>`_.
Note that Libabigail uses the regular expression engine of the `GNU C
Library`_.

Escaping a character in a regular expression
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

When trying to match a string that contains a ``*`` character, like in
the pointer type ``int*``, one must be careful to notice that the
character ``*`` is a special character in the extended POSIX regular
expression syntax.  And that character must be escaped for the regular
expression engine.  Thus the regular expression that would match the
string ``int*`` in a suppression file should be ::

  int\\*

Wait; but then why the two ``\`` characters?  Well, because the ``\``
character is a special character in the `Ini File Syntax`_ used for
specifying suppressions.  So it must be escaped as well, so that the
Ini File parser leaves a ``\`` character intact in the data stream
that is handed to the regular expression engine.  Hence the ``\\``
targeted at the Ini File parser.

So, in short, to escape a character in a regular expression, always
prefix the character with the ``\\`` sequence.

Modus operandi
^^^^^^^^^^^^^^


Suppression specifications can be applied at two different points of
the processing pipeline of libabigail.

.. _late_suppression_mode_label:

In the default operating mode called "late suppression mode",
suppression specifications are applied to the result of comparing the
in-memory internal representations of two ABIs.  In this mode, if an
ABI artifact matches a suppression specification, its changes are not
mentioned in the ABI change report.  The internal representation of
the "suppressed" changed ABI artifact is still present in memory; it
is just not mentioned in the ABI change report.  The change report can
still mention statistics about the number of changed ABI artifacts
that were suppressed.

.. _early_suppression_mode_label:

There is another operating mode called the "early suppression mode"
where suppression specifications are applied during the construction
of the in-memory internal representation of a given ABI.  In that
mode, if an ABI artifact matches a suppression specification, no
in-memory internal representation is built for it.  As a result, no
change about the matched ABI artifact is going to be mentioned in the
ABI change report and no statistic about the number of suppressed ABI
changes is available.  Also, please note that because suppressed ABI
artifacts are removed from the in-memory internal representation in
this mode, the amount memory used by the internal representation is
potentially smaller than the memory consumption in the late
suppression mode.

Sections
^^^^^^^^

Properties are then grouped into arbitrarily named sections that shall
not be nested.  The name of the section is on a line by itself and is
surrounded by square brackets, i.e: ::

	 [section_name]
	 property1_name = property1_value
	 property2_name = property2_value


A section might or might not have properties.  Sections that expect to
have properties and which are found nonetheless empty are just
ignored.  Properties that are not recognized by the reader are ignored
as well.

Section names
^^^^^^^^^^^^^

Each different section can be thought of as being a directive to
suppress ABI change reports for a particular kind of ABI artifact.

``[suppress_file]``
$$$$$$$$$$$$$$$$$$$

This directive prevents a given tool from loading a file (binary or
abixml file) if its file name or other properties match certain
properties.  Thus, if the tool is meant to compare the ABIs of two
files, and if the directive prevents it from loading either one of the
files, then no comparison is performed.

Note that for the ``[suppress_file]`` 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``.

If none of the above properties are provided, then the
``[suppress_file]`` directive is simply ignored.

The potential properties of this sections are listed below:

* ``file_name_not_regexp``

  Usage:

    ``file_name_not_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

  Prevents the system from loading the file which name does not match
  the regular expression specified as value of this property.



* ``file_name_regexp``

  Usage:

    ``file_name_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

  Prevents the system from loading the file which name matches the
  regular expression specified as value of this property.


* ``label``

 Usage:

   ``label`` ``=`` <some-value>

 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.


* ``soname_regexp``

  Usage:

    ``soname_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

  Prevents the system from loading the file which contains a SONAME
  property that matches the regular expression of this property.  Note
  that this property also works on an abixml file if it contains a
  SONAME property.

* ``soname_not_regexp``

  Usage:

    ``soname_not_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

  Prevents the system from loading the file which contains a SONAME
  property that does *NOT* match the regular expression of this
  property.  Note that this property also works on an abixml file if
  it contains a SONAME property.

``[suppress_type]``
$$$$$$$$$$$$$$$$$$$

This directive suppresses report messages about a type change.

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``,
  ``name_not_regexp``, ``source_location_not_in``,
  ``source_location_not_regexp``, ``type_kind``.

If none of the above properties are provided, then the
``[suppress_type]`` directive is simply ignored.

The potential properties of this sections are listed below:


 .. _suppr_accessed_through_property_label:

* ``accessed_through``

 Usage:

   ``accessed_through`` ``=`` <some-predefined-values>

 Suppress change reports involving a type which is referred to either
 directly or through a pointer or a reference.  The potential values
 of this property are the predefined keywords below:

	 * ``direct``

	   So if the ``[suppress_type]`` contains the property
	   description: ::

	     accessed_through = direct

	   then changes about a type that is referred-to
	   directly (i.e, not through a pointer or a reference)
	   are going to be suppressed.

	 * ``pointer``

	   If the ``accessed_through`` property is set to the
	   value ``pointer`` then changes about a type that is
	   referred-to through a pointer are going to be
	   suppressed.

	 * ``reference``

	   If the ``accessed_through`` property is set to the
	   value ``reference`` then changes about a type that is
	   referred-to through a reference are going to be
	   suppressed.

	 * ``reference-or-pointer``

	   If the ``accessed_through`` property is set to the
	   value ``reference-or-pointer`` then changes about a
	   type that is referred-to through either a reference
	   or a pointer are going to be suppressed.

 For an extensive example of how to use this property, please check
 out the example below about :ref:`suppressing change reports about
 types accessed either directly or through pointers
 <example_accessed_through_label>`.


.. _suppr_changed_enumerators_label:

* ``changed_enumerators``

  Usage:

    ``changed_enumerators`` ``=`` <list-of-enumerators>

  Suppresses change reports involving changes in the value of
  enumerators of a given enum type.  This property is applied if the
  ``type_kind`` property is set to the value ``enum``, at least.  The
  value of the ``changed_enumerators`` is a comma-separated list of
  the enumerators that the user expects to change.  For instance: ::

      changed_enumerators = LAST_ENUMERATORS0, LAST_ENUMERATOR1


.. _suppr_changed_enumerators_regexp_label:

* ``changed_enumerators_regexp``

  Usage:

    ``changed_enumerators_regexp`` ``=`` <list-of-enumerator-regular-expressions>

  Suppresses change reports involving changes in the value of
  enumerators of a given enum type.  This property is applied if the
  ``type_kind`` property is set to the value ``enum``, at least.  The
  value of the ``changed_enumerators_regexp`` property is a
  comma-separated list of regular expressions that should match the
  names of the enumerators that the user expects to change.  For
  instance: ::

      changed_enumerators_regexp = .*_MAX$, .*_LAST$, .*_NUM$, .*_NBITS$

  In the example above, change reports to any enumerator which name
  ends with _MAX, _LAST, _NUM or _NBITS will be suppressed.

  Note that for this property to be applied to changes to an enum
  type, the size of the enum type must *NOT* have changed.


* ``drop``

 Usage:

   ``drop`` ``=`` yes | no

 If a type is matched by a suppression specification which contains
 the "drop" property set to "yes" (or to "true") then the type is not
 even going to be represented in the internal representation of the
 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.

 Please note that for this property to be effective, the enclosing
 suppression specification must have at least one of the following
 properties specified: ``name_regexp``, ``name``, ``name_regexp``,
 ``source_location_not_in`` or ``source_location_not_regexp``.


* ``file_name_not_regexp``

  Usage:

    ``file_name_not_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

  Suppresses change reports about ABI artifacts that are defined in a
  binary file which name does not match the regular expression
  specified as value of this property.


* ``file_name_regexp``

  Usage:

    ``file_name_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

  Suppresses change reports about ABI artifacts that are defined in a
  binary file which name matches the regular expression specified as
  value of this 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``

 Usage:

   ``has_data_member_inserted_at`` ``=`` <``offset-in-bit``>

 Suppresses change reports involving a type which has at least one
 data member inserted at an offset specified by the property value
 ``offset-in-bit``.  Please note that if the size of the type changed,
 then the type change will *NOT* be suppressed by the evaluation of
 this property, unless the
 :ref:`has_size_change<suppr_has_size_change_property_label>` property
 is present and set to ``yes``.

 The value ``offset-in-bit`` is either:

	 - an integer value, expressed in bits, which denotes the
	   offset of the insertion point of the data member, starting
	   from the beginning of the relevant structure or class.

.. _suppr_data_member_offset_selector_expressions_label:

	 - data member offset selector expressions, such as:

	     - the keyword ``end`` which is a named constant which
	       value equals the offset of the end of the structure or
	       class.

	     - the keyword ``offset_of_flexible_array_data_member``
               which is a named constant that evaluates to the offset
               of the flexible array data member contained in the
               relevant structure.

	     - the function call expression
	       ``offset_of(data-member-name)`` where `data-member-name` is
	       the name of a given data member of the relevant structure
	       or class.  The value of this function call expression is an
	       integer that represents the offset of the data member
	       denoted by ``data-member-name``.

	     - the function call expression
	       ``offset_after(data-member-name)`` where `data-member-name`
	       is the name of a given data member of the relevant
	       structure or class.  The value of this function call
	       expression is an integer that represents the offset of the
	       point that comes right after the region occupied by the
	       data member denoted by ``data-member-name``.

	     - the function call expression
	       ``offset_of_first_data_member_regexp(data-member-name-regexp)``
	       where `data-member-name-regexp` is a regular expression
	       matching a data member.  The value of this function
	       call expression is an integer that represents the
	       offset of the first data member which name matches the
	       regular expression argument.  If no data member of a
	       given class type matches the regular expression, then
	       the class type won't match the current directive.

	     - the function call expression
	       ``offset_of_last_data_member_regexp(data-member-name-regexp)``
	       where `data-member-name-regexp` is a regular expression
	       matching a data member.  The value of this function
	       call expression is an integer that represents the
	       offset of the last data member which name matches the
	       regular expression argument.  If no data member of a
	       given class type matches the regular expression, then
	       the class type won't match the current directive.

  .. _suppr_has_data_member_inserted_between_label:


* ``has_data_member_inserted_between``

 Usage:

   ``has_data_member_inserted_between`` ``=`` {<``range-begin``>, <``range-end``>}

 Suppresses change reports involving a type which has at least one
 data member inserted at an offset that is comprised in the range
 between ``range-begin`` and ``range-end``.  Please note that each of
 the values ``range-begin`` and ``range-end`` can be of the same form
 as the :ref:`has_data_member_inserted_at
 <suppr_has_data_member_inserted_at_label>` property above.  Please
 also note that if the size of the type changed, then the type change
 will *NOT* be suppressed by the evaluation of this property, unless
 the :ref:`has_size_change<suppr_has_size_change_property_label>`
 property is present and set to ``yes``.  Note that data member
 deletions happening in the range between ``range-begin`` and
 ``range-end`` won't prevent the type change from being suppressed by
 the evaluation of this property if the size of the type doesn't
 change or if the
 :ref:`has_size_change<suppr_has_size_change_property_label>` property
 is present and set to ``yes``.

 Usage examples of this properties are: ::

   has_data_member_inserted_between = {8, 64}

 or: ::

   has_data_member_inserted_between = {16, end}

 or: ::

   has_data_member_inserted_between = {offset_after(member1), end}

.. _suppr_has_data_members_inserted_between_label:


* ``has_data_members_inserted_between``

 Usage:

   ``has_data_members_inserted_between`` ``=`` {<sequence-of-ranges>}

 Suppresses change reports involving a type which has multiple data
 member inserted in various offset ranges.  A usage example of this
 property is, for instance: ::

   has_data_members_inserted_between = {{8, 31}, {72, 95}}

 This usage example suppresses change reports involving a type which
 has data members inserted in bit offset ranges [8 31] and [72 95].
 The length of the sequence of ranges or this
 ``has_data_members_inserted_between`` is not bounded; it can be as
 long as the system can cope with.  The values of the boundaries of
 the ranges are of the same kind as for the
 :ref:`has_data_member_inserted_at
 <suppr_has_data_member_inserted_at_label>` property above.  Please
 also note that if the size of the type changed, then the type will
 *NOT* be suppressed by the evaluation of this property, unless the
 :ref:`has_size_change<suppr_has_size_change_property_label>` property
 is present and set to ``yes``.  Note that data member deletions
 happening in the defined ranges won't prevent the type change from
 being suppressed by the evaluation of this property if the size of
 the type doesn't change or if the
 :ref:`has_size_change<suppr_has_size_change_property_label>` property
 is present and set to ``yes``.

 Another usage example of this property is thus: ::

   has_data_members_inserted_between =
     {
	  {offset_after(member0), offset_of(member1)},
	  {72, end}
     }

.. _suppr_has_strict_flexible_array_data_member_conversion_label:


* ``has_strict_flexible_array_data_member_conversion``

 Usage:

   ``has_strict_flexible_array_data_member_conversion`` ``=`` yes | no

 Suppresses change reports involving a type which has a "fake"
 flexible array member at the end of the struct which is converted
 to a real flexible array member. This would be a member like
 ``data[1]`` being converted to ``data[]``.

 Please note that if the size of the type changed, then the type
 change will *NOT* be suppressed by the evaluation of this property,
 unless the
 :ref:`has_size_change<suppr_has_size_change_property_label>` property
 is present and set to ``yes``.

.. _suppr_has_size_change_property_label:


* ``has_size_change``

 Usage:

   ``has_size_change`` ``=`` yes | no


This property is to be used in conjunction with the properties
:ref:`has_data_member_inserted_between<suppr_has_data_member_inserted_between_label>`,
:ref:`has_data_members_inserted_between<suppr_has_data_members_inserted_between_label>`,
and
:ref:`has_strict_flexible_array_data_member_conversion<suppr_has_strict_flexible_array_data_member_conversion_label>`
Those properties will not match a type change if the size of the type
changes, unless the ``has_size_changes`` property is set to ``yes``.

 .. _suppr_label_property_label:

* ``label``

 Usage:

   ``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.


* ``name``

 Usage:

   ``name`` ``=`` <a-value>

 Suppresses change reports involving types whose name equals the value
 of this property.


* ``name_not_regexp``

 Usage:

   ``name_not_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

 Suppresses change reports involving types whose name does *NOT* match
 the regular expression specified as value of this property.  Said
 otherwise, this property specifies which types to keep, rather than
 types to suppress from reports.


* ``name_regexp``

 Usage:

   ``name_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

 Suppresses change reports involving types whose name matches the
 regular expression specified as value of this property.


* ``soname_not_regexp``

  Usage:

    ``soname_not_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

  Suppresses change reports about ABI artifacts that are defined in a
  shared library which SONAME property does not match the regular
  expression specified as value of this property.


* ``soname_regexp``

  Usage:

    ``soname_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

  Suppresses change reports about ABI artifacts that are defined in a
  shared library which SONAME property matches the regular expression
  specified as value of this property.

 .. _suppr_source_location_not_in_label:

* ``source_location_not_in``

 Usage:

    ``source_location_not_in`` ``=`` <``list-of-file-paths``>

 Suppresses change reports involving a type which is defined in a file
 which path is *NOT* listed in the value ``list-of-file-paths``.  Note
 that the value is a comma-separated list of file paths e.g, this
 property ::
 
   source_location_not_in = libabigail/abg-ir.h, libabigail/abg-dwarf-reader.h 

 suppresses change reports about all the types that are *NOT* defined
 in header files whose path end up with the strings
 libabigail/abg-ir.h or libabigail/abg-dwarf-reader.h.

 .. _suppr_source_location_not_regexp_label:


* ``source_location_not_regexp``

 Usage:

   ``source_location_not_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

 Suppresses change reports involving a type which is defined in a file
 which path does *NOT* match the :ref:`regular expression
 <suppr_regexp_label>` provided as value of the property. E.g, this
 property ::

   source_location_not_regexp = libabigail/abg-.*\\.h

 suppresses change reports involving all the types that are *NOT*
 defined in header files whose path match the regular expression
 provided a value of the property.


* ``type_kind``

 Usage:

   ``type_kind`` ``=`` ``class`` | ``struct`` | ``union`` | ``enum`` |
		       ``array`` | ``typedef`` | ``builtin``

 Suppresses change reports involving a certain kind of type.  The kind
 of type to suppress change reports for is specified by the possible
 values listed above:

   - ``class``: suppress change reports for class types.  Note that
	 even if class types don't exist for C, this value still
	 triggers the suppression of change reports for struct types,
	 in C.  In C++ however, it should do what it suggests.

   - ``struct``: suppress change reports for struct types in C or C++.
	 Note that the value ``class`` above is a super-set of this
	 one.

   - ``union``: suppress change reports for union types.

   - ``enum``: suppress change reports for enum types.

   - ``array``: suppress change reports for array types.

   - ``typedef``: suppress change reports for typedef types.

   - ``builtin``: suppress change reports for built-in (or native)
     types.  Example of built-in types are char, int, unsigned int,
     etc.


``[suppress_function]``
$$$$$$$$$$$$$$$$$$$$$$$$

This directive suppresses report messages about changes on a set of
functions.

Note that for the ``[suppress_function]`` directive to work, at least
one of the following properties must be provided:

  ``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 none of the above properties are provided, then the
``[suppress_function]`` directive is simply ignored.

The potential properties of this sections are:


  .. _suppr_change_kind_property_label:

* ``change_kind``

 Usage:

   ``change_kind`` ``=`` <predefined-possible-values>

 Specifies the kind of changes this suppression specification should
 apply to.  The possible values of this property as well as their
 meaning are listed below:

	 - ``function-subtype-change``

	   This suppression specification applies to functions
	   that which have at least one sub-type that has
	   changed.

	 - ``added-function``

	   This suppression specification applies to functions
	   that have been added to the binary.

	 - ``deleted-function``

	   This suppression specification applies to functions
	   that have been removed from the binary.

	 - ``all``

	   This suppression specification applies to functions
	   that have all of the changes above.  Note that not
	   providing the ``change_kind`` property at all is
	   equivalent to setting it to the value ``all``.


* ``drop``

 Usage:

   ``drop`` ``=`` yes | no

 If a function is matched by a suppression specification which
 contains the "drop" property set to "yes" (or to "true") then the
 function is not even going to be represented in the internal
 representation of the 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.

 Please note that for this property to be effective, the enclosing
 suppression specification must have at least one of the following
 properties specified: ``name_regexp``, ``name``, ``name_regexp``,
 ``source_location_not_in`` or ``source_location_not_regexp``.


* ``file_name_not_regexp``

  Usage:

    ``file_name_not_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

  Suppresses change reports about ABI artifacts that are defined in a
  binary file which name does not match the regular expression
  specified as value of this property.


* ``file_name_regexp``

  Usage:

  ``file_name_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

  Suppresses change reports about ABI artifacts that are defined in a
  binary file which name matches the regular expression specified as
  value of this property.


* ``label``

 Usage:

   ``label`` ``=`` <some-value>

 This property is the same as the :ref:`label property
 <suppr_label_property_label>` defined above.


* ``name``

 Usage:

   ``name`` ``=`` <some-value>

 Suppresses change reports involving functions whose name equals the
 value of this property.


* ``name_not_regexp``

 Usage:

   ``name_not_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

 Suppresses change reports involving functions whose names don't match
 the regular expression specified as value of this property.

 The rules for functions that have several symbol names are the same
 rules as for the ``name_regexp`` property above.


* ``name_regexp``

 Usage:

   ``name_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

 Suppresses change reports involving functions whose name matches the
 regular expression specified as value of this property.

 Let's consider the case of functions that have several symbol names.
 This happens when the underlying symbol for the function has
 aliases.  Each symbol name is actually one alias name.

 In this case, if the regular expression matches the name of
 at least one of the aliases names, then it must match the names of
 all of the aliases of the function for the directive to actually
 suppress the diff reports for said function.


* ``parameter``

 Usage:

   ``parameter`` ``=`` <function-parameter-specification>

 Suppresses change reports involving functions whose
 parameters match the parameter specification indicated as
 value of this property.

 The format of the function parameter specification is:

 ``'`` ``<parameter-index>`` ``<space>`` ``<type-name-or-regular-expression>``

 That is, an apostrophe followed by a number that is the
 index of the parameter, followed by one of several spaces,
 followed by either the name of the type of the parameter,
 or a regular expression describing a family of parameter
 type names.

 If the parameter type name is designated by a regular
 expression, then said regular expression must be enclosed
 between two slashes; like ``/some-regular-expression/``.

 The index of the first parameter of the function is zero.
 Note that for member functions (methods of classes), the
 this is the first parameter that comes after the implicit
 "this" pointer parameter.

 Examples of function parameter specifications are: ::

   '0 int

 Which means, the parameter at index 0, whose type name is
 ``int``. ::

   '4 unsigned char*

 Which means, the parameter at index 4, whose type name is
 ``unsigned char*``.  ::

   '2 /^foo.*&/

 Which means, the parameter at index 2, whose type name
 starts with the string "foo" and ends with an '&'.  In
 other words, this is the third parameter and it's a
 reference on a type that starts with the string "foo".


* ``return_type_name``

 Usage:

   ``return_type_name`` ``=`` <some-value>

 Suppresses change reports involving functions whose return type name
 equals the value of this property.


* ``return_type_regexp``

 Usage:

   ``return_type_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

 Suppresses change reports involving functions whose return type name
 matches the regular expression specified as value of this property.


* ``soname_regexp``

  Usage:

    ``soname_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

  Suppresses change reports about ABI artifacts that are defined in a
  shared library which SONAME property matches the regular expression
  specified as value of this property.


* ``soname_not_regexp``

  Usage:

    ``soname_not_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

  Suppresses change reports about ABI artifacts that are defined in a
  shared library which SONAME property does not match the regular
  expression specified as value of this property.


* ``symbol_name``

 Usage:

   ``symbol_name`` ``=`` <some-value>

 Suppresses change reports involving functions whose symbol name equals
 the value of this property.


* ``symbol_name_regexp``

 Usage:

   ``symbol_name_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

 Suppresses change reports involving functions whose symbol name
 matches the regular expression specified as value of this property.

 Let's consider the case of functions that have several symbol names.
 This happens when the underlying symbol for the function has
 aliases.  Each symbol name is actually one alias name.

 In this case, the regular expression must match the names of all of
 the aliases of the function for the directive to actually suppress
 the diff reports for said function.


* ``symbol_name_not_regexp``

 Usage:

   ``symbol_name_not_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

 Suppresses change reports involving functions whose symbol name does
 not match the regular expression specified as value of this property.


* ``symbol_version``

 Usage:

   ``symbol_version`` ``=`` <some-value>

 Suppresses change reports involving functions whose symbol version
 equals the value of this property.


* ``symbol_version_regexp``

 Usage:

   ``symbol_version_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

 Suppresses change reports involving functions whose symbol version
 matches the regular expression specified as value of this property.


``[suppress_variable]``
$$$$$$$$$$$$$$$$$$$$$$$$

This directive suppresses report messages about changes on a set of
variables.

Note that for the ``[suppress_variable]`` directive to work, at least
one of the following properties must be provided:

  ``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 none of the above properties are provided, then the
``[suppress_variable]`` directive is simply ignored.

The potential properties of this sections are:

* ``label``

 Usage:

   ``label`` ``=`` <some-value>

 This property is the same as the :ref:`label property
 <suppr_label_property_label>` defined above.


* ``file_name_regexp``

  Usage:

  ``file_name_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

  Suppresses change reports about ABI artifacts that are defined in a
  binary file which name matches the regular expression specified as
  value of this property.

* ``file_name_not_regexp``

  Usage:

   ``file_name_not_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

  Suppresses change reports about ABI artifacts that are defined in a
  binary file which name does not match the regular expression
  specified as value of this property.


* ``soname_regexp``

  Usage:

   ``soname_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

  Suppresses change reports about ABI artifacts that are defined in a
  shared library which SONAME property matches the regular expression
  specified as value of this property.


* ``soname_not_regexp``

  Usage:

    ``soname_not_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

  Suppresses change reports about ABI artifacts that are defined in a
  shared library which SONAME property does not match the regular
  expression specified as value of this property.


* ``name``

 Usage:

   ``name`` ``=`` <some-value>

 Suppresses change reports involving variables whose name equals the
 value of this property.

* ``name_regexp``

 Usage:

   ``name_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

 Suppresses change reports involving variables whose name matches the
 regular expression specified as value of this property.

* ``change_kind``

 Usage:

   ``change_kind`` ``=`` <predefined-possible-values>

 Specifies the kind of changes this suppression specification should
 apply to.  The possible values of this property as well as their
 meaning are the same as when it's :ref:`used in the
 [suppress_function] section <suppr_change_kind_property_label>`.

* ``symbol_name``

 Usage:

   ``symbol_name`` ``=`` <some-value>

 Suppresses change reports involving variables whose symbol name equals
 the value of this property.

* symbol_name_regexp

 Usage:

   ``symbol_name_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

 Suppresses change reports involving variables whose symbol name
 matches the regular expression specified as value of this property.


* ``symbol_name_not_regexp``

 Usage:

   ``symbol_name_not_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

 Suppresses change reports involving variables whose symbol name does
 not match the regular expression specified as value of this property.

* ``symbol_version``

 Usage:

   ``symbol_version`` ``=`` <some-value>

 Suppresses change reports involving variables whose symbol version
 equals the value of this property.

* ``symbol_version_regexp``

 Usage:

   ``symbol_version_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

 Suppresses change reports involving variables whose symbol version
 matches the regular expression specified as value of this property.

* ``type_name``

 Usage:

   ``type_name`` ``=`` <some-value>

 Suppresses change reports involving variables whose type name equals
 the value of this property.

* ``type_name_regexp``

 Usage:

   ``type_name_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>

 Suppresses change reports involving variables whose type name matches
 the regular expression specified as value of this property.

Comments
^^^^^^^^

``;`` or ``#`` ASCII character at the beginning of a line
indicates a comment.  Comment lines are ignored.

Code examples
^^^^^^^^^^^^^

1. Suppressing change reports about types.

   Suppose we have a library named ``libtest1-v0.so`` which
   contains this very useful code: ::

	$ cat -n test1-v0.cc
	     1	// A forward declaration for a type considered to be opaque to
	     2	// function foo() below.
	     3	struct opaque_type;
	     4
	     5	// This function cannot touch any member of opaque_type.  Hence,
	     6	// changes to members of opaque_type should not impact foo, as far as
	     7	// ABI is concerned.
	     8	void
	     9	foo(opaque_type*)
	    10	{
	    11	}
	    12
	    13	struct opaque_type
	    14	{
	    15	  int member0;
	    16	  char member1;
	    17	};
	$

Let's change the layout of struct opaque_type by inserting a data
member around line 15, leading to a new version of the library,
that we shall name ``libtest1-v1.so``: ::

	$ cat -n test1-v1.cc
	     1	// A forward declaration for a type considered to be opaque to
	     2	// function foo() below.
	     3	struct opaque_type;
	     4
	     5	// This function cannot touch any member of opaque_type;  Hence,
	     6	// changes to members of opaque_type should not impact foo, as far as
	     7	// ABI is concerned.
	     8	void
	     9	foo(opaque_type*)
	    10	{
	    11	}
	    12
	    13	struct opaque_type
	    14	{
	    15	  char added_member; // <-- a new member got added here now.
	    16	  int member0;
	    17	  char member1;
	    18	};
	$

Let's compile both examples.  We shall not forget to compile them
with debug information generation turned on: ::

	$ g++ -shared -g -Wall -o libtest1-v0.so test1-v0.cc
	$ g++ -shared -g -Wall -o libtest1-v1.so test1-v1.cc

Let's ask :ref:`abidiff <abidiff_label>` which ABI differences it sees
between ``libtest1-v0.so`` and ``libtest1-v1.so``: ::

	$ abidiff libtest1-v0.so libtest1-v1.so
	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 void foo(opaque_type*)' has some indirect sub-type changes:
	    parameter 0 of type 'opaque_type*' has sub-type changes:
	      in pointed to type 'struct opaque_type':
		size changed from 64 to 96 bits
		1 data member insertion:
		  'char opaque_type::added_member', at offset 0 (in bits)
		2 data member changes:
		 'int opaque_type::member0' offset changed from 0 to 32
		 'char opaque_type::member1' offset changed from 32 to 64


So ``abidiff`` reports that the opaque_type's layout has changed
in a significant way, as far as ABI implications are concerned, in
theory.  After all, a sub-type (``struct opaque_type``) of an
exported function (``foo()``) has seen its layout change.  This
might have non negligible ABI implications.  But in practice here,
the programmer of the litest1-v1.so library knows that the "soft"
contract between the function ``foo()`` and the type ``struct
opaque_type`` is to stay away from the data members of the type.
So layout changes of ``struct opaque_type`` should not impact
``foo()``.

Now to teach ``abidiff`` about this soft contract and have it
avoid emitting what amounts to false positives in this case, we
write the suppression specification file below: ::

	$ cat test1.suppr
	[suppress_type]
	  type_kind = struct
	  name = opaque_type

Translated in plain English, this suppression specification would
read: "Do not emit change reports about a struct which name is
opaque_type".

Let's now invoke ``abidiff`` on the two versions of the library
again, but this time with the suppression specification: ::

	$ abidiff --suppressions test1.suppr libtest1-v0.so libtest1-v1.so
	Functions changes summary: 0 Removed, 0 Changed (1 filtered out), 0 Added function
	Variables changes summary: 0 Removed, 0 Changed, 0 Added variable

As you can see, ``abidiff`` does not report the change anymore; it
tells us that it was filtered out instead.

Suppressing change reports about types with data member
insertions

Suppose the first version of a library named ``libtest3-v0.so``
has this source code: ::

	/* Compile this with:
	     gcc -g -Wall -shared -o libtest3-v0.so test3-v0.c
	 */

	struct S
	{
	  char member0;
	  int member1; /* 
			  between member1 and member2, there is some padding,
			  at least on some popular platforms.  On
			  these platforms, adding a small enough data
			  member into that padding shouldn't change
			  the offset of member1.  Right?
			*/
	};

	int
	foo(struct S* s)
	{
	  return s->member0 + s->member1;
	}

Now, suppose the second version of the library named
``libtest3-v1.so`` has this source code in which a data member
has been added in the padding space of struct S and another data
member has been added at its end: ::

	/* Compile this with:
	     gcc -g -Wall -shared -o libtest3-v1.so test3-v1.c
	 */

	struct S
	{
	  char member0;
	  char inserted1; /* <---- A data member has been added here...  */
	  int member1;
	  char inserted2; /* <---- ... and another one has been added here.  */
	};

	int
	foo(struct S* s)
	{
	  return s->member0 + s->member1;
	}


In libtest3-v1.so, adding char data members ``S::inserted1`` and
``S::inserted2`` can be considered harmless (from an ABI compatibility
perspective), at least on the x86 platform, because that doesn't
change the offsets of the data members S::member0 and S::member1.  But
then running ``abidiff`` on these two versions of library yields: ::

	$ abidiff libtest3-v0.so libtest3-v1.so
	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 int foo(S*)' has some indirect sub-type changes:
	    parameter 0 of type 'S*' has sub-type changes:
	      in pointed to type 'struct S':
		type size changed from 64 to 96 bits
		2 data member insertions:
		  'char S::inserted1', at offset 8 (in bits)
		  'char S::inserted2', at offset 64 (in bits)
	$



That is, ``abidiff`` shows us the two changes, even though we (the
developers of that very involved library) know that these changes
are harmless in this particular context.

Luckily, we can devise a suppression specification that essentially
tells abidiff to filter out change reports about adding a data
member between ``S::member0`` and ``S::member1``, and adding a data
member at the end of struct S.  We have written such a suppression
specification in a file called test3-1.suppr and it unsurprisingly
looks like: ::

	[suppress_type]
	  name = S
	  has_data_member_inserted_between = {offset_after(member0), offset_of(member1)}
	  has_data_member_inserted_at = end


Now running ``abidiff`` with this suppression specification yields: ::

	$ ../build/tools/abidiff --suppressions test3-1.suppr libtest3-v0.so libtest3-v1.so
	Functions changes summary: 0 Removed, 0 Changed (1 filtered out), 0 Added function
	Variables changes summary: 0 Removed, 0 Changed, 0 Added variable

	$ 


Hooora! \\o/ (I guess)

.. _example_accessed_through_label:

Suppressing change reports about types accessed either directly
or through pointers

Suppose we have a first version of an object file which source
code is the file widget-v0.cc below: ::

	// Compile with: g++ -g -c widget-v0.cc

	struct widget
	{
	  int x;
	  int y;

	  widget()
	    :x(), y()
	  {}
	};

	void
	fun0(widget*)
	{
	  // .. do stuff here.
	}

	void
	fun1(widget&)
	{
	  // .. do stuff here ..
	}

	void
	fun2(widget w)
	{
	  // ... do other stuff here ...
	}

Now suppose in the second version of that file, named
widget-v1.cc, we have added some data members at the end of
the type ``struct widget``; here is what the content of that file
would look like: ::

	// Compile with: g++ -g -c widget-v1.cc

	struct widget
	{
	  int x;
	  int y;
	  int w; // We have added these two new data members here ..
	  int h; // ... and here.

	  widget()
	    : x(), y(), w(), h()
	  {}
	};

	void
	fun0(widget*)
	{
	  // .. do stuff here.
	}

	void
	fun1(widget&)
	{
	  // .. do stuff here ..
	}

	void
	fun2(widget w)
	{
	  // ... do other stuff here ...
	}

When we invoke ``abidiff`` on the object files resulting from the
compilation of the two file above, here is what we get: ::

	$ abidiff widget-v0.o widget-v1.o
	Functions changes summary: 0 Removed, 2 Changed (1 filtered out), 0 Added functions
	Variables changes summary: 0 Removed, 0 Changed, 0 Added variable

	2 functions with some indirect sub-type change:

	  [C]'function void fun0(widget*)' has some indirect sub-type changes:
	    parameter 1 of type 'widget*' has sub-type changes:
	      in pointed to type 'struct widget':
		type size changed from 64 to 128 bits
		2 data member insertions:
		  'int widget::w', at offset 64 (in bits)
		  'int widget::h', at offset 96 (in bits)

	  [C]'function void fun2(widget)' has some indirect sub-type changes:
	    parameter 1 of type 'struct widget' has sub-type changes:
	      details were reported earlier
       $

I guess a little bit of explaining is due here.  ``abidiff``
detects that two data member got added at the end of ``struct
widget``.  it also tells us that the type change impacts the
exported function ``fun0()`` which uses the type ``struct
widget`` through a pointer, in its signature.

Careful readers will notice that the change to ``struct widget``
also impacts the exported function ``fun1()``, that uses type
``struct widget`` through a reference.  But then ``abidiff``
doesn't tell us about the impact on that function ``fun1()``
because it has evaluated that change as being **redundant** with
the change it reported on ``fun0()``.  It has thus filtered it
out, to avoid cluttering the output with noise.

Redundancy detection and filtering is fine and helpful to avoid
burying the important information in a sea of noise.  However, it
must be treated with care, by fear of mistakenly filtering out
relevant and important information.

That is why ``abidiff`` tells us about the impact that the change
to ``struct widget`` has on function ``fun2()``.  In this case,
that function uses the type ``struct widget`` **directly** (in
its signature).  It does not use it via a pointer or a reference.
In this case, the direct use of this type causes ``fun2()`` to be
exposed to a potentially harmful ABI change.  Hence, the report
about ``fun2()`` is not filtered out, even though it's about that
same change on ``struct widget``.

To go further in suppressing reports about changes that are
harmless and keeping only those that we know are harmful, we
would like to go tell abidiff to suppress reports about this
particular ``struct widget`` change when it impacts uses of
``struct widget`` through a pointer or reference.  In other
words, suppress the change reports about ``fun0()`` **and**
``fun1()``.  We would then write this suppression specification,
in file ``widget.suppr``: ::

	[suppress_type]
	  name = widget
	  type_kind = struct
	  has_data_member_inserted_at = end
	  accessed_through = reference-or-pointer

	  # So this suppression specification says to suppress reports about
	  # the type 'struct widget', if this type was added some data member
	  # at its end, and if the change impacts uses of the type through a
	  # reference or a pointer.

Invoking ``abidiff`` on ``widget-v0.o`` and ``widget-v1.o`` with
this suppression specification yields: ::

	$ abidiff --suppressions widget.suppr widget-v0.o widget-v1.o
	Functions changes summary: 0 Removed, 1 Changed (2 filtered out), 0 Added function
	Variables changes summary: 0 Removed, 0 Changed, 0 Added variable

	1 function with some indirect sub-type change:

	  [C]'function void fun2(widget)' has some indirect sub-type changes:
	    parameter 1 of type 'struct widget' has sub-type changes:
	      type size changed from 64 to 128 bits
	      2 data member insertions:
		'int widget::w', at offset 64 (in bits)
		'int widget::h', at offset 96 (in bits)
	$

As expected, I guess.

Suppressing change reports about functions.

Suppose we have a first version a library named
``libtest2-v0.so`` whose source code is: ::

	 $ cat -n test2-v0.cc

	  1	struct S1
	  2	{
	  3	  int m0;
	  4	
	  5	  S1()
	  6	    : m0()
	  7	  {}
	  8	};
	  9	
	 10	struct S2
	 11	{
	 12	  int m0;
	 13	
	 14	  S2()
	 15	    : m0()
	 16	  {}
	 17	};
	 18	
	 19	struct S3
	 20	{
	 21	  int m0;
	 22	
	 23	  S3()
	 24	    : m0()
	 25	  {}
	 26	};
	 27	
	 28	int
	 29	func(S1&)
	 30	{
	 31	  // suppose the code does something with the argument.
	 32	  return 0;
	 33	
	 34	}
	 35	
	 36	char
	 37	func(S2*)
	 38	{
	 39	  // suppose the code does something with the argument.
	 40	  return 0;
	 41	}
	 42	
	 43	unsigned
	 44	func(S3)
	 45	{
	 46	  // suppose the code does something with the argument.
	 47	  return 0;
	 48	}
	$
	
And then we come up with a second version ``libtest2-v1.so`` of
that library; the source code is modified by making the
structures ``S1``, ``S2``, ``S3`` inherit another struct: ::

	$ cat -n test2-v1.cc
	      1	struct base_type
	      2	{
	      3	  int m_inserted;
	      4	};
	      5	
	      6	struct S1 : public base_type // <--- S1 now has base_type as its base
	      7				     // type.
	      8	{
	      9	  int m0;
	     10	
	     11	  S1()
	     12	    : m0()
	     13	  {}
	     14	};
	     15	
	     16	struct S2 : public base_type // <--- S2 now has base_type as its base
	     17				     // type.
	     18	{
	     19	  int m0;
	     20	
	     21	  S2()
	     22	    : m0()
	     23	  {}
	     24	};
	     25	
	     26	struct S3 : public base_type // <--- S3 now has base_type as its base
	     27				     // type.
	     28	{
	     29	  int m0;
	     30	
	     31	  S3()
	     32	    : m0()
	     33	  {}
	     34	};
	     35	
	     36	int
	     37	func(S1&)
	     38	{
	     39	  // suppose the code does something with the argument.
	     40	  return 0;
	     41	
	     42	}
	     43	
	     44	char
	     45	func(S2*)
	     46	{
	     47	  // suppose the code does something with the argument.
	     48	  return 0;
	     49	}
	     50	
	     51	unsigned
	     52	func(S3)
	     53	{
	     54	  // suppose the code does something with the argument.
	     55	  return 0;
	     56	}
	 $ 

Now let's build the two libraries: ::

	 g++ -Wall -g -shared -o libtest2-v0.so test2-v0.cc
	 g++ -Wall -g -shared -o libtest2-v0.so test2-v0.cc

Let's look at the output of ``abidiff``: ::

	 $ abidiff libtest2-v0.so libtest2-v1.so 
	 Functions changes summary: 0 Removed, 3 Changed, 0 Added functions
	 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable

	 3 functions with some indirect sub-type change:

	   [C]'function unsigned int func(S3)' has some indirect sub-type changes:
	     parameter 0 of type 'struct S3' has sub-type changes:
	       size changed from 32 to 64 bits
	       1 base class insertion:
		 struct base_type
	       1 data member change:
		'int S3::m0' offset changed from 0 to 32

	   [C]'function char func(S2*)' has some indirect sub-type changes:
	     parameter 0 of type 'S2*' has sub-type changes:
	       in pointed to type 'struct S2':
		 size changed from 32 to 64 bits
		 1 base class insertion:
		   struct base_type
		 1 data member change:
		  'int S2::m0' offset changed from 0 to 32

	   [C]'function int func(S1&)' has some indirect sub-type changes:
	     parameter 0 of type 'S1&' has sub-type changes:
	       in referenced type 'struct S1':
		 size changed from 32 to 64 bits
		 1 base class insertion:
		   struct base_type
		 1 data member change:
		  'int S1::m0' offset changed from 0 to 32
	 $

Let's tell ``abidiff`` to avoid showing us the differences on the
overloads of ``func`` that takes either a pointer or a reference.
For that, we author this simple suppression specification: ::

	 $ cat -n libtest2.suppr
	      1	[suppress_function]
	      2	  name = func
	      3	  parameter = '0 S1&
	      4	
	      5	[suppress_function]
	      6	  name = func
	      7	  parameter = '0 S2*
	 $

And then let's invoke ``abidiff`` with the suppression
specification: ::

  $ ../build/tools/abidiff --suppressions libtest2.suppr libtest2-v0.so libtest2-v1.so 
  Functions changes summary: 0 Removed, 1 Changed (2 filtered out), 0 Added function
  Variables changes summary: 0 Removed, 0 Changed, 0 Added variable

  1 function with some indirect sub-type change:

	 [C]'function unsigned int func(S3)' has some indirect sub-type changes:
	   parameter 0 of type 'struct S3' has sub-type changes:
	     size changed from 32 to 64 bits
	     1 base class insertion:
	       struct base_type
	     1 data member change:
	      'int S3::m0' offset changed from 0 to 32


The suppression specification could be reduced using
:ref:`regular expressions <suppr_regexp_label>`: ::

  $ cat -n libtest2-1.suppr
	    1	[suppress_function]
	    2	  name = func
	    3	  parameter = '0 /^S.(&|\\*)/
  $

  $ ../build/tools/abidiff --suppressions libtest2-1.suppr libtest2-v0.so libtest2-v1.so 
  Functions changes summary: 0 Removed, 1 Changed (2 filtered out), 0 Added function
  Variables changes summary: 0 Removed, 0 Changed, 0 Added variable

  1 function with some indirect sub-type change:

	 [C]'function unsigned int func(S3)' has some indirect sub-type changes:
	   parameter 0 of type 'struct S3' has sub-type changes:
	     size changed from 32 to 64 bits
	     1 base class insertion:
	       struct base_type
	     1 data member change:
	      'int S3::m0' offset changed from 0 to 32

  $

.. _ELF: http://en.wikipedia.org/wiki/Executable_and_Linkable_Format

.. _Ini File Syntax: http://en.wikipedia.org/wiki/INI_file

.. _GNU C Library: http://www.gnu.org/software/libc