Ada subscripting of pointer to array with dynamic bounds
authorJoel Brobecker <brobecker@adacore.com>
Fri, 29 Aug 2014 17:50:03 +0000 (19:50 +0200)
committerJoel Brobecker <brobecker@adacore.com>
Wed, 10 Sep 2014 13:30:58 +0000 (06:30 -0700)
Consider a pointer to an array which dynamic bounds, described in
DWARF as follow:

        <1><25>: Abbrev Number: 4 (DW_TAG_array_type)
           <26>   DW_AT_name        : foo__array_type
        [...]
        <2><3b>: Abbrev Number: 5 (DW_TAG_subrange_type)
           [...]
           <40>   DW_AT_lower_bound : 5 byte block: 97 38 1c 94 4
                  (DW_OP_push_object_address; DW_OP_lit8; DW_OP_minus;
                   DW_OP_deref_size: 4)
           <46>   DW_AT_upper_bound : 5 byte block: 97 34 1c 94 4
                  (DW_OP_push_object_address; DW_OP_lit4; DW_OP_minus;
                   DW_OP_deref_size: 4)

GDB is now able to correctly print the entire array, but not one
element of the array. Eg:

    (gdb) p foo.three_ptr.all
    $1 = (1, 2, 3)
    (gdb) p foo.three_ptr.all(1)
    Cannot access memory at address 0xfffffffff4123a0c

The problem occurs because we are missing a dynamic resolution of
the variable's array type when subscripting the array. What the current
code does is "fix"-ing the array type using the GNAT encodings, but
that operation ignores any of the array's dynamic properties.

This patch fixes the issue by using ada_value_ind to dereference
the array pointer, which takes care of the array type resolution.
It also continues to "fix" arrays described using GNAT encodings,
so backwards compatibility is preserved.

gdb/ChangeLog:

        * ada-lang.c (ada_value_ptr_subscript): Remove parameter "type".
        Adjust function implementation and documentation accordingly.
        (ada_evaluate_subexp) <OP_FUNCALL>: Only assign "type" if
        NOSIDE is EVAL_AVOID_SIDE_EFFECTS.
        Update call to ada_value_ptr_subscript.

gdb/testsuite/ChangeLog:

        * gdb.dwarf2/dynarr-ptr.exp: Add subscripting tests.

gdb/ChangeLog
gdb/ada-lang.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.dwarf2/dynarr-ptr.exp

index 82e36229877fe36b30f79047079eb5b918cf173f..67f631d2be493ddfa712762849526078e952c186 100644 (file)
@@ -1,3 +1,11 @@
+2014-09-10  Joel Brobecker  <brobecker@adacore.com>
+
+       * ada-lang.c (ada_value_ptr_subscript): Remove parameter "type".
+       Adjust function implementation and documentation accordingly.
+       (ada_evaluate_subexp) <OP_FUNCALL>: Only assign "type" if
+       NOSIDE is EVAL_AVOID_SIDE_EFFECTS.
+       Update call to ada_value_ptr_subscript.
+
 2014-09-10  Joel Brobecker  <brobecker@adacore.com>
 
        * ada-valprint.c (ada_value_print): Use VAL's enclosing type
index 28999c7efd14fd674a2c9ed78ddf9a1653661835..4c6d03933a61ed06562e38c7c302988dc12d0e41 100644 (file)
@@ -2715,15 +2715,16 @@ ada_value_subscript (struct value *arr, int arity, struct value **ind)
   return elt;
 }
 
-/* Assuming ARR is a pointer to a standard GDB array of type TYPE, the
-   value of the element of *ARR at the ARITY indices given in
-   IND.  Does not read the entire array into memory.  */
+/* Assuming ARR is a pointer to a GDB array, the value of the element
+   of *ARR at the ARITY indices given in IND.
+   Does not read the entire array into memory.  */
 
 static struct value *
-ada_value_ptr_subscript (struct value *arr, struct type *type, int arity,
-                         struct value **ind)
+ada_value_ptr_subscript (struct value *arr, int arity, struct value **ind)
 {
   int k;
+  struct type *type
+    = check_typedef (value_enclosing_type (ada_value_ind (arr)));
 
   for (k = 0; k < arity; k += 1)
     {
@@ -10323,9 +10324,9 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
                           (ada_coerce_to_simple_array (argvec[0]),
                            nargs, argvec + 1));
         case TYPE_CODE_PTR:     /* Pointer to array */
-          type = to_fixed_array_type (TYPE_TARGET_TYPE (type), NULL, 1);
           if (noside == EVAL_AVOID_SIDE_EFFECTS)
             {
+             type = to_fixed_array_type (TYPE_TARGET_TYPE (type), NULL, 1);
               type = ada_array_element_type (type, nargs);
               if (type == NULL)
                 error (_("element type of array unknown"));
@@ -10333,8 +10334,8 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
                 return value_zero (ada_aligned_type (type), lval_memory);
             }
           return
-            unwrap_value (ada_value_ptr_subscript (argvec[0], type,
-                                                   nargs, argvec + 1));
+            unwrap_value (ada_value_ptr_subscript (argvec[0],
+                                                  nargs, argvec + 1));
 
         default:
           error (_("Attempt to index or call something other than an "
index e7bba7790f0b5209878bcc053608dbc7522db3dc..ebb7e6a917d38caa261543f4d84d27dc08271073 100644 (file)
@@ -1,3 +1,7 @@
+2014-09-10  Joel Brobecker  <brobecker@adacore.com>
+
+       * gdb.dwarf2/dynarr-ptr.exp: Add subscripting tests.
+
 2014-09-10  Joel Brobecker  <brobecker@adacore.com>
 
        * gdb.dwarf2/dynarr-ptr.c: New file.
index 501f1290c3b1e893bec7beaa614875472f12ee09..1df5e3c018d230799c6170326e8765083740f9b2 100644 (file)
@@ -137,17 +137,121 @@ gdb_test_no_output "set language ada"
 gdb_test "print foo.three_ptr.all" \
          " = \\(1, 2, 3\\)"
 
+gdb_test "print foo.three_ptr.all(1)" \
+         " = 1"
+
+gdb_test "print foo.three_ptr.all(2)" \
+         " = 2"
+
+gdb_test "print foo.three_ptr.all(3)" \
+         " = 3"
+
+# foo.three_ptr
+
+gdb_test "print foo.three_ptr(1)" \
+         " = 1"
+
+gdb_test "print foo.three_ptr(2)" \
+         " = 2"
+
+gdb_test "print foo.three_ptr(3)" \
+         " = 3"
+
 # foo.three_ptr_tdef.all
 
 gdb_test "print foo.three_ptr_tdef.all" \
          " = \\(1, 2, 3\\)"
 
+gdb_test "print foo.three_ptr_tdef.all(1)" \
+         " = 1"
+
+gdb_test "print foo.three_ptr_tdef.all(2)" \
+         " = 2"
+
+gdb_test "print foo.three_ptr_tdef.all(3)" \
+         " = 3"
+
+# foo.three_ptr_tdef
+
+gdb_test "print foo.three_ptr_tdef(1)" \
+         " = 1"
+
+gdb_test "print foo.three_ptr_tdef(2)" \
+         " = 2"
+
+gdb_test "print foo.three_ptr_tdef(3)" \
+         " = 3"
+
 # foo.five_ptr.all
 
 gdb_test "print foo.five_ptr.all" \
          " = \\(2 => 5, 8, 13, 21, 34\\)"
 
+gdb_test "print foo.five_ptr.all(2)" \
+         " = 5"
+
+gdb_test "print foo.five_ptr.all(3)" \
+         " = 8"
+
+gdb_test "print foo.five_ptr.all(4)" \
+         " = 13"
+
+gdb_test "print foo.five_ptr.all(5)" \
+         " = 21"
+
+gdb_test "print foo.five_ptr.all(6)" \
+         " = 34"
+
+# foo.five_ptr
+
+gdb_test "print foo.five_ptr(2)" \
+         " = 5"
+
+gdb_test "print foo.five_ptr(3)" \
+         " = 8"
+
+gdb_test "print foo.five_ptr(4)" \
+         " = 13"
+
+gdb_test "print foo.five_ptr(5)" \
+         " = 21"
+
+gdb_test "print foo.five_ptr(6)" \
+         " = 34"
+
 # foo.five_ptr_tdef.all
 
 gdb_test "print foo.five_ptr_tdef.all" \
          " = \\(2 => 5, 8, 13, 21, 34\\)"
+
+gdb_test "print foo.five_ptr_tdef.all(2)" \
+         " = 5"
+
+gdb_test "print foo.five_ptr_tdef.all(3)" \
+         " = 8"
+
+gdb_test "print foo.five_ptr_tdef.all(4)" \
+         " = 13"
+
+gdb_test "print foo.five_ptr_tdef.all(5)" \
+         " = 21"
+
+gdb_test "print foo.five_ptr_tdef.all(6)" \
+         " = 34"
+
+# foo.five_ptr_tdef
+
+gdb_test "print foo.five_ptr_tdef(2)" \
+         " = 5"
+
+gdb_test "print foo.five_ptr_tdef(3)" \
+         " = 8"
+
+gdb_test "print foo.five_ptr_tdef(4)" \
+         " = 13"
+
+gdb_test "print foo.five_ptr_tdef(5)" \
+         " = 21"
+
+gdb_test "print foo.five_ptr_tdef(6)" \
+         " = 34"