Home | History | Annotate | Line # | Download | only in gdb.cp
      1 # Copyright 2017-2024 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 
     20 standard_testfile .c
     21 
     22 # A few expected errors.
     23 set syntax_re "A syntax error in expression, near.*"
     24 set 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 #
     29 proc 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)
     49 set 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 
    111 set 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
    122 set 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 
    128 proc 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 { ![allow_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 
    270 foreach lang {"c" "c++"} {
    271     with_test_prefix $lang {
    272 	do_test $lang
    273     }
    274 }
    275