[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