binutils-gdb/gdb/testsuite/gdb.cp/member-ptr.exp
Andrew Burgess 1d506c26d9 Update copyright year range in header of all files managed by GDB
This commit is the result of the following actions:

  - Running gdb/copyright.py to update all of the copyright headers to
    include 2024,

  - Manually updating a few files the copyright.py script told me to
    update, these files had copyright headers embedded within the
    file,

  - Regenerating gdbsupport/Makefile.in to refresh it's copyright
    date,

  - Using grep to find other files that still mentioned 2023.  If
    these files were updated last year from 2022 to 2023 then I've
    updated them this year to 2024.

I'm sure I've probably missed some dates.  Feel free to fix them up as
you spot them.
2024-01-12 15:49:57 +00:00

634 lines
18 KiB
Plaintext

# Copyright 1998-2024 Free Software Foundation, Inc.
# This file is part of the gdb testsuite
# 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/>.
# Tests for pointer-to-member support
# Written by Satish Pai <pai@apollo.hp.com> 1997-08-19
# Rewritten by Michael Chastain <mec.gnu@mindspring.com> 2004-01-11
set vhn "\\$\[0-9\]+"
require allow_cplus_tests
standard_testfile .cc
if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug c++}]} {
return -1
}
if {![runto_main]} {
return
}
gdb_breakpoint [gdb_get_line_number "Breakpoint 1 here"]
gdb_continue_to_breakpoint "continue to pmi = NULL"
# ======================
# pointer to member data
# ======================
# ptype on pointer to data member
set name "ptype pmi (A::j)"
gdb_test_multiple "ptype pmi" $name {
-re "type = int A::\\*\r\n$gdb_prompt $" {
pass $name
}
}
# print pointer to data member
set name "print pmi (A::j) "
gdb_test_multiple "print pmi" $name {
-re "$vhn = &A::j\r\n$gdb_prompt $" {
pass $name
}
-re "$vhn = \\(int ?\\( ?A::\\*\\)\\) &A::j\r\n$gdb_prompt $" {
pass $name
}
-re "$vhn = \\(int ?\\( ?A::\\*\\)\\) ?&A::j ?\\+ ?1 bytes\r\n$gdb_prompt $" {
# gcc 2.95.3 -gdwarf-2
kfail "gdb/NNNN" $name
}
-re "$vhn = &A::j ?\\+ ?1 bytes\r\n$gdb_prompt $" {
# gcc 2.95.3 -gstabs+
kfail "gdb/NNNN" $name
}
-re "$vhn = not implemented: member type in c_val_print\r\n$gdb_prompt $" {
# gcc HEAD 2004-01-11 05:33:21 -gdwarf-2
# gcc HEAD 2004-01-11 05:33:21 -gstabs+
kfail "gdb/NNNN" $name
}
}
# print dereferenced pointer to data member
set name "print a.*pmi (A::j)"
gdb_test_multiple "print a.*pmi" $name {
-re "$vhn = 121\r\n$gdb_prompt $" {
pass $name
}
-re "$vhn = 855638016\r\n$gdb_prompt $" {
# gcc 2.95.3 -gdwarf-2
# gcc 2.95.3 -gstabs+
kfail "gdb/NNNN" $name
}
-re "not implemented: member types in unpack_long\r\n$gdb_prompt $" {
# gcc HEAD 2004-01-10 -gdwarf-2
# gcc HEAD 2004-01-10 -gstabs+
kfail "gdb/NNNN" $name
}
}
# print dereferenced pointer to data member
# this time, dereferenced through a pointer
set name "print a_p->*pmi (A::j)"
gdb_test_multiple "print a_p->*pmi" $name {
-re "$vhn = 121\r\n$gdb_prompt $" {
pass $name
}
-re "$vhn = 855638016\r\n$gdb_prompt $" {
# gcc 2.95.3 -gdwarf-2
# gcc 2.95.3 -gstabs+
kfail "gdb/NNNN" $name
}
-re "not implemented: member types in unpack_long\r\n$gdb_prompt $" {
# gcc HEAD 2004-01-10 -gdwarf-2
# gcc HEAD 2004-01-10 -gstabs+
kfail "gdb/NNNN" $name
}
}
# set the pointer to a different data member
set name "set var pmi = &A::jj"
gdb_test_multiple "set var pmi = &A::jj" $name {
-re "Invalid cast.\r\n$gdb_prompt $" {
# gcc HEAD 2004-01-10 -gdwarf-2
# gcc HEAD 2004-01-10 -gstabs+
kfail "gdb/NNNN" $name
}
-re "set var pmi = &A::jj\r\n$gdb_prompt $" {
# I have to match the echo'ed input explicitly here.
# If I leave it out, the pattern becomes too general
# and matches anything that ends in "$gdb_prompt $".
pass $name
}
}
# print the pointer again
set name "print pmi (A::jj)"
gdb_test_multiple "print pmi" $name {
-re "$vhn = &A::jj\r\n$gdb_prompt $" {
pass $name
}
-re "$vhn = \\(int ?\\( ?A::\\*\\)\\) &A::jj\r\n$gdb_prompt $" {
pass $name
}
-re "$vhn = not implemented: member type in c_val_print\r\n$gdb_prompt $" {
# gcc HEAD 2004-01-11 05:33:21 -gdwarf-2
# gcc HEAD 2004-01-11 05:33:21 -gstabs+
kfail "gdb/NNNN" $name
}
}
# print dereferenced pointer to data member again
set name "print a.*pmi (A::jj)"
gdb_test_multiple "print a.*pmi" $name {
-re "$vhn = 1331\r\n$gdb_prompt $" {
pass $name
}
-re "not implemented: member types in unpack_long\r\n$gdb_prompt $" {
# gcc HEAD 2004-01-10 -gdwarf-2
# gcc HEAD 2004-01-10 -gstabs+
kfail "gdb/NNNN" $name
}
}
# set the pointer to data member back to A::j
set name "set var pmi = &A::j"
gdb_test_multiple "set var pmi = &A::j" $name {
-re "Invalid cast.\r\n$gdb_prompt $" {
# gcc HEAD 2004-01-10 -gdwarf-2
# gcc HEAD 2004-01-10 -gstabs+
kfail "gdb/NNNN" $name
}
-re "set var pmi = &A::j\r\n$gdb_prompt $" {
# I have to match the echo'ed input explicitly here.
# If I leave it out, the pattern becomes too general
# and matches anything that ends in "$gdb_prompt $".
pass $name
}
}
# print dereferenced pointer to data member yet again (extra check, why not)
set name "print a.*pmi (A::j) (again)"
gdb_test_multiple "print a.*pmi" $name {
-re "$vhn = 121\r\n$gdb_prompt $" {
pass $name
}
-re "not implemented: member types in unpack_long\r\n$gdb_prompt $" {
# gcc HEAD 2004-01-10 -gdwarf-2
# gcc HEAD 2004-01-10 -gstabs+
kfail "gdb/NNNN" $name
}
}
# Set the data member pointed to.
set name "print a.*pmi = 33"
gdb_test_multiple "print a.*pmi = 33" $name {
-re "$vhn = 33\r\n$gdb_prompt $" {
pass $name
}
-re "not implemented: member types in unpack_long\r\n$gdb_prompt $" {
# gcc HEAD 2004-01-10 -gdwarf-2
# gcc HEAD 2004-01-10 -gstabs+
kfail "gdb/NNNN" $name
}
}
# Now check that the data really was changed
set name "print a.*pmi (A::j) (33)"
gdb_test_multiple "print a.*pmi" $name {
-re "$vhn = 33\r\n$gdb_prompt $" {
pass $name
}
-re "not implemented: member types in unpack_long\r\n$gdb_prompt $" {
# gcc HEAD 2004-01-10 -gdwarf-2
# gcc HEAD 2004-01-10 -gstabs+
kfail "gdb/NNNN" $name
}
}
# Double-check by printing a.
set name "print a (j = 33)"
gdb_test_multiple "print a" $name {
-re "$vhn = \{c = 120 'x', j = 33, jj = 1331, (static|static int) s = 10, (_vptr.A|_vptr\\$) = ($hex|$hex <A virtual table>)\}\r\n$gdb_prompt $" {
pass $name
}
-re "$vhn = \{c = 120 'x', j = 33, jj = 1331, (static|static int) s = 10, Virtual table at $hex\}\r\n$gdb_prompt $" {
pass $name
}
-re "$vhn = \{(_vptr.A|_vptr\\$) = ${hex}( <vtable for A.*>)?, c = 120 'x', j = 33, jj = 1331, (static|static int) s = 10\}\r\n$gdb_prompt $" {
pass $name
}
-re "$vhn = \{(_vptr.A|_vptr\\$) = $hex, c = 120 'x', j = 121, jj = 1331, (static|static int) s = 10\}\r\n$gdb_prompt $" {
# gcc HEAD 2004-01-10 -gdwarf-2
# gcc HEAD 2004-01-10 -gstabs+
kfail "gdb/NNNN" $name
}
}
# Set the data member pointed to, using ->*
set name "print a_p->*pmi = 44"
gdb_test_multiple "print a_p->*pmi = 44" $name {
-re "$vhn = 44\r\n$gdb_prompt $" {
pass $name
}
-re "not implemented: member types in unpack_long\r\n$gdb_prompt $" {
# gcc HEAD 2004-01-10 -gdwarf-2
# gcc HEAD 2004-01-10 -gstabs+
kfail "gdb/NNNN" $name
}
}
# Check that the data really was changed
set name "print a_p->*pmi (44)"
gdb_test_multiple "print a_p->*pmi" $name {
-re "$vhn = 44\r\n$gdb_prompt $" {
pass $name
}
-re "not implemented: member types in unpack_long\r\n$gdb_prompt $" {
# gcc HEAD 2004-01-10 -gdwarf-2
# gcc HEAD 2004-01-10 -gstabs+
kfail "gdb/NNNN" $name
}
}
# Double-check by printing a.
set name "print a (j = 44)"
gdb_test_multiple "print a" $name {
-re "$vhn = \{c = 120 'x', j = 44, jj = 1331, (static|static int) s = 10, (_vptr.A|_vptr\\$) = ($hex|$hex <A virtual table>)\}\r\n$gdb_prompt $" {
pass $name
}
-re "$vhn = \{c = 120 'x', j = 44, jj = 1331, (static|static int) s = 10, Virtual table at $hex\}\r\n$gdb_prompt $" {
pass $name
}
-re "$vhn = \{(_vptr.A|_vptr\\$) = ${hex}( <vtable for A.*>), c = 120 'x', j = 44, jj = 1331, (static|static int) s = 10\}\r\n$gdb_prompt $" {
pass $name
}
-re "$vhn = \{(_vptr.A|_vptr\\$) = $hex, c = 120 'x', j = 121, jj = 1331, (static|static int) s = 10\}\r\n$gdb_prompt $" {
# gcc HEAD 2004-01-10 -gdwarf-2
# gcc HEAD 2004-01-10 -gstabs+
kfail "gdb/NNNN" $name
}
}
# ptype the dereferenced pointer to member.
set name "ptype a.*pmi"
gdb_test_multiple "ptype a.*pmi" $name {
-re "type = int\r\n$gdb_prompt" {
pass $name
}
-re "not implemented: member types in unpack_long\r\n$gdb_prompt $" {
# gcc HEAD 2004-01-10 -gdwarf-2
# gcc HEAD 2004-01-10 -gstabs+
kfail "gdb/NNNN" $name
}
}
# dereference the pointer to data member without any object
# this is not allowed: a pmi must be bound to an object to dereference
set name "print *pmi"
gdb_test_multiple "print *pmi" $name {
-re "Attempt to dereference pointer to member without an object\r\n$gdb_prompt $" {
pass $name
}
-re "Cannot access memory at address 0x4\r\n$gdb_prompt $" {
# gcc 2.95.3 -gstabs+
kfail "gdb/NNNN" $name
}
-re "Cannot access memory at address 0x8\r\n$gdb_prompt $" {
# gcc 3.3.2 -gdwarf-2
# gcc 3.3.2 -gstabs+
kfail "gdb/NNNN" $name
}
}
# dereference the pointer to data member without any object
# this is not allowed: a pmi must be bound to an object to dereference
set name "ptype *pmi"
gdb_test_multiple "ptype *pmi" $name {
-re "Attempt to dereference pointer to member without an object\r\n$gdb_prompt $" {
pass $name
}
-re "type = int A::\r\n$gdb_prompt $" {
# gcc 2.95.3 -gstabs+
# gcc HEAD 2004-01-10 -gdwarf-2
# gcc HEAD 2004-01-10 -gstabs+
kfail "gdb/NNNN" $name
}
}
# Check cast of pointer to member to integer.
# This is similar to "offset-of".
# such as "A a; print (size_t) &A.j - (size_t) &A".
set name "print (int) pmi"
gdb_test_multiple "print (int) pmi" $name {
-re "$vhn = (4|8|12)\r\n$gdb_prompt" {
pass $name
}
}
# Check "(int) pmi" explicitly for equality.
set name "print ((int) pmi) == ((char *) &a.j - (char *) &a)"
gdb_test_multiple "print ((int) pmi) == ((char *) &a.j - (char *) & a)" $name {
-re "$vhn = true\r\n$gdb_prompt" {
pass $name
}
}
# Check pointers to data members, which are themselves pointers to
# functions. These behave like data members, not like pointers to
# member functions.
gdb_test "ptype diamond_pfunc_ptr" \
"type = int \\(\\*Diamond::\\*\\)\\(int\\)"
gdb_test "ptype diamond.*diamond_pfunc_ptr" \
"type = int \\(\\*\\)\\(int\\)"
# This one is invalid; () binds more tightly than .*, so it tries to
# call the member pointer as a normal pointer-to-function.
gdb_test "print diamond.*diamond_pfunc_ptr (20)" \
"Invalid data type for function to be called."
# With parentheses, it is valid.
gdb_test "print (diamond.*diamond_pfunc_ptr) (20)" \
"$vhn = 39"
# Make sure that we do not interpret this as either a member pointer
# call or a member function call.
gdb_test "print diamond.func_ptr (20)" \
"$vhn = 39"
# ==========================
# pointer to member function
# ==========================
# ptype a pointer to a method
set name "ptype pmf"
gdb_test_multiple "ptype pmf" $name {
-re "type = int \\( ?A::\\*\\)\\(A \\*( const)?, int\\)\r\n$gdb_prompt $" {
pass $name
}
-re "type = struct \{.*\}\r\n$gdb_prompt $" {
# gcc 2.95.3 -gdwarf-2
# gcc 2.95.3 -gstabs+
# gcc 3.2.2 -gdwarf-2
# gcc 3.2.2 -gstabs+
# gcc HEAD 2004-01-10 -gdwarf-2
# gcc HEAD 2004-01-10 -gstabs+
kfail "gdb/NNNN" $name
}
}
# print a pointer to a method
set name "print pmf"
gdb_test_multiple "print pmf" $name {
-re "$vhn = \\(int \\(A::\\*\\)\\(A \\*( const)?, int\\)\\) $hex <A::bar\\(int\\)>\r\n$gdb_prompt $" {
pass $name
}
-re "$vhn = \{.*\}\r\n$gdb_prompt $" {
# gcc 2.95.3 -gdwarf-2
# gcc 2.95.3 -gstabs+
# gcc 3.2.2 -gdwarf-2
# gcc 3.2.2 -gstabs+
# gcc HEAD 2004-01-10 -gdwarf-2
# gcc HEAD 2004-01-10 -gstabs+
kfail "gdb/NNNN" $name
}
}
# ptype a pointer to a pointer to a method
set name "ptype pmf_p"
gdb_test_multiple "ptype pmf_p" $name {
-re "type = int \\( ?A::\\*\\*\\)\\(A \\*( const)?, int\\)\r\n$gdb_prompt $" {
pass $name
}
-re "type = struct \{.*\} \\*\r\n$gdb_prompt $" {
# gcc 2.95.3 -gdwarf-2
# gcc 2.95.3 -gstabs+
# gcc 3.2.2 -gdwarf-2
# gcc 3.2.2 -gstabs+
# gcc HEAD 2004-01-10 -gdwarf-2
# gcc HEAD 2004-01-10 -gstabs+
kfail "gdb/NNNN" $name
}
}
# print a pointer to a pointer to a method
set name "print pmf_p"
gdb_test_multiple "print pmf_p" $name {
-re "$vhn = \\(int \\( ?A::\\*\\*\\)\\)\\(int\\)\\) $hex\r\n$gdb_prompt $" {
pass $name
}
-re "$vhn = \\(PMF \\*\\) $hex\r\n$gdb_prompt $" {
pass "gdb/NNNN"
}
-re "$vhn = \\(struct \{.*\} \\*\\) $hex\r\n$gdb_prompt $" {
# gcc 2.95.3 -gdwarf-2
kfail "gdb/NNNN" $name
}
}
# print dereferenced pointer to method
set name "print a.*pmf"
gdb_test_multiple "print a.*pmf" $name {
-re "$vhn = {int \\(A \\*( const)?, int\\)} $hex <A::bar\\(int\\)>\r\n$gdb_prompt $" {
pass $name
}
-re "Value can't be converted to integer.\r\n$gdb_prompt $" {
# gcc 2.95.3 -gdwarf-2
# gcc 2.95.3 -gstabs+
# gcc 3.2.2 -gdwarf-2
# gcc 3.2.2 -gstabs+
# gcc HEAD 2004-01-10 -gdwarf-2
# gcc HEAD 2004-01-10 -gstabs+
kfail "gdb/NNNN" $name
}
}
# print dereferenced pointer to method, using ->*
set name "print a_p->*pmf"
gdb_test_multiple "print a_p->*pmf" $name {
-re "$vhn = {int \\(A \\*( const)?, int\\)} $hex <A::bar\\(int\\)>\r\n$gdb_prompt $" {
pass $name
}
-re "Value can't be converted to integer.\r\n$gdb_prompt $" {
# gcc 2.95.3 -gdwarf-2
# gcc 2.95.3 -gstabs+
# gcc 3.2.2 -gdwarf-2
# gcc 3.2.2 -gstabs+
# gcc HEAD 2004-01-10 -gdwarf-2
# gcc HEAD 2004-01-10 -gstabs+
kfail "gdb/NNNN" $name
}
}
# set the pointer to data member
set name "set var pmf = &A::foo"
gdb_test_multiple "set var pmf = &A::foo" $name {
-re "set var pmf = &A::foo\r\n$gdb_prompt $" {
# I have to match the echo'ed input explicitly here.
# If I leave it out, the pattern becomes too general
# and matches anything that ends in "$gdb_prompt $".
pass $name
}
-re "Invalid cast.\r\n$gdb_prompt $" {
# gcc 2.95.3 -gdwarf-2
# gcc 2.95.3 -gstabs+
# gcc 3.2.2 -gdwarf-2
# gcc 3.2.2 -gstabs+
# gcc HEAD 2004-01-10 -gdwarf-2
# gcc HEAD 2004-01-10 -gstabs+
kfail "gdb/NNNN" $name
}
}
# dereference the pointer to data member without any object
# this is not allowed: a pmf must be bound to an object to dereference
set name "print *pmf"
gdb_test_multiple "print *pmf" $name {
-re "Attempt to dereference pointer to member without an object\r\n$gdb_prompt $" {
pass $name
}
-re "Structure has no component named operator\\*.\r\n$gdb_prompt $" {
# gcc 2.95.3 -gdwarf-2
# gcc 2.95.3 -gstabs+
# gcc 3.3.2 -gdwarf-2
# gcc 3.3.2 -gstabs+
# gcc HEAD 2004-01-10 -gdwarf-2
# gcc HEAD 2004-01-10 -gstabs+
kfail "gdb/NNNN" $name
}
}
# dereference the pointer to data member without any object
# this is not allowed: a pmf must be bound to an object to dereference
set name "ptype *pmf"
gdb_test_multiple "ptype *pmf" $name {
-re "Attempt to dereference pointer to member without an object\r\n$gdb_prompt $" {
pass $name
}
-re "Structure has no component named operator\\*.\r\n$gdb_prompt $" {
# gcc 2.95.3 -gdwarf-2
# gcc 2.95.3 -gstabs+
# gcc 3.3.2 -gdwarf-2
# gcc 3.3.2 -gstabs+
# gcc HEAD 2004-01-10 -gdwarf-2
# gcc HEAD 2004-01-10 -gstabs+
kfail "gdb/NNNN" $name
}
}
# Call a function through a pmf.
set name "print (a.*pmf)(3)"
gdb_test_multiple "print (a.*pmf)(3)" $name {
-re "$vhn = 50\r\n$gdb_prompt $" {
pass $name
}
-re "Value can't be converted to integer.\r\n$gdb_prompt $" {
# gcc 2.95.3 -gdwarf-2
# gcc 2.95.3 -gstabs+
# gcc 3.3.2 -gdwarf-2
# gcc 3.3.2 -gstabs+
# gcc HEAD 2004-01-10 -gdwarf-2
# gcc HEAD 2004-01-10 -gstabs+
kfail "gdb/NNNN" $name
}
}
gdb_test "ptype a.*pmf" "type = int \\(A \\*( const)?, int\\)"
gdb_test "ptype (a.*pmf)(3)" "type = int"
# Print out a pointer to data member which requires looking into
# a base class.
gdb_test "print diamond_pmi" "$vhn = &Base::x"
gdb_test "print diamond.*diamond_pmi" "$vhn = 77"
# Examine some more complicated pmfs, which require adjusting "this"
# and looking through virtual tables.
# These two have a different object adjustment, but call the same method.
gdb_test "print diamond.*left_pmf" \
"$vhn = {int \\(Diamond \\*( const)?\\)} $hex <Base::get_x\\((void|)\\)>"
gdb_test "print diamond.*right_pmf" \
"$vhn = {int \\(Diamond \\*( const)?\\)} $hex <Base::get_x\\((void|)\\)>"
gdb_test "print (diamond.*left_pmf) ()" "$vhn = 77"
gdb_test "print (diamond.*right_pmf) ()" "$vhn = 88"
# These two point to different methods, although they have the same
# virtual table offsets.
gdb_test "print diamond.*left_vpmf" \
"$vhn = {int \\(Diamond \\*( const)?\\)} $hex <Left::vget\\((void|)\\)>"
gdb_test "print diamond.*right_vpmf" \
"$vhn = {int \\(Diamond \\*( const)?\\)} $hex <Right::vget\\((void|)\\)>"
gdb_test "print (diamond.*left_vpmf) ()" "$vhn = 177"
gdb_test "print (diamond.*left_base_vpmf) ()" "$vhn = 2077"
gdb_test "print (diamond.*right_vpmf) ()" "$vhn = 288"
# We should be able to figure out left_vpmf even without an object,
# because it comes from a non-virtual base. The same for right_vpmf.
gdb_test "print left_vpmf" "$vhn = &virtual Left::vget\\(\\)"
gdb_test "print right_vpmf" "$vhn = &virtual Right::vget\\(\\)"
# But we should gracefully fail to figure out base_vpmf, because
# its runtime type is more derived than its static type. This
# is a valid but unspecified cast (it is value preserving, i.e.
# can be casted back to the correct type and used).
gdb_test "print base_vpmf" \
"$vhn = &virtual table offset \[0-9\]*, this adjustment -\[0-9\]*"
# Make sure we parse this correctly; it's invalid.
gdb_test "print diamond.*left_vpmf ()" \
"Invalid data type for function to be called\\."
# NULL pointer to member tests.
gdb_test "print null_pmi" "$vhn = NULL"
gdb_test "print null_pmi = &A::j" "$vhn = &A::j"
gdb_test "print null_pmi = 0" "$vhn = NULL"
gdb_test "print null_pmf" "$vhn = NULL"
gdb_test "print null_pmf = &A::foo" "$vhn = \\(int \\(A::\\*\\)\\(A \\*( const)?, int\\)\\) $hex <A::foo ?\\(int\\)>"
gdb_test "print null_pmf = 0" "$vhn = NULL"
# Print with a format, bypassing the direct call to the scalar
# printer. See PR c++/29243.
gdb_test "print/x contain" " = {member = $hex}"