diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
index 7257052e..aa1bb2b5 100644
--- a/src/abg-dwarf-reader.cc
+++ b/src/abg-dwarf-reader.cc
@@ -392,25 +392,12 @@ die_signed_constant_attribute(const Dwarf_Die*die,
 static bool
 die_constant_attribute(const Dwarf_Die *die,
 		       unsigned attr_name,
+		       bool is_signed,
 		       array_type_def::subrange_type::bound_value &value);
 
-static bool
-die_attribute_has_form(const Dwarf_Die* die,
-		       unsigned	attr_name,
-		       unsigned int	form);
-
 static bool
 form_is_DW_FORM_strx(unsigned form);
 
-static bool
-die_attribute_is_signed(const Dwarf_Die* die, unsigned attr_name);
-
-static bool
-die_attribute_is_unsigned(const Dwarf_Die* die, unsigned attr_name);
-
-static bool
-die_attribute_has_no_signedness(const Dwarf_Die* die, unsigned attr_name);
-
 static bool
 die_address_attribute(Dwarf_Die* die, unsigned attr_name, Dwarf_Addr& result);
 
@@ -8111,7 +8098,7 @@ die_unsigned_constant_attribute(const Dwarf_Die*	die,
 
 /// Read a signed constant value from a given attribute.
 ///
-/// The signed constant expected must be of form DW_FORM_sdata.
+/// The signed constant expected must be of constant form.
 ///
 /// @param die the DIE to get the attribute from.
 ///
@@ -8149,6 +8136,9 @@ die_signed_constant_attribute(const Dwarf_Die *die,
 ///
 /// @param attr_name the attribute name to consider.
 ///
+/// @param is_signed true if the attribute value has to read as
+/// signed.
+///
 /// @param value the resulting value read from attribute @p attr_name
 /// on DIE @p die.
 ///
@@ -8157,10 +8147,10 @@ die_signed_constant_attribute(const Dwarf_Die *die,
 static bool
 die_constant_attribute(const Dwarf_Die *die,
 		       unsigned attr_name,
+		       bool is_signed,
 		       array_type_def::subrange_type::bound_value &value)
 {
-  if (die_attribute_is_unsigned(die, attr_name)
-      || die_attribute_has_no_signedness(die, attr_name))
+  if (!is_signed)
     {
       uint64_t l = 0;
       if (!die_unsigned_constant_attribute(die, attr_name, l))
@@ -8177,29 +8167,6 @@ die_constant_attribute(const Dwarf_Die *die,
   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(const Dwarf_Die	*die,
-		       unsigned	attr_name,
-		       unsigned int	attr_form)
-{
-  Dwarf_Attribute attr;
-  if (!dwarf_attr_integrate(const_cast<Dwarf_Die*>(die), attr_name, &attr))
-    return false;
-
-  return dwarf_hasform(&attr, attr_form);
-}
-
 /// Test if a given DWARF form is DW_FORM_strx{1,4}.
 ///
 /// Unfortunaly, the DW_FORM_strx{1,4} are enumerators of an untagged
@@ -8228,55 +8195,6 @@ form_is_DW_FORM_strx(unsigned form)
   return false;
 }
 
-/// 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(const 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(const 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(const 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.
 ///
@@ -8387,17 +8305,17 @@ die_die_attribute(const Dwarf_Die* die,
   return dwarf_formref_die(&attr, &result);
 }
 
-/// Read and return a DW_FORM_addr attribute from a given DIE.
+/// Read and return an addresss class attribute from a given DIE.
 ///
 /// @param die the DIE to consider.
 ///
-/// @param attr_name the name of the DW_FORM_addr attribute to read
+/// @param attr_name the name of the address class attribute to read
 /// the value from.
 ///
 /// @param the resulting address.
 ///
 /// @return true iff the attribute could be read, was of the expected
-/// DW_FORM_addr and could thus be translated into the @p result.
+/// address class and could thus be translated into the @p result.
 static bool
 die_address_attribute(Dwarf_Die* die, unsigned attr_name, Dwarf_Addr& result)
 {
@@ -14744,6 +14662,27 @@ build_subrange_type(read_context&	ctxt,
 
   string name = die_name(die);
 
+  // load the underlying type.
+  Dwarf_Die underlying_type_die;
+  type_base_sptr underlying_type;
+  /* Unless there is an underlying type which says differently.  */
+  bool is_signed = true;
+  if (die_die_attribute(die, DW_AT_type, underlying_type_die))
+    underlying_type =
+      is_type(build_ir_node_from_die(ctxt,
+				     &underlying_type_die,
+				     /*called_from_public_decl=*/true,
+				     where_offset));
+
+  if (underlying_type)
+    {
+      uint64_t ate;
+      if (die_unsigned_constant_attribute (&underlying_type_die,
+					   DW_AT_encoding,
+					   ate))
+	  is_signed = (ate == DW_ATE_signed || ate == DW_ATE_signed_char);
+    }
+
   translation_unit::language language = ctxt.cur_transl_unit()->get_language();
   array_type_def::subrange_type::bound_value lower_bound =
     get_default_array_lower_bound(language);
@@ -14760,10 +14699,10 @@ build_subrange_type(read_context&	ctxt,
   //     values of the subrange.
   //
   // So let's look for DW_AT_lower_bound first.
-  die_constant_attribute(die, DW_AT_lower_bound, lower_bound);
+  die_constant_attribute(die, DW_AT_lower_bound, is_signed, lower_bound);
 
   // Then, DW_AT_upper_bound.
-  if (!die_constant_attribute(die, DW_AT_upper_bound, upper_bound))
+  if (!die_constant_attribute(die, DW_AT_upper_bound, is_signed, upper_bound))
     {
       // The DWARF 4 spec says, in [5.11 Subrange Type
       // Entries]:
@@ -14807,16 +14746,6 @@ build_subrange_type(read_context&	ctxt,
 				       location()));
   result->is_infinite(is_infinite);
 
-  // load the underlying type.
-  Dwarf_Die underlying_type_die;
-  type_base_sptr underlying_type;
-  if (die_die_attribute(die, DW_AT_type, underlying_type_die))
-    underlying_type =
-      is_type(build_ir_node_from_die(ctxt,
-				     &underlying_type_die,
-				     /*called_from_public_decl=*/true,
-				     where_offset));
-
   if (underlying_type)
     result->set_underlying_type(underlying_type);