binutils-gdb/gdb/testsuite/gdb.python/flexible-array-member.exp
Simon Marchi 858c8f2c1b gdb/testsuite: adjust gdb.python/flexible-array-member.exp expected pattern
The `Type.range ()` tests in gdb.python/flexible-array-member.exp pass
when the test is compiled with gcc 9 or later, but not with gcc 8 or
earlier:

    $ make check TESTS="gdb.python/flexible-array-member.exp" RUNTESTFLAGS="CC_FOR_TARGET='gcc-8'"

    python print(zs['items'].type.range())^M
    (0, 0)^M
    (gdb) FAIL: gdb.python/flexible-array-member.exp: python print(zs['items'].type.range())
    python print(zso['items'].type.range())^M
    (0, 0)^M
    (gdb) FAIL: gdb.python/flexible-array-member.exp: python print(zso['items'].type.range())

The value that we get for the upper bound of a flexible array member
declared with a "0" size is 0 with gcc <= 8 and is -1 for gcc >= 9.
This is due to different debug info.  For this member, gcc 8 does:

    0x000000d5:   DW_TAG_array_type
                    DW_AT_type [DW_FORM_ref4]       (0x00000034 "int")
                    DW_AT_sibling [DW_FORM_ref4]    (0x000000e4)

    0x000000de:     DW_TAG_subrange_type
                      DW_AT_type [DW_FORM_ref4]     (0x0000002d "long unsigned int")

For the same type, gcc 9 does:

    0x000000d5:   DW_TAG_array_type
                    DW_AT_type [DW_FORM_ref4]       (0x00000034 "int")
                    DW_AT_sibling [DW_FORM_ref4]    (0x000000e5)

    0x000000de:     DW_TAG_subrange_type
                      DW_AT_type [DW_FORM_ref4]     (0x0000002d "long unsigned int")
                      DW_AT_count [DW_FORM_data1]   (0x00)

Ideally, GDB would present a consistent and documented value for an
array member declared with size 0, regardless of how the debug info
looks like.  But for now, just change the test to accept the two
values, to get rid of the failure and make the test in sync

I also realized (by looking at the py-type.exp test) that calling the
fields method on an array type yields one field representing the "index"
of the array.  The type of that field is of type range
(gdb.TYPE_CODE_RANGE).  When calling `.range()` on that range type, it
yields the same range tuple as when calling `.range()` on the array type
itself.  For completeness, add some tests to access the range tuple
through that range type as well.

gdb/testsuite/ChangeLog:

	* gdb.python/flexible-array-member.exp: Adjust expected range
	value for member declared with 0 size.  Test accessing range
	tuple through range type.

Change-Id: Ie4e06d99fe9315527f04577888f48284d649ca4c
2021-05-04 11:20:19 -04:00

92 lines
3.7 KiB
Text

# Copyright 2020-2021 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 getting the range of flexible array members in Python.
standard_testfile
if { [prepare_for_testing "failed to prepare" \
${testfile} ${srcfile}] } {
return
}
# Skip all tests if Python scripting is not enabled.
if { [skip_python_tests] } { continue }
if { ![runto break_here] } {
untested "could not run to break_here"
return
}
# The various cases are:
#
# - ns: flexible array member with no size
# - zs: flexible array member with size 0 (GNU C extension that predates the
# standardization of the feature, but widely supported)
# - zso: zero-size only, a corner case where the array is the sole member of
# the structure
gdb_test "python ns = gdb.parse_and_eval('ns').dereference()"
gdb_test "python zs = gdb.parse_and_eval('zs').dereference()"
gdb_test "python zso = gdb.parse_and_eval('zso').dereference()"
# Print the whole structure.
gdb_test "python print(ns)" "{n = 3, items = $hex}"
gdb_test "python print(zs)" "{n = 3, items = $hex}"
gdb_test "python print(zso)" "{items = $hex}"
# Print all items.
gdb_test "python print(ns\['items'\])" "$hex"
gdb_test "python print(ns\['items'\]\[0\])" "101"
gdb_test "python print(ns\['items'\]\[1\])" "102"
gdb_test "python print(ns\['items'\]\[2\])" "103"
gdb_test "python print(zs\['items'\])" "$hex"
gdb_test "python print(zs\['items'\]\[0\])" "201"
gdb_test "python print(zs\['items'\]\[1\])" "202"
gdb_test "python print(zs\['items'\]\[2\])" "203"
gdb_test "python print(zso\['items'\])" "$hex"
gdb_test "python print(zso\['items'\]\[0\])" "301"
gdb_test "python print(zso\['items'\]\[1\])" "302"
gdb_test "python print(zso\['items'\]\[2\])" "303"
# Check taking the address of array elements (how PR 28675 was originally
# reported).
gdb_test "python print(ns\['items'\] == ns\['items'\]\[0\].address)" "True"
gdb_test "python print(ns\['items'\]\[0\].address + 1 == ns\['items'\]\[1\].address)" "True"
gdb_test "python print(zs\['items'\] == zs\['items'\]\[0\].address)" "True"
gdb_test "python print(zs\['items'\]\[0\].address + 1 == zs\['items'\]\[1\].address)" "True"
gdb_test "python print(zso\['items'\] == zso\['items'\]\[0\].address)" "True"
gdb_test "python print(zso\['items'\]\[0\].address + 1 == zso\['items'\]\[1\].address)" "True"
# Verify the range attribute. It looks a bit inconsistent that the high bound
# is sometimes 0, sometimes -1. It depends on the way the flexible array
# member is specified and on the compiler version (the debug info is
# different). But that's what GDB produces today, so that's what we test.
gdb_test "python print(ns\['items'\].type.range())" "\\(0, 0\\)"
gdb_test "python print(zs\['items'\].type.range())" "\\(0, (0|-1)\\)"
gdb_test "python print(zso\['items'\].type.range())" "\\(0, (0|-1)\\)"
# Test the same thing, but going explicitly through the array index's range
# type.
gdb_test "python print(ns\['items'\].type.fields()\[0\].type.range())" "\\(0, 0\\)"
gdb_test "python print(zs\['items'\].type.fields()\[0\].type.range())" "\\(0, (0|-1)\\)"
gdb_test "python print(zso\['items'\].type.fields()\[0\].type.range())" "\\(0, (0|-1)\\)"