This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFA/commit] Handling of empty Ada ranges with a negative upper bound.


Hello,

Consider the following variable declaration:

    type Array_Type is array (Integer range <>) of Integer;
    Var: Array_Type (0 .. -1);

"ptype var" prints the wrong upper bound for that array:

    (gdb) ptype var
    type = array (0 .. 4294967295) of integer

The debugging info for the type of variable "Var" is as follow:

  <2><cf>: Abbrev Number: 13 (DW_TAG_structure_type)
     <d0>   DW_AT_name        : foo__var___PAD
  <3><db>: Abbrev Number: 14 (DW_TAG_member)
     <dc>   DW_AT_name        : F
     <e0>   DW_AT_type        : <0xa5>

This is just an artifact from code generation, which is just
a wrapper that we should ignore. The real type is the type of
field "F" in that PAD type, which is described as:

  <2><a5>: Abbrev Number: 10 (DW_TAG_array_type)
     <a6>   DW_AT_name        : foo__TvarS
  <3><b6>: Abbrev Number: 11 (DW_TAG_subrange_type)
     <b7>   DW_AT_type        : <0xc1>
     <bb>   DW_AT_lower_bound : 0
     <bc>   DW_AT_upper_bound : 0xffffffff

Trouble occurs because DW_AT_upper_bound is encoded using
a DW_FORM_data4, which is ambiguous regarding signedness.
In that case, dwarf2read.c::dwarf2_get_attr_constant_value
reads the value as unsigned, which is not what we want
in this case.

As it happens, we already have code dealing with this situation
in dwarf2read.c::read_subrange_type which checks whether
the subrange's type is signed or not, and if it is, fixes
the bound's value by sign-extending it:

  if (high.kind == PROP_CONST
      && !TYPE_UNSIGNED (base_type) && (high.data.const_val & negative_mask))
    high.data.const_val |= negative_mask;

Unfortunately, what happens in our case is that the base type
of the array's subrange type is marked as being unsigned, and
so we never get to apply the sign extension. Following the DWARF
trail, the range's base type is described as another subrange type...

  <2><c1>: Abbrev Number: 12 (DW_TAG_subrange_type)
     <c7>   DW_AT_name        : foo__TTvarSP1___XDLU_0__1m
     <cb>   DW_AT_type        : <0x2d>

... whose base type is, (finally), a basic type (signed):

  <1><2d>: Abbrev Number: 2 (DW_TAG_base_type)
     <2e>   DW_AT_byte_size   : 4
     <2f>   DW_AT_encoding    : 5        (signed)
     <30>   DW_AT_name        : integer

The reason why GDB thinks that foo__TTvarSP1___XDLU_0__1m
(the base type of the array's range type) is an unsigned type
is found in gdbtypes.c::create_range_type.  We consider that
a range type is unsigned iff its lower bound is >= 0:

  if (low_bound->kind == PROP_CONST && low_bound->data.const_val >= 0)
    TYPE_UNSIGNED (result_type) = 1;

That is normally sufficient, as one would expect the upper bound to
always be greater or equal to the lower bound. But Ada actually
allows the declaration of empty range types where the upper bound
is less than the lower bound. In this case, the upper bound is
negative, so we should not be marking the type as unsigned.

This patch fixes the issue by simply checking the upper bound as well
as the lower bound, and clears the range type's unsigned flag when
it is found to be constant and negative.

gdb/ChangeLog:

        * gdbtypes.c (create_range_type): Unset RESULT_TYPE's
        flag_unsigned if HIGH_BOUND is constant and negative.

gdb/testsuite/ChangeLog:

        * gdb.ada/n_arr_bound: New testcase.

Tested on x86_64-linux. It seems like a fairly straightforward
change to me, so I'm comfortable pushing it say, a week from now,
but I would welcome a review nonetheless (JIC).

Thank you!
-- 
Joel

---
 gdb/gdbtypes.c                            |  7 +++++++
 gdb/testsuite/gdb.ada/n_arr_bound.exp     | 32 +++++++++++++++++++++++++++++++
 gdb/testsuite/gdb.ada/n_arr_bound/foo.adb | 23 ++++++++++++++++++++++
 gdb/testsuite/gdb.ada/n_arr_bound/pck.adb | 21 ++++++++++++++++++++
 gdb/testsuite/gdb.ada/n_arr_bound/pck.ads | 19 ++++++++++++++++++
 5 files changed, 102 insertions(+)
 create mode 100644 gdb/testsuite/gdb.ada/n_arr_bound.exp
 create mode 100644 gdb/testsuite/gdb.ada/n_arr_bound/foo.adb
 create mode 100644 gdb/testsuite/gdb.ada/n_arr_bound/pck.adb
 create mode 100644 gdb/testsuite/gdb.ada/n_arr_bound/pck.ads

diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 8e44b7c..b921c64 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -821,6 +821,13 @@ create_range_type (struct type *result_type, struct type *index_type,
   if (low_bound->kind == PROP_CONST && low_bound->data.const_val >= 0)
     TYPE_UNSIGNED (result_type) = 1;
 
+  /* Ada allows the declaration of range types whose upper bound is
+     less than the lower bound, so checking the lower bound is not
+     enough.  Make sure we do not mark a range type whose upper bound
+     is negative as unsigned.  */
+  if (high_bound->kind == PROP_CONST && high_bound->data.const_val < 0)
+    TYPE_UNSIGNED (result_type) = 0;
+
   return result_type;
 }
 
diff --git a/gdb/testsuite/gdb.ada/n_arr_bound.exp b/gdb/testsuite/gdb.ada/n_arr_bound.exp
new file mode 100644
index 0000000..52044eb
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/n_arr_bound.exp
@@ -0,0 +1,32 @@
+# Copyright 2014 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/>.
+
+load_lib "ada.exp"
+
+if { [skip_ada_tests] } { return -1 }
+
+standard_ada_testfile foo
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable {debug}] != ""} {
+    return -1
+}
+
+clean_restart ${testfile}
+
+set bp_location [gdb_get_line_number "STOP" ${testdir}/foo.adb]
+runto "foo.adb:$bp_location"
+
+gdb_test "ptype var" \
+         "= array \\(0 .. -1\\) of integer"
diff --git a/gdb/testsuite/gdb.ada/n_arr_bound/foo.adb b/gdb/testsuite/gdb.ada/n_arr_bound/foo.adb
new file mode 100644
index 0000000..d9c6fe6
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/n_arr_bound/foo.adb
@@ -0,0 +1,23 @@
+--  Copyright 2014 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 Array_Type is array (Integer range <>) of Integer;
+   Var: Array_Type (0 .. -1);
+begin
+   Do_Nothing (Var'Address); -- STOP
+end Foo;
diff --git a/gdb/testsuite/gdb.ada/n_arr_bound/pck.adb b/gdb/testsuite/gdb.ada/n_arr_bound/pck.adb
new file mode 100644
index 0000000..2b31332
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/n_arr_bound/pck.adb
@@ -0,0 +1,21 @@
+--  Copyright 2014 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
+   procedure Do_Nothing (A : System.Address) is
+   begin
+      null;
+   end Do_Nothing;
+end Pck;
diff --git a/gdb/testsuite/gdb.ada/n_arr_bound/pck.ads b/gdb/testsuite/gdb.ada/n_arr_bound/pck.ads
new file mode 100644
index 0000000..100d7d5
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/n_arr_bound/pck.ads
@@ -0,0 +1,19 @@
+--  Copyright 2014 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
+   procedure Do_Nothing (A : System.Address);
+end Pck;
-- 
1.9.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]