Rewrite GNAT-encoded fixed point types in DWARF reader
authorTom Tromey <tromey@adacore.com>
Tue, 2 Mar 2021 20:08:24 +0000 (13:08 -0700)
committerTom Tromey <tromey@adacore.com>
Tue, 2 Mar 2021 20:08:25 +0000 (13:08 -0700)
gdb currently supports two different styles of fixed-point.  The
original style, where fixed point types are "GNAT encoded", is handled
primarily in the Ada code.  The newer style, encoded using DWARF, is
handled by the core of gdb.

This patch changes gdb to read the GNAT encodings in the DWARF reader
as well.  This removes some code and unifies the two paths.  As a
result, GNAT-encoded fixed-point now works a bit better.

One possible drawback of this change is that, if someone uses stabs,
then fixed-point might now stop working.  I consider stabs to be fully
obsolete, though, so I don't intend to address this.

gdb/ChangeLog
2021-03-02  Tom Tromey  <tromey@adacore.com>

* ada-lang.c (cast_from_gnat_encoded_fixed_point_type)
(cast_to_gnat_encoded_fixed_point_type): Remove.
(ada_value_cast, ada_evaluate_subexp): Update.
(gnat_encoded_fixed_point_type_info)
(ada_is_gnat_encoded_fixed_point_type)
(gnat_encoded_fixed_point_delta)
(gnat_encoded_fixed_point_scaling_factor): Remove.
* ada-lang.h (ada_is_gnat_encoded_fixed_point_type)
(gnat_encoded_fixed_point_delta)
(gnat_encoded_fixed_point_scaling_factor): Don't declare.
* ada-typeprint.c (print_gnat_encoded_fixed_point_type): Remove.
(ada_print_type): Update.
* ada-valprint.c (ada_value_print_num): Update.
* dwarf2/read.c (ada_get_gnat_encoded_number)
(ada_get_gnat_encoded_ratio): New functions.
(finish_fixed_point_type): Use them.  Add parameters.
(GNAT_FIXED_POINT_SUFFIX): New define.
(gnat_encoded_fixed_point_type_info): New function.
(read_base_type): Handle gnat encodings.

gdb/testsuite/ChangeLog
2021-03-02  Tom Tromey  <tromey@adacore.com>

* gdb.ada/fixed_points.exp: Remove most special cases for minimal
encodings.

gdb/ChangeLog
gdb/ada-lang.c
gdb/ada-lang.h
gdb/ada-typeprint.c
gdb/ada-valprint.c
gdb/dwarf2/read.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.ada/fixed_points.exp

index 05e53caad669fb729c6b72fe6e0f32f319bce542..518e5c29218c7180310bdf0a536450e6087e71d7 100644 (file)
@@ -1,3 +1,25 @@
+2021-03-02  Tom Tromey  <tromey@adacore.com>
+
+       * ada-lang.c (cast_from_gnat_encoded_fixed_point_type)
+       (cast_to_gnat_encoded_fixed_point_type): Remove.
+       (ada_value_cast, ada_evaluate_subexp): Update.
+       (gnat_encoded_fixed_point_type_info)
+       (ada_is_gnat_encoded_fixed_point_type)
+       (gnat_encoded_fixed_point_delta)
+       (gnat_encoded_fixed_point_scaling_factor): Remove.
+       * ada-lang.h (ada_is_gnat_encoded_fixed_point_type)
+       (gnat_encoded_fixed_point_delta)
+       (gnat_encoded_fixed_point_scaling_factor): Don't declare.
+       * ada-typeprint.c (print_gnat_encoded_fixed_point_type): Remove.
+       (ada_print_type): Update.
+       * ada-valprint.c (ada_value_print_num): Update.
+       * dwarf2/read.c (ada_get_gnat_encoded_number)
+       (ada_get_gnat_encoded_ratio): New functions.
+       (finish_fixed_point_type): Use them.  Add parameters.
+       (GNAT_FIXED_POINT_SUFFIX): New define.
+       (gnat_encoded_fixed_point_type_info): New function.
+       (read_base_type): Handle gnat encodings.
+
 2021-03-02  Tom Tromey  <tromey@adacore.com>
 
        * ada-lang.c (ada_fold_name, ada_variant_discrim_name)
index 44afbd975c013bcd8711c8cc2c69f9fa9cae0742..7d94586c7f286e9e52597520d33f3acb145a62d6 100644 (file)
@@ -9129,33 +9129,6 @@ unwrap_value (struct value *val)
     }
 }
 
-static struct value *
-cast_from_gnat_encoded_fixed_point_type (struct type *type, struct value *arg)
-{
-  struct value *scale
-    = gnat_encoded_fixed_point_scaling_factor (value_type (arg));
-  arg = value_cast (value_type (scale), arg);
-
-  arg = value_binop (arg, scale, BINOP_MUL);
-  return value_cast (type, arg);
-}
-
-static struct value *
-cast_to_gnat_encoded_fixed_point_type (struct type *type, struct value *arg)
-{
-  if (type == value_type (arg))
-    return arg;
-
-  struct value *scale = gnat_encoded_fixed_point_scaling_factor (type);
-  if (ada_is_gnat_encoded_fixed_point_type (value_type (arg)))
-    arg = cast_from_gnat_encoded_fixed_point_type (value_type (scale), arg);
-  else
-    arg = value_cast (value_type (scale), arg);
-
-  arg = value_binop (arg, scale, BINOP_DIV);
-  return value_cast (type, arg);
-}
-
 /* Given two array types T1 and T2, return nonzero iff both arrays
    contain the same number of elements.  */
 
@@ -9655,12 +9628,6 @@ ada_value_cast (struct type *type, struct value *arg2)
   if (type == ada_check_typedef (value_type (arg2)))
     return arg2;
 
-  if (ada_is_gnat_encoded_fixed_point_type (type))
-    return cast_to_gnat_encoded_fixed_point_type (type, arg2);
-
-  if (ada_is_gnat_encoded_fixed_point_type (value_type (arg2)))
-    return cast_from_gnat_encoded_fixed_point_type (type, arg2);
-
   return value_cast (type, arg2);
 }
 
@@ -10058,11 +10025,6 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
        {
          /* Nothing.  */
        }
-      else if (ada_is_gnat_encoded_fixed_point_type (value_type (arg1)))
-       arg2 = cast_to_gnat_encoded_fixed_point_type (value_type (arg1), arg2);
-      else if (ada_is_gnat_encoded_fixed_point_type (value_type (arg2)))
-       error
-         (_("Fixed-point values must be assigned to fixed-point variables"));
       else
        arg2 = coerce_for_assign (value_type (arg1), arg2);
       return ada_value_assign (arg1, arg2);
@@ -10086,14 +10048,7 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
       type = value_type (arg1);
       while (type->code () == TYPE_CODE_REF)
        type = TYPE_TARGET_TYPE (type);
-      if (ada_is_gnat_encoded_fixed_point_type (value_type (arg1))
-         || ada_is_gnat_encoded_fixed_point_type (value_type (arg2)))
-       {
-         if (value_type (arg1) != value_type (arg2))
-           error (_("Operands of fixed-point addition must have the same type"));
-       }
-      else
-       binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
+      binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
       arg1 = value_binop (arg1, arg2, BINOP_ADD);
       /* We need to special-case the result of adding to a range.
         This is done for the benefit of "ptype".  gdb's Ada support
@@ -10122,15 +10077,7 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
       type = value_type (arg1);
       while (type->code () == TYPE_CODE_REF)
        type = TYPE_TARGET_TYPE (type);
-      if (ada_is_gnat_encoded_fixed_point_type (value_type (arg1))
-         || ada_is_gnat_encoded_fixed_point_type (value_type (arg2)))
-       {
-         if (value_type (arg1) != value_type (arg2))
-           error (_("Operands of fixed-point subtraction "
-                    "must have the same type"));
-       }
-      else
-       binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
+      binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
       arg1 = value_binop (arg1, arg2, BINOP_SUB);
       /* We need to special-case the result of adding to a range.
         This is done for the benefit of "ptype".  gdb's Ada support
@@ -10156,10 +10103,6 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
       else
        {
          type = builtin_type (exp->gdbarch)->builtin_double;
-         if (ada_is_gnat_encoded_fixed_point_type (value_type (arg1)))
-           arg1 = cast_from_gnat_encoded_fixed_point_type (type, arg1);
-         if (ada_is_gnat_encoded_fixed_point_type (value_type (arg2)))
-           arg2 = cast_from_gnat_encoded_fixed_point_type (type, arg2);
          binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
          return ada_value_binop (arg1, arg2, op);
        }
@@ -10186,8 +10129,6 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
       arg1 = evaluate_subexp (nullptr, exp, pos, noside);
       if (noside == EVAL_SKIP)
        goto nosideret;
-      else if (ada_is_gnat_encoded_fixed_point_type (value_type (arg1)))
-       return value_cast (value_type (arg1), value_neg (arg1));
       else
        {
          unop_promote (exp->language_defn, exp->gdbarch, &arg1);
@@ -11053,41 +10994,6 @@ nosideret:
 }
 \f
 
-                               /* Fixed point */
-
-/* If TYPE encodes an Ada fixed-point type, return the suffix of the
-   type name that encodes the 'small and 'delta information.
-   Otherwise, return NULL.  */
-
-static const char *
-gnat_encoded_fixed_point_type_info (struct type *type)
-{
-  const char *name = ada_type_name (type);
-  enum type_code code = (type == NULL) ? TYPE_CODE_UNDEF : type->code ();
-
-  if ((code == TYPE_CODE_INT || code == TYPE_CODE_RANGE) && name != NULL)
-    {
-      const char *tail = strstr (name, "___XF_");
-
-      if (tail == NULL)
-       return NULL;
-      else
-       return tail + 5;
-    }
-  else if (code == TYPE_CODE_RANGE && TYPE_TARGET_TYPE (type) != type)
-    return gnat_encoded_fixed_point_type_info (TYPE_TARGET_TYPE (type));
-  else
-    return NULL;
-}
-
-/* Returns non-zero iff TYPE represents an Ada fixed-point type.  */
-
-int
-ada_is_gnat_encoded_fixed_point_type (struct type *type)
-{
-  return gnat_encoded_fixed_point_type_info (type) != NULL;
-}
-
 /* Return non-zero iff TYPE represents a System.Address type.  */
 
 int
@@ -11096,60 +11002,6 @@ ada_is_system_address_type (struct type *type)
   return (type->name () && strcmp (type->name (), "system__address") == 0);
 }
 
-/* Assuming that TYPE is the representation of an Ada fixed-point
-   type, return the target floating-point type to be used to represent
-   of this type during internal computation.  */
-
-static struct type *
-ada_scaling_type (struct type *type)
-{
-  return builtin_type (type->arch ())->builtin_long_double;
-}
-
-/* Assuming that TYPE is the representation of an Ada fixed-point
-   type, return its delta, or NULL if the type is malformed and the
-   delta cannot be determined.  */
-
-struct value *
-gnat_encoded_fixed_point_delta (struct type *type)
-{
-  const char *encoding = gnat_encoded_fixed_point_type_info (type);
-  struct type *scale_type = ada_scaling_type (type);
-
-  long long num, den;
-
-  if (sscanf (encoding, "_%lld_%lld", &num, &den) < 2)
-    return nullptr;
-  else
-    return value_binop (value_from_longest (scale_type, num),
-                       value_from_longest (scale_type, den), BINOP_DIV);
-}
-
-/* Assuming that ada_is_gnat_encoded_fixed_point_type (TYPE), return
-   the scaling factor ('SMALL value) associated with the type.  */
-
-struct value *
-gnat_encoded_fixed_point_scaling_factor (struct type *type)
-{
-  const char *encoding = gnat_encoded_fixed_point_type_info (type);
-  struct type *scale_type = ada_scaling_type (type);
-
-  long long num0, den0, num1, den1;
-  int n;
-
-  n = sscanf (encoding, "_%lld_%lld_%lld_%lld",
-             &num0, &den0, &num1, &den1);
-
-  if (n < 2)
-    return value_from_longest (scale_type, 1);
-  else if (n == 4)
-    return value_binop (value_from_longest (scale_type, num1),
-                       value_from_longest (scale_type, den1), BINOP_DIV);
-  else
-    return value_binop (value_from_longest (scale_type, num0),
-                       value_from_longest (scale_type, den0), BINOP_DIV);
-}
-
 \f
 
                                /* Range types */
index 8be4bf4ba6991b09f488525539cb39c5e4b23514..c3807339559e114b31483114442b3a2e36b3d594 100644 (file)
@@ -280,14 +280,8 @@ extern struct type *ada_aligned_type (struct type *);
 extern const gdb_byte *ada_aligned_value_addr (struct type *,
                                               const gdb_byte *);
 
-extern int ada_is_gnat_encoded_fixed_point_type (struct type *);
-
 extern int ada_is_system_address_type (struct type *);
 
-extern struct value *gnat_encoded_fixed_point_delta (struct type *);
-
-extern struct value *gnat_encoded_fixed_point_scaling_factor (struct type *);
-
 extern int ada_which_variant_applies (struct type *, struct value *);
 
 extern struct type *ada_to_fixed_type (struct type *, const gdb_byte *,
index 2b4af67fc9380839deee2a74db5c1cea9a858d56..54bbe0f1a011ddc21b9332cedccd29a9b6bc0c54 100644 (file)
@@ -339,31 +339,6 @@ print_enum_type (struct type *type, struct ui_file *stream)
   fprintf_filtered (stream, ")");
 }
 
-/* Print representation of Ada fixed-point type TYPE on STREAM.  */
-
-static void
-print_gnat_encoded_fixed_point_type (struct type *type, struct ui_file *stream)
-{
-  struct value *delta = gnat_encoded_fixed_point_delta (type);
-  struct value *small = gnat_encoded_fixed_point_scaling_factor (type);
-
-  if (delta == nullptr)
-    fprintf_filtered (stream, "delta ??");
-  else
-    {
-      std::string str;
-      str = target_float_to_string (value_contents (delta),
-                                   value_type (delta), "%g");
-      fprintf_filtered (stream, "delta %s", str.c_str());
-      if (!value_equal (delta, small))
-       {
-         str = target_float_to_string (value_contents (small),
-                                       value_type (small), "%g");
-         fprintf_filtered (stream, " <'small = %s>", str.c_str());
-       }
-    }
-}
-
 /* Print simple (constrained) array type TYPE on STREAM.  LEVEL is the
    recursion (indentation) level, in case the element type itself has
    nested structure, and SHOW is the number of levels of internal
@@ -1026,27 +1001,22 @@ ada_print_type (struct type *type0, const char *varstring,
        fprintf_filtered (stream, "(false, true)");
        break;
       case TYPE_CODE_INT:
-       if (ada_is_gnat_encoded_fixed_point_type (type))
-         print_gnat_encoded_fixed_point_type (type, stream);
-       else
-         {
-           const char *name = ada_type_name (type);
-
-           if (!ada_is_range_type_name (name))
-             fprintf_styled (stream, metadata_style.style (),
-                             _("<%s-byte integer>"),
-                             pulongest (TYPE_LENGTH (type)));
-           else
-             {
-               fprintf_filtered (stream, "range ");
-               print_range_type (type, stream, 1 /* bounds_prefered_p */);
-             }
-         }
+       {
+         const char *name = ada_type_name (type);
+
+         if (!ada_is_range_type_name (name))
+           fprintf_styled (stream, metadata_style.style (),
+                           _("<%s-byte integer>"),
+                           pulongest (TYPE_LENGTH (type)));
+         else
+           {
+             fprintf_filtered (stream, "range ");
+             print_range_type (type, stream, 1 /* bounds_prefered_p */);
+           }
+       }
        break;
       case TYPE_CODE_RANGE:
-       if (ada_is_gnat_encoded_fixed_point_type (type))
-         print_gnat_encoded_fixed_point_type (type, stream);
-       else if (is_fixed_point_type (type))
+       if (is_fixed_point_type (type))
          {
            fprintf_filtered (stream, "<");
            print_type_fixed_point (type, stream);
index 8af9ef0012f9b13513cc1e4ced81e8f4ffa98ea1..0d5b6d73076b154131c59428857a73b34ed29b1d 100644 (file)
@@ -741,22 +741,10 @@ ada_value_print_num (struct value *val, struct ui_file *stream, int recurse,
   struct type *type = ada_check_typedef (value_type (val));
   const gdb_byte *valaddr = value_contents_for_printing (val);
 
-  if (ada_is_gnat_encoded_fixed_point_type (type))
-    {
-      struct value *scale = gnat_encoded_fixed_point_scaling_factor (type);
-      val = value_cast (value_type (scale), val);
-      val = value_binop (val, scale, BINOP_MUL);
-
-      const char *fmt = TYPE_LENGTH (type) < 4 ? "%.11g" : "%.17g";
-      std::string str
-       = target_float_to_string (value_contents (val), value_type (val), fmt);
-      fputs_filtered (str.c_str (), stream);
-      return;
-    }
-  else if (type->code () == TYPE_CODE_RANGE
-          && (TYPE_TARGET_TYPE (type)->code () == TYPE_CODE_ENUM
-              || TYPE_TARGET_TYPE (type)->code () == TYPE_CODE_BOOL
-              || TYPE_TARGET_TYPE (type)->code () == TYPE_CODE_CHAR))
+  if (type->code () == TYPE_CODE_RANGE
+      && (TYPE_TARGET_TYPE (type)->code () == TYPE_CODE_ENUM
+         || TYPE_TARGET_TYPE (type)->code () == TYPE_CODE_BOOL
+         || TYPE_TARGET_TYPE (type)->code () == TYPE_CODE_CHAR))
     {
       /* For enum-valued ranges, we want to recurse, because we'll end
         up printing the constant's name rather than its numeric
index 7ab5d719004176f45a7ffa9537650816d504bb79..d4f13229ced091432692811f3f533fba15d88ea4 100644 (file)
@@ -18408,24 +18408,77 @@ get_dwarf2_unsigned_rational_constant (struct die_info *die,
   *denominator = std::move (denom);
 }
 
+/* Assuming that ENCODING is a string whose contents starting at the
+   K'th character is "_nn" where "nn" is a decimal number, scan that
+   number and set RESULT to the value. K is updated to point to the
+   character immediately following the number.
+
+   If the string does not conform to the format described above, false
+   is returned, and K may or may not be changed.  */
+
+static bool
+ada_get_gnat_encoded_number (const char *encoding, int &k, gdb_mpz *result)
+{
+  /* The next character should be an underscore ('_') followed
+     by a digit.  */
+  if (encoding[k] != '_' || !isdigit (encoding[k + 1]))
+    return false;
+
+  /* Skip the underscore.  */
+  k++;
+  int start = k;
+
+  /* Determine the number of digits for our number.  */
+  while (isdigit (encoding[k]))
+    k++;
+  if (k == start)
+    return false;
+
+  std::string copy (&encoding[start], k - start);
+  if (mpz_set_str (result->val, copy.c_str (), 10) == -1)
+    return false;
+
+  return true;
+}
+
+/* Scan two numbers from ENCODING at OFFSET, assuming the string is of
+   the form _NN_DD, where NN and DD are decimal numbers.  Set NUM and
+   DENOM, update OFFSET, and return true on success.  Return false on
+   failure.  */
+
+static bool
+ada_get_gnat_encoded_ratio (const char *encoding, int &offset,
+                           gdb_mpz *num, gdb_mpz *denom)
+{
+  if (!ada_get_gnat_encoded_number (encoding, offset, num))
+    return false;
+  return ada_get_gnat_encoded_number (encoding, offset, denom);
+}
+
 /* Assuming DIE corresponds to a fixed point type, finish the creation
-   of the corresponding TYPE by setting its type-specific data.
-   CU is the DIE's CU.  */
+   of the corresponding TYPE by setting its type-specific data.  CU is
+   the DIE's CU.  SUFFIX is the "XF" type name suffix coming from GNAT
+   encodings.  It is nullptr if the GNAT encoding should be
+   ignored.  */
 
 static void
-finish_fixed_point_type (struct type *type, struct die_info *die,
-                        struct dwarf2_cu *cu)
+finish_fixed_point_type (struct type *type, const char *suffix,
+                        struct die_info *die, struct dwarf2_cu *cu)
 {
-  struct attribute *attr;
-
   gdb_assert (type->code () == TYPE_CODE_FIXED_POINT
              && TYPE_SPECIFIC_FIELD (type) == TYPE_SPECIFIC_FIXED_POINT);
 
-  attr = dwarf2_attr (die, DW_AT_binary_scale, cu);
-  if (!attr)
-    attr = dwarf2_attr (die, DW_AT_decimal_scale, cu);
-  if (!attr)
-    attr = dwarf2_attr (die, DW_AT_small, cu);
+  /* If GNAT encodings are preferred, don't examine the
+     attributes.  */
+  struct attribute *attr = nullptr;
+  if (suffix == nullptr)
+    {
+      attr = dwarf2_attr (die, DW_AT_binary_scale, cu);
+      if (attr == nullptr)
+       attr = dwarf2_attr (die, DW_AT_decimal_scale, cu);
+      if (attr == nullptr)
+       attr = dwarf2_attr (die, DW_AT_small, cu);
+    }
 
   /* Numerator and denominator of our fixed-point type's scaling factor.
      The default is a scaling factor of 1, which we use as a fallback
@@ -18438,11 +18491,29 @@ finish_fixed_point_type (struct type *type, struct die_info *die,
 
   if (attr == nullptr)
     {
-      /* Scaling factor not found.  Assume a scaling factor of 1,
-        and hope for the best.  At least the user will be able to see
-        the encoded value.  */
-      complaint (_("no scale found for fixed-point type (DIE at %s)"),
-                sect_offset_str (die->sect_off));
+      int offset = 0;
+      if (suffix != nullptr
+         && ada_get_gnat_encoded_ratio (suffix, offset, &scale_num,
+                                        &scale_denom)
+         /* The number might be encoded as _nn_dd_nn_dd, where the
+            second ratio is the 'small value.  In this situation, we
+            want the second value.  */
+         && (suffix[offset] != '_'
+             || ada_get_gnat_encoded_ratio (suffix, offset, &scale_num,
+                                            &scale_denom)))
+       {
+         /* Found it.  */
+       }
+      else
+       {
+         /* Scaling factor not found.  Assume a scaling factor of 1,
+            and hope for the best.  At least the user will be able to
+            see the encoded value.  */
+         scale_num = 1;
+         scale_denom = 1;
+         complaint (_("no scale found for fixed-point type (DIE at %s)"),
+                    sect_offset_str (die->sect_off));
+       }
     }
   else if (attr->name == DW_AT_binary_scale)
     {
@@ -18486,6 +18557,20 @@ finish_fixed_point_type (struct type *type, struct die_info *die,
   mpq_canonicalize (scaling_factor.val);
 }
 
+/* The gnat-encoding suffix for fixed point.  */
+
+#define GNAT_FIXED_POINT_SUFFIX "___XF_"
+
+/* If NAME encodes an Ada fixed-point type, return a pointer to the
+   "XF" suffix of the name.  The text after this is what encodes the
+   'small and 'delta information.  Otherwise, return nullptr.  */
+
+static const char *
+gnat_encoded_fixed_point_type_info (const char *name)
+{
+  return strstr (name, GNAT_FIXED_POINT_SUFFIX);
+}
+
 /* Allocate a floating-point type of size BITS and name NAME.  Pass NAME_HINT
    (which may be different from NAME) to the architecture back-end to allow
    it to guess the correct format if necessary.  */
@@ -18674,20 +18759,38 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
         of fixed point types for which GNAT is unable to provide
         the scaling factor via the standard DWARF mechanisms, and
         for which the info is provided via the GNAT encodings instead.
-        This is likely what this DIE is about.
-
-        Ideally, GNAT should be declaring this type the same way
-        it declares other fixed point types when using the legacy
-        GNAT encoding, which is to use a simple signed or unsigned
-        base type.  A report to the GNAT team has been created to
-        look into it.  In the meantime, pretend this type is a simple
-        signed or unsigned integral, rather than a fixed point type,
-        to avoid any confusion later on as to how to process this type.  */
+        This is likely what this DIE is about.  */
       encoding = (encoding == DW_ATE_signed_fixed
                  ? DW_ATE_signed
                  : DW_ATE_unsigned);
     }
 
+  /* With GNAT encodings, fixed-point information will be encoded in
+     the type name.  Note that this can also occur with the above
+     zero-over-zero case, which is why this is a separate "if" rather
+     than an "else if".  */
+  const char *gnat_encoding_suffix = nullptr;
+  if ((encoding == DW_ATE_signed || encoding == DW_ATE_unsigned)
+      && cu->language == language_ada
+      && name != nullptr)
+    {
+      gnat_encoding_suffix = gnat_encoded_fixed_point_type_info (name);
+      if (gnat_encoding_suffix != nullptr)
+       {
+         gdb_assert (startswith (gnat_encoding_suffix,
+                                 GNAT_FIXED_POINT_SUFFIX));
+         name = obstack_strndup (&cu->per_objfile->objfile->objfile_obstack,
+                                 name, gnat_encoding_suffix - name);
+         /* Use -1 here so that SUFFIX points at the "_" after the
+            "XF".  */
+         gnat_encoding_suffix += strlen (GNAT_FIXED_POINT_SUFFIX) - 1;
+
+         encoding = (encoding == DW_ATE_signed
+                     ? DW_ATE_signed_fixed
+                     : DW_ATE_unsigned_fixed);
+       }
+    }
+
   switch (encoding)
     {
       case DW_ATE_address:
@@ -18766,11 +18869,11 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
        break;
       case DW_ATE_signed_fixed:
        type = init_fixed_point_type (objfile, bits, 0, name);
-       finish_fixed_point_type (type, die, cu);
+       finish_fixed_point_type (type, gnat_encoding_suffix, die, cu);
        break;
       case DW_ATE_unsigned_fixed:
        type = init_fixed_point_type (objfile, bits, 1, name);
-       finish_fixed_point_type (type, die, cu);
+       finish_fixed_point_type (type, gnat_encoding_suffix, die, cu);
        break;
 
       default:
index b92e67c9557fe68871ae29b07fd3f35d54e23a59..4f7bdbfccf24634ea2b28fa2d95525f973aab00f 100644 (file)
@@ -1,3 +1,8 @@
+2021-03-02  Tom Tromey  <tromey@adacore.com>
+
+       * gdb.ada/fixed_points.exp: Remove most special cases for minimal
+       encodings.
+
 2021-02-27  Lancelot Six  <lsix@lancelotix.com>
 
        PR gdb/27393
index ac45ef92ce948fd9c8f38914fb7a93526c49a95c..7267c3181ed5569ff516f17a12bc33a8f53e2df5 100644 (file)
@@ -49,84 +49,41 @@ foreach_with_prefix scenario {all minimal} {
     gdb_test "print Overprecise_Object" \
        "= 0.13579135791"
 
-    gdb_test_multiple "ptype Overprecise_Object" "" {
-       -re "type = <2-byte fixed point \\(small = 135791357913579/1000000000000000\\)>\r\n$gdb_prompt $" {
-           pass $gdb_test_name
-       }
-       -re "type = delta 0.135791\r\n$gdb_prompt $" {
-           # The (legacy) output we obtain when the compiler described
-           # our fixed point types using the GNAT encodings rather than
-           # standard DWARF.  OK as well.
-           pass $gdb_test_name
-       }
-    }
+    gdb_test "ptype Overprecise_Object" \
+       "type = <2-byte fixed point \\(small = 135791357913579/1000000000000000\\)>"
 
     # FP*_Var...
 
     gdb_test "print fp1_var" \
        " = 0.25"
 
-    gdb_test_multiple "ptype fp1_var" "" {
-       -re "type = <1-byte fixed point \\(small = 1/16\\)>\r\n$gdb_prompt $" {
-           pass $gdb_test_name
-       }
-       -re "type = delta 0\\.1 <'small = 0\\.0625>\r\n$gdb_prompt $" {
-           # The (legacy) output we obtain when the compiler described
-           # our fixed point types using the GNAT encodings rather than
-           # standard DWARF.  OK as well.
-           pass $gdb_test_name
-       }
-    }
+    gdb_test "ptype fp1_var" "type = <1-byte fixed point \\(small = 1/16\\)>"
 
     gdb_test "print fp2_var" \
        " = -0.01"
 
-    gdb_test_multiple "ptype fp2_var" "" {
-       -re "type = <8-byte fixed point \\(small = 1/100\\)>\r\n$gdb_prompt $" {
-           pass $gdb_test_name
-       }
-       -re "type = delta 0\\.01\r\n$gdb_prompt $" {
-           # The (legacy) output we obtain when the compiler described
-           # our fixed point types using the GNAT encodings rather than
-           # standard DWARF.  OK as well.
-           pass $gdb_test_name
-       }
-    }
+    gdb_test "ptype fp2_var" "type = <8-byte fixed point \\(small = 1/100\\)>"
 
     gdb_test "print fp3_var" \
        " = 0.1"
 
-    gdb_test_multiple "ptype fp3_var" "" {
-       -re "type = <1-byte fixed point \\(small = 1/30\\)>\r\n$gdb_prompt $" {
-           pass $gdb_test_name
-       }
-       -re "type = delta 0\\.1 <'small = 0\\.0333333>\r\n$gdb_prompt $" {
-           # The (legacy) output we obtain when the compiler described
-           # our fixed point types using the GNAT encodings rather than
-           # standard DWARF.  OK as well.
-           pass $gdb_test_name
-       }
-    }
+    gdb_test "ptype fp3_var" "type = <1-byte fixed point \\(small = 1/30\\)>"
+
+    gdb_test "print fp2_var + 0" \
+       " = -0.01"
+    gdb_test "print 0 + fp2_var" \
+       " = -0.01"
+    gdb_test "print fp2_var - 0" \
+       " = -0.01"
+
+    set fp4 "= 2e-07"
+    gdb_test "print fp4_var" $fp4
+    gdb_test "print fp4_var * 1" $fp4
+    gdb_test "print 1 * fp4_var" $fp4
+    gdb_test "print fp4_var / 1" $fp4
 
-    # One of the benefits of minimal encoding is that operations work
-    # a bit better.
-    if {$scenario == "minimal"} {
-       gdb_test "print fp2_var + 0" \
-           " = -0.01"
-       gdb_test "print 0 + fp2_var" \
-           " = -0.01"
-       gdb_test "print fp2_var - 0" \
-           " = -0.01"
-
-       set fp4 "= 2e-07"
-       gdb_test "print fp4_var" $fp4
-       gdb_test "print fp4_var * 1" $fp4
-       gdb_test "print 1 * fp4_var" $fp4
-       gdb_test "print fp4_var / 1" $fp4
-
-       # This only started working in GCC 11.
-       if {[test_compiler_info {gcc-11-*}]} {
-           gdb_test "print fp5_var" " = 3e-19"
-       }
+    # This only started working in GCC 11.
+    if {$scenario == "minimal" && [test_compiler_info {gcc-11-*}]} {
+       gdb_test "print fp5_var" " = 3e-19"
     }
 }