# Copyright 1998-2023 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 . # This file is part of the gdb testsuite # Print out various class objects' members and check that the error # about the field or baseclass being ambiguous is emitted at the right # times. if { [skip_cplus_tests] } { return } standard_testfile .cc set additional_flags "" if {[test_compiler_info {gcc-[0-9]-*}]} { # GCCs prior to 10.1 do not support -Wno-inaccessible-base. set additional_flags "additional_flags=-w" } elseif {[test_compiler_info gcc*] || [test_compiler_info clang*]} { set additional_flags "additional_flags=-Wno-inaccessible-base" } if {[prepare_for_testing "failed to prepare" $testfile $srcfile \ [list debug c++ $additional_flags]]} { return -1 } if {![runto_main]} { return } # Run to a breakpoint after the variables have been initialized so we # can play with the variable values. set lineno [gdb_get_line_number "set breakpoint here"] gdb_breakpoint $lineno gdb_continue_to_breakpoint "breakpoint here" set number -?$decimal with_test_prefix "all vars" { gdb_test "print a1" \ " = \{x = 1, y = 2\}" gdb_test "print a2" \ " = \{x = 1, y = 2\}" gdb_test "print a3" \ " = \{x = 1, y = 2\}" gdb_test "print x" \ " = \{ = \{x = 1, y = 2\}, = \{x = 3, y = 4\}, z = 5\}" gdb_test "print l" \ " = \{ = \{x = 1, y = 2\}, z = 3\}" gdb_test "print m" \ " = \{ = \{x = 1, y = 2\}, w = 3\}" gdb_test "print n" \ " = \{ = \{ = \{x = 1, y = 2\}, z = 7\}, = \{ = \{x = 3, y = 4\}, w = 5\}, r = 6\}" gdb_test "print k" \ " = \{ = \{x = 1, y = 2\}, i = 3\}" gdb_test "print j" \ " = { = { = {x = 1, y = 2}, i = 5}, = { = {x = 3, y = 4}, z = 6}, j = 7}" gdb_test "print jv" \ " = \{ = \{ = \{x = 1, y = 2\}, _vptr.KV = $hex , i = 3\}, = \{_vptr.LV = $hex , z = 4\}, jv = 5\}" # No way to initialize one of the A1's, so just take any number there. gdb_test "print jva1" \ " = \{ = \{ = \{x = 3, y = 4\}, _vptr.KV = $hex , i = 6\}, = \{_vptr.LV = $hex , z = 5\}, = \{x = $number, y = $number\}, jva1 = 7\}" gdb_test "print jva2" \ " = \{ = \{ = \{x = 3, y = 4\}, _vptr.KV = $hex , i = 8\}, = \{_vptr.LV = $hex , z = 7\}, = \{x = 5, y = 6\}, jva2 = 9\}" gdb_test "print jva1v" \ " = \{ = \{ = \{x = 1, y = 2\}, _vptr.KV = $hex , i = 4\}, = \{_vptr.LV = $hex , z = 3\}, jva1v = 5\}" } # Check that we can access all the fields correctly, using the same # syntax as used in the .cc file. Keep the order here in sync with # the .cc file. with_test_prefix "all fields" { gdb_test "print a1.x" " = 1" gdb_test "print a1.y" " = 2" gdb_test "print a2.x" " = 1" gdb_test "print a2.y" " = 2" gdb_test "print a3.x" " = 1" gdb_test "print a3.y" " = 2" gdb_test "print x.A1::x" " = 1" gdb_test "print x.A1::y" " = 2" gdb_test "print x.A2::x" " = 3" gdb_test "print x.A2::y" " = 4" gdb_test "print x.z" " = 5" gdb_test "print l.x" " = 1" gdb_test "print l.y" " = 2" gdb_test "print l.z" " = 3" gdb_test "print m.x" " = 1" gdb_test "print m.y" " = 2" gdb_test "print m.w" " = 3" gdb_test "print n.A1::x" " = 1" gdb_test "print n.A1::y" " = 2" gdb_test "print n.A2::x" " = 3" gdb_test "print n.A2::y" " = 4" gdb_test "print n.w" " = 5" gdb_test "print n.r" " = 6" gdb_test "print n.z" " = 7" gdb_test "print k.x" " = 1" gdb_test "print k.y" " = 2" gdb_test "print k.i" " = 3" gdb_test "print j.K::x" " = 1" gdb_test "print j.K::y" " = 2" gdb_test "print j.L::x" " = 3" gdb_test "print j.L::y" " = 4" gdb_test "print j.i" " = 5" gdb_test "print j.z" " = 6" gdb_test "print j.j" " = 7" gdb_test "print jv.x" " = 1" gdb_test "print jv.y" " = 2" gdb_test "print jv.i" " = 3" gdb_test "print jv.z" " = 4" gdb_test "print jv.jv" " = 5" setup_kfail "c++/26550" *-*-* gdb_test "print jva1.KV::x" " = 1" setup_kfail "c++/26550" *-*-* gdb_test "print jva1.KV::y" " = 2" setup_kfail "c++/26550" *-*-* gdb_test "print jva1.LV::x" " = 3" setup_kfail "c++/26550" *-*-* gdb_test "print jva1.LV::y" " = 4" gdb_test "print jva1.z" " = 5" gdb_test "print jva1.i" " = 6" gdb_test "print jva1.jva1" "= 7" setup_kfail "c++/26550" *-*-* gdb_test "print jva2.KV::x" " = 1" setup_kfail "c++/26550" *-*-* gdb_test "print jva2.KV::y" " = 2" setup_kfail "c++/26550" *-*-* gdb_test "print jva2.LV::x" " = 3" setup_kfail "c++/26550" *-*-* gdb_test "print jva2.LV::y" " = 4" gdb_test "print jva2.A2::x" " = 5" gdb_test "print jva2.A2::y" " = 6" gdb_test "print jva2.z" " = 7" gdb_test "print jva2.i" " = 8" gdb_test "print jva2.jva2" "= 9" gdb_test "print jva1v.x" " = 1" gdb_test "print jva1v.y" " = 2" gdb_test "print jva1v.z" " = 3" gdb_test "print jva1v.i" " = 4" gdb_test "print jva1v.jva1v" " = 5" } # Test that printing WHAT reports an error about FIELD being ambiguous # in TYPE, and that the candidates are CANDIDATES. proc test_ambiguous {what field type candidates} { set msg "Request for member '$field' is ambiguous in type '$type'. Candidates are:" foreach c $candidates { set c_re [string_to_regexp $c] append msg "\r\n $c_re" } gdb_test "print $what" $msg } # X is derived from A1 and A2; both A1 and A2 have a member 'x' test_ambiguous "x.x" "x" "X" { "'int A1::x' (X -> A1)" "'int A2::x' (X -> A2)" } # N is derived from A1 and A2, but not immediately -- two steps # up in the hierarchy. Both A1 and A2 have a member 'x'. test_ambiguous "n.x" "x" "N" { "'int A1::x' (N -> L -> A1)" "'int A2::x' (N -> M -> A2)" } # J is derived from A1 twice. A1 has a member x. test_ambiguous "j.x" "x" "J" { "'int A1::x' (J -> K -> A1)" "'int A1::x' (J -> L -> A1)" } # JV is derived from A1 but A1 is a virtual base. Should not # report an ambiguity in this case. gdb_test "print jv.x" " = 1" # JVA1 is derived from A1; A1 occurs as a virtual base in two # ancestors, and as a non-virtual immediate base. Ambiguity must # be reported. test_ambiguous "jva1.x" "x" "JVA1" { "'int A1::x' (JVA1 -> KV -> A1)" "'int A1::x' (JVA1 -> A1)" } # JVA2 is derived from A1 & A2; A1 occurs as a virtual base in two # ancestors, and A2 is a non-virtual immediate base. Ambiguity must # be reported as A1 and A2 both have a member 'x'. test_ambiguous "jva2.x" "x" "JVA2" { "'int A1::x' (JVA2 -> KV -> A1)" "'int A2::x' (JVA2 -> A2)" } # JVA1V is derived from A1; A1 occurs as a virtual base in two # ancestors, and also as a virtual immediate base. Ambiguity must # not be reported. gdb_test "print jva1v.x" " = 1" # Now check for ambiguous bases. # J is derived from A1 twice; report ambiguity if a J is # cast to an A1. gdb_test "print (A1)j" "base class 'A1' is ambiguous in type 'J'" # JV is derived from A1 twice, but A1 is a virtual base; should # not report ambiguity when a JV is cast to an A1. gdb_test "print (A1)jv" " = {x = 1, y = 2}" # JVA1 is derived from A1; A1 is a virtual base and also a # non-virtual base. Must report ambiguity if a JVA1 is cast to an A1. gdb_test "print (A1)jva1" "base class 'A1' is ambiguous in type 'JVA1'" # Add an intermediate cast to KV, and it should work. setup_kfail "c++/26550" *-*-* gdb_test "print (KV)jva1" " = \{ = \{x = 3, y = 4\}, _vptr.KV = $hex , i = 6\}" setup_kfail "c++/26550" *-*-* gdb_test "print (A1)(KV)jva1" " = \{x = 3, y = 4\}" # JVA1V is derived from A1; A1 is a virtual base indirectly # and also directly; must not report ambiguity when a JVA1V is cast to an A1. gdb_test "print (A1)jva1v" " = {x = 1, y = 2}" # C++20 introduced a way to have ambiguous fields with the same byte offset. # This class explicitly tests for that. # if this is tested with a compiler that can't handle [[no_unique_address]] # the code should still correctly identify the ambiguity because of # different byte offsets. test_ambiguous "je.x" "x" "JE" { "'int A1::x' (JE -> A1)" "'empty A4::x' (JE -> A4)" }