Bug 24157 - Wrong support of Ada ranges
authorDodji Seketeli <dodji@redhat.com>
Wed, 6 Feb 2019 12:16:44 +0000 (13:16 +0100)
committerDodji Seketeli <dodji@redhat.com>
Thu, 7 Feb 2019 10:21:34 +0000 (11:21 +0100)
In this problem report, the DWARF reader comes across an ADA subrange
which lower bound is a negative signed integer.  The problem is that
the internal representation of libabigail expects the bounds of the
subrange to be unsigned integer.  This incompatibility leads to an
assertion failure.

Further down the road I realized that the function
types_have_similar_structure doesn't support subrange types.

This patch thus introduces a new
array_type_def::subrange_type::bound_value class that captures the
signedness of the bound value.  This allows the internal
representation to keep the sign information of the bound value, and
yet be able to treat the bound value as either a signed or unsigned
value depending on the contexts.

The patch also extends the function types_have_similar_structure to
make it support subrange types.

* include/abg-ir.h (array_type_def::subrange_type::bound_value):
Define new class.
(array_type_def::subrange_type::subrange_type): Adjust to use the
new bound_value type for bound values.
(array_type_def::subrange_type::{get_upper_bound, get_lower_bound,
set_upper_bound, set_lower_bound}): Return or take int64_t rather
than size_t.
(array_type_def::subrange_type::get_length): Return uint64_t
rather than size_t.
* src/abg-dwarf-reader.cc (die_signed_constant_attribute)
(die_constant_attribute, die_attribute_has_form)
(die_attribute_is_signed, die_attribute_is_unsigned)
(die_attribute_has_no_signedness): Define new static functions.
(get_default_array_lower_bound): Return uint64_t rather than int.
(build_subrange_type): Use the new
array_type_def::subrange_type::bound_value type for bound values.
Use the new die_constant_attribute function, rather than
die_unsigned_constant_attribute to fecth the bound values.
* src/abg-ir.cc
(array_type_def::subrange_type::bound_value::{bound_value,
get_signedness, set_signedness, get_signed_value,
get_unsigned_value, set_unsigned, set_signed}): Define new member
functions.
(array_type_def::subrange_type::priv::{lower_bound_,
upper_bound}): Use the new class bound_value.
(array_type_def::subrange_type::priv::priv): Adjust to use the new
bound_value class to hold bound values.
(array_type_def::subrange_type::subrange_type): Likewise.
(array_type_def::subrange_type::{get_upper_bound, get_lower_bound,
set_upper_bound, set_lower_bound}): Return or take int64_t rather
than size_t.
(array_type_def::subrange_type::get_length): Return uint64_t
rather than size_t.
(types_have_similar_structure): Handle array_type_def::subrange_type
* src/abg-reader.cc (build_subrange_type): Use the new
array_type_def::subrange_type::bound_value to hold bound values.
* tests/data/test-diff-pkg/GtkAda-debuginfo-2.24.2-29.fc29.x86_64.rpm:
New binary RPM as test input.
* tests/data/test-diff-pkg/GtkAda-debuginfo-2.24.2-30.fc30.x86_64.rpm:
Likewise.
* tests/data/test-diff-pkg/GtkAda-devel-2.24.2-29.fc29.x86_64.rpm:
Likewise.
* tests/data/test-diff-pkg/GtkAda-devel-2.24.2-30.fc30.x86_64.rpm:
Likewise.
* tests/data/test-diff-pkg/GtkAda-gl-2.24.2-29.fc29.x86_64--2.24.2-30.fc30.x86_64-report-0.txt:
New expected test output.
* tests/data/test-diff-pkg/GtkAda-gl-2.24.2-29.fc29.x86_64.rpm:
New binary RPM as test input.
* tests/data/test-diff-pkg/GtkAda-gl-2.24.2-30.fc30.x86_64.rpm:
Likewise.
* tests/data/test-diff-pkg/GtkAda-gl-debuginfo-2.24.2-29.fc29.x86_64.rpm:
Likewise.
* tests/data/test-diff-pkg/GtkAda-gl-debuginfo-2.24.2-30.fc30.x86_64.rpm:
Likewise.
* tests/data/Makefile.am: Add the new test material above to source
distribution.
* tests/test-diff-pkg.cc (in_out_specs): Add the new input testing
RPMs in here.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
15 files changed:
include/abg-ir.h
src/abg-dwarf-reader.cc
src/abg-ir.cc
src/abg-reader.cc
tests/data/Makefile.am
tests/data/test-diff-pkg/GtkAda-debuginfo-2.24.2-29.fc29.x86_64.rpm [new file with mode: 0644]
tests/data/test-diff-pkg/GtkAda-debuginfo-2.24.2-30.fc30.x86_64.rpm [new file with mode: 0644]
tests/data/test-diff-pkg/GtkAda-devel-2.24.2-29.fc29.x86_64.rpm [new file with mode: 0644]
tests/data/test-diff-pkg/GtkAda-devel-2.24.2-30.fc30.x86_64.rpm [new file with mode: 0644]
tests/data/test-diff-pkg/GtkAda-gl-2.24.2-29.fc29.x86_64--2.24.2-30.fc30.x86_64-report-0.txt [new file with mode: 0644]
tests/data/test-diff-pkg/GtkAda-gl-2.24.2-29.fc29.x86_64.rpm [new file with mode: 0644]
tests/data/test-diff-pkg/GtkAda-gl-2.24.2-30.fc30.x86_64.rpm [new file with mode: 0644]
tests/data/test-diff-pkg/GtkAda-gl-debuginfo-2.24.2-29.fc29.x86_64.rpm [new file with mode: 0644]
tests/data/test-diff-pkg/GtkAda-gl-debuginfo-2.24.2-30.fc30.x86_64.rpm [new file with mode: 0644]
tests/test-diff-pkg.cc

index fb65d9d..55452ec 100644 (file)
@@ -2056,27 +2056,61 @@ public:
     subrange_type();
   public:
 
+    /// This class is to hold the value of the bound of a subrange.
+    /// The value can be either signed or unsigned, at least when it
+    /// comes from DWARF.  The class keeps the sign information, but
+    /// allows users to access the value as signed or unsigned as they
+    /// see fit.
+    class bound_value
+    {
+    public:
+      enum signedness
+      {
+       UNSIGNED_SIGNEDNESS,
+       SIGNED_SIGNEDNESS
+      };
+
+    private:
+      signedness s_;
+
+    public:
+      union
+      {
+       uint64_t unsigned_;
+       int64_t signed_;
+      } v_;
+      bound_value();
+      bound_value(uint64_t);
+      bound_value(int64_t);
+      enum signedness get_signedness() const;
+      void set_signedness(enum signedness s);
+      int64_t get_signed_value() const;
+      uint64_t get_unsigned_value();
+      void set_unsigned(uint64_t v);
+      void set_signed(int64_t v);
+    }; //end class bound_value
+
     /// Hasher for an instance of array::subrange
     struct hash;
 
     subrange_type(const environment*   env,
                  const string& name,
-                 size_t                lower_bound,
-                 size_t                upper_bound,
+                 bound_value           lower_bound,
+                 bound_value           upper_bound,
                  type_base_sptr&       underlying_type,
                  const location&       loc,
                  translation_unit::language l = translation_unit::LANG_C11);
 
     subrange_type(const environment* env,
                  const string& name,
-                 size_t lower_bound,
-                 size_t upper_bound,
+                 bound_value lower_bound,
+                 bound_value upper_bound,
                  const location& loc,
                  translation_unit::language l = translation_unit::LANG_C11);
 
     subrange_type(const environment* env,
                  const string& name,
-                 size_t upper_bound,
+                 bound_value upper_bound,
                  const location& loc,
                  translation_unit::language l = translation_unit::LANG_C11);
 
@@ -2086,19 +2120,19 @@ public:
     void
     set_underlying_type(const type_base_sptr &);
 
-    size_t
+    int64_t
     get_upper_bound() const;
 
-    size_t
+    int64_t
     get_lower_bound() const;
 
     void
-    set_upper_bound(size_t ub);
+    set_upper_bound(int64_t ub);
 
     void
-    set_lower_bound(size_t lb);
+    set_lower_bound(int64_t lb);
 
-    size_t
+    uint64_t
     get_length() const;
 
     bool
index d6bb0c7..ab286f2 100644 (file)
@@ -376,6 +376,30 @@ die_unsigned_constant_attribute(Dwarf_Die* die,
                                uint64_t&       cst);
 
 static bool
+die_signed_constant_attribute(Dwarf_Die*die,
+                             unsigned  attr_name,
+                             int64_t&  cst);
+
+static bool
+die_constant_attribute(Dwarf_Die *die,
+                      unsigned attr_name,
+                      array_type_def::subrange_type::bound_value &value);
+
+static bool
+die_attribute_has_form(Dwarf_Die*                                       die,
+                      unsigned                                          attr_name,
+                      unsigned int                                      form);
+
+static bool
+die_attribute_is_signed(Dwarf_Die* die, unsigned attr_name);
+
+static bool
+die_attribute_is_unsigned(Dwarf_Die* die, unsigned attr_name);
+
+static bool
+die_attribute_has_no_signedness(Dwarf_Die* die, unsigned attr_name);
+
+static bool
 die_address_attribute(Dwarf_Die* die, unsigned attr_name, Dwarf_Addr& result);
 
 static string
@@ -448,7 +472,7 @@ die_pretty_print(read_context& ctxt, Dwarf_Die* die, size_t where_offset);
 static void
 maybe_canonicalize_type(Dwarf_Die* die, read_context& ctxt);
 
-static int
+static uint64_t
 get_default_array_lower_bound(translation_unit::language l);
 
 static bool
@@ -8254,6 +8278,146 @@ die_unsigned_constant_attribute(Dwarf_Die*      die,
   return true;
 }
 
+/// Read a signed constant value from a given attribute.
+///
+/// The signed constant expected must be of form DW_FORM_sdata.
+///
+/// @param die the DIE to get the attribute from.
+///
+/// @param attr_name the attribute name.
+///
+/// @param cst the resulting signed constant read.
+///
+/// @return true iff a signed constant attribute of the name @p
+/// attr_name was found on the DIE @p die.
+static bool
+die_signed_constant_attribute(Dwarf_Die *die,
+                             unsigned  attr_name,
+                             int64_t&  cst)
+{
+  if (!die)
+    return false;
+
+  Dwarf_Attribute attr;
+  Dwarf_Sword result = 0;
+  if (!dwarf_attr_integrate(die, attr_name, &attr)
+      || dwarf_formsdata(&attr, &result))
+    return false;
+
+  cst = result;
+  return true;
+}
+
+/// Read the value of a constant attribute that is either signed or
+/// unsigned into a array_type_def::subrange_type::bound_value value.
+///
+/// The bound_value instance will capture the actual signedness of the
+/// read attribute.
+///
+/// @param die the DIE from which to read the value of the attribute.
+///
+/// @param attr_name the attribute name to consider.
+///
+/// @param value the resulting value read from attribute @p attr_name
+/// on DIE @p die.
+///
+/// @return true iff DIE @p die has an attribute named @p attr_name
+/// with a constant value.
+static bool
+die_constant_attribute(Dwarf_Die *die,
+                      unsigned attr_name,
+                      array_type_def::subrange_type::bound_value &value)
+{
+  if (die_attribute_is_unsigned(die, attr_name)
+      || die_attribute_has_no_signedness(die, attr_name))
+    {
+      uint64_t l = 0;
+      if (!die_unsigned_constant_attribute(die, attr_name, l))
+       return false;
+      value.set_unsigned(l);
+    }
+  else
+    {
+      int64_t l = 0;
+      if (!die_signed_constant_attribute(die, attr_name, l))
+       return false;
+      value.set_signed(l);
+    }
+  return true;
+}
+
+/// Test if a given attribute on a DIE has a particular form.
+///
+/// @param die the DIE to consider.
+///
+/// @param attr_name the attribute name to consider on DIE @p die.
+///
+/// @param attr_form the attribute form that we expect attribute @p
+/// attr_name has on DIE @p die.
+///
+/// @return true iff the attribute named @p attr_name on DIE @p die
+/// has the form @p attr_form.
+static bool
+die_attribute_has_form(Dwarf_Die       *die,
+                      unsigned attr_name,
+                      unsigned int     attr_form)
+{
+  Dwarf_Attribute attr;
+  if (!dwarf_attr_integrate(die, attr_name, &attr))
+    return false;
+
+  return dwarf_hasform(&attr, attr_form);
+}
+
+/// Test if a given DIE attribute is signed.
+///
+/// @param die the DIE to consider.
+///
+/// @param attr_name the attribute name to consider.
+///
+/// @return true iff the attribute named @p attr_name on DIE @p die is
+/// signed.
+static bool
+die_attribute_is_signed(Dwarf_Die* die, unsigned attr_name)
+{
+  if (die_attribute_has_form(die, attr_name, DW_FORM_sdata))
+    return true;
+  return false;
+}
+
+/// Test if a given DIE attribute is unsigned.
+///
+/// @param die the DIE to consider.
+///
+/// @param attr_name the attribute name to consider.
+///
+/// @return true iff the attribute named @p attr_name on DIE @p die is
+/// unsigned.
+static bool
+die_attribute_is_unsigned(Dwarf_Die* die, unsigned attr_name)
+{
+  if (die_attribute_has_form(die, attr_name, DW_FORM_udata))
+    return true;
+  return false;
+}
+
+/// Test if a given DIE attribute is neither explicitely signed nor
+/// unsigned.  Usually this is the case for attribute of the form
+/// DW_FORM_data*.
+///
+/// @param die the DIE to consider.
+///
+/// @param attr_name the name of the attribute to consider.
+///
+/// @return true iff the attribute named @p attr_name of DIE @p die is
+/// neither specifically signed nor unsigned.
+static bool
+die_attribute_has_no_signedness(Dwarf_Die *die, unsigned attr_name)
+{
+  return (!die_attribute_is_unsigned(die, attr_name)
+         && !die_attribute_is_signed(die, attr_name));
+}
+
 /// Get the value of a DIE attribute; that value is meant to be a
 /// flag.
 ///
@@ -12288,7 +12452,7 @@ dwarf_language_to_tu_language(size_t l)
 /// @param l the language of the translation unit.
 ///
 /// @return the default array lower bound value.
-static int
+static uint64_t
 get_default_array_lower_bound(translation_unit::language l)
 {
   int value = 0;
@@ -14184,8 +14348,9 @@ build_subrange_type(read_context&       ctxt,
   string name = die_name(die);
 
   translation_unit::language language = ctxt.cur_transl_unit()->get_language();
-  uint64_t lower_bound = get_default_array_lower_bound(language);
-  uint64_t upper_bound = 0;
+  array_type_def::subrange_type::bound_value lower_bound =
+    get_default_array_lower_bound(language);
+  array_type_def::subrange_type::bound_value upper_bound;
   uint64_t count = 0;
   bool is_infinite = false;
 
@@ -14198,10 +14363,10 @@ build_subrange_type(read_context&     ctxt,
   //     values of the subrange.
   //
   // So let's look for DW_AT_lower_bound first.
-  die_unsigned_constant_attribute(die, DW_AT_lower_bound, lower_bound);
+  die_constant_attribute(die, DW_AT_lower_bound, lower_bound);
 
   // Then, DW_AT_upper_bound.
-  if (!die_unsigned_constant_attribute(die, DW_AT_upper_bound, upper_bound))
+  if (!die_constant_attribute(die, DW_AT_upper_bound, upper_bound))
     {
       // The DWARF 4 spec says, in [5.11 Subrange Type
       // Entries]:
@@ -14219,22 +14384,22 @@ build_subrange_type(read_context&     ctxt,
       // We can deduce the upper_bound from the
       // lower_bound and the number of elements of the
       // array:
-      if (size_t u = lower_bound + count)
+      if (int64_t u = lower_bound.get_signed_value() + count)
        upper_bound = u - 1;
 
-      if (upper_bound == 0 && count == 0)
+      if (upper_bound.get_unsigned_value() == 0 && count == 0)
        // No upper_bound nor count was present on the DIE, this means
        // the array is considered to have an infinite (or rather not
        // known) size.
        is_infinite = true;
     }
 
-  if (UINT64_MAX == upper_bound)
+  if (UINT64_MAX == upper_bound.get_unsigned_value())
     {
-      // Of the upper_bound size is the max of the integer value, then
+      // If the upper_bound size is the max of the integer value, then
       // it most certainly means infinite size.
       is_infinite = true;
-      upper_bound = 0;
+      upper_bound.set_unsigned(0);
     }
 
   result.reset
index 27dd6c2..f264be1 100644 (file)
@@ -12613,25 +12613,107 @@ operator!=(const reference_type_def_sptr& l, const reference_type_def_sptr& r)
 // <array_type_def definitions>
 
 // <array_type_def::subrange_type>
+
+// <array_type_def::subrante_type::bound_value>
+
+/// Default constructor of the @ref
+/// array_type_def::subrange_type::bound_value class.
+///
+/// Constructs an unsigned bound_value of value zero.
+array_type_def::subrange_type::bound_value::bound_value()
+  : s_(UNSIGNED_SIGNEDNESS)
+{
+  v_.unsigned_ = 0;
+}
+
+/// Initialize an unsigned bound_value with a given value.
+///
+/// @param v the initial bound value.
+array_type_def::subrange_type::bound_value::bound_value(uint64_t v)
+  : s_(UNSIGNED_SIGNEDNESS)
+{
+  v_.unsigned_ = v;
+}
+
+/// Initialize a signed bound_value with a given value.
+///
+/// @param v the initial bound value.
+array_type_def::subrange_type::bound_value::bound_value(int64_t v)
+  : s_(SIGNED_SIGNEDNESS)
+{
+  v_.signed_ = v;
+}
+
+/// Getter of the signedness (unsigned VS signed) of the bound value.
+///
+/// @return the signedness of the bound value.
+enum array_type_def::subrange_type::bound_value::signedness
+array_type_def::subrange_type::bound_value::get_signedness() const
+{return s_;}
+
+/// Setter of the signedness (unsigned VS signed) of the bound value.
+///
+/// @param s the new signedness of the bound value.
+void
+array_type_def::subrange_type::bound_value::set_signedness(enum signedness s)
+{ s_ = s;}
+
+/// Getter of the bound value as a signed value.
+///
+/// @return the bound value as signed.
+int64_t
+array_type_def::subrange_type::bound_value::get_signed_value() const
+{return v_.signed_;
+}
+
+/// Getter of the bound value as an unsigned value.
+///
+/// @return the bound value as unsigned.
+uint64_t
+array_type_def::subrange_type::bound_value::get_unsigned_value()
+{return v_.unsigned_;}
+
+/// Setter of the bound value as unsigned.
+///
+/// @param v the new unsigned value.
+void
+array_type_def::subrange_type::bound_value::set_unsigned(uint64_t v)
+{
+    s_ = UNSIGNED_SIGNEDNESS;
+  v_.unsigned_ = v;
+}
+
+/// Setter of the bound value as signed.
+///
+/// @param v the new signed value.
+void
+array_type_def::subrange_type::bound_value::set_signed(int64_t v)
+{
+  s_ = SIGNED_SIGNEDNESS;
+  v_.signed_ = v;
+}
+
+// </array_type_def::subrante_type::bound_value>
+
 struct array_type_def::subrange_type::priv
 {
-  size_t               lower_bound_;
-  size_t               upper_bound_;
+  bound_value          lower_bound_;
+  bound_value          upper_bound_;
   type_base_wptr       underlying_type_;
   translation_unit::language language_;
   bool                 infinite_;
 
-  priv(size_t ub,
+  priv(bound_value ub,
        translation_unit::language l = translation_unit::LANG_C11)
-    : lower_bound_(0), upper_bound_(ub), language_(l), infinite_(false)
+    : upper_bound_(ub), language_(l), infinite_(false)
   {}
 
-  priv(size_t lb, size_t ub,
+  priv(bound_value lb, bound_value ub,
        translation_unit::language l = translation_unit::LANG_C11)
     : lower_bound_(lb), upper_bound_(ub), language_(l)
   {}
 
-  priv(size_t lb, size_t ub, const type_base_sptr &u,
+  priv(bound_value lb, bound_value ub, const type_base_sptr &u,
        translation_unit::language l = translation_unit::LANG_C11)
     : lower_bound_(lb), upper_bound_(ub), underlying_type_(u), language_(l)
   {}
@@ -12653,13 +12735,16 @@ struct array_type_def::subrange_type::priv
 /// @param loc the source location where the type is defined.
 array_type_def::subrange_type::subrange_type(const environment* env,
                                             const string&      name,
-                                            size_t             lower_bound,
-                                            size_t             upper_bound,
+                                            bound_value        lower_bound,
+                                            bound_value        upper_bound,
                                             type_base_sptr&    underlying_type,
                                             const location&    loc,
                                             translation_unit::language l)
   : type_or_decl_base(env),
-    type_base(env, upper_bound - lower_bound, 0),
+    type_base(env,
+             upper_bound.get_unsigned_value()
+             - lower_bound.get_unsigned_value(),
+             0),
     decl_base(env, name, loc, ""),
     priv_(new priv(lower_bound, upper_bound, underlying_type, l))
 {}
@@ -12680,12 +12765,14 @@ array_type_def::subrange_type::subrange_type(const environment* env,
 /// @param l the language that generated this subrange.
 array_type_def::subrange_type::subrange_type(const environment* env,
                                             const string&      name,
-                                            size_t             lower_bound,
-                                            size_t             upper_bound,
+                                            bound_value        lower_bound,
+                                            bound_value        upper_bound,
                                             const location&    loc,
                                             translation_unit::language l)
   : type_or_decl_base(env),
-    type_base(env, upper_bound - lower_bound, 0),
+    type_base(env,
+             upper_bound.get_unsigned_value()
+             - lower_bound.get_unsigned_value(), 0),
     decl_base(env, name, loc, ""),
     priv_(new priv(lower_bound, upper_bound, l))
 {}
@@ -12704,11 +12791,11 @@ array_type_def::subrange_type::subrange_type(const environment* env,
 /// @param the language that generated this type.
 array_type_def::subrange_type::subrange_type(const environment* env,
                                             const string&      name,
-                                            size_t             upper_bound,
+                                            bound_value        upper_bound,
                                             const location&    loc,
                                             translation_unit::language l)
   : type_or_decl_base(env),
-    type_base(env, upper_bound, 0),
+    type_base(env, upper_bound.get_unsigned_value(), 0),
     decl_base(env, name, loc, ""),
     priv_(new priv(upper_bound, l))
 {}
@@ -12739,29 +12826,29 @@ array_type_def::subrange_type::set_underlying_type(const type_base_sptr &u)
 /// Getter of the upper bound of the subrange type.
 ///
 /// @return the upper bound of the subrange type.
-size_t
+int64_t
 array_type_def::subrange_type::get_upper_bound() const
-{return priv_->upper_bound_;}
+{return priv_->upper_bound_.get_signed_value();}
 
 /// Getter of the lower bound of the subrange type.
 ///
 /// @return the lower bound of the subrange type.
-size_t
+int64_t
 array_type_def::subrange_type::get_lower_bound() const
-{return priv_->lower_bound_;}
+{return priv_->lower_bound_.get_signed_value();}
 
 /// Setter of the upper bound of the subrange type.
 ///
 /// @param ub the new value of the upper bound.
 void
-array_type_def::subrange_type::set_upper_bound(size_t ub)
+array_type_def::subrange_type::set_upper_bound(int64_t ub)
 {priv_->upper_bound_ = ub;}
 
 /// Setter of the lower bound.
 ///
 /// @param lb the new value of the lower bound.
 void
-array_type_def::subrange_type::set_lower_bound(size_t lb)
+array_type_def::subrange_type::set_lower_bound(int64_t lb)
 {priv_->lower_bound_ = lb;}
 
 /// Getter of the length of the subrange type.
@@ -12770,7 +12857,7 @@ array_type_def::subrange_type::set_lower_bound(size_t lb)
 /// rather a non-known) size.
 ///
 /// @return the length of the subrange type.
-size_t
+uint64_t
 array_type_def::subrange_type::get_length() const
 {
   if (is_infinite())
@@ -21047,6 +21134,22 @@ types_have_similar_structure(const type_base* first, const type_base* second)
       return true;
     }
 
+  if (const array_type_def::subrange_type *ty1 = is_subrange_type(first))
+    {
+      const array_type_def::subrange_type *ty2 = is_subrange_type(second);
+      if (!ty2)
+       return false;
+
+      if (ty1->get_upper_bound() != ty2->get_upper_bound()
+         || ty1->get_lower_bound() != ty2->get_lower_bound()
+         || ty1->get_language() != ty2->get_language()
+         || !types_have_similar_structure(ty1->get_underlying_type(),
+                                         ty2->get_underlying_type()))
+       return false;
+
+      return true;
+    }
+
   if (const function_type* ty1 = is_function_type(first))
     {
       const function_type* ty2 = is_function_type(second);
index cd23d63..2204e15 100644 (file)
@@ -3735,14 +3735,15 @@ build_subrange_type(read_context&       ctxt,
 
   // Note that DWARF would actually have a lower_bound of -1 for an
   // array of length 0.
-  size_t max_bound = 0;
+  array_type_def::subrange_type::bound_value max_bound;
+  array_type_def::subrange_type::bound_value min_bound;
   if (!is_infinite)
     if (length > 0)
-      max_bound = length - 1;
+      max_bound.set_signed(length - 1);
 
   array_type_def::subrange_sptr p
     (new array_type_def::subrange_type(ctxt.get_environment(),
-                                      name, 0, max_bound,
+                                      name, min_bound, max_bound,
                                       underlying_type, loc));
   p->is_infinite(is_infinite);
 
index 56a42d4..ac42d78 100644 (file)
@@ -1443,6 +1443,15 @@ test-diff-pkg/nss-debuginfo-3.24.0-1.0.fc23.x86_64.rpm \
 test-diff-pkg/nss-devel-3.23.0-1.0.fc23.x86_64.rpm \
 test-diff-pkg/nss-devel-3.24.0-1.0.fc23.x86_64.rpm \
 test-diff-pkg/nss-3.23.0-1.0.fc23.x86_64-report-0.txt \
+test-diff-pkg/GtkAda-debuginfo-2.24.2-29.fc29.x86_64.rpm \
+test-diff-pkg/GtkAda-debuginfo-2.24.2-30.fc30.x86_64.rpm \
+test-diff-pkg/GtkAda-devel-2.24.2-29.fc29.x86_64.rpm \
+test-diff-pkg/GtkAda-devel-2.24.2-30.fc30.x86_64.rpm \
+test-diff-pkg/GtkAda-gl-2.24.2-29.fc29.x86_64--2.24.2-30.fc30.x86_64-report-0.txt \
+test-diff-pkg/GtkAda-gl-2.24.2-29.fc29.x86_64.rpm \
+test-diff-pkg/GtkAda-gl-2.24.2-30.fc30.x86_64.rpm \
+test-diff-pkg/GtkAda-gl-debuginfo-2.24.2-29.fc29.x86_64.rpm \
+test-diff-pkg/GtkAda-gl-debuginfo-2.24.2-30.fc30.x86_64.rpm \
 \
 test-fedabipkgdiff/dbus-glib-0.104-3.fc23.x86_64.rpm \
 test-fedabipkgdiff/dbus-glib-debuginfo-0.104-3.fc23.x86_64.rpm \
diff --git a/tests/data/test-diff-pkg/GtkAda-debuginfo-2.24.2-29.fc29.x86_64.rpm b/tests/data/test-diff-pkg/GtkAda-debuginfo-2.24.2-29.fc29.x86_64.rpm
new file mode 100644 (file)
index 0000000..1b46447
Binary files /dev/null and b/tests/data/test-diff-pkg/GtkAda-debuginfo-2.24.2-29.fc29.x86_64.rpm differ
diff --git a/tests/data/test-diff-pkg/GtkAda-debuginfo-2.24.2-30.fc30.x86_64.rpm b/tests/data/test-diff-pkg/GtkAda-debuginfo-2.24.2-30.fc30.x86_64.rpm
new file mode 100644 (file)
index 0000000..768862f
Binary files /dev/null and b/tests/data/test-diff-pkg/GtkAda-debuginfo-2.24.2-30.fc30.x86_64.rpm differ
diff --git a/tests/data/test-diff-pkg/GtkAda-devel-2.24.2-29.fc29.x86_64.rpm b/tests/data/test-diff-pkg/GtkAda-devel-2.24.2-29.fc29.x86_64.rpm
new file mode 100644 (file)
index 0000000..a5280eb
Binary files /dev/null and b/tests/data/test-diff-pkg/GtkAda-devel-2.24.2-29.fc29.x86_64.rpm differ
diff --git a/tests/data/test-diff-pkg/GtkAda-devel-2.24.2-30.fc30.x86_64.rpm b/tests/data/test-diff-pkg/GtkAda-devel-2.24.2-30.fc30.x86_64.rpm
new file mode 100644 (file)
index 0000000..e34f05a
Binary files /dev/null and b/tests/data/test-diff-pkg/GtkAda-devel-2.24.2-30.fc30.x86_64.rpm differ
diff --git a/tests/data/test-diff-pkg/GtkAda-gl-2.24.2-29.fc29.x86_64--2.24.2-30.fc30.x86_64-report-0.txt b/tests/data/test-diff-pkg/GtkAda-gl-2.24.2-29.fc29.x86_64--2.24.2-30.fc30.x86_64-report-0.txt
new file mode 100644 (file)
index 0000000..645324b
--- /dev/null
@@ -0,0 +1,67 @@
+================ changes of 'libgtkada_gl-2.24.so.2'===============
+  Functions changes summary: 0 Removed, 2 Changed (3 filtered out), 0 Added functions
+  Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+  Function symbols changes summary: 0 Removed, 0 Added function symbol not referenced by debug info
+  Variable symbols changes summary: 6 Removed, 6 Added variable symbols not referenced by debug info
+
+  2 functions with some indirect sub-type change:
+
+    [C]'function void gl_h__glgentextures(const gdk__gl__gl_configs, const gl_h__gluint_vec___XUP)' at gl_h.adb:35:1 has some indirect sub-type changes:
+      parameter 2 of type 'const gl_h__gluint_vec___XUP' has sub-type changes:
+        in unqualified underlying type 'struct gl_h__gluint_vec___XUP' at gl_h.ads:57:1:
+          type size hasn't changed
+          1 data member change:
+           type of 'gl_h__gluint_vec___XUP::gl_h__gluint_vec___XUB* gl_h__gluint_vec___XUP::P_BOUNDS' changed:
+             in pointed to type 'struct gl_h__gluint_vec___XUP::gl_h__gluint_vec___XUB' at gl_h.ads:57:1:
+               type size hasn't changed
+               2 data member changes:
+                type of 'integer gl_h__gluint_vec___XUP::gl_h__gluint_vec___XUB::LB0' changed:
+                  entity changed from 'integer' to '<range natural___XDLU_0__2147483647>[2147483648]'
+                  type size changed from 32 to 2147483647 (in bits)
+
+                type of 'integer gl_h__gluint_vec___XUP::gl_h__gluint_vec___XUB::UB0' changed:
+                  entity changed from 'integer' to '<range natural___XDLU_0__2147483647>[2147483648]'
+                  type size changed from 32 to 2147483647 (in bits)
+
+
+
+    [C]'function gtk__glarea__gtk_glarea gtk__glarea__gtk_new(gtk__glarea__gtk_glarea, const gtk__glarea__attributes_array___XUP)' at gtk-glarea.adb:63:1 has some indirect sub-type changes:
+      parameter 2 of type 'const gtk__glarea__attributes_array___XUP' has sub-type changes:
+        in unqualified underlying type 'struct gtk__glarea__attributes_array___XUP' at gtk-glarea.ads:48:1:
+          type size hasn't changed
+          1 data member change:
+           type of 'gtk__glarea__attributes_array___XUP::gtk__glarea__attributes_array___XUB* gtk__glarea__attributes_array___XUP::P_BOUNDS' changed:
+             in pointed to type 'struct gtk__glarea__attributes_array___XUP::gtk__glarea__attributes_array___XUB':
+               type size hasn't changed
+               2 data member changes:
+                type of 'integer gtk__glarea__attributes_array___XUP::gtk__glarea__attributes_array___XUB::LB0' changed:
+                  entity changed from 'integer' to '<range natural___XDLU_0__2147483647>[2147483648]'
+                  type size changed from 32 to 2147483647 (in bits)
+
+                type of 'integer gtk__glarea__attributes_array___XUP::gtk__glarea__attributes_array___XUB::UB0' changed:
+                  entity changed from 'integer' to '<range natural___XDLU_0__2147483647>[2147483648]'
+                  type size changed from 32 to 2147483647 (in bits)
+
+
+
+
+  6 Removed variable symbols not referenced by debug info:
+
+    gtk__glarea__C210s
+    gtk__glarea__gtk_glarea_recordB43s
+    gtk__glarea__gtk_glarea_recordE39s
+    gtk__glarea__gtk_glarea_recordH40s
+    gtk__glarea__gtk_glarea_recordR41s
+    gtk__glarea__gtk_glarea_recordR41s___UNC
+
+  6 Added variable symbols not referenced by debug info:
+
+    gtk__glarea__C208s
+    gtk__glarea__gtk_glarea_recordB41s
+    gtk__glarea__gtk_glarea_recordE37s
+    gtk__glarea__gtk_glarea_recordH38s
+    gtk__glarea__gtk_glarea_recordR39s
+    gtk__glarea__gtk_glarea_recordR39s___UNC
+
+================ end of changes of 'libgtkada_gl-2.24.so.2'===============
+
diff --git a/tests/data/test-diff-pkg/GtkAda-gl-2.24.2-29.fc29.x86_64.rpm b/tests/data/test-diff-pkg/GtkAda-gl-2.24.2-29.fc29.x86_64.rpm
new file mode 100644 (file)
index 0000000..eebe781
Binary files /dev/null and b/tests/data/test-diff-pkg/GtkAda-gl-2.24.2-29.fc29.x86_64.rpm differ
diff --git a/tests/data/test-diff-pkg/GtkAda-gl-2.24.2-30.fc30.x86_64.rpm b/tests/data/test-diff-pkg/GtkAda-gl-2.24.2-30.fc30.x86_64.rpm
new file mode 100644 (file)
index 0000000..fa6dc91
Binary files /dev/null and b/tests/data/test-diff-pkg/GtkAda-gl-2.24.2-30.fc30.x86_64.rpm differ
diff --git a/tests/data/test-diff-pkg/GtkAda-gl-debuginfo-2.24.2-29.fc29.x86_64.rpm b/tests/data/test-diff-pkg/GtkAda-gl-debuginfo-2.24.2-29.fc29.x86_64.rpm
new file mode 100644 (file)
index 0000000..0a0673f
Binary files /dev/null and b/tests/data/test-diff-pkg/GtkAda-gl-debuginfo-2.24.2-29.fc29.x86_64.rpm differ
diff --git a/tests/data/test-diff-pkg/GtkAda-gl-debuginfo-2.24.2-30.fc30.x86_64.rpm b/tests/data/test-diff-pkg/GtkAda-gl-debuginfo-2.24.2-30.fc30.x86_64.rpm
new file mode 100644 (file)
index 0000000..91dc145
Binary files /dev/null and b/tests/data/test-diff-pkg/GtkAda-gl-debuginfo-2.24.2-30.fc30.x86_64.rpm differ
index 626af96..8b4b2a7 100644 (file)
@@ -563,6 +563,20 @@ static InOutSpec in_out_specs[] =
     "data/test-diff-pkg/nss-3.23.0-1.0.fc23.x86_64-report-0.txt",
     "output/test-diff-pkg/nss-3.23.0-1.0.fc23.x86_64-report-0.txt"
   },
+  {
+    "data/test-diff-pkg/GtkAda-gl-2.24.2-29.fc29.x86_64.rpm",
+    "data/test-diff-pkg/GtkAda-gl-2.24.2-30.fc30.x86_64.rpm",
+    "--fail-no-dbg",
+    "",
+    "data/test-diff-pkg/GtkAda-debuginfo-2.24.2-29.fc29.x86_64.rpm, "
+    "data/test-diff-pkg/GtkAda-gl-debuginfo-2.24.2-29.fc29.x86_64.rpm",
+    "data/test-diff-pkg/GtkAda-debuginfo-2.24.2-30.fc30.x86_64.rpm, "
+    "data/test-diff-pkg/GtkAda-gl-debuginfo-2.24.2-30.fc30.x86_64.rpm",
+    "data/test-diff-pkg/GtkAda-devel-2.24.2-29.fc29.x86_64.rpm",
+    "data/test-diff-pkg/GtkAda-devel-2.24.2-30.fc30.x86_64.rpm",
+    "data/test-diff-pkg/GtkAda-gl-2.24.2-29.fc29.x86_64--2.24.2-30.fc30.x86_64-report-0.txt",
+    "output/test-diff-pkg/GtkAda-gl-2.24.2-29.fc29.x86_64--2.24.2-30.fc30.x86_64-report-0.txt"
+  },
 #endif //WITH_RPM
 
 #ifdef WITH_DEB