]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Introduce and use attribute::unsigned_constant
authorTom Tromey <tromey@adacore.com>
Thu, 6 Feb 2025 16:32:48 +0000 (09:32 -0700)
committerTom Tromey <tromey@adacore.com>
Tue, 18 Mar 2025 18:40:58 +0000 (12:40 -0600)
This introduces a new 'unsigned_constant' method on attribute.  This
method can be used to get the value as an unsigned number.  Unsigned
scalar forms are handled, and signed scalar forms are handled as well
provided that the value is non-negative.

Several spots in the reader that expect small DWARF-defined constants
are updated to use this new method.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32680
Approved-By: Simon Marchi <simon.marchi@efficios.com>
gdb/dwarf2/attribute.c
gdb/dwarf2/attribute.h
gdb/dwarf2/cooked-indexer.c
gdb/dwarf2/read.c
gdb/dwarf2/read.h

index 3eb32b65f1406bfc67edf5134c73874d8adbb490..49c0bc07d75dd23f5b4f952f4ccb7c46cebc5265 100644 (file)
@@ -164,6 +164,27 @@ attribute::constant_value (int default_value) const
 
 /* See attribute.h.  */
 
+std::optional<ULONGEST>
+attribute::unsigned_constant () const
+{
+  if (form_is_strictly_signed ())
+    {
+      if (u.snd >= 0)
+       return u.snd;
+      complaint (_("Attribute value is not unsigned (%s)"),
+                dwarf_form_name (form));
+    }
+  else if (form_is_constant ())
+    return u.unsnd;
+
+  /* For DW_FORM_data16 see attribute::form_is_constant.  */
+  complaint (_("Attribute value is not a constant (%s)"),
+            dwarf_form_name (form));
+  return {};
+}
+
+/* See attribute.h.  */
+
 bool
 attribute::form_is_unsigned () const
 {
@@ -216,21 +237,24 @@ attribute::form_requires_reprocessing () const
 dwarf_defaulted_attribute
 attribute::defaulted () const
 {
-  LONGEST value = constant_value (-1);
+  std::optional<ULONGEST> value = unsigned_constant ();
 
-  switch (value)
+  if (value.has_value ())
     {
-    case DW_DEFAULTED_no:
-    case DW_DEFAULTED_in_class:
-    case DW_DEFAULTED_out_of_class:
-      return (dwarf_defaulted_attribute) value;
+      switch (*value)
+       {
+       case DW_DEFAULTED_no:
+       case DW_DEFAULTED_in_class:
+       case DW_DEFAULTED_out_of_class:
+         return (dwarf_defaulted_attribute) *value;
+
+       default:
+         complaint (_("unrecognized DW_AT_defaulted value (%s)"),
+                    plongest (*value));
+         break;
+       }
     }
 
-  /* If the form was not constant, we already complained in
-     constant_value, so there's no need to complain again.  */
-  if (form_is_constant ())
-    complaint (_("unrecognized DW_AT_defaulted value (%s)"),
-              plongest (value));
   return DW_DEFAULTED_no;
 }
 
@@ -239,21 +263,24 @@ attribute::defaulted () const
 dwarf_virtuality_attribute
 attribute::as_virtuality () const
 {
-  LONGEST value = constant_value (-1);
+  std::optional<ULONGEST> value = unsigned_constant ();
 
-  switch (value)
+  if (value.has_value ())
     {
-    case DW_VIRTUALITY_none:
-    case DW_VIRTUALITY_virtual:
-    case DW_VIRTUALITY_pure_virtual:
-      return (dwarf_virtuality_attribute) value;
+      switch (*value)
+       {
+       case DW_VIRTUALITY_none:
+       case DW_VIRTUALITY_virtual:
+       case DW_VIRTUALITY_pure_virtual:
+         return (dwarf_virtuality_attribute) *value;
+
+       default:
+         complaint (_("unrecognized DW_AT_virtuality value (%s)"),
+                    plongest (*value));
+         break;
+       }
     }
 
-  /* If the form was not constant, we already complained in
-     constant_value, so there's no need to complain again.  */
-  if (form_is_constant ())
-    complaint (_("unrecognized DW_AT_virtuality value (%s)"),
-              plongest (value));
   return DW_VIRTUALITY_none;
 }
 
index 6332b399c6d33b575cdb53582978201961235248..824e92bf9cf991817e4ba0f48aebc211c2106036 100644 (file)
@@ -124,6 +124,18 @@ struct attribute
 
   bool form_is_section_offset () const;
 
+  /* Return an unsigned constant value.  This only handles constant
+     forms (i.e., form_is_constant -- and not the extended list of
+     "unsigned" forms) and assumes an unsigned value is desired.  This
+     can intended for use with DWARF-defined enumerations like DW_CC_*
+     or DW_INL_*, but also in situations where a nonnegative constant
+     integer is specified by DWARF.
+
+     If a signed form and negative value is used, or if a non-constant
+     form is used, then complaint is issued and an empty value is
+     returned.  */
+  std::optional<ULONGEST> unsigned_constant () const;
+
   /* Return non-zero if ATTR's value falls in the 'constant' class, or
      zero otherwise.  When this function returns true, you can apply
      the constant_value method to it.
index 441a85272fb03e342d429bc6b473e268518e60a1..3b80cd6c50089c82963881845713b93655b25ec4 100644 (file)
@@ -202,8 +202,11 @@ cooked_indexer::scan_attributes (dwarf2_per_cu *scanning_per_cu,
           the DW_AT_calling_convention attribute was used instead as
           the only means available.  We handle both variants then.  */
        case DW_AT_calling_convention:
-         if (attr.constant_value (DW_CC_normal) == DW_CC_program)
-           *flags |= IS_MAIN;
+         {
+           std::optional<ULONGEST> value = attr.unsigned_constant ();
+           if (value.has_value () && *value == DW_CC_program)
+             *flags |= IS_MAIN;
+         }
          break;
 
        case DW_AT_declaration:
index f41723c69456e674ec6b9693a68a85665063401c..30205f2e8aa17c4486d5745bf676e5aaa6edcf9f 100644 (file)
@@ -8499,8 +8499,10 @@ dwarf2_func_is_main_p (struct die_info *die, struct dwarf2_cu *cu)
   if (dwarf2_flag_true_p (die, DW_AT_main_subprogram, cu))
     return true;
   struct attribute *attr = dwarf2_attr (die, DW_AT_calling_convention, cu);
-  return (attr != nullptr
-         && attr->constant_value (DW_CC_normal) == DW_CC_program);
+  if (attr == nullptr)
+    return false;
+  std::optional<ULONGEST> value = attr->unsigned_constant ();
+  return value.has_value () && *value == DW_CC_program;
 }
 
 /* A helper to handle Ada's "Pragma Import" feature when it is applied
@@ -8620,11 +8622,14 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
          attr = dwarf2_attr (die, DW_AT_external, cu);
          bool external_p = attr != nullptr && attr->as_boolean ();
          attr = dwarf2_attr (die, DW_AT_inline, cu);
-         bool inlined_p
-           = (attr != nullptr
-              && attr->is_nonnegative ()
-              && (attr->as_nonnegative () == DW_INL_inlined
-                  || attr->as_nonnegative () == DW_INL_declared_inlined));
+         bool inlined_p = false;
+         if (attr != nullptr)
+           {
+             std::optional<ULONGEST> value = attr->unsigned_constant ();
+             inlined_p = (value.has_value ()
+                          && (*value == DW_INL_inlined
+                              || *value == DW_INL_declared_inlined));
+           }
          attr = dwarf2_attr (die, DW_AT_declaration, cu);
          bool decl_p = attr != nullptr && attr->as_boolean ();
          if (!external_p && !inlined_p && !decl_p)
@@ -10093,13 +10098,16 @@ dwarf2_access_attribute (struct die_info *die, struct dwarf2_cu *cu)
   attribute *attr = dwarf2_attr (die, DW_AT_accessibility, cu);
   if (attr != nullptr)
     {
-      LONGEST value = attr->constant_value (-1);
-      if (value == DW_ACCESS_public
-         || value == DW_ACCESS_protected
-         || value == DW_ACCESS_private)
-       return (dwarf_access_attribute) value;
-      complaint (_("Unhandled DW_AT_accessibility value (%s)"),
-                plongest (value));
+      std::optional<ULONGEST> value = attr->unsigned_constant ();
+      if (value.has_value ())
+       {
+         if (*value == DW_ACCESS_public
+             || *value == DW_ACCESS_protected
+             || *value == DW_ACCESS_private)
+           return (dwarf_access_attribute) *value;
+         complaint (_("Unhandled DW_AT_accessibility value (%s)"),
+                    pulongest (*value));
+       }
     }
 
   if (cu->header.version < 3 || cu->producer_is_gxx_lt_4_6 ())
@@ -11302,12 +11310,16 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
      the die.  Otherwise the calling convention remains set to
      the default value DW_CC_normal.  */
   attr = dwarf2_attr (die, DW_AT_calling_convention, cu);
-  if (attr != nullptr
-      && is_valid_DW_AT_calling_convention_for_type (attr->constant_value (0)))
+  if (attr != nullptr)
     {
-      ALLOCATE_CPLUS_STRUCT_TYPE (type);
-      TYPE_CPLUS_CALLING_CONVENTION (type)
-       = (enum dwarf_calling_convention) (attr->constant_value (0));
+      std::optional<ULONGEST> value = attr->unsigned_constant ();
+      if (value.has_value ()
+         && is_valid_DW_AT_calling_convention_for_type (*value))
+       {
+         ALLOCATE_CPLUS_STRUCT_TYPE (type);
+         TYPE_CPLUS_CALLING_CONVENTION (type)
+           = (enum dwarf_calling_convention) *value;
+       }
     }
 
   attr = dwarf2_attr (die, DW_AT_byte_size, cu);
@@ -11773,19 +11785,23 @@ die_byte_order (die_info *die, dwarf2_cu *cu, enum bfd_endian *byte_order)
   attribute *attr = dwarf2_attr (die, DW_AT_endianity, cu);
   if (attr != nullptr && attr->form_is_constant ())
     {
-      int endianity = attr->constant_value (0);
+      std::optional<ULONGEST> endianity = attr->unsigned_constant ();
 
-      switch (endianity)
+      if (endianity.has_value ())
        {
-       case DW_END_big:
-         new_order = BFD_ENDIAN_BIG;
-         break;
-       case DW_END_little:
-         new_order = BFD_ENDIAN_LITTLE;
-         break;
-       default:
-         complaint (_("DW_AT_endianity has unrecognized value %d"), endianity);
-         break;
+         switch (*endianity)
+           {
+           case DW_END_big:
+             new_order = BFD_ENDIAN_BIG;
+             break;
+           case DW_END_little:
+             new_order = BFD_ENDIAN_LITTLE;
+             break;
+           default:
+             complaint (_("DW_AT_endianity has unrecognized value %s"),
+                        pulongest (*endianity));
+             break;
+           }
        }
     }
 
@@ -12439,9 +12455,10 @@ read_array_order (struct die_info *die, struct dwarf2_cu *cu)
 
   if (attr != nullptr)
     {
-      LONGEST val = attr->constant_value (-1);
-      if (val == DW_ORD_row_major || val == DW_ORD_col_major)
-       return (enum dwarf_array_dim_ordering) val;
+      std::optional<ULONGEST> val = attr->unsigned_constant ();
+      if (val.has_value () &&
+         (*val == DW_ORD_row_major || *val == DW_ORD_col_major))
+       return (enum dwarf_array_dim_ordering) *val;
     }
 
   /* GNU F77 is a special case, as at 08/2004 array type info is the
@@ -12847,7 +12864,7 @@ read_tag_pointer_type (struct die_info *die, struct dwarf2_cu *cu)
   struct type *type;
   struct attribute *attr_byte_size;
   struct attribute *attr_address_class;
-  int byte_size, addr_class;
+  int byte_size;
   struct type *target_type;
 
   target_type = die_type (die, cu);
@@ -12866,8 +12883,10 @@ read_tag_pointer_type (struct die_info *die, struct dwarf2_cu *cu)
     byte_size = cu_header->addr_size;
 
   attr_address_class = dwarf2_attr (die, DW_AT_address_class, cu);
+  ULONGEST addr_class;
   if (attr_address_class)
-    addr_class = attr_address_class->constant_value (DW_ADDR_none);
+    addr_class = (attr_address_class->unsigned_constant ()
+                 .value_or (DW_ADDR_none));
   else
     addr_class = DW_ADDR_none;
 
@@ -13269,10 +13288,14 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
      the subroutine die.  Otherwise set the calling convention to
      the default value DW_CC_normal.  */
   attr = dwarf2_attr (die, DW_AT_calling_convention, cu);
-  if (attr != nullptr
-      && is_valid_DW_AT_calling_convention_for_subroutine (attr->constant_value (0)))
-    TYPE_CALLING_CONVENTION (ftype)
-      = (enum dwarf_calling_convention) attr->constant_value (0);
+  if (attr != nullptr)
+    {
+      std::optional<ULONGEST> value = attr->unsigned_constant ();
+      if (value.has_value ()
+         && is_valid_DW_AT_calling_convention_for_subroutine (*value))
+       TYPE_CALLING_CONVENTION (ftype)
+         = (enum dwarf_calling_convention) *value;
+    }
   else if (cu->producer_is_xlc_opencl ())
     TYPE_CALLING_CONVENTION (ftype) = DW_CC_GDB_IBM_OpenCL;
   else
@@ -13863,12 +13886,17 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
   struct objfile *objfile = cu->per_objfile->objfile;
   struct type *type;
   struct attribute *attr;
-  int encoding = 0, bits = 0;
+  ULONGEST encoding = 0;
+  int bits = 0;
   const char *name;
 
   attr = dwarf2_attr (die, DW_AT_encoding, cu);
-  if (attr != nullptr && attr->form_is_constant ())
-    encoding = attr->constant_value (0);
+  if (attr != nullptr)
+    {
+      std::optional<ULONGEST> value = attr->unsigned_constant ();
+      if (value.has_value ())
+       encoding = *value;
+    }
   attr = dwarf2_attr (die, DW_AT_byte_size, cu);
   if (attr != nullptr)
     bits = attr->constant_value (0) * TARGET_CHAR_BIT;
@@ -15699,7 +15727,7 @@ leb128_size (const gdb_byte *buf)
 /* Converts DWARF language names to GDB language names.  */
 
 enum language
-dwarf_lang_to_enum_language (unsigned int lang)
+dwarf_lang_to_enum_language (ULONGEST lang)
 {
   enum language language;
 
@@ -19730,8 +19758,15 @@ cutu_reader::prepare_one_comp_unit (struct dwarf2_cu *cu,
     }
   else if (attr != nullptr)
     {
-      lang = dwarf_lang_to_enum_language (attr->constant_value (0));
-      dw_lang = (dwarf_source_language) attr->constant_value (0);
+      std::optional<ULONGEST> lang_val = attr->unsigned_constant ();
+      if (lang_val.has_value ())
+       {
+         lang = dwarf_lang_to_enum_language (*lang_val);
+         if (lang_val <= DW_LANG_hi_user)
+           dw_lang = (dwarf_source_language) *lang_val;
+       }
+      else
+       lang = language_minimal;
     }
   else
     lang = pretend_language;
index be6549beec7f583148362fa25b56157a94f5ffe8..164c3136cf87f1b2cfb781154bc0823948341f09 100644 (file)
@@ -1047,7 +1047,7 @@ private:
 
 /* Converts DWARF language names to GDB language names.  */
 
-enum language dwarf_lang_to_enum_language (unsigned int lang);
+enum language dwarf_lang_to_enum_language (ULONGEST lang);
 
 /* Get the dwarf2_per_objfile associated to OBJFILE.  */