[binutils-gdb] Fix 'ptype' of a certain Ada modular type
Tom Tromey
tromey@sourceware.org
Thu Dec 4 18:51:21 GMT 2025
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=2e4861cb9ce250275d6be08e8a64d948a4f00008
commit 2e4861cb9ce250275d6be08e8a64d948a4f00008
Author: Tom Tromey <tromey@adacore.com>
Date: Thu Dec 4 07:36:59 2025 -0700
Fix 'ptype' of a certain Ada modular type
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>
Diff:
---
gdb/ada-exp.y | 7 +++++--
gdb/ada-lang.c | 16 +++++++--------
gdb/ada-lang.h | 5 ++++-
gdb/ada-typeprint.c | 14 +++++++++++--
gdb/testsuite/gdb.ada/modular.exp | 36 ++++++++++++++++++++++++++++++++++
gdb/testsuite/gdb.ada/modular/prog.adb | 32 ++++++++++++++++++++++++++++++
6 files changed, 97 insertions(+), 13 deletions(-)
diff --git a/gdb/ada-exp.y b/gdb/ada-exp.y
index ed5694e2f1f..c87b91e92e0 100644
--- a/gdb/ada-exp.y
+++ b/gdb/ada-exp.y
@@ -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 ());
}
;
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 21b081854a8..87ae5975788 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -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 {};
}
diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h
index c7430c713fd..6a5cc553275 100644
--- a/gdb/ada-lang.h
+++ b/gdb/ada-lang.h
@@ -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 *);
diff --git a/gdb/ada-typeprint.c b/gdb/ada-typeprint.c
index 2bafa5de68d..4a9152b3b7b 100644
--- a/gdb/ada-typeprint.c
+++ b/gdb/ada-typeprint.c
@@ -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
index 00000000000..9d2a000de81
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/modular.exp
@@ -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
index 00000000000..aa91148aab4
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/modular/prog.adb
@@ -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;
More information about the Gdb-cvs
mailing list