smash_to_methodptr_type (type, new_type);
}
+/* Helper for quirk_ada_thick_pointer. If TYPE is an array type that
+ requires rewriting, then copy it and return the updated copy.
+ Otherwise return nullptr. */
+
+static struct type *
+rewrite_array_type (struct type *type)
+{
+ if (type->code () != TYPE_CODE_ARRAY)
+ return nullptr;
+
+ struct type *index_type = type->index_type ();
+ range_bounds *current_bounds = index_type->bounds ();
+
+ /* Handle multi-dimensional arrays. */
+ struct type *new_target = rewrite_array_type (TYPE_TARGET_TYPE (type));
+ if (new_target == nullptr)
+ {
+ /* Maybe we don't need to rewrite this array. */
+ if (current_bounds->low.kind () == PROP_CONST
+ && current_bounds->high.kind () == PROP_CONST)
+ return nullptr;
+ }
+
+ /* Either the target type was rewritten, or the bounds have to be
+ updated. Either way we want to copy the type and update
+ everything. */
+ struct type *copy = copy_type (type);
+ int nfields = copy->num_fields ();
+ field *new_fields
+ = ((struct field *) TYPE_ZALLOC (copy,
+ nfields * sizeof (struct field)));
+ memcpy (new_fields, copy->fields (), nfields * sizeof (struct field));
+ copy->set_fields (new_fields);
+ if (new_target != nullptr)
+ TYPE_TARGET_TYPE (copy) = new_target;
+
+ struct type *index_copy = copy_type (index_type);
+ range_bounds *bounds
+ = (struct range_bounds *) TYPE_ZALLOC (index_copy,
+ sizeof (range_bounds));
+ *bounds = *current_bounds;
+ bounds->low.set_const_val (1);
+ bounds->high.set_const_val (0);
+ index_copy->set_bounds (bounds);
+ copy->set_index_type (index_copy);
+
+ return copy;
+}
+
/* While some versions of GCC will generate complicated DWARF for an
array (see quirk_ada_thick_pointer), more recent versions were
modified to emit an explicit thick pointer structure. However, in
/* Make sure we're looking at a pointer to an array. */
if (type->field (0).type ()->code () != TYPE_CODE_PTR)
return;
- struct type *ary_type = TYPE_TARGET_TYPE (type->field (0).type ());
-
- while (ary_type->code () == TYPE_CODE_ARRAY)
- {
- /* The Ada code already knows how to handle these types, so all
- that we need to do is turn the bounds into static bounds. */
- struct type *index_type = ary_type->index_type ();
- index_type->bounds ()->low.set_const_val (1);
- index_type->bounds ()->high.set_const_val (0);
-
- /* Handle multi-dimensional arrays. */
- ary_type = TYPE_TARGET_TYPE (ary_type);
- }
+ /* The Ada code already knows how to handle these types, so all that
+ we need to do is turn the bounds into static bounds. However, we
+ don't want to rewrite existing array or index types in-place,
+ because those may be referenced in other contexts where this
+ rewriting is undesirable. */
+ struct type *new_ary_type
+ = rewrite_array_type (TYPE_TARGET_TYPE (type->field (0).type ()));
+ if (new_ary_type != nullptr)
+ type->field (0).set_type (lookup_pointer_type (new_ary_type));
}
/* If the DIE has a DW_AT_alignment attribute, return its value, doing
--- /dev/null
+# Copyright 2020 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 that handling of Ada thick pointers does not rewrite other
+# similar types.
+
+load_lib dwarf.exp
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+if {![dwarf2_support]} {
+ return 0
+}
+
+standard_testfile main.c -debug.S
+
+# Set up the DWARF for the test.
+
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+ global srcdir subdir srcfile
+
+ cu {} {
+ DW_TAG_compile_unit {
+ {DW_AT_language @DW_LANG_Ada95}
+ {DW_AT_name $srcfile}
+ } {
+ declare_labels integer array array_pointer bounds_pointer
+
+ integer: DW_TAG_base_type {
+ {DW_AT_byte_size 8 DW_FORM_sdata}
+ {DW_AT_encoding @DW_ATE_signed}
+ {DW_AT_name integer}
+ }
+
+ array: DW_TAG_array_type {
+ {DW_AT_name array_type}
+ {DW_AT_type :$integer}
+ } {
+ DW_TAG_subrange_type {
+ {DW_AT_type :$integer}
+ {DW_AT_lower_bound 1 DW_FORM_data1}
+ {DW_AT_upper_bound 7 DW_FORM_data1}
+ }
+ }
+
+ array_pointer: DW_TAG_pointer_type {
+ {DW_AT_type :$array}
+ {DW_AT_byte_size 8 DW_FORM_sdata}
+ }
+
+ # This isn't exactly what GNAT emits, but it doesn't
+ # matter.
+ bounds_pointer: DW_TAG_pointer_type {
+ {DW_AT_type :$integer}
+ {DW_AT_byte_size 8 DW_FORM_sdata}
+ }
+
+ DW_TAG_structure_type {
+ {DW_AT_name thick_pointer_type}
+ {DW_AT_byte_size 8 DW_FORM_sdata}
+ } {
+ DW_TAG_member {
+ {DW_AT_name P_ARRAY}
+ {DW_AT_type :$array_pointer}
+ {DW_AT_data_member_location 0 DW_FORM_sdata}
+ }
+ DW_TAG_member {
+ {DW_AT_name P_BOUNDS}
+ {DW_AT_type :$bounds_pointer}
+ {DW_AT_data_member_location 8 DW_FORM_sdata}
+ }
+ }
+ }
+ }
+}
+
+if { [prepare_for_testing "failed to prepare" ${testfile} \
+ [list $srcfile $asm_file] {nodebug}] } {
+ return -1
+}
+
+gdb_test_no_output "set language ada"
+gdb_test "ptype array_type" "type = array \\(1 \\.\\. 7\\) of integer"