]> sourceware.org Git - libabigail.git/commitdiff
suppression: Fix has_data_member_inserted_between = {offset_of(), offset_of()}
authorDodji Seketeli <dodji@redhat.com>
Thu, 2 Dec 2021 09:08:14 +0000 (10:08 +0100)
committerDodji Seketeli <dodji@redhat.com>
Mon, 6 Dec 2021 13:39:32 +0000 (14:39 +0100)
This should fix bug https://sourceware.org/bugzilla/show_bug.cgi?id=28073

There is at least a case where the evaluation of the suppression
specification rule incarnated by the property
has_data_member_inserted_between doesn't work.  This is in the context
of the following suppression specification:

    [suppress_type]
     name = struct_foo
     has_data_member_inserted_between = {offset_of(dm1), offset_of(dm2)}

The evaluation of the rule incarnated by
has_data_member_inserted_between fails in the context of a type change
where the data member "dm1" is removed from the type struct_foo.  In
that case, the evaluation of the suppression should ALWAYS yield to
the suppression specification NOT suppressing the change.  But in some
cases the change is suppressed nonetheless.

This patch fixes that.

The idea of the patch is that if the class has a removed data member
or if its size shrinks then no type change on that class can be
suppressed.  This is because those two kinds of change are
incompatible ABI (or at least API) changes.  So they should be
reported.

The patch also fixes the evaluation of the boundaries of the insertion
range expressed as an "offset_after" expression.

* doc/manuals/libabigail-concepts.rst: Update the documentation to
reflect that has_data_member* properties will never suppress any
type change if the change carries a data member suppression or a
type size reduction.
* include/abg-fwd.h (get_last_data_member)
(get_next_data_member_offset): Declare new functions.
* include/abg-suppression.h
(insertion_range::boundary_value_is_end): Declare new static
member function.
(type_supression::insertion_range::eval_boundary): Make this
static function take an uint64_t rather than ssize_t.
(type_suppression::insertion_range::integer_boundary::{integer_boundary,
as_integer, operator int}): Make these member functions and
operator take or return uint64_t rather than int.
* src/abg-ir.cc (get_last_data_member)
(get_next_data_member_offset): Define new functions.
* src/abg-suppression.cc
(type_suppression::suppresses_diff): Rework logic to better handle
"has_data_member_inserted_*" properties in the context of class
diffs.  If the diff object carries data member removal or size
reduction, the diff object is not suppressed by the current type
suppression.  Also, the property "has_data_member_inserted_at =
end", is now represented by an insertion range where the beginning
and the end of the range are both the max possible value of
insertion range boundaries; the code is made to recognize that.
(type_suppression::insertion_range::eval_boundary): Make this
static function take an uint64_t rather than ssize_t.  If the
boundary is expressed as a "offset_after" expression, make sure
the offset of the next data member is considered if it's present.
(type_suppression::insertion_range::integer_boundary::{integer_boundary,
as_integer, operator int}): Make these take or return uint64_t
rather than int.
(type_suppression::insertion_range::boundary_value_is_end): Define
new member function.
(type_suppression::insertion_range::integer_boundary::priv::value_):
Turn the type of this into uint64_t, from int.
(type_suppression::insertion_range::integer_boundary::priv::priv):
The parameter of this is now uint64_t, from int.
* tests/data/test-diff-suppr/PR28073/PR28073-bitfield-removed.c:
New test source code.
* tests/data/test-diff-suppr/PR28073/PR28073-bitfield-removed.o:
New test binary.
* tests/data/test-diff-suppr/PR28073/PR28073-bitfield-removed.o.abi:
New test input.
* tests/data/test-diff-suppr/PR28073/PR28073-output-{1,2}.txt: New
test reference output.
* tests/data/test-diff-suppr/PR28073/PR28073.after.o: New test
binary.
* tests/data/test-diff-suppr/PR28073/PR28073.after.o.abi: New test
input.
* tests/data/test-diff-suppr/PR28073/PR28073.before.o: New test
binary.
* tests/data/test-diff-suppr/PR28073/PR28073.before.o.abi: New
test input.
* tests/data/test-diff-suppr/PR28073/PR28073.c: New test source
code.
* tests/data/test-diff-suppr/PR28073/bitfield.suppr: New test
input.
* tests/data/Makefile.am: Add the new test material to source
distribution.
* tests/test-diff-suppr.cc: Add the new test input to this test
harness.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
18 files changed:
doc/manuals/libabigail-concepts.rst
include/abg-fwd.h
include/abg-suppression.h
src/abg-ir.cc
src/abg-suppression.cc
tests/data/Makefile.am
tests/data/test-diff-suppr/PR28073/PR28073-bitfield-removed.c [new file with mode: 0644]
tests/data/test-diff-suppr/PR28073/PR28073-bitfield-removed.o [new file with mode: 0644]
tests/data/test-diff-suppr/PR28073/PR28073-bitfield-removed.o.abi [new file with mode: 0644]
tests/data/test-diff-suppr/PR28073/PR28073-output-1.txt [new file with mode: 0644]
tests/data/test-diff-suppr/PR28073/PR28073-output-2.txt [new file with mode: 0644]
tests/data/test-diff-suppr/PR28073/PR28073.after.o [new file with mode: 0644]
tests/data/test-diff-suppr/PR28073/PR28073.after.o.abi [new file with mode: 0644]
tests/data/test-diff-suppr/PR28073/PR28073.before.o [new file with mode: 0644]
tests/data/test-diff-suppr/PR28073/PR28073.before.o.abi [new file with mode: 0644]
tests/data/test-diff-suppr/PR28073/PR28073.c [new file with mode: 0644]
tests/data/test-diff-suppr/PR28073/bitfield.suppr [new file with mode: 0644]
tests/test-diff-suppr.cc

index b11c2c872cac4b559bc511abb66073b4b8b07725..c30e87e87c9e93af14cd4149106ac5c396dc46d2 100644 (file)
@@ -433,7 +433,11 @@ The potential properties of this sections are listed below:
 
  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``.  The value ``offset-in-bit`` is either:
+ ``offset-in-bit``.  Please note that if a type has a change in which
+ at least one of its data members is removed or its size is reduced,
+ the type will *NOT* be suppressed by the evaluation of this property.
+
+ 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
@@ -468,11 +472,14 @@ The potential properties of this sections are listed below:
    ``has_data_member_inserted_between`` ``=`` {<``range-begin``>, <``range-end``>}
 
  Suppresses change reports involving a type which has at least one
- data mber inserted at an offset that is comprised in the range
- between range-begin`` and ``range-end``.  Please note that each of
+ 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.
+ <suppr_has_data_member_inserted_at_label>` property above.  Please
+ also note that if a type has a change in which at least one of its
+ data members is removed or its size is reduced, the type will *NOT* be
+ suppressed by the evaluation of this property.
 
  Usage examples of this properties are: ::
 
@@ -508,7 +515,10 @@ The potential properties of this sections are listed below:
  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.
+ <suppr_has_data_member_inserted_at_label>` property above.  Please
+ note that if a type has a change in which at least one of its data
+ members is removed or its size is reduced, the type will *NOT* be
+ suppressed by the evaluation of this property.
 
  Another usage example of this property is thus: ::
 
index 638953144971b045546b4215ffff8bac4edcf026..36a99c3b63868665b7b6f6ee1b04112ccaf4293d 100644 (file)
@@ -639,6 +639,9 @@ is_data_member(const decl_base *);
 const var_decl_sptr
 get_next_data_member(const class_or_union_sptr&, const var_decl_sptr&);
 
+var_decl_sptr
+get_last_data_member(const class_or_union_sptr&);
+
 bool
 is_anonymous_data_member(const decl_base&);
 
@@ -721,6 +724,11 @@ get_data_member_offset(const decl_base_sptr);
 uint64_t
 get_absolute_data_member_offset(const var_decl&);
 
+bool
+get_next_data_member_offset(const class_or_union_sptr&,
+                           const var_decl_sptr&,
+                           uint64_t&);
+
 uint64_t
 get_var_size_in_bits(const var_decl_sptr&);
 
index db0334e71d548adf49707a75c9a351406ba6a953..6c13e33df318f889cd0b868d2ba70662518c2783 100644 (file)
@@ -328,7 +328,10 @@ public:
   static bool
   eval_boundary(boundary_sptr  boundary,
                class_decl_sptr context,
-               ssize_t&        value);
+               uint64_t&       value);
+
+  static bool
+  boundary_value_is_end(uint64_t value);
 }; // end class insertion_range
 
 type_suppression::insertion_range::integer_boundary_sptr
@@ -360,9 +363,9 @@ class type_suppression::insertion_range::integer_boundary
   integer_boundary();
 
 public:
-  integer_boundary(int value);
-  int as_integer() const;
-  operator int() const;
+  integer_boundary(uint64_t value);
+  uint64_t as_integer() const;
+  operator uint64_t () const;
   ~integer_boundary();
 }; //end class type_suppression::insertion_range::integer_boundary
 
index 17a62153c1bd6c239bb25c5a4854a92b030ff300..2cc4cf8cff1329a04c7e624063137c9b20b2e00c 100644 (file)
@@ -5739,6 +5739,13 @@ get_next_data_member(const class_or_union_sptr &klass,
   return var_decl_sptr();
 }
 
+/// Get the last data member of a class type.
+///
+/// @param klass the class type to consider.
+var_decl_sptr
+get_last_data_member(const class_or_union_sptr &klass)
+{return klass->get_non_static_data_members().back();}
+
 /// Test if a decl is an anonymous data member.
 ///
 /// @param d the decl to consider.
@@ -6003,6 +6010,35 @@ uint64_t
 get_data_member_offset(const decl_base_sptr d)
 {return get_data_member_offset(dynamic_pointer_cast<var_decl>(d));}
 
+/// Get the offset of the non-static data member that comes after a
+/// given one.
+///
+/// If there is no data member after after the one given to this
+/// function (maybe because the given one is the last data member of
+/// the class type) then the function return false.
+///
+/// @param klass the class to consider.
+///
+/// @param dm the data member before the one we want to retrieve.
+///
+/// @param offset out parameter.  This parameter is set by the
+/// function to the offset of the data member that comes right after
+/// the data member @p dm, iff the function returns true.
+///
+/// @return true iff the data member coming right after @p dm was
+/// found.
+bool
+get_next_data_member_offset(const class_or_union_sptr& klass,
+                           const var_decl_sptr& dm,
+                           uint64_t& offset)
+{
+  var_decl_sptr next_dm = get_next_data_member(klass, dm);
+  if (!next_dm)
+    return false;
+  offset = get_data_member_offset(next_dm);
+  return true;
+}
+
 /// Get the absolute offset of a data member.
 ///
 /// If the data member is part of an anonymous data member then this
index d3343a814ef4dc0d7919850a3645c62f890065b6..48c73cf81f4a605dda705104124a27bdba2b2799 100644 (file)
@@ -14,6 +14,7 @@
 
 #include "abg-internal.h"
 #include <memory>
+#include <limits>
 
 // <headers defining libabigail's API go under here>
 ABG_BEGIN_EXPORT_DECLARATIONS
@@ -773,67 +774,93 @@ type_suppression::suppresses_diff(const diff* diff) const
       d = is_type_diff(get_typedef_diff_underlying_type_diff(d));
     }
 
+  // Now let's consider class diffs in the context of a suppr spec
+  // that contains properties like "has_data_member_inserted_*".
+
   const class_diff* klass_diff = dynamic_cast<const class_diff*>(d);
-  if (// We are looking at a class diff ...
-      klass_diff
-      // ... that has inserted data members ...
-      && !get_data_member_insertion_ranges().empty()
-      // ... that has no deleted data members ...
-      && klass_diff->deleted_data_members().empty()
-      // ... and in which the class size hasn't shrunk (because, e.g,
-      // the base classes have changed).
-      && (klass_diff->first_class_decl()->get_size_in_bits()
-         <= klass_diff->second_class_decl()->get_size_in_bits()))
+  if (klass_diff)
     {
-      const class_decl_sptr& first_type_decl = klass_diff->first_class_decl();
-      const class_decl_sptr& second_type_decl = klass_diff->second_class_decl();
-      size_t first_type_size = first_type_decl->get_size_in_bits();
-      size_t second_type_size = second_type_decl->get_size_in_bits();
-
-      for (string_decl_base_sptr_map::const_iterator m =
-            klass_diff->inserted_data_members().begin();
-          m != klass_diff->inserted_data_members().end();
-          ++m)
+      // We are looking at a class diff ...
+      if (!get_data_member_insertion_ranges().empty())
        {
-         decl_base_sptr member = m->second;
-         size_t dm_offset = get_data_member_offset(member);
-         bool matched = false;
-
-         for (insertion_ranges::const_iterator i =
-                get_data_member_insertion_ranges().begin();
-              i != get_data_member_insertion_ranges().end();
-              ++i)
+         // ... and the suppr spec contains a
+         // "has_data_member_inserted_*" clause ...
+         if (klass_diff->deleted_data_members().empty()
+             && (klass_diff->first_class_decl()->get_size_in_bits()
+                 <= klass_diff->second_class_decl()->get_size_in_bits()))
            {
-             type_suppression::insertion_range_sptr range = *i;
-             ssize_t range_begin_val = 0,range_end_val = 0;
-             if (!type_suppression::insertion_range::eval_boundary
-                 (range->begin(), first_type_decl, range_begin_val))
-               break;
-             if (!type_suppression::insertion_range::eval_boundary
-                 (range->end(), first_type_decl, range_end_val))
-               break;
-
-             unsigned range_begin =
-               (range_begin_val < 0) ? first_type_size : range_begin_val;
-
-             unsigned range_end =
-               (range_end_val < 0) ? second_type_size : range_end_val;
-
-             if (range_begin > range_end)
-               continue;
-
-             if (range_begin_val < 0 || range_end_val < 0)
+             // That "has_data_member_inserted_*" clause doesn't hold
+             // if the class has deleted data members or shrunk.
+
+             const class_decl_sptr& first_type_decl =
+               klass_diff->first_class_decl();
+             const class_decl_sptr& second_type_decl =
+               klass_diff->second_class_decl();
+
+             for (string_decl_base_sptr_map::const_iterator m =
+                    klass_diff->inserted_data_members().begin();
+                  m != klass_diff->inserted_data_members().end();
+                  ++m)
                {
-                 if (dm_offset < range_begin)
-                   continue;
+                 decl_base_sptr member = m->second;
+                 size_t dm_offset = get_data_member_offset(member);
+                 bool matched = false;
+
+                 for (insertion_ranges::const_iterator i =
+                        get_data_member_insertion_ranges().begin();
+                      i != get_data_member_insertion_ranges().end();
+                      ++i)
+                   {
+                     type_suppression::insertion_range_sptr range = *i;
+                     uint64_t range_begin_val = 0, range_end_val = 0;
+                     if (!type_suppression::insertion_range::eval_boundary
+                         (range->begin(), first_type_decl, range_begin_val))
+                       break;
+                     if (!type_suppression::insertion_range::eval_boundary
+                         (range->end(), first_type_decl, range_end_val))
+                       break;
+
+                     uint64_t range_begin = range_begin_val;
+                     uint64_t range_end = range_end_val;
+
+                     if (insertion_range::boundary_value_is_end(range_begin)
+                         && insertion_range::boundary_value_is_end(range_end))
+                       {
+                         // This idiom represents the predicate
+                         // "has_data_member_inserted_at = end"
+                         if (dm_offset >
+                             get_data_member_offset(get_last_data_member
+                                                    (first_type_decl)))
+                           {
+                             // So the data member was added after
+                             // last data member of the klass.  That
+                             // matches the suppr spec
+                             // "has_data_member_inserted_at = end".
+                             matched = true;
+                             continue;
+                           }
+                       }
+
+                       if (range_begin > range_end)
+                         // Wrong suppr spec.  Ignore it.
+                         continue;
+
+                     if (dm_offset < range_begin || dm_offset > range_end)
+                       // The offset of the added data member doesn't
+                       // match the insertion range specified.  So
+                       // the diff object won't be suppressed.
+                       continue;
+
+                     // If we reached this point, then all the
+                     // insertion range constraints have been
+                     // satisfied.  So
+                     matched = true;
+                   }
+                 if (!matched)
+                   return false;
                }
-             else
-               if (dm_offset < range_begin || dm_offset > range_end)
-                 continue;
-
-             matched = true;
            }
-         if (!matched)
+         else
            return false;
        }
     }
@@ -1311,7 +1338,7 @@ type_suppression::insertion_range::create_fn_call_expr_boundary(const string& s)
 bool
 type_suppression::insertion_range::eval_boundary(boundary_sptr  boundary,
                                                 class_decl_sptr context,
-                                                ssize_t&        value)
+                                                uint64_t&       value)
 {
   if (integer_boundary_sptr b = is_integer_boundary(boundary))
     {
@@ -1338,8 +1365,13 @@ type_suppression::insertion_range::eval_boundary(boundary_sptr    boundary,
                  if (fn_call->get_name() == "offset_of")
                    value = get_data_member_offset(*it);
                  else if (fn_call->get_name() == "offset_after")
-                   value = get_data_member_offset(*it) +
-                     (*it)->get_type()->get_size_in_bits();
+                   {
+                     if (!get_next_data_member_offset(context, *it, value))
+                       {
+                         value = get_data_member_offset(*it) +
+                           (*it)->get_type()->get_size_in_bits();
+                       }
+                   }
                  else
                    // We should not reach this point.
                    abort();
@@ -1351,6 +1383,19 @@ type_suppression::insertion_range::eval_boundary(boundary_sptr    boundary,
   return false;
 }
 
+/// Test if a given value supposed to be inside an insertion range
+/// represents the end of the range.
+///
+/// @param value the value to test for.
+///
+/// @return true iff @p value represents the end of the insertion
+/// range.
+bool
+type_suppression::insertion_range::boundary_value_is_end(uint64_t value)
+{
+  return value == std::numeric_limits<uint64_t>::max();
+}
+
 /// Tests if a given instance of @ref
 /// type_suppression::insertion_range::boundary is actually an integer boundary.
 ///
@@ -1398,13 +1443,13 @@ type_suppression::insertion_range::boundary::~boundary()
 /// type_suppression::insertion_range::integer_boundary.
 struct type_suppression::insertion_range::integer_boundary::priv
 {
-  int value_;
+  uint64_t value_;
 
   priv()
     : value_()
   {}
 
-  priv(int value)
+  priv(uint64_t value)
     : value_(value)
   {}
 }; // end type_suppression::insertion_range::integer_boundary::priv
@@ -1413,22 +1458,22 @@ struct type_suppression::insertion_range::integer_boundary::priv
 /// type_suppression::insertion_range::integer_boundary.
 ///
 /// @param value the integer value of the newly created integer boundary.
-type_suppression::insertion_range::integer_boundary::integer_boundary(int value)
+type_suppression::insertion_range::integer_boundary::integer_boundary(uint64_t value)
   : priv_(new priv(value))
 {}
 
-/// Return the integer value of the current inace of @ref
+/// Return the integer value of the current instance of @ref
 /// type_suppression::insertion_range::integer_boundary.
 ///
 /// @return the integer value of the current boundary.
-int
+uint64_t
 type_suppression::insertion_range::integer_boundary::as_integer() const
 {return priv_->value_;}
 
 /// Converts the current boundary into an integer value.
 ///
 /// @return the integer value of the current boundary.
-type_suppression::insertion_range::integer_boundary::operator int() const
+type_suppression::insertion_range::integer_boundary::operator uint64_t() const
 {return as_integer();}
 
 /// Destructor of @ref type_suppression::insertion_range::integer_boundary.
index b83f05bef20411e3c966056e1a5f18ccd8b5704d..7edb1e24a2d70b5bd3e95e0a37ba634bd516fb96 100644 (file)
@@ -1550,6 +1550,17 @@ test-diff-suppr/PR27267/v1.c \
 test-diff-suppr/PR27267/libtestpr27267-v0.so \
 test-diff-suppr/PR27267/libtestpr27267-v1.so \
 test-diff-suppr/PR27267/report-1.txt \
+test-diff-suppr/PR28073/PR28073-bitfield-removed.c \
+test-diff-suppr/PR28073/PR28073-bitfield-removed.o \
+test-diff-suppr/PR28073/PR28073-bitfield-removed.o.abi \
+test-diff-suppr/PR28073/PR28073-output-1.txt \
+test-diff-suppr/PR28073/PR28073-output-2.txt \
+test-diff-suppr/PR28073/PR28073.after.o \
+test-diff-suppr/PR28073/PR28073.after.o.abi \
+test-diff-suppr/PR28073/PR28073.before.o \
+test-diff-suppr/PR28073/PR28073.before.o.abi \
+test-diff-suppr/PR28073/PR28073.c \
+test-diff-suppr/PR28073/bitfield.suppr \
 \
 test-diff-dwarf-abixml/test0-pr19026-libvtkIOSQL-6.1.so.1 \
 test-diff-dwarf-abixml/test0-pr19026-libvtkIOSQL-6.1.so.1.abi \
diff --git a/tests/data/test-diff-suppr/PR28073/PR28073-bitfield-removed.c b/tests/data/test-diff-suppr/PR28073/PR28073-bitfield-removed.c
new file mode 100644 (file)
index 0000000..e88aec9
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Compile this with:
+ * gcc -g -c PR28073-bitfield-removed.c
+ */
+#include <inttypes.h>
+
+struct bigstruct {
+  char name[128];
+  uint8_t other;
+};
+
+void access_bigstruct(struct bigstruct *st __attribute__((unused)))
+{
+}
diff --git a/tests/data/test-diff-suppr/PR28073/PR28073-bitfield-removed.o b/tests/data/test-diff-suppr/PR28073/PR28073-bitfield-removed.o
new file mode 100644 (file)
index 0000000..bdfe7d3
Binary files /dev/null and b/tests/data/test-diff-suppr/PR28073/PR28073-bitfield-removed.o differ
diff --git a/tests/data/test-diff-suppr/PR28073/PR28073-bitfield-removed.o.abi b/tests/data/test-diff-suppr/PR28073/PR28073-bitfield-removed.o.abi
new file mode 100644 (file)
index 0000000..3d3756c
--- /dev/null
@@ -0,0 +1,29 @@
+<abi-corpus version='2.1' path='PR28073-bitfield-removed.o' architecture='elf-amd-x86_64'>
+  <elf-function-symbols>
+    <elf-symbol name='access_bigstruct' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-function-symbols>
+  <abi-instr address-size='64' path='PR28073-bitfield-removed.c' comp-dir-path='/home/dodji/git/libabigail/fixes/prtests/PR28073' language='LANG_C11'>
+    <type-decl name='char' size-in-bits='8' id='type-id-1'/>
+    <array-type-def dimensions='1' type-id='type-id-1' size-in-bits='1024' id='type-id-2'>
+      <subrange length='128' type-id='type-id-3' id='type-id-4'/>
+    </array-type-def>
+    <type-decl name='unsigned char' size-in-bits='8' id='type-id-5'/>
+    <type-decl name='unsigned long int' size-in-bits='64' id='type-id-3'/>
+    <class-decl name='bigstruct' size-in-bits='1032' is-struct='yes' visibility='default' filepath='/home/dodji/git/libabigail/fixes/prtests/PR28073/PR28073-bitfield-removed.c' line='7' column='1' id='type-id-6'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='name' type-id='type-id-2' visibility='default' filepath='/home/dodji/git/libabigail/fixes/prtests/PR28073/PR28073-bitfield-removed.c' line='8' column='1'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='1024'>
+        <var-decl name='other' type-id='type-id-7' visibility='default' filepath='/home/dodji/git/libabigail/fixes/prtests/PR28073/PR28073-bitfield-removed.c' line='9' column='1'/>
+      </data-member>
+    </class-decl>
+    <typedef-decl name='uint8_t' type-id='type-id-8' filepath='/usr/include/bits/stdint-uintn.h' line='24' column='1' id='type-id-7'/>
+    <typedef-decl name='__uint8_t' type-id='type-id-5' filepath='/usr/include/bits/types.h' line='38' column='1' id='type-id-8'/>
+    <pointer-type-def type-id='type-id-6' size-in-bits='64' id='type-id-9'/>
+    <function-decl name='access_bigstruct' mangled-name='access_bigstruct' filepath='/home/dodji/git/libabigail/fixes/prtests/PR28073/PR28073-bitfield-removed.c' line='12' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='access_bigstruct'>
+      <parameter type-id='type-id-9' name='st' filepath='/home/dodji/git/libabigail/fixes/prtests/PR28073/PR28073-bitfield-removed.c' line='12' column='1'/>
+      <return type-id='type-id-10'/>
+    </function-decl>
+    <type-decl name='void' id='type-id-10'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-diff-suppr/PR28073/PR28073-output-1.txt b/tests/data/test-diff-suppr/PR28073/PR28073-output-1.txt
new file mode 100644 (file)
index 0000000..9666a8f
--- /dev/null
@@ -0,0 +1,3 @@
+Functions changes summary: 0 Removed, 0 Changed (1 filtered out), 0 Added function
+Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+
diff --git a/tests/data/test-diff-suppr/PR28073/PR28073-output-2.txt b/tests/data/test-diff-suppr/PR28073/PR28073-output-2.txt
new file mode 100644 (file)
index 0000000..8731043
--- /dev/null
@@ -0,0 +1,14 @@
+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 access_bigstruct(bigstruct*)' at PR28073-bitfield-removed.c:12:1 has some indirect sub-type changes:
+    parameter 1 of type 'bigstruct*' has sub-type changes:
+      in pointed to type 'struct bigstruct' at PR28073-bitfield-removed.c:7:1:
+        type size changed from 1040 to 1032 (in bits)
+        1 data member deletion:
+          'uint8_t bitfield0', at offset 1024 (in bits) at plop.c:5:1
+        1 data member change:
+          'uint8_t other' offset changed from 1032 to 1024 (in bits) (by -8 bits)
+
diff --git a/tests/data/test-diff-suppr/PR28073/PR28073.after.o b/tests/data/test-diff-suppr/PR28073/PR28073.after.o
new file mode 100644 (file)
index 0000000..948323d
Binary files /dev/null and b/tests/data/test-diff-suppr/PR28073/PR28073.after.o differ
diff --git a/tests/data/test-diff-suppr/PR28073/PR28073.after.o.abi b/tests/data/test-diff-suppr/PR28073/PR28073.after.o.abi
new file mode 100644 (file)
index 0000000..d594bf6
--- /dev/null
@@ -0,0 +1,35 @@
+<abi-corpus version='2.1' path='PR28073.after.o' architecture='elf-amd-x86_64'>
+  <elf-function-symbols>
+    <elf-symbol name='access_bigstruct' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-function-symbols>
+  <abi-instr address-size='64' path='PR28073.c' comp-dir-path='/home/dodji/git/libabigail/fixes/prtests/PR28073' language='LANG_C11'>
+    <type-decl name='char' size-in-bits='8' id='type-id-1'/>
+    <array-type-def dimensions='1' type-id='type-id-1' size-in-bits='1024' id='type-id-2'>
+      <subrange length='128' type-id='type-id-3' id='type-id-4'/>
+    </array-type-def>
+    <type-decl name='unsigned char' size-in-bits='8' id='type-id-5'/>
+    <type-decl name='unsigned long int' size-in-bits='64' id='type-id-3'/>
+    <class-decl name='bigstruct' size-in-bits='1040' is-struct='yes' visibility='default' filepath='/home/dodji/git/libabigail/fixes/prtests/PR28073/PR28073.c' line='9' column='1' id='type-id-6'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='name' type-id='type-id-2' visibility='default' filepath='/home/dodji/git/libabigail/fixes/prtests/PR28073/PR28073.c' line='10' column='1'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='1024'>
+        <var-decl name='bitfield0' type-id='type-id-7' visibility='default' filepath='/home/dodji/git/libabigail/fixes/prtests/PR28073/PR28073.c' line='11' column='1'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='1025'>
+        <var-decl name='bitfield1' type-id='type-id-7' visibility='default' filepath='/home/dodji/git/libabigail/fixes/prtests/PR28073/PR28073.c' line='13' column='1'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='1032'>
+        <var-decl name='other' type-id='type-id-7' visibility='default' filepath='/home/dodji/git/libabigail/fixes/prtests/PR28073/PR28073.c' line='16' column='1'/>
+      </data-member>
+    </class-decl>
+    <typedef-decl name='uint8_t' type-id='type-id-8' filepath='/usr/include/bits/stdint-uintn.h' line='24' column='1' id='type-id-7'/>
+    <typedef-decl name='__uint8_t' type-id='type-id-5' filepath='/usr/include/bits/types.h' line='38' column='1' id='type-id-8'/>
+    <pointer-type-def type-id='type-id-6' size-in-bits='64' id='type-id-9'/>
+    <function-decl name='access_bigstruct' mangled-name='access_bigstruct' filepath='/home/dodji/git/libabigail/fixes/prtests/PR28073/PR28073.c' line='19' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='access_bigstruct'>
+      <parameter type-id='type-id-9' name='st' filepath='/home/dodji/git/libabigail/fixes/prtests/PR28073/PR28073.c' line='19' column='1'/>
+      <return type-id='type-id-10'/>
+    </function-decl>
+    <type-decl name='void' id='type-id-10'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-diff-suppr/PR28073/PR28073.before.o b/tests/data/test-diff-suppr/PR28073/PR28073.before.o
new file mode 100644 (file)
index 0000000..84d14ee
Binary files /dev/null and b/tests/data/test-diff-suppr/PR28073/PR28073.before.o differ
diff --git a/tests/data/test-diff-suppr/PR28073/PR28073.before.o.abi b/tests/data/test-diff-suppr/PR28073/PR28073.before.o.abi
new file mode 100644 (file)
index 0000000..81c4ac2
--- /dev/null
@@ -0,0 +1,32 @@
+<abi-corpus version='2.1' path='PR28073.before.o' architecture='elf-amd-x86_64'>
+  <elf-function-symbols>
+    <elf-symbol name='access_bigstruct' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-function-symbols>
+  <abi-instr address-size='64' path='plop.c' comp-dir-path='/home/dodji/git/libabigail/fixes/prtests/PR28073' language='LANG_C11'>
+    <type-decl name='char' size-in-bits='8' id='type-id-1'/>
+    <array-type-def dimensions='1' type-id='type-id-1' size-in-bits='1024' id='type-id-2'>
+      <subrange length='128' type-id='type-id-3' id='type-id-4'/>
+    </array-type-def>
+    <type-decl name='unsigned char' size-in-bits='8' id='type-id-5'/>
+    <type-decl name='unsigned long int' size-in-bits='64' id='type-id-3'/>
+    <class-decl name='bigstruct' size-in-bits='1040' is-struct='yes' visibility='default' filepath='/home/dodji/git/libabigail/fixes/prtests/PR28073/plop.c' line='3' column='1' id='type-id-6'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='name' type-id='type-id-2' visibility='default' filepath='/home/dodji/git/libabigail/fixes/prtests/PR28073/plop.c' line='4' column='1'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='1024'>
+        <var-decl name='bitfield0' type-id='type-id-7' visibility='default' filepath='/home/dodji/git/libabigail/fixes/prtests/PR28073/plop.c' line='5' column='1'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='1032'>
+        <var-decl name='other' type-id='type-id-7' visibility='default' filepath='/home/dodji/git/libabigail/fixes/prtests/PR28073/plop.c' line='10' column='1'/>
+      </data-member>
+    </class-decl>
+    <typedef-decl name='uint8_t' type-id='type-id-8' filepath='/usr/include/bits/stdint-uintn.h' line='24' column='1' id='type-id-7'/>
+    <typedef-decl name='__uint8_t' type-id='type-id-5' filepath='/usr/include/bits/types.h' line='38' column='1' id='type-id-8'/>
+    <pointer-type-def type-id='type-id-6' size-in-bits='64' id='type-id-9'/>
+    <function-decl name='access_bigstruct' mangled-name='access_bigstruct' filepath='/home/dodji/git/libabigail/fixes/prtests/PR28073/plop.c' line='13' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='access_bigstruct'>
+      <parameter type-id='type-id-9' name='st' filepath='/home/dodji/git/libabigail/fixes/prtests/PR28073/plop.c' line='13' column='1'/>
+      <return type-id='type-id-10'/>
+    </function-decl>
+    <type-decl name='void' id='type-id-10'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-diff-suppr/PR28073/PR28073.c b/tests/data/test-diff-suppr/PR28073/PR28073.c
new file mode 100644 (file)
index 0000000..2b84d59
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Compile this twice:
+ * gcc -g -c -DBEFORE -o PR28073.before.o PR28073.c
+ * gcc -g -c -o PR28073.after.o PR28073.c
+ */
+
+#include <inttypes.h>
+
+struct bigstruct {
+  char name[128];
+  uint8_t bitfield0:1
+  #ifndef BEFORE
+  ,bitfield1:1
+    #endif
+    ;
+  uint8_t other;
+};
+
+void access_bigstruct(struct bigstruct *st)
+{
+  #ifndef BEFORE
+  st->bitfield1 = 1;
+  #endif
+}
diff --git a/tests/data/test-diff-suppr/PR28073/bitfield.suppr b/tests/data/test-diff-suppr/PR28073/bitfield.suppr
new file mode 100644 (file)
index 0000000..4acd81b
--- /dev/null
@@ -0,0 +1,4 @@
+[suppress_type]
+  name = bigstruct
+  type_kind = struct
+  has_data_member_inserted_between = {offset_of(bitfield0), offset_of(other)}
index 5b4d08d3923fa8dbdb99d9a7b63b8f578c1b784f..0f797fa6a4723055f67ce025c23c5177641fb508 100644 (file)
@@ -2036,6 +2036,26 @@ InOutSpec in_out_specs[] =
     "data/test-diff-suppr/PR27267/report-1.txt",
     "output/test-diff-suppr/PR27267/report-1.txt"
   },
+  {
+    "data/test-diff-suppr/PR28073/PR28073.before.o.abi",
+    "data/test-diff-suppr/PR28073/PR28073.after.o.abi",
+    "",
+    "",
+    "data/test-diff-suppr/PR28073/bitfield.suppr",
+    "--drop-private-types --no-default-suppression",
+    "data/test-diff-suppr/PR28073/PR28073-output-1.txt",
+    "output/test-diff-suppr/PR28073/PR28073-output-1.txt"
+  },
+  {
+    "data/test-diff-suppr/PR28073/PR28073.before.o.abi",
+    "data/test-diff-suppr/PR28073/PR28073-bitfield-removed.o.abi",
+    "",
+    "",
+    "data/test-diff-suppr/PR28073/bitfield.suppr",
+    "--drop-private-types --no-default-suppression",
+    "data/test-diff-suppr/PR28073/PR28073-output-2.txt",
+    "output/test-diff-suppr/PR28073/PR28073-output-2.txt"
+  },
   // This should be the last entry
   {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
 };
This page took 0.086301 seconds and 5 git commands to generate.