1 # Copyright 1998-2024 Free Software Foundation, Inc.
3 # This file is part of the gdb testsuite
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 # Tests for pointer-to-member support
19 # Written by Satish Pai <pai@apollo.hp.com> 1997-08-19
20 # Rewritten by Michael Chastain <mec.gnu@mindspring.com> 2004-01-11
24 require allow_cplus_tests
29 if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug c++}]} {
37 gdb_breakpoint [gdb_get_line_number "Breakpoint 1 here"]
38 gdb_continue_to_breakpoint "continue to pmi = NULL"
40 # ======================
41 # pointer to member data
42 # ======================
44 # ptype on pointer to data member
46 set name "ptype pmi, A::j"
47 gdb_test_multiple "ptype pmi" $name {
48 -re "type = int A::\\*\r\n$gdb_prompt $" {
53 # print pointer to data member
55 set name "print pmi, A::j"
56 gdb_test_multiple "print pmi" $name {
57 -re "$vhn = &A::j\r\n$gdb_prompt $" {
60 -re "$vhn = \\(int ?\\( ?A::\\*\\)\\) &A::j\r\n$gdb_prompt $" {
63 -re "$vhn = \\(int ?\\( ?A::\\*\\)\\) ?&A::j ?\\+ ?1 bytes\r\n$gdb_prompt $" {
64 # gcc 2.95.3 -gdwarf-2
65 kfail "gdb/NNNN" $name
67 -re "$vhn = &A::j ?\\+ ?1 bytes\r\n$gdb_prompt $" {
69 kfail "gdb/NNNN" $name
71 -re "$vhn = not implemented: member type in c_val_print\r\n$gdb_prompt $" {
72 # gcc HEAD 2004-01-11 05:33:21 -gdwarf-2
73 # gcc HEAD 2004-01-11 05:33:21 -gstabs+
74 kfail "gdb/NNNN" $name
78 # print dereferenced pointer to data member
80 set name "print a.*pmi, A::j"
81 gdb_test_multiple "print a.*pmi" $name {
82 -re "$vhn = 121\r\n$gdb_prompt $" {
85 -re "$vhn = 855638016\r\n$gdb_prompt $" {
86 # gcc 2.95.3 -gdwarf-2
88 kfail "gdb/NNNN" $name
90 -re "not implemented: member types in unpack_long\r\n$gdb_prompt $" {
91 # gcc HEAD 2004-01-10 -gdwarf-2
92 # gcc HEAD 2004-01-10 -gstabs+
93 kfail "gdb/NNNN" $name
97 # print dereferenced pointer to data member
98 # this time, dereferenced through a pointer
100 set name "print a_p->*pmi, A::j"
101 gdb_test_multiple "print a_p->*pmi" $name {
102 -re "$vhn = 121\r\n$gdb_prompt $" {
105 -re "$vhn = 855638016\r\n$gdb_prompt $" {
106 # gcc 2.95.3 -gdwarf-2
107 # gcc 2.95.3 -gstabs+
108 kfail "gdb/NNNN" $name
110 -re "not implemented: member types in unpack_long\r\n$gdb_prompt $" {
111 # gcc HEAD 2004-01-10 -gdwarf-2
112 # gcc HEAD 2004-01-10 -gstabs+
113 kfail "gdb/NNNN" $name
117 # set the pointer to a different data member
119 set name "set var pmi = &A::jj"
120 gdb_test_multiple "set var pmi = &A::jj" $name {
121 -re "Invalid cast.\r\n$gdb_prompt $" {
122 # gcc HEAD 2004-01-10 -gdwarf-2
123 # gcc HEAD 2004-01-10 -gstabs+
124 kfail "gdb/NNNN" $name
126 -re "set var pmi = &A::jj\r\n$gdb_prompt $" {
127 # I have to match the echo'ed input explicitly here.
128 # If I leave it out, the pattern becomes too general
129 # and matches anything that ends in "$gdb_prompt $".
134 # print the pointer again
136 set name "print pmi, A::jj"
137 gdb_test_multiple "print pmi" $name {
138 -re "$vhn = &A::jj\r\n$gdb_prompt $" {
141 -re "$vhn = \\(int ?\\( ?A::\\*\\)\\) &A::jj\r\n$gdb_prompt $" {
144 -re "$vhn = not implemented: member type in c_val_print\r\n$gdb_prompt $" {
145 # gcc HEAD 2004-01-11 05:33:21 -gdwarf-2
146 # gcc HEAD 2004-01-11 05:33:21 -gstabs+
147 kfail "gdb/NNNN" $name
151 # print dereferenced pointer to data member again
153 set name "print a.*pmi, A::jj"
154 gdb_test_multiple "print a.*pmi" $name {
155 -re "$vhn = 1331\r\n$gdb_prompt $" {
158 -re "not implemented: member types in unpack_long\r\n$gdb_prompt $" {
159 # gcc HEAD 2004-01-10 -gdwarf-2
160 # gcc HEAD 2004-01-10 -gstabs+
161 kfail "gdb/NNNN" $name
165 # set the pointer to data member back to A::j
167 set name "set var pmi = &A::j"
168 gdb_test_multiple "set var pmi = &A::j" $name {
169 -re "Invalid cast.\r\n$gdb_prompt $" {
170 # gcc HEAD 2004-01-10 -gdwarf-2
171 # gcc HEAD 2004-01-10 -gstabs+
172 kfail "gdb/NNNN" $name
174 -re "set var pmi = &A::j\r\n$gdb_prompt $" {
175 # I have to match the echo'ed input explicitly here.
176 # If I leave it out, the pattern becomes too general
177 # and matches anything that ends in "$gdb_prompt $".
182 # print dereferenced pointer to data member yet again (extra check, why not)
184 set name "print a.*pmi, A::j, again"
185 gdb_test_multiple "print a.*pmi" $name {
186 -re "$vhn = 121\r\n$gdb_prompt $" {
189 -re "not implemented: member types in unpack_long\r\n$gdb_prompt $" {
190 # gcc HEAD 2004-01-10 -gdwarf-2
191 # gcc HEAD 2004-01-10 -gstabs+
192 kfail "gdb/NNNN" $name
196 # Set the data member pointed to.
198 set name "print a.*pmi = 33"
199 gdb_test_multiple "print a.*pmi = 33" $name {
200 -re "$vhn = 33\r\n$gdb_prompt $" {
203 -re "not implemented: member types in unpack_long\r\n$gdb_prompt $" {
204 # gcc HEAD 2004-01-10 -gdwarf-2
205 # gcc HEAD 2004-01-10 -gstabs+
206 kfail "gdb/NNNN" $name
210 # Now check that the data really was changed
212 set name "print a.*pmi, A::j, 33"
213 gdb_test_multiple "print a.*pmi" $name {
214 -re "$vhn = 33\r\n$gdb_prompt $" {
217 -re "not implemented: member types in unpack_long\r\n$gdb_prompt $" {
218 # gcc HEAD 2004-01-10 -gdwarf-2
219 # gcc HEAD 2004-01-10 -gstabs+
220 kfail "gdb/NNNN" $name
224 # Double-check by printing a.
226 set name "print a, j = 33"
227 gdb_test_multiple "print a" $name {
228 -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 $" {
231 -re "$vhn = \{c = 120 'x', j = 33, jj = 1331, (static|static int) s = 10, Virtual table at $hex\}\r\n$gdb_prompt $" {
234 -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 $" {
237 -re "$vhn = \{(_vptr.A|_vptr\\$) = $hex, c = 120 'x', j = 121, jj = 1331, (static|static int) s = 10\}\r\n$gdb_prompt $" {
238 # gcc HEAD 2004-01-10 -gdwarf-2
239 # gcc HEAD 2004-01-10 -gstabs+
240 kfail "gdb/NNNN" $name
244 # Set the data member pointed to, using ->*
246 set name "print a_p->*pmi = 44"
247 gdb_test_multiple "print a_p->*pmi = 44" $name {
248 -re "$vhn = 44\r\n$gdb_prompt $" {
251 -re "not implemented: member types in unpack_long\r\n$gdb_prompt $" {
252 # gcc HEAD 2004-01-10 -gdwarf-2
253 # gcc HEAD 2004-01-10 -gstabs+
254 kfail "gdb/NNNN" $name
258 # Check that the data really was changed
260 set name "print a_p->*pmi, 44"
261 gdb_test_multiple "print a_p->*pmi" $name {
262 -re "$vhn = 44\r\n$gdb_prompt $" {
265 -re "not implemented: member types in unpack_long\r\n$gdb_prompt $" {
266 # gcc HEAD 2004-01-10 -gdwarf-2
267 # gcc HEAD 2004-01-10 -gstabs+
268 kfail "gdb/NNNN" $name
272 # Double-check by printing a.
274 set name "print a, j = 44"
275 gdb_test_multiple "print a" $name {
276 -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 $" {
279 -re "$vhn = \{c = 120 'x', j = 44, jj = 1331, (static|static int) s = 10, Virtual table at $hex\}\r\n$gdb_prompt $" {
282 -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 $" {
285 -re "$vhn = \{(_vptr.A|_vptr\\$) = $hex, c = 120 'x', j = 121, jj = 1331, (static|static int) s = 10\}\r\n$gdb_prompt $" {
286 # gcc HEAD 2004-01-10 -gdwarf-2
287 # gcc HEAD 2004-01-10 -gstabs+
288 kfail "gdb/NNNN" $name
292 # ptype the dereferenced pointer to member.
294 set name "ptype a.*pmi"
295 gdb_test_multiple "ptype a.*pmi" $name {
296 -re "type = int\r\n$gdb_prompt" {
299 -re "not implemented: member types in unpack_long\r\n$gdb_prompt $" {
300 # gcc HEAD 2004-01-10 -gdwarf-2
301 # gcc HEAD 2004-01-10 -gstabs+
302 kfail "gdb/NNNN" $name
306 # dereference the pointer to data member without any object
307 # this is not allowed: a pmi must be bound to an object to dereference
309 set name "print *pmi"
310 gdb_test_multiple "print *pmi" $name {
311 -re "Attempt to dereference pointer to member without an object\r\n$gdb_prompt $" {
314 -re "Cannot access memory at address 0x4\r\n$gdb_prompt $" {
315 # gcc 2.95.3 -gstabs+
316 kfail "gdb/NNNN" $name
318 -re "Cannot access memory at address 0x8\r\n$gdb_prompt $" {
319 # gcc 3.3.2 -gdwarf-2
321 kfail "gdb/NNNN" $name
325 # dereference the pointer to data member without any object
326 # this is not allowed: a pmi must be bound to an object to dereference
328 set name "ptype *pmi"
329 gdb_test_multiple "ptype *pmi" $name {
330 -re "Attempt to dereference pointer to member without an object\r\n$gdb_prompt $" {
333 -re "type = int A::\r\n$gdb_prompt $" {
334 # gcc 2.95.3 -gstabs+
335 # gcc HEAD 2004-01-10 -gdwarf-2
336 # gcc HEAD 2004-01-10 -gstabs+
337 kfail "gdb/NNNN" $name
341 # Check cast of pointer to member to integer.
342 # This is similar to "offset-of".
343 # such as "A a; print (size_t) &A.j - (size_t) &A".
345 set name "print (int) pmi"
346 gdb_test_multiple "print (int) pmi" $name {
347 -re "$vhn = (4|8|12)\r\n$gdb_prompt" {
352 # Check "(int) pmi" explicitly for equality.
354 set name "print ((int) pmi) == ((char *) &a.j - (char *) &a)"
355 gdb_test_multiple "print ((int) pmi) == ((char *) &a.j - (char *) & a)" $name {
356 -re "$vhn = true\r\n$gdb_prompt" {
361 # Check pointers to data members, which are themselves pointers to
362 # functions. These behave like data members, not like pointers to
365 gdb_test "ptype diamond_pfunc_ptr" \
366 "type = int \\(\\*Diamond::\\*\\)\\(int\\)"
368 gdb_test "ptype diamond.*diamond_pfunc_ptr" \
369 "type = int \\(\\*\\)\\(int\\)"
371 # This one is invalid; () binds more tightly than .*, so it tries to
372 # call the member pointer as a normal pointer-to-function.
374 gdb_test "print diamond.*diamond_pfunc_ptr (20)" \
375 "Invalid data type for function to be called."
377 # With parentheses, it is valid.
379 gdb_test "print (diamond.*diamond_pfunc_ptr) (20)" \
382 # Make sure that we do not interpret this as either a member pointer
383 # call or a member function call.
385 gdb_test "print diamond.func_ptr (20)" \
388 # ==========================
389 # pointer to member function
390 # ==========================
392 # ptype a pointer to a method
395 gdb_test_multiple "ptype pmf" $name {
396 -re "type = int \\( ?A::\\*\\)\\(A \\*( const)?, int\\)\r\n$gdb_prompt $" {
399 -re "type = struct \{.*\}\r\n$gdb_prompt $" {
400 # gcc 2.95.3 -gdwarf-2
401 # gcc 2.95.3 -gstabs+
402 # gcc 3.2.2 -gdwarf-2
404 # gcc HEAD 2004-01-10 -gdwarf-2
405 # gcc HEAD 2004-01-10 -gstabs+
406 kfail "gdb/NNNN" $name
410 # print a pointer to a method
413 gdb_test_multiple "print pmf" $name {
414 -re "$vhn = \\(int \\(A::\\*\\)\\(A \\*( const)?, int\\)\\) $hex <A::bar\\(int\\)>\r\n$gdb_prompt $" {
417 -re "$vhn = \{.*\}\r\n$gdb_prompt $" {
418 # gcc 2.95.3 -gdwarf-2
419 # gcc 2.95.3 -gstabs+
420 # gcc 3.2.2 -gdwarf-2
422 # gcc HEAD 2004-01-10 -gdwarf-2
423 # gcc HEAD 2004-01-10 -gstabs+
424 kfail "gdb/NNNN" $name
428 # ptype a pointer to a pointer to a method
430 set name "ptype pmf_p"
431 gdb_test_multiple "ptype pmf_p" $name {
432 -re "type = int \\( ?A::\\*\\*\\)\\(A \\*( const)?, int\\)\r\n$gdb_prompt $" {
435 -re "type = struct \{.*\} \\*\r\n$gdb_prompt $" {
436 # gcc 2.95.3 -gdwarf-2
437 # gcc 2.95.3 -gstabs+
438 # gcc 3.2.2 -gdwarf-2
440 # gcc HEAD 2004-01-10 -gdwarf-2
441 # gcc HEAD 2004-01-10 -gstabs+
442 kfail "gdb/NNNN" $name
446 # print a pointer to a pointer to a method
448 set name "print pmf_p"
449 gdb_test_multiple "print pmf_p" $name {
450 -re "$vhn = \\(int \\( ?A::\\*\\*\\)\\)\\(int\\)\\) $hex\r\n$gdb_prompt $" {
453 -re "$vhn = \\(PMF \\*\\) $hex\r\n$gdb_prompt $" {
456 -re "$vhn = \\(struct \{.*\} \\*\\) $hex\r\n$gdb_prompt $" {
457 # gcc 2.95.3 -gdwarf-2
458 kfail "gdb/NNNN" $name
462 # print dereferenced pointer to method
464 set name "print a.*pmf"
465 gdb_test_multiple "print a.*pmf" $name {
466 -re "$vhn = {int \\(A \\*( const)?, int\\)} $hex <A::bar\\(int\\)>\r\n$gdb_prompt $" {
469 -re "Value can't be converted to integer.\r\n$gdb_prompt $" {
470 # gcc 2.95.3 -gdwarf-2
471 # gcc 2.95.3 -gstabs+
472 # gcc 3.2.2 -gdwarf-2
474 # gcc HEAD 2004-01-10 -gdwarf-2
475 # gcc HEAD 2004-01-10 -gstabs+
476 kfail "gdb/NNNN" $name
480 # print dereferenced pointer to method, using ->*
482 set name "print a_p->*pmf"
483 gdb_test_multiple "print a_p->*pmf" $name {
484 -re "$vhn = {int \\(A \\*( const)?, int\\)} $hex <A::bar\\(int\\)>\r\n$gdb_prompt $" {
487 -re "Value can't be converted to integer.\r\n$gdb_prompt $" {
488 # gcc 2.95.3 -gdwarf-2
489 # gcc 2.95.3 -gstabs+
490 # gcc 3.2.2 -gdwarf-2
492 # gcc HEAD 2004-01-10 -gdwarf-2
493 # gcc HEAD 2004-01-10 -gstabs+
494 kfail "gdb/NNNN" $name
498 # set the pointer to data member
500 set name "set var pmf = &A::foo"
501 gdb_test_multiple "set var pmf = &A::foo" $name {
502 -re "set var pmf = &A::foo\r\n$gdb_prompt $" {
503 # I have to match the echo'ed input explicitly here.
504 # If I leave it out, the pattern becomes too general
505 # and matches anything that ends in "$gdb_prompt $".
508 -re "Invalid cast.\r\n$gdb_prompt $" {
509 # gcc 2.95.3 -gdwarf-2
510 # gcc 2.95.3 -gstabs+
511 # gcc 3.2.2 -gdwarf-2
513 # gcc HEAD 2004-01-10 -gdwarf-2
514 # gcc HEAD 2004-01-10 -gstabs+
515 kfail "gdb/NNNN" $name
519 # dereference the pointer to data member without any object
520 # this is not allowed: a pmf must be bound to an object to dereference
522 set name "print *pmf"
523 gdb_test_multiple "print *pmf" $name {
524 -re "Attempt to dereference pointer to member without an object\r\n$gdb_prompt $" {
527 -re "Structure has no component named operator\\*.\r\n$gdb_prompt $" {
528 # gcc 2.95.3 -gdwarf-2
529 # gcc 2.95.3 -gstabs+
530 # gcc 3.3.2 -gdwarf-2
532 # gcc HEAD 2004-01-10 -gdwarf-2
533 # gcc HEAD 2004-01-10 -gstabs+
534 kfail "gdb/NNNN" $name
538 # dereference the pointer to data member without any object
539 # this is not allowed: a pmf must be bound to an object to dereference
541 set name "ptype *pmf"
542 gdb_test_multiple "ptype *pmf" $name {
543 -re "Attempt to dereference pointer to member without an object\r\n$gdb_prompt $" {
546 -re "Structure has no component named operator\\*.\r\n$gdb_prompt $" {
547 # gcc 2.95.3 -gdwarf-2
548 # gcc 2.95.3 -gstabs+
549 # gcc 3.3.2 -gdwarf-2
551 # gcc HEAD 2004-01-10 -gdwarf-2
552 # gcc HEAD 2004-01-10 -gstabs+
553 kfail "gdb/NNNN" $name
557 # Call a function through a pmf.
559 set name "print (a.*pmf)(3)"
560 gdb_test_multiple "print (a.*pmf)(3)" $name {
561 -re "$vhn = 50\r\n$gdb_prompt $" {
564 -re "Value can't be converted to integer.\r\n$gdb_prompt $" {
565 # gcc 2.95.3 -gdwarf-2
566 # gcc 2.95.3 -gstabs+
567 # gcc 3.3.2 -gdwarf-2
569 # gcc HEAD 2004-01-10 -gdwarf-2
570 # gcc HEAD 2004-01-10 -gstabs+
571 kfail "gdb/NNNN" $name
575 gdb_test "ptype a.*pmf" "type = int \\(A \\*( const)?, int\\)"
576 gdb_test "ptype (a.*pmf)(3)" "type = int"
578 # Print out a pointer to data member which requires looking into
580 gdb_test "print diamond_pmi" "$vhn = &Base::x"
581 gdb_test "print diamond.*diamond_pmi" "$vhn = 77"
583 # Examine some more complicated pmfs, which require adjusting "this"
584 # and looking through virtual tables.
586 # These two have a different object adjustment, but call the same method.
587 gdb_test "print diamond.*left_pmf" \
588 "$vhn = {int \\(Diamond \\*( const)?\\)} $hex <Base::get_x\\((void|)\\)>"
589 gdb_test "print diamond.*right_pmf" \
590 "$vhn = {int \\(Diamond \\*( const)?\\)} $hex <Base::get_x\\((void|)\\)>"
592 gdb_test "print (diamond.*left_pmf) ()" "$vhn = 77"
593 gdb_test "print (diamond.*right_pmf) ()" "$vhn = 88"
595 # These two point to different methods, although they have the same
596 # virtual table offsets.
597 gdb_test "print diamond.*left_vpmf" \
598 "$vhn = {int \\(Diamond \\*( const)?\\)} $hex <Left::vget\\((void|)\\)>"
599 gdb_test "print diamond.*right_vpmf" \
600 "$vhn = {int \\(Diamond \\*( const)?\\)} $hex <Right::vget\\((void|)\\)>"
602 gdb_test "print (diamond.*left_vpmf) ()" "$vhn = 177"
603 gdb_test "print (diamond.*left_base_vpmf) ()" "$vhn = 2077"
604 gdb_test "print (diamond.*right_vpmf) ()" "$vhn = 288"
606 # We should be able to figure out left_vpmf even without an object,
607 # because it comes from a non-virtual base. The same for right_vpmf.
608 gdb_test "print left_vpmf" "$vhn = &virtual Left::vget\\(\\)"
609 gdb_test "print right_vpmf" "$vhn = &virtual Right::vget\\(\\)"
611 # But we should gracefully fail to figure out base_vpmf, because
612 # its runtime type is more derived than its static type. This
613 # is a valid but unspecified cast (it is value preserving, i.e.
614 # can be casted back to the correct type and used).
615 gdb_test "print base_vpmf" \
616 "$vhn = &virtual table offset \[0-9\]*, this adjustment -\[0-9\]*"
618 # Make sure we parse this correctly; it's invalid.
619 gdb_test "print diamond.*left_vpmf ()" \
620 "Invalid data type for function to be called\\."
622 # NULL pointer to member tests.
623 gdb_test "print null_pmi" "$vhn = NULL"
624 gdb_test "print null_pmi = &A::j" "$vhn = &A::j"
625 gdb_test "print null_pmi = 0" "$vhn = NULL"
627 gdb_test "print null_pmf" "$vhn = NULL"
628 gdb_test "print null_pmf = &A::foo" "$vhn = \\(int \\(A::\\*\\)\\(A \\*( const)?, int\\)\\) $hex <A::foo ?\\(int\\)>"
629 gdb_test "print null_pmf = 0" "$vhn = NULL"
631 # Print with a format, bypassing the direct call to the scalar
632 # printer. See PR c++/29243.
633 gdb_test "print/x contain" " = {member = $hex}"