1# Copyright 2017-2023 Free Software Foundation, Inc. 2 3# This program is free software; you can redistribute it and/or modify 4# it under the terms of the GNU General Public License as published by 5# the Free Software Foundation; either version 3 of the License, or 6# (at your option) any later version. 7# 8# This program is distributed in the hope that it will be useful, 9# but WITHOUT ANY WARRANTY; without even the implied warranty of 10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11# GNU General Public License for more details. 12# 13# You should have received a copy of the GNU General Public License 14# along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16# Tests for function local static variables, both C and C++. 17 18# This file is part of the gdb testsuite. 19 20standard_testfile .c 21 22# A few expected errors. 23set syntax_re "A syntax error in expression, near.*" 24set cannot_resolve_re "Cannot resolve method S::method to any overloaded instance" 25 26# Build an "Cannot resolve method ..." expected error string for 27# method METH. 28# 29proc cannot_resolve {meth} { 30 return "Cannot resolve method $meth to any overloaded instance" 31} 32 33# A list of scopes that have the static variables that we want to 34# print. Each entry has, in order, the scope/function name, and the 35# prefix used by the static variables. The prefix exists both to make 36# it easier to debug the test if something goes wrong, and, to make 37# sure that printing the static local of one method overload doesn't 38# find the variables of the wrong overload. 39# 40# While at it, we also try printing each scope without the static 41# local, to check that the parse copes with cv overloads without 42# quoting. That's what the third and forth columns are for. Note 43# that printing "func()" is different from "func(void)". The former 44# is an inferior function call, while the latter is a reference to the 45# function. 46 47 #SCOPE #PREFIX #PRINT-SCOPE-QUOTED 48 #PRINT-SCOPE-UNQUOTED (opt) 49set cxx_scopes_list { 50 {"S::method()" "S_M" {= \\{void \\(S \\* const\\)\\} $hex <S::method\\(\\)>} 51 {[cannot_resolve "S::method"]}} 52 53 {"S::method() const" "S_M_C" {= \\{void \\(const S \\* const\\)\\} $hex <S::method\\(\\) const>} 54 $syntax_re} 55 56 {"S::method() volatile" "S_M_V" {= \\{void \\(volatile S \\* const\\)\\} $hex <S::method\\(\\) volatile>} 57 $syntax_re} 58 59 {"S::method() const volatile" "S_M_CV" {= \\{void \\(const volatile S \\* const\\)\\} $hex <S::method\\(\\) const volatile>} 60 $syntax_re} 61 62 {"S::method() volatile const" "S_M_CV" {= \\{void \\(const volatile S \\* const\\)\\} $hex <S::method\\(\\) const volatile>} 63 $syntax_re} 64 65 {"S::method(void)" "S_M" {= \\{void \\(S \\* const\\)\\} $hex <S::method\\(\\)>}} 66 {"S::method(void) const" "S_M_C" {= \\{void \\(const S \\* const\\)\\} $hex <S::method\\(\\) const>}} 67 {"S::method(void) volatile" "S_M_V" {= \\{void \\(volatile S \\* const\\)\\} $hex <S::method\\(\\) volatile>}} 68 {"S::method(void) const volatile" "S_M_CV" {= \\{void \\(const volatile S \\* const\\)\\} $hex <S::method\\(\\) const volatile>}} 69 {"S::method(void) volatile const" "S_M_CV" {= \\{void \\(const volatile S \\* const\\)\\} $hex <S::method\\(\\) const volatile>}} 70 71 {"S::static_method()" "S_SM" {= \\{void \\(void\\)\\} $hex <S::static_method\\(\\)>} 72 "void"} 73 74 {"S::static_method(void)" "S_SM" {= \\{void \\(void\\)\\} $hex <S::static_method\\(\\)>}} 75 76 {"S::inline_method()" "S_IM" {= \\{void \\(S \\* const\\)\\} $hex <S::inline_method\\(\\)>} 77 {[cannot_resolve "S::inline_method"]}} 78 79 {"S::inline_method(void)" "S_IM" {= \\{void \\(S \\* const\\)\\} $hex <S::inline_method\\(\\)>}} 80 81 {"S::static_inline_method()" "S_SIM" {= \\{void \\(void\\)\\} $hex <S::static_inline_method\\(\\)>} 82 "void"} 83 84 {"S::static_inline_method(void)" "S_SIM" {= \\{void \\(void\\)\\} $hex <S::static_inline_method\\(\\)>}} 85 86 {"S2<int>::method()" "S2_M" {= \\{void \\(S2<int> \\* const\\)\\} $hex <S2<int>::method\\(\\)>} 87 {[cannot_resolve "S2<int>::method"]}} 88 89 {"S2<int>::static_method()" "S2_SM" {= \\{void \\(void\\)\\} $hex <S2<int>::static_method\\(\\)>} 90 "void"} 91 92 {"S2<int>::inline_method()" "S2_IM" {= \\{void \\(S2<int> \\* const\\)\\} $hex <S2<int>::inline_method\\(\\)>} 93 {[cannot_resolve "S2<int>::inline_method"]}} 94 95 {"S2<int>::static_inline_method()" "S2_SIM" {= \\{void \\(void\\)\\} $hex <S2<int>::static_inline_method\\(\\)>} 96 "void"} 97 98 {"free_func" "FF" {= \\{void \\(void\\)\\} $hex <free_func\\(\\)>}} 99 100 {"free_func()" "FF" {= \\{void \\(void\\)\\} $hex <free_func\\(\\)>} 101 "void"} 102 103 {"free_func(void)" "FF" {= \\{void \\(void\\)\\} $hex <free_func\\(\\)>}} 104 105 {"free_inline_func()" "FIF" {= \\{void \\(void\\)\\} $hex <free_inline_func\\(\\)>} 106 "void"} 107 108 {"free_inline_func(void)" "FIF" {= \\{void \\(void\\)\\} $hex <free_inline_func\\(\\)>}} 109} 110 111set c_scopes_list { 112 {"free_func" "FF" {= \\{void \\(void\\)\\} $hex <free_func>}} 113 {"free_inline_func" "FIF" {= \\{void \\(void\\)\\} $hex <free_inline_func>}} 114} 115 116# A list of all the static varibles defined in each scope. The first 117# column is the name of the variable, without the prefix, and the 118# second column is a regex matching what printing the variable should 119# output. 120 121 #VAR #PRINT 122set vars_list { 123 {"s_var_int" " = 4"} 124 {"s_var_float" " = 3.14.*"} 125 {"s_var_aggregate" " = \\{i1 = 1, i2 = 2, i3 = 3\\}"} 126} 127 128proc do_test {lang} { 129 global c_scopes_list 130 global cxx_scopes_list 131 global vars_list 132 global srcfile testfile 133 global gdb_prompt 134 135 set options {debug} 136 137 if {$lang == "c++"} { 138 if { [skip_cplus_tests] } { 139 return 140 } 141 lappend options $lang 142 set src ${srcfile}c 143 } else { 144 set src ${srcfile} 145 } 146 147 if {[prepare_for_testing "failed to prepare" $testfile-$lang \ 148 [list $src] $options]} { 149 return -1 150 } 151 152 if {![runto_main]} { 153 return 154 } 155 156 gdb_test "show language" " currently [string_to_regexp $lang]\"\\." 157 158 if {$lang == "c"} { 159 set scopes_list $c_scopes_list 160 } else { 161 set scopes_list $cxx_scopes_list 162 } 163 164 # Print each scope/function using these syntaxes: 165 # 166 # "(gdb) p 'S::method() const'" # quoted 167 # "(gdb) p S::method() const" # unquoted 168 # 169 foreach scope_line $scopes_list { 170 set scope [lindex $scope_line 0] 171 172 set print_quoted_re [lindex $scope_line 2] 173 set print_quoted_re [uplevel 1 "subst -nobackslashes -nocommands \"$print_quoted_re\""] 174 175 set print_unquoted_re [lindex $scope_line 3] 176 set print_unquoted_re [uplevel 1 "subst -nobackslashes -nocommands \"$print_unquoted_re\""] 177 178 gdb_test "print '${scope}'" $print_quoted_re 179 180 if {$print_unquoted_re != ""} { 181 gdb_test "print ${scope}" $print_unquoted_re 182 } else { 183 gdb_test "print ${scope}" $print_quoted_re 184 } 185 } 186 187 # Print each variable using these syntaxes: 188 # 189 # 'func()'::var 190 # func()::var 191 # 'func()::var' 192 # 193 # In C++, the latter case makes sure that symbol lookup finds the 194 # debug symbol instead of the minimal symbol with that exact same 195 # name. 196 197 foreach scope_line $scopes_list { 198 set scope [lindex $scope_line 0] 199 set var_prefix [lindex $scope_line 1] 200 foreach var_line $vars_list { 201 set var [lindex $var_line 0] 202 set print_re [lindex $var_line 1] 203 204 # The gcc PR debug/55541 has the effect that local statics are 205 # wrapped in a DW_TAG_lexical_block, making them unaddressable from 206 # outside the function. XFAIL the relevant tests. 207 set test "print '${scope}'::${var_prefix}_${var}" 208 set xfail_pattern "No symbol \".*\" in specified context." 209 gdb_test_multiple $test $test { 210 -re "\[\r\n\]*(?:$print_re)\[\r\n\]+$gdb_prompt $" { 211 pass $test 212 } 213 -re "\[\r\n\]*(?:$xfail_pattern)\[\r\n\]+$gdb_prompt $" { 214 xfail $test 215 } 216 } 217 set test "print ${scope}::${var_prefix}_${var}" 218 gdb_test_multiple $test $test { 219 -re "\[\r\n\]*(?:$print_re)\[\r\n\]+$gdb_prompt $" { 220 pass $test 221 } 222 -re "\[\r\n\]*(?:$xfail_pattern)\[\r\n\]+$gdb_prompt $" { 223 xfail $test 224 } 225 } 226 227 set sym "${scope}::${var_prefix}_${var}" 228 if {$lang == "c++"} { 229 set test "print '${sym}'" 230 set xfail_pattern "No symbol .* in current context." 231 set xfail_pattern2 "has unknown type; cast it to its declared type" 232 gdb_test_multiple $test $test { 233 -re "\[\r\n\]*(?:$print_re)\[\r\n\]+$gdb_prompt $" { 234 pass $test 235 } 236 -re "\[\r\n\]*(?:$xfail_pattern)\[\r\n\]+$gdb_prompt $" { 237 xfail $test 238 } 239 -re "\[\r\n\]*(?:$xfail_pattern2)\[\r\n\]+$gdb_prompt $" { 240 xfail $test 241 } 242 } 243 } else { 244 gdb_test "print '${sym}'" "No symbol \"$sym\" in current context\\." 245 } 246 } 247 } 248 249 # Now run to each function, and print its variables using the 250 # localy-visible name. 251 foreach scope_line $scopes_list { 252 set scope [lindex $scope_line 0] 253 set var_prefix [lindex $scope_line 1] 254 255 with_test_prefix "$scope" { 256 delete_breakpoints 257 gdb_breakpoint "$scope" 258 gdb_continue_to_breakpoint "$scope" 259 260 foreach var_line $vars_list { 261 set var [lindex $var_line 0] 262 set print_re [lindex $var_line 1] 263 264 gdb_test "print ${var_prefix}_${var}" $print_re 265 } 266 } 267 } 268} 269 270foreach lang {"c" "c++"} { 271 with_test_prefix $lang { 272 do_test $lang 273 } 274} 275