mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-01-24 12:35:55 +08:00
1f5d1570c0
ada_value_struct_elt is used when displaying a component (say, 'N') of a record object (say, 'Obj') of type, say, 't1'. Now if Obj is tagged (Ada parlance: "tagged types" are what other object-oriented languages call "classes"), then 'N' may not be visible in the current view and we need to look for it in its actual type. We do that at the same time as resolving variable-length fields. This would typically be done by the following call to ada_value_struct_elt, with the last parameter check_tag set to 1: t1 = ada_to_fixed_type (ada_get_base_type (t1), NULL, address, NULL, 1); This is the general logic, but recently we introduced a special case to handle homonyms. Different components may have the same name in a tagged type. For instance: type Top_T is tagged record N : Integer := 1; end record; type Middle_T is new Top.Top_T with record N : Character := 'a'; end record; Middle_T extends Top_T and both define a (different) component with the same name ('N'). In such a case, using the actual type of a Middle_T object would create a confusion, since we would have two component 'N' in this actual type. So, to handle homonyms, we convert t1 to the actual type *if and only if* N cannot be found in the current view. For example, if Obj has been created as a Middle_T but is seen as a Top_T'Class at our point of execution, then "print Obj.N" will display the integer field defined in Top_T's declaration. Now, even if we find N in the current view, we still have to get a fixed type: for instance, the record can be unconstrained and we still need a fixed type to get the proper offset to each field. That is to say, in this case: type Dyn_Top_T (Disc : Natural) is tagged record S : Integer_Array (1 .. Disc) := (others => Disc); N : Integer := 1; end record; type Dyn_Middle_T is new Dyn_Top.Dyn_Top_T with record N : Character := 'a'; U : Integer := 42; end record; If we have an object Obj of type Dyn_Middle_T and we want to display U, we don't need to build, from its tag, a real type with all its real fields. In other words, we don't need to add the parent components: Disc, S, and the integer N. We only need to access U and it is directly visible in Dyn_Middle_T. So no tag handling. However, we do need to build a fixed-size type to have the proper offset to U (since this offset to U depends on the size of Obj.S, which itself is dynamic and depends on the value of Obj.Disc). We accidentally lost some of this treatment when we introduced the resolution of homonyms. This patch re-install this part by uncoupling the tag resolution from the "fixing" of variable-length components. This change also slightly simplifies the non-tagged case: in the non-tagged case, no need to set check_tag to 1, since we already know that there is no tag. gdb/ChangeLog: * ada-lang.c (ada_value_struct_elt): Call ada_to_fixed_type with check_tag to 1 if and only if the type is tagged and the component being searched cannot been found in the current view. Otherwise, always call ada_to_fixed_type with check_tag to 0. gdb/testsuite/ChangeLog: * gdb.ada/same_component_name: Add test for case of tagged record with variable-length fields.
71 lines
2.4 KiB
Plaintext
71 lines
2.4 KiB
Plaintext
# Copyright 2017-2018 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"
|
|
|
|
standard_ada_testfile foo
|
|
|
|
if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug ]] != "" } {
|
|
return -1
|
|
}
|
|
|
|
clean_restart ${testfile}
|
|
|
|
set bp_top_location [gdb_get_line_number "BREAK_TOP" ${testdir}/pck.adb]
|
|
set bp_middle_location [gdb_get_line_number "BREAK_MIDDLE" ${testdir}/pck.adb]
|
|
set bp_bottom_location [gdb_get_line_number "BREAK_BOTTOM" ${testdir}/pck.adb]
|
|
set bp_dyn_middle_location [gdb_get_line_number "BREAK_DYN_MIDDLE" ${testdir}/pck.adb]
|
|
|
|
gdb_breakpoint "pck.adb:$bp_top_location"
|
|
gdb_breakpoint "pck.adb:$bp_middle_location"
|
|
gdb_breakpoint "pck.adb:$bp_bottom_location"
|
|
gdb_breakpoint "pck.adb:$bp_dyn_middle_location"
|
|
|
|
gdb_run_cmd
|
|
|
|
gdb_test "" \
|
|
".*Breakpoint $decimal, pck.top.assign \\(.*\\).*" \
|
|
"run to top assign breakpoint"
|
|
|
|
gdb_test "print obj.n" " = 1" "Print top component field"
|
|
|
|
gdb_test "continue" \
|
|
".*Breakpoint $decimal, pck.assign \\(.*\\).*" \
|
|
"continue to bottom assign breakpoint"
|
|
|
|
gdb_test "print obj.n" " = 4\\.0" "Print bottom component field"
|
|
|
|
gdb_test "continue" \
|
|
".*Breakpoint $decimal, pck.middle.assign \\(.*\\).*" \
|
|
"continue to middle assign breakpoint"
|
|
|
|
gdb_test "print obj.a" " = 48" \
|
|
"Print top component field in middle assign function"
|
|
|
|
gdb_test "continue" \
|
|
".*Breakpoint $decimal, pck.assign \\(.*\\).*" \
|
|
"continue to bottom assign breakpoint (2nd time)"
|
|
|
|
gdb_test "print obj.x" " = 6" \
|
|
"Print field existing only in bottom component"
|
|
|
|
gdb_test "continue" \
|
|
".*Breakpoint $decimal, pck.dyn_middle.assign \\(.*\\).*" \
|
|
"continue to dyn_middle assign breakpoint"
|
|
|
|
gdb_test "print obj.u" " = 42" \
|
|
"Print field existing only in dyn_middle component"
|
|
|