]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Fix sign of Ada rational constants
authorTom Tromey <tromey@adacore.com>
Fri, 2 May 2025 17:03:07 +0000 (11:03 -0600)
committerTom Tromey <tromey@adacore.com>
Mon, 5 May 2025 13:37:18 +0000 (07:37 -0600)
My earlier patch commit 0c03db90 ("Use correct sign in get_mpz") was
(very) incorrect.  It changed get_mpz to check for a strict sign when
examining part of an Ada rational constant.  However, in Ada the
"delta" for a fixed-point type must be positive, and so the components
of the rational representation will be positive.

This patch corrects the error.  It also renames the get_mpz function,
in case anyone is tempted to reuse this code for another purpose.

Finally, this pulls over the test from the internal AdaCore test suite
that found this issue.

gdb/dwarf2/read.c
gdb/testsuite/gdb.ada/fixed_points.exp
gdb/testsuite/gdb.ada/fixed_points/fixed_points.adb

index 6848f63aa2e4552b293a5cf7756a95af4e335c91..f90b22781e0dd6daf7852a3966b6357f96cc000a 100644 (file)
@@ -13165,7 +13165,7 @@ read_typedef (struct die_info *die, struct dwarf2_cu *cu)
    a given gmp_mpz given an attribute.  */
 
 static void
-get_mpz (struct dwarf2_cu *cu, gdb_mpz *value, struct attribute *attr)
+get_mpz_for_rational (dwarf2_cu *cu, gdb_mpz *value, attribute *attr)
 {
   /* GCC will sometimes emit a 16-byte constant value as a DWARF
      location expression that pushes an implicit value.  */
@@ -13199,10 +13199,11 @@ get_mpz (struct dwarf2_cu *cu, gdb_mpz *value, struct attribute *attr)
                   ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE,
                   true);
     }
-  else if (attr->form_is_strictly_unsigned ())
-    *value = gdb_mpz (attr->as_unsigned ());
   else
-    *value = gdb_mpz (attr->signed_constant ().value_or (1));
+    {
+      /* Rational constants for Ada are always unsigned.  */
+      *value = gdb_mpz (attr->unsigned_constant ().value_or (1));
+    }
 }
 
 /* Assuming DIE is a rational DW_TAG_constant, read the DIE's
@@ -13231,8 +13232,8 @@ get_dwarf2_rational_constant (struct die_info *die, struct dwarf2_cu *cu,
   if (num_attr == nullptr || denom_attr == nullptr)
     return;
 
-  get_mpz (cu, numerator, num_attr);
-  get_mpz (cu, denominator, denom_attr);
+  get_mpz_for_rational (cu, numerator, num_attr);
+  get_mpz_for_rational (cu, denominator, denom_attr);
 }
 
 /* Same as get_dwarf2_rational_constant, but extracting an unsigned
index 8bb9e10982fae2424f33353dad681389986c5f08..0e65004767415ceafc47e2a0dff2840458a78970 100644 (file)
@@ -90,6 +90,10 @@ foreach_gnat_encoding scenario flags {all minimal} {
     # This only started working in GCC 11.
     if {$scenario == "minimal" && [gnat_version_compare >= 11]} {
        gdb_test "print fp5_var" " = 3e-19"
+
+       gdb_test "print Float(Object_Fixed) = Float(Semicircle_Delta * 5)" \
+           " = true" \
+           "examine object_fixed"
     }
 
     # This failed before GCC 10.
index adab6149b1c0687da7903678200d07e4ace99a85..94a41b9fabd940b557837229ede0f1ff8b6affb6 100644 (file)
@@ -64,6 +64,12 @@ procedure Fixed_Points is
    for  Another_Type'size  use 64;
    Another_Fixed : Another_Type := Another_Delta * 5;
 
+   Semicircle_Delta : constant := 1.0/(2**31);
+   type Semicircle_Type is delta Semicircle_Delta range -1.0 .. (1.0 - Semicircle_Delta);
+   for  Semicircle_Type'small use Semicircle_Delta;
+   for  Semicircle_Type'size  use 32;
+   Object_Fixed : Semicircle_Type := Semicircle_Delta * 5;
+
 begin
    Base_Object := 1.0/16.0;   -- Set breakpoint here
    Subtype_Object := 1.0/16.0;
@@ -75,4 +81,5 @@ begin
    Do_Nothing (FP4_Var'Address);
    Do_Nothing (FP5_Var'Address);
    Do_Nothing (Another_Fixed'Address);
+   Do_Nothing (Object_Fixed'Address);
 end Fixed_Points;