]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Fix 'ptype' of a certain Ada modular type
authorTom Tromey <tromey@adacore.com>
Thu, 4 Dec 2025 14:36:59 +0000 (07:36 -0700)
committerTom Tromey <tromey@adacore.com>
Thu, 4 Dec 2025 18:48:21 +0000 (11:48 -0700)
If an Ada modular type is the same size as gdb's own ULONGEST, ptype
will show "mod 0".  This happens because ada_modulus does:

    return (ULONGEST) high.const_val () + 1;

This patch cleans this up, replacing ada_modulus with a function to
return the upper bound (if available), and then fixing the various
callers.  The type-printing caller still does the "+1", but now this
is done with a gdb_mpz.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33690
Approved-By: Simon Marchi <simon.marchi@efficios.com>
gdb/ada-exp.y
gdb/ada-lang.c
gdb/ada-lang.h
gdb/ada-typeprint.c
gdb/testsuite/gdb.ada/modular.exp [new file with mode: 0644]
gdb/testsuite/gdb.ada/modular/prog.adb [new file with mode: 0644]

index ed5694e2f1f5cfba29d06cb5011a722e065cf51c..c87b91e92e09562a204ffbfd40b7aad33c5f4b13 100644 (file)
@@ -947,8 +947,11 @@ primary :  primary TICK_ACCESS
                          struct type *type_arg = check_typedef ($1);
                          if (!ada_is_modular_type (type_arg))
                            error (_("'modulus must be applied to modular type"));
-                         write_int (pstate, ada_modulus (type_arg),
-                                    type_arg->target_type ());
+                         std::optional<ULONGEST> bound
+                           = ada_modular_bound (type_arg);
+                         if (!bound.has_value ())
+                           error (_("'modulus applied to type with non-constant bound"));
+                         write_int (pstate, *bound, type_arg->target_type ());
                        }
        ;
 
index 21b081854a8f68015f34582209474ddffaf18a9e..87ae5975788415bcd709071153565501e9baaf65 100644 (file)
@@ -2607,7 +2607,7 @@ decode_constrained_packed_array (struct value *arr)
       int bit_size, bit_pos;
       ULONGEST mod;
 
-      mod = ada_modulus (arr->type ()) - 1;
+      mod = ada_modular_bound (arr->type ()).value_or (0);
       bit_size = 0;
       while (mod > 0)
        {
@@ -11638,19 +11638,19 @@ ada_is_modular_type (struct type *type)
          && subranged_type->is_unsigned ());
 }
 
-/* Assuming ada_is_modular_type (TYPE), the modulus of TYPE.  */
+/* See ada-lang.h.  */
 
-ULONGEST
-ada_modulus (struct type *type)
+std::optional<ULONGEST>
+ada_modular_bound (struct type *type)
 {
   const dynamic_prop &high = type->bounds ()->high;
 
   if (high.is_constant ())
-    return (ULONGEST) high.const_val () + 1;
+    return (ULONGEST) high.const_val ();
 
-  /* If TYPE is unresolved, the high bound might be a location list.  Return
-     0, for lack of a better value to return.  */
-  return 0;
+  /* If TYPE is unresolved, the high bound might be a location
+     list.  */
+  return {};
 }
 \f
 
index c7430c713fdb87b0c7f87165899894d09b6801ce..6a5cc553275447e18089b631767f55ae115da62c 100644 (file)
@@ -326,7 +326,10 @@ extern const char *ada_enum_name (const char *);
 
 extern bool ada_is_modular_type (struct type *);
 
-extern ULONGEST ada_modulus (struct type *);
+/* Return the upper bound of a modular type.  If the upper bound is
+   non-constant, returns an empty optional.  */
+
+extern std::optional<ULONGEST> ada_modular_bound (struct type *);
 
 extern struct value *ada_value_ind (struct value *);
 
index 2bafa5de68da9dab488393c0df72557a671f85b4..4a9152b3b7bbdab37502ed9b273c4809420c4306 100644 (file)
@@ -1040,8 +1040,18 @@ ada_print_type (struct type *type0, const char *varstring,
            gdb_printf (stream, ">");
          }
        else if (ada_is_modular_type (type))
-         gdb_printf (stream, "mod %s",
-                     int_string (ada_modulus (type), 10, 0, 0, 1));
+         {
+           std::optional<ULONGEST> bound = ada_modular_bound (type);
+           gdb_mpz modulus;
+           if (bound.has_value ())
+             {
+               modulus = *bound;
+               modulus += 1;
+             }
+           else
+             modulus = 0;
+           gdb_printf (stream, "mod %s", modulus.str ().c_str ());
+         }
        else
          {
            gdb_printf (stream, "range ");
diff --git a/gdb/testsuite/gdb.ada/modular.exp b/gdb/testsuite/gdb.ada/modular.exp
new file mode 100644 (file)
index 0000000..9d2a000
--- /dev/null
@@ -0,0 +1,36 @@
+# Copyright 2025 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test for a bug when printing a large modular type.
+
+load_lib "ada.exp"
+
+require allow_ada_tests
+
+standard_ada_testfile prog
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable {debug}] != ""} {
+    return
+}
+
+clean_restart ${testfile}
+
+set bp_location [gdb_get_line_number "STOP" ${testdir}/prog.adb]
+runto "prog.adb:$bp_location"
+
+# The bug was that a modular type with a size equal to gdb's ULONGEST
+# was displayed, gdb would say "mod 0".
+gdb_test "ptype mod1_type" "type = mod 4294967296"
+gdb_test "ptype mod2_type" "type = mod 18446744073709551616"
diff --git a/gdb/testsuite/gdb.ada/modular/prog.adb b/gdb/testsuite/gdb.ada/modular/prog.adb
new file mode 100644 (file)
index 0000000..aa91148
--- /dev/null
@@ -0,0 +1,32 @@
+--  Copyright 2025 Free Software Foundation, Inc.
+--
+--  This program is free software; you can redistribute it and/or modify
+--  it under the terms of the GNU General Public License as published by
+--  the Free Software Foundation; either version 3 of the License, or
+--  (at your option) any later version.
+--
+--  This program is distributed in the hope that it will be useful,
+--  but WITHOUT ANY WARRANTY; without even the implied warranty of
+--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+--  GNU General Public License for more details.
+--
+--  You should have received a copy of the GNU General Public License
+--  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+procedure Prog is
+   type Mod1_Type_Base is mod 2 ** 32;
+   type Mod2_Type_Base is mod 2 ** 64;
+
+   --  We use subtypes here because GCC emits the above modular types
+   --  as base types with the expected size, which gdb then displays
+   --  as <4-byte integer> (e.g.).  However we want to see the real
+   --  modular type display.
+   subtype Mod1_Type is Mod1_Type_Base;
+   subtype Mod2_Type is Mod2_Type_Base;
+
+   X : Mod1_Type := 23;
+   Y : Mod2_Type := 91;
+
+begin
+   null;  -- STOP
+end Prog;