| # Copyright (C) 1998 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 2 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, write to the Free Software |
| # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| |
| # Please email any bugs, comments, and/or additions to this file to: |
| # bug-gdb@prep.ai.mit.edu |
| # Tests for pointer-to-member support |
| # Written by Satish Pai <pai@apollo.hp.com> 1997-08-19 |
| |
| # This file is part of the gdb testsuite |
| |
| |
| if $tracelevel then { |
| strace $tracelevel |
| } |
| |
| # |
| # test running programs |
| # |
| |
| # Start with a fresh gdb |
| gdb_exit |
| gdb_start |
| gdb_reinitialize_dir $srcdir/$subdir |
| |
| set prms_id 0 |
| set bug_id 0 |
| |
| set testfile "member-ptr" |
| set srcfile ${testfile}.cc |
| set binfile ${objdir}/${subdir}/${testfile} |
| |
| # Create and source the file that provides information about the compiler |
| # used to compile the test case. |
| |
| if [get_compiler_info ${binfile} "c++"] { |
| return -1 |
| } |
| |
| # Nearly all of these tests fail when compiled with G++, so just give up |
| # until GDB gets enhanced. -sts 1999-06-22 |
| |
| if {$gcc_compiled} { |
| continue |
| } |
| |
| if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { |
| gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." |
| } |
| |
| |
| gdb_exit |
| gdb_start |
| gdb_reinitialize_dir $srcdir/$subdir |
| gdb_load ${binfile} |
| |
| |
| if ![runto_main] then { |
| perror "couldn't run to breakpoint" |
| continue |
| } |
| |
| send_gdb "break 83\n" |
| gdb_expect { |
| -re "Breakpoint \[0-9\]*.*line 83\\.\r\n$gdb_prompt $" { |
| pass "set break at 83" |
| } |
| -re ".*$gdb_prompt $" { fail "set break at 83" } |
| timeout { fail "(timeout) set break at 83" } |
| } |
| |
| send_gdb "continue\n" |
| gdb_expect { |
| -re "Continuing\\.\r\n\r\nBreakpoint.*at.*member-ptr\\.cc:83\r\n83\[ \t]*pmi = NULL;\r\n$gdb_prompt $" { |
| pass "continue to 83" |
| } |
| -re ".*$gdb_prompt $" { fail "continue to 83" } |
| timeout { fail "(timeout) continue to 83" } |
| } |
| |
| # ptype on pointer to data member |
| |
| send_gdb "ptype pmi\n" |
| gdb_expect { |
| -re "type = int \\( A::\\*\\)\r\n$gdb_prompt $" { |
| pass "ptype pmi" |
| } |
| -re ".*$gdb_prompt $" { fail "ptype pmi" } |
| timeout { fail "(timeout) ptype pmi" } |
| } |
| |
| # print pointer to data member |
| |
| send_gdb "print pmi\n" |
| gdb_expect { |
| -re "\\$\[0-9\]* = \\(int \\( A::\\*\\)\\) &A::j\r\n$gdb_prompt $" { |
| pass "print pmi" |
| } |
| -re ".*$gdb_prompt $" { fail "print pmi" } |
| timeout { fail "(timeout) print pmi" } |
| } |
| |
| |
| # print dereferenced pointer to data member |
| |
| send_gdb "print a.*pmi\n" |
| gdb_expect { |
| -re "\\$\[0-9\]* = 121\r\n$gdb_prompt $" { |
| pass "print a.*pmi" |
| } |
| -re ".*$gdb_prompt $" { fail "print a.*pmi" } |
| timeout { fail "(timeout) print a.*pmi" } |
| } |
| |
| # print dereferenced pointer to data member |
| # this time, dereferenced through a pointer |
| |
| send_gdb "print a_p->*pmi\n" |
| gdb_expect { |
| -re "\\$\[0-9\]* = 121\r\n$gdb_prompt $" { |
| pass "print a->*pmi" |
| } |
| -re ".*$gdb_prompt $" { fail "print a->*pmi" } |
| timeout { fail "(timeout) print a->*pmi" } |
| } |
| |
| |
| # set the pointer to data member |
| |
| send_gdb "set var pmi = &A::jj\n" |
| gdb_expect { |
| -re "$gdb_prompt $" { |
| pass "set var (not really a pass)" |
| } |
| timeout { fail "(timeout) " } |
| } |
| |
| # Now print the pointer again |
| |
| send_gdb "print pmi\n" |
| gdb_expect { |
| -re "\\$\[0-9\]* = \\(int \\( A::\\*\\)\\) &A::jj\r\n$gdb_prompt $" { |
| pass "print pmi after setting" |
| } |
| -re ".*$gdb_prompt $" { fail "print pmi after setting" } |
| timeout { fail "(timeout) print pmi after setting" } |
| } |
| |
| # print dereferenced pointer to data member again |
| |
| send_gdb "print a.*pmi\n" |
| gdb_expect { |
| -re "\\$\[0-9\]* = 1331\r\n$gdb_prompt $" { |
| pass "print a.*pmi after setting" |
| } |
| -re ".*$gdb_prompt $" { fail "print a.*pmi after setting" } |
| timeout { fail "(timeout) print a.*pmi after setting" } |
| } |
| |
| # set the pointer to data member back to A::j |
| |
| send_gdb "set var pmi = &A::j\n" |
| gdb_expect { |
| -re "$gdb_prompt $" { |
| pass "set var back to A::j (not really a pass)" |
| } |
| timeout { fail "(timeout) set var pmi" } |
| } |
| |
| # print dereferenced pointer to data member yet again (extra check, why not) |
| |
| send_gdb "print a.*pmi\n" |
| gdb_expect { |
| -re "\\$\[0-9\]* = 121\r\n$gdb_prompt $" { |
| pass "print a.*pmi after resetting" |
| } |
| -re ".*$gdb_prompt $" { fail "print a.*pmi after resetting" } |
| timeout { fail "(timeout) print a.*pmi after resetting" } |
| } |
| |
| # Set the data member pointed to. |
| |
| send_gdb "print a.*pmi = 33\n" |
| gdb_expect { |
| -re "\\$\[0-9\]* = 33\r\n$gdb_prompt $" { |
| pass "print command to set" |
| } |
| -re ".*$gdb_prompt $" { fail "print command to set" } |
| timeout { fail "(timeout) print command to set" } |
| } |
| |
| # Now check that the data really was changed |
| send_gdb "print a.*pmi\n" |
| gdb_expect { |
| -re "\\$\[0-9\]* = 33\r\n$gdb_prompt $" { |
| pass "print a.*pmi after setting member pointed to" |
| } |
| -re ".*$gdb_prompt $" { fail "print a.*pmi after setting member pointed to" } |
| timeout { fail "(timeout) print a.*pmi after setting member pointed to" } |
| } |
| |
| # Double-check by printing a. |
| send_gdb "print a\n" |
| gdb_expect { |
| -re "\\$\[0-9\]* = \{c = 120 'x', j = 33, jj = 1331, static s = 10, Virtual table at $hex\}\r\n$gdb_prompt $" { |
| pass "print a after setting member pointed to by pmi" |
| } |
| -re ".*$gdb_prompt $" { fail "print a after setting member pointed to by pmi" } |
| timeout { fail "(timeout) print a after setting member pointed to by pmi" } |
| } |
| |
| |
| # Set the data member pointed to, using ->* |
| |
| send_gdb "print a_p->*pmi = 44\n" |
| gdb_expect { |
| -re "\\$\[0-9\]* = 44\r\n$gdb_prompt $" { |
| pass "print command to set (->)" |
| } |
| -re ".*$gdb_prompt $" { fail "print command to set (->)" } |
| timeout { fail "(timeout) print command to set (->)" } |
| } |
| |
| # Now check that the data really was changed |
| send_gdb "print a_p->*pmi\n" |
| gdb_expect { |
| -re "\\$\[0-9\]* = 44\r\n$gdb_prompt $" { |
| pass "print a_p->*pmi after setting member pointed to" |
| } |
| -re ".*$gdb_prompt $" { fail "print a_p->*pmi after setting member pointed to" } |
| timeout { fail "(timeout) print a_p->*pmi after setting member pointed to" } |
| } |
| |
| # Double-check by printing a. |
| send_gdb "print a\n" |
| gdb_expect { |
| -re "\\$\[0-9\]* = \{c = 120 'x', j = 44, jj = 1331, static s = 10, Virtual table at $hex\}\r\n$gdb_prompt $" { |
| pass "print a after setting member pointed to by pmi (->) " |
| } |
| -re ".*$gdb_prompt $" { fail "print a after setting member pointed to by pmi (->) " } |
| timeout { fail "(timeout) print a after setting member pointed to by pmi (->) " } |
| } |
| |
| |
| # Do a ptype on the dereferenced pointer to member |
| # pai/1997-08-20 Doesn't work |
| |
| # send_gdb "ptype a.*pmi\n" |
| # gdb_expect { |
| # -re "type = int\r\n$gdb_prompt $" { |
| # pass "ptype a.*pmi" |
| # } |
| # -re ".*$gdb_prompt $" { fail "ptype a.*pmi" } |
| # timeout { fail "(timeout) ptype a.*pmi" } |
| #} |
| |
| # Try to dereference the pointer to data member without any object |
| |
| send_gdb "print *pmi\n" |
| gdb_expect { |
| -re "Attempt to dereference pointer to member without an object\r\n$gdb_prompt $" { |
| pass "attempt to print ptr to member without object" |
| } |
| -re ".*$gdb_prompt $" { fail "attempt to print ptr to member without object" } |
| timeout { fail "(timeout) attempt to print ptr to member without object" } |
| } |
| |
| # Try to ptype a dereference of the pointer to data member without any object |
| |
| send_gdb "ptype *pmi\n" |
| gdb_expect { |
| -re "Attempt to dereference pointer to member without an object\r\n$gdb_prompt $" { |
| pass "attempt to ptype ptr to member without object" |
| } |
| -re ".*$gdb_prompt $" { fail "attempt to ptype ptr to member without object" } |
| timeout { fail "(timeout) attempt to ptype ptr to member without object" } |
| } |
| |
| # Ptype a pointer to a method. |
| |
| send_gdb "ptype pmf\n" |
| gdb_expect { |
| -re "type = int \\( A::\\*\\)\\(\\.\\.\\.\\)\r\n$gdb_prompt $" { |
| pass "ptype pmf" |
| } |
| -re ".*$gdb_prompt $" { fail "ptype pmf" } |
| timeout { fail "(timeout) ptype pmf" } |
| } |
| |
| # print a pointer to a method |
| |
| send_gdb "print pmf\n" |
| gdb_expect { |
| -re "\\$\[0-9\]* = \\(int \\( A::\\*\\)\\(\\.\\.\\.\\)\\) \\?\\? <not supported with HP aCC>\r\n$gdb_prompt $" { |
| pass "print pmf" |
| } |
| -re ".*$gdb_prompt $" { fail "print pmf" } |
| timeout { fail "(timeout) print pmf" } |
| } |
| |
| |
| # Ptype a pointer to a pointer to a method |
| |
| send_gdb "ptype pmf_p\n" |
| gdb_expect { |
| -re "type = int \\( A::\\*\\*\\)\\(\\.\\.\\.\\)\r\n$gdb_prompt $" { |
| pass "ptype pmf_p" |
| } |
| -re ".*$gdb_prompt $" { fail "ptype pmf_p" } |
| timeout { fail "(timeout) ptype pmf_p" } |
| } |
| |
| # print a pointer to a pointer to a method |
| |
| send_gdb "print pmf_p\n" |
| gdb_expect { |
| -re "\\$\[0-9\]* = \\(int \\( A::\\*\\*\\)\\(\\.\\.\\.\\)\\) $hex\r\n$gdb_prompt $" { |
| pass "print pmf_p" |
| } |
| -re ".*$gdb_prompt $" { fail "print pmf_p" } |
| timeout { fail "(timeout) print pmf_p" } |
| } |
| |
| # print dereferenced pointer to method |
| |
| send_gdb "print a.*pmf\n" |
| gdb_expect { |
| -re "Pointers to methods not supported with HP aCC\r\n$gdb_prompt $" { |
| pass "print a.*pmf (known aCC limitation)" |
| } |
| -re ".*$gdb_prompt $" { fail "print a.*pmf -- ??" } |
| timeout { fail "(timeout) print a.*pmf" } |
| } |
| |
| # print dereferenced pointer to method, using ->* |
| |
| send_gdb "print a_p->*pmf\n" |
| gdb_expect { |
| -re "Pointers to methods not supported with HP aCC\r\n$gdb_prompt $" { |
| pass "print a_p->*pmf (known aCC limitation)" |
| } |
| -re ".*$gdb_prompt $" { fail "print a_p->*pmf -- ??" } |
| timeout { fail "(timeout) print a_p->*pmf" } |
| } |
| |
| # set the pointer to data member |
| |
| send_gdb "set var pmf = &A::foo\n" |
| gdb_expect { |
| -re "Assignment to pointers to methods not implemented with HP aCC\r\n$gdb_prompt $" { |
| pass "set var pmf (known aCC limitation)" |
| } |
| -re ".*$gdb_prompt $" { fail "set var pmf -- ??" } |
| timeout { fail "(timeout) set var pmf" } |
| } |
| |
| # Try to dereference the pointer to method without any object |
| |
| send_gdb "print *pmf\n" |
| gdb_expect { |
| -re "Attempt to dereference pointer to member without an object\r\n$gdb_prompt $" { |
| pass "attempt to print ptr to method without object" |
| } |
| -re ".*$gdb_prompt $" { fail "attempt to print ptr to method without object" } |
| timeout { fail "(timeout) attempt to print ptr to method without object" } |
| } |
| |
| # Try to ptype a dereference of the pointer to method without any object |
| |
| send_gdb "ptype *pmi\n" |
| gdb_expect { |
| -re "Attempt to dereference pointer to member without an object\r\n$gdb_prompt $" { |
| pass "attempt to ptype ptr to member without object" |
| } |
| -re ".*$gdb_prompt $" { fail "attempt to ptype ptr to member without object" } |
| timeout { fail "(timeout) attempt to ptype ptr to member without object" } |
| } |
| |
| # Check cast of pointer to member to integer |
| send_gdb "print (int) pmi\n" |
| gdb_expect { |
| -re "\\$\[0-9\]* = 8\r\n$gdb_prompt $" { |
| pass "casting pmi to int" |
| } |
| -re ".*$gdb_prompt $" { fail "casting pmi to int" } |
| timeout { fail "(timeout) casting pmi to int" } |
| } |
| |
| # Check cast of pointer to method to integer |
| send_gdb "print (int) pmf\n" |
| gdb_expect { |
| -re "Pointers to methods not supported with HP aCC\r\n$gdb_prompt $" { |
| pass "casting pmf to int (known aCC limitation)" |
| } |
| -re ".*$gdb_prompt $" { fail "casting pmf to int -- ??" } |
| timeout { fail "(timeout) casting pmf to int" } |
| } |
| |
| # Try to invoke a function through a pointer to data member |
| send_gdb "print (a.*pmi)(3)\n" |
| gdb_expect { |
| -re "Not implemented: function invocation through pointer to method with HP aCC\r\n$gdb_prompt $" { |
| pass "print (a.*pmi)(3) -- error message should be different" |
| } |
| -re ".*$gdb_prompt $" { fail "print (a.*pmi)(3) -- ???" } |
| timeout { fail "(timeout) print (a.*pmi)(3)" } |
| } |
| |
| # Try to invoke a function through a pointer to a method |
| send_gdb "print (a.*pmf)(3)\n" |
| gdb_expect { |
| -re "Not implemented: function invocation through pointer to method with HP aCC\r\n$gdb_prompt $" { |
| pass "print (a.*pmi)(3) -- known aCC limitation" |
| } |
| -re ".*$gdb_prompt $" { fail "print (a.*pmf)(3) -- ???" } |
| timeout { fail "(timeout) print (a.*pmf)(3)" } |
| } |
| |
| |
| # Go past assignment of NULL to pmi |
| send_gdb "next\n" |
| gdb_expect { |
| -re "\r\n85\[ \t\]*k = \\(a.\\*pmf\\)\\(3\\);\r\n$gdb_prompt $" { |
| pass "next past 83" |
| } |
| -re ".*$gdb_prompt $" { fail "next past 83" } |
| timeout { fail "(timeout) next past 83" } |
| } |
| |
| #send_gdb "print pmi\n" |
| #gdb_expect { |
| # -re "Attempted dereference of null pointer-to-member\r\n$gdb_prompt $" { |
| # pass "" |
| # } |
| # -re ".*$gdb_prompt $" { fail "" } |
| # timeout { fail "(timeout) " } |
| #} |
| |
| # Dereference the null pointer to member |
| send_gdb "print a.*pmi\n" |
| gdb_expect { |
| -re "Attempted dereference of null pointer-to-member\r\n$gdb_prompt $" { |
| pass "print a.*NULL" |
| } |
| -re ".*$gdb_prompt $" { fail "print a.*NULL" } |
| timeout { fail "(timeout) print a.*NULL" } |
| } |
| |
| |
| # Go to another part of the program |
| send_gdb "break 91\n" |
| gdb_expect { |
| -re "Breakpoint \[0-9\]*.*line 91\\.\r\n$gdb_prompt $" { |
| pass "set break at 91" |
| } |
| -re ".*$gdb_prompt $" { fail "set break at 91" } |
| timeout { fail "(timeout) set break at 91" } |
| } |
| |
| send_gdb "continue\n" |
| gdb_expect { |
| -re "Continuing\\.\r\n\r\nBreakpoint.*at.*member-ptr\\.cc:91\r\n91\[ \t]*k = \\(a.\\*pmf\\)\\(4\\);\r\n$gdb_prompt $" { |
| pass "continue to 91" |
| } |
| -re ".*$gdb_prompt $" { fail "continue to 91" } |
| timeout { fail "(timeout) continue to 91" } |
| } |
| |
| |
| # Now check again that pmi works even when not set to |
| # something that's at the beginning of the object |
| |
| send_gdb "print pmi\n" |
| gdb_expect { |
| -re "\\$\[0-9\]* = \\(int \\( A::\\*\\)\\) &A::jj\r\n$gdb_prompt $" { |
| pass "print pmi (2)" |
| } |
| -re ".*$gdb_prompt $" { fail "print pmi (2)" } |
| timeout { fail "(timeout) print pmi (2)" } |
| } |
| |
| |
| # print dereferenced pointer to data member |
| |
| send_gdb "print a.*pmi\n" |
| gdb_expect { |
| -re "\\$\[0-9\]* = 1331\r\n$gdb_prompt $" { |
| pass "print a.*pmi (2)" |
| } |
| -re ".*$gdb_prompt $" { fail "print a.*pmi (2)" } |
| timeout { fail "(timeout) print a.*pmi (2)" } |
| } |
| |
| # print dereferenced pointer to data member |
| # this time, dereferenced through a pointer |
| |
| send_gdb "print a_p->*pmi\n" |
| gdb_expect { |
| -re "\\$\[0-9\]* = 1331\r\n$gdb_prompt $" { |
| pass "print a->*pmi" |
| } |
| -re ".*$gdb_prompt $" { fail "print a->*pmi (2)" } |
| timeout { fail "(timeout) print a->*pmi (2)" } |
| } |
| |
| |
| # p a.*pmf - fail |
| |
| # p pmi |
| |
| # p a.*pmi |
| |