[RFA] Add handling of null Ada arrays

Joel Brobecker
2008-01-09T06:34:32Z

[-- Attachment #1: Type: text/plain, Size: 1019 bytes --]

Hello,

In Ada, arrays can be empty by setting the high bound to a smaller value
than the low bound. For instance, a typical declaration would be:

type Empty_Array is array (1 .. 0) of Integer;

The attached patch fixes a bug when trying to print a variable
of such a type:

(gdb) print my_table
object size is larger than varsize-limit

The problem is that we compute the array length using the bounds
from the index type without checking first that the high bound
is larger or equal to the small bound. There were a couple of
places were we did that, so we made some adjustments there.

2008-01-09 Joel Brobecker <brobecker@adacore.com>

* gdbtypes.c (create_array_type): Add handling of null Ada arrays.
(check_typedef): Likewise.

I was able to write a testcase too:

2008-01-09 Joel Brobecker <brobecker@adacore.com>

* gdb.ada/null_array: New test program.
* gdb.ada/null_array.exp: New testcase.

Tested on x86-linux, no regression.
OK to commit?

Thanks,
--
Joel

[-- Attachment #2: null_array.diff --]
[-- Type: text/plain, Size: 1908 bytes --]

Index: gdbtypes.c
===================================================================
--- gdbtypes.c (revision 113)
+++ gdbtypes.c (revision 116)
@@ -811,8 +811,14 @@ create_array_type (struct type *result_t
if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0)
low_bound = high_bound = 0;
CHECK_TYPEDEF (element_type);
- TYPE_LENGTH (result_type) =
- TYPE_LENGTH (element_type) * (high_bound - low_bound + 1);
+ /* Be careful when setting the array length. Ada arrays can be
+ empty arrays with the high_bound being smaller than the low_bound.
+ In such cases, the array length should be zero. */
+ if (high_bound < low_bound)
+ TYPE_LENGTH (result_type) = 0;
+ else
+ TYPE_LENGTH (result_type) =
+ TYPE_LENGTH (element_type) * (high_bound - low_bound + 1);
TYPE_NFIELDS (result_type) = 1;
TYPE_FIELDS (result_type) =
(struct field *) TYPE_ALLOC (result_type, sizeof (struct field));
@@ -1492,11 +1498,19 @@ check_typedef (struct type *type)
== TYPE_CODE_RANGE))
{
/* Now recompute the length of the array type, based on its
- number of elements and the target type's length. */
- TYPE_LENGTH (type) =
- ((TYPE_FIELD_BITPOS (range_type, 1)
- - TYPE_FIELD_BITPOS (range_type, 0) + 1)
- * TYPE_LENGTH (target_type));
+ number of elements and the target type's length.
+ Watch out for Ada null Ada arrays where the high bound
+ is smaller than the low bound. */
+ const int low_bound = TYPE_FIELD_BITPOS (range_type, 0);
+ const int high_bound = TYPE_FIELD_BITPOS (range_type, 1);
+ int nb_elements;
+
+ if (high_bound < low_bound)
+ nb_elements = 0;
+ else
+ nb_elements = high_bound - low_bound + 1;
+
+ TYPE_LENGTH (type) = nb_elements * TYPE_LENGTH (target_type);
TYPE_FLAGS (type) &= ~TYPE_FLAG_TARGET_STUB;
}
else if (TYPE_CODE (type) == TYPE_CODE_RANGE)

[-- Attachment #3: null_array-tc.diff --]
[-- Type: text/plain, Size: 5097 bytes --]

Index: gdb.ada/null_array.exp
===================================================================
--- gdb.ada/null_array.exp (revision 0)
+++ gdb.ada/null_array.exp (revision 115)
@@ -0,0 +1,50 @@
+# Copyright 2008 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/>.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+load_lib "ada.exp"
+
+set testdir "null_array"
+set testfile "${testdir}/foo"
+set srcfile ${srcdir}/${subdir}/${testfile}.adb
+set binfile ${objdir}/${subdir}/${testfile}
+
+file mkdir ${objdir}/${subdir}/${testdir}
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug]] != "" } {
+ return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+set bp_location [gdb_get_line_number "START" ${testdir}/foo.adb]
+runto "foo.adb:$bp_location"
+
+# Test printing and type-printing of a tagged type that is not
+# class-wide.
+
+gdb_test "print my_table" \
+ "\\(\\)" \
+ "print my_table"
+
+gdb_test "ptype my_table" \
+ "type = array \\(10 \\.\\. 1\\) of integer" \
+ "ptype my_table"
+
Index: gdb.ada/null_array/pck.adb
===================================================================
--- gdb.ada/null_array/pck.adb (revision 0)
+++ gdb.ada/null_array/pck.adb (revision 115)
@@ -0,0 +1,28 @@
+-- Copyright 2008 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/>.
+
+package body Pck is
+
+ function Ident (I : Integer) return Integer is
+ begin
+ return I;
+ end Ident;
+
+ procedure Do_Nothing (A : System.Address) is
+ begin
+ null;
+ end Do_Nothing;
+
+end Pck;
Index: gdb.ada/null_array/pck.ads
===================================================================
--- gdb.ada/null_array/pck.ads (revision 0)
+++ gdb.ada/null_array/pck.ads (revision 115)
@@ -0,0 +1,24 @@
+-- Copyright 2008 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/>.
+
+with System;
+
+package Pck is
+
+ function Ident (I : Integer) return Integer;
+
+ procedure Do_Nothing (A : System.Address);
+
+end Pck;
Index: gdb.ada/null_array/foo.adb
===================================================================
--- gdb.ada/null_array/foo.adb (revision 0)
+++ gdb.ada/null_array/foo.adb (revision 115)
@@ -0,0 +1,24 @@
+-- Copyright 2008 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/>.
+
+with Pck; use Pck;
+
+procedure Foo is
+ type Table is array (Integer range <>) of Integer;
+
+ My_Table : Table (Ident (10) .. Ident (1));
+begin
+ Do_Nothing (My_Table'Address); -- START
+end Foo;