1# Copyright 2017-2020 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# Test "whatis"/"ptype" of different typedef types, and of expressions 17# involving casts to/from different typedefs. 18# 19# Particularly, when "whatis" is given a type name directly, it should 20# strip one (and only one) typedef level. Otherwise, it should not 21# strip any typedef at all. GDB used to incorrectly strip typedefs of 22# expressions involving casts to typedef types. E.g., (gdb) print 23# (int_typedef)0" shall result in a value of type "int_typedef", not 24# "int". 25 26standard_testfile 27 28# Prepare for testing in language LANG. Lang can be "c" or "c++". 29 30proc prepare {lang} { 31 global srcfile testfile 32 33 if [target_info exists no_long_long] { 34 set options [list debug additional_flags=-DNO_LONG_LONG] 35 } else { 36 set options [list debug] 37 } 38 39 if {$lang == "c++"} { 40 lappend options c++ 41 set out $testfile-cxx 42 } else { 43 set out $testfile-c 44 } 45 46 if { [prepare_for_testing "failed to prepare" \ 47 ${out} [list $srcfile] $options] } { 48 return 0 49 } 50 51 if ![runto_main] then { 52 fail "can't run to main" 53 return 0 54 } 55 56 return 1 57} 58 59# The following list is layed out as a table. It is composed by 60# sub-lists (lines), with each line representing one whatis/ptype 61# test. The sub-list (line) elements (columns) are (in order): 62# 63# EXP - The user expression passed to whatis/ptype. 64# 65# WHATIS - What "whatis" should print. 66# 67# If the EXP column is a type name, then this will be the same type, 68# with one (and only one) typedef level removed. Otherwise, this is 69# the type of the expression on the first column, with all typedefs 70# preserved. 71# 72# PTYPE - What "ptype" should print. 73# 74# This is always the type of the input type/expression stripped from 75# all typedefs. 76# 77# LANGUAGE - If the line is language-specific, which language. 78# 79# This can be "c" or "c++". 80# 81# Columns in the table represent: 82 # EXP # whatis # ptype # language 83set table { 84 {"void_typedef" "void" "void"} 85 {"void_typedef2" "void_typedef" "void"} 86 87 {"int_typedef" "int" "int"} 88 {"int_typedef2" "int_typedef" "int"} 89 {"v_int_typedef" "int_typedef" "int"} 90 {"v_int_typedef2" "int_typedef2" "int"} 91 92 {"float_typedef" "float" "float"} 93 {"float_typedef2" "float_typedef" "float"} 94 {"v_float_typedef" "float_typedef" "float"} 95 {"v_float_typedef2" "float_typedef2" "float"} 96 97 {"double_typedef" "double" "double"} 98 {"double_typedef2" "double_typedef" "double"} 99 {"v_double_typedef" "double_typedef" "double"} 100 {"v_double_typedef2" "double_typedef2" "double"} 101 102 {"long_double_typedef" "long double" "long double"} 103 {"long_double_typedef2" "long_double_typedef" "long double"} 104 {"v_long_double_typedef" "long_double_typedef" "long double"} 105 {"v_long_double_typedef2" "long_double_typedef2" "long double"} 106 107 {"colors_typedef" "(enum )?colors" "enum colors( : unsigned int)? {red, green, blue}"} 108 {"colors_typedef2" "colors_typedef" "enum colors( : unsigned int)? {red, green, blue}"} 109 {"v_colors_typedef" "colors_typedef" "enum colors( : unsigned int)? {red, green, blue}"} 110 {"v_colors_typedef2" "colors_typedef2" "enum colors( : unsigned int)? {red, green, blue}"} 111 112 {"func_ftype" "void \\(void\\)" "void \\(void\\)"} 113 {"func_ftype2" "func_ftype" "void \\(void\\)"} 114 115 {"func_ftype *" "func_ftype \\*" "void \\(\\*\\)\\(void\\)"} 116 {"func_ftype2 *" "func_ftype2 \\*" "void \\(\\*\\)\\(void\\)"} 117 {"v_func_ftype" "func_ftype \\*" "void \\(\\*\\)\\(void\\)"} 118 {"v_func_ftype2" "func_ftype2 \\*" "void \\(\\*\\)\\(void\\)"} 119 120 {"v_t_struct_typedef" "t_struct_typedef" "struct t_struct {.* member;.*}"} 121 {"v_t_struct_typedef2" "t_struct_typedef2" "struct t_struct {.* member;.*}"} 122 {"v_t_struct_union_wrapper_typedef" "t_struct_union_wrapper_typedef" "union t_struct_union_wrapper {.*base;.*}"} 123 {"v_t_struct_union_wrapper_typedef2" "t_struct_union_wrapper_typedef2" "union t_struct_union_wrapper {.*base;.*}"} 124 {"v_uchar_array_t_struct_typedef" "uchar_array_t_struct_typedef" "unsigned char \\[.*\\]"} 125 {"v_uchar_array_t_struct_typedef2" "uchar_array_t_struct_typedef2" "unsigned char \\[.*\\]"} 126 127 {"v_ns_Struct_typedef" "ns_Struct_typedef" "struct ns::Struct {.* method.*}" "c++"} 128 129 {"ns_method_ptr_typedef" 130 "void \\(ns::Struct::\\*\\)\\(ns::Struct \\* const\\)" 131 "void \\(ns::Struct::\\*\\)\\(ns::Struct \\* const\\)" 132 "c++"} 133 134 {"ns::method_ptr_typedef" 135 "void \\(ns::Struct::\\*\\)\\(ns::Struct \\* const\\)" 136 "void \\(ns::Struct::\\*\\)\\(ns::Struct \\* const\\)" 137 "c++"} 138 139 {"ns_method_ptr_typedef2" 140 "ns_method_ptr_typedef" 141 "void \\(ns::Struct::\\*\\)\\(ns::Struct \\* const\\)" 142 "c++"} 143 144 {"ns::method_ptr_typedef2" 145 "ns::method_ptr_typedef" 146 "void \\(ns::Struct::\\*\\)\\(ns::Struct \\* const\\)" 147 "c++"} 148 149 {"ns::Struct::method" 150 "void \\(ns::Struct \\* const\\)" 151 "void \\(ns::Struct \\* const\\)" 152 "c++"} 153} 154 155# The 4th column above is optional. If present, it indicates that the 156# line should only be tested in the specified language. This is a 157# helper function that checks whether LINE's language matches LANG. 158proc line_lang_match {line lang} { 159 if {[llength $line] <= 3} { 160 return true 161 } 162 163 set line_lang [lindex $line 3] 164 if {$line_lang == "" || $lang == $line_lang} { 165 return true 166 } 167 168 return false 169} 170 171# Run tests in language LANG. 172 173proc run_tests {lang} { 174 global table 175 global gdb_prompt 176 177 # Test passing all EXP in the list/table above to whatis/ptype, 178 # and check what comes out. 179 with_test_prefix "whatis/ptype" { 180 foreach line $table { 181 set type [lindex $line 0] 182 set whatis [lindex $line 1] 183 set ptype [lindex $line 2] 184 185 if {![line_lang_match $line $lang]} { 186 continue 187 } 188 189 # GCC doesn't record the target type of "typedef of 190 # typedef of void" types in the DWARF. See 191 # <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81267>. 192 # Handle that case manually in order to be able to xfail 193 # it. 194 if {$type == "void_typedef2"} { 195 set test "whatis $type" 196 gdb_test_multiple $test $test { 197 -re "type = void\r\n$gdb_prompt $" { 198 # gcc/81267. 199 setup_xfail "*-*-*" 200 fail "$test (void)" 201 } 202 -re "type = void_typedef\r\n$gdb_prompt $" { 203 pass $test 204 } 205 } 206 } else { 207 gdb_test "whatis $type" "type = $whatis" 208 } 209 210 gdb_test "ptype $type" "type = $ptype" 211 } 212 } 213 214 # If floats and pointers have the same size on this architecture, 215 # then casting from array/function to float works, because 216 # arrays/functions first decay to pointers, and then GDB's cast is 217 # more general than a C cast and accepts any two types of the same 218 # length. 219 set float_ptr_same_size \ 220 [get_integer_valueof "sizeof (float) == sizeof (void *)" -1] 221 222 # Ditto double. 223 set double_ptr_same_size \ 224 [get_integer_valueof "sizeof (double) == sizeof (void *)" -1] 225 226 # Ditto long double. 227 set long_double_ptr_same_size \ 228 [get_integer_valueof "sizeof (long double) == sizeof (void *)" -1] 229 230 # Test converting/casting all variables in the first column of the 231 # table to all types (found in the first column of the table). 232 # The aggregates are all defined to be the same size so that 233 # casting actually works. (GDB's casting operator is more general 234 # than a C cast.) 235 # 236 # The main idea here is testing all the different paths in the 237 # value casting code in GDB (value_cast), making sure typedefs are 238 # preserved. 239 with_test_prefix "cast" { 240 foreach line1 $table { 241 set from [lindex $line1 0] 242 243 if {![line_lang_match $line1 $lang]} { 244 continue 245 } 246 247 foreach line2 $table { 248 set to [lindex $line2 0] 249 set whatis [lindex $line2 1] 250 set ptype [lindex $line2 2] 251 252 if {![line_lang_match $line2 $lang]} { 253 continue 254 } 255 256 # We try all combinations, even those that don't 257 # parse, or are invalid, to catch the case of a 258 # regression making them inadvertently valid. For 259 # example, these convertions are invalid: 260 # 261 # float <-> array [iff sizeof pointer != sizeof float] 262 # array -> function (not function pointer) 263 # array -> member_ptr 264 # 265 # while these are invalid syntax: 266 # 267 # (anything) type 268 # (var) anything 269 # (method) anything [not method pointer] 270 # (float) method 271 # 272 if {([string match "v_*" $to] 273 || (![string match "v_*" $from] && ![string match "*method" $from]) 274 || [string match "*method" $to])} { 275 gdb_test "whatis ($to) $from" "syntax error.*" "whatis ($to) $from (syntax)" 276 gdb_test "ptype ($to) $from" "syntax error.*" "ptype ($to) $from (syntax)" 277 } elseif {([string match "*float*" $from] && [string match "*array*" $to]) 278 || (!$float_ptr_same_size 279 && ([string match "float*" $to] && [string match "*array*" $from] 280 || [string match "float*" $to] && [string match "*method" $from])) 281 || (!$double_ptr_same_size 282 && ([string match "double*" $to] && [string match "*array*" $from] 283 || [string match "double*" $to] && [string match "*method" $from])) 284 || (!$long_double_ptr_same_size 285 && ([string match "long_double*" $to] && [string match "*array*" $from] 286 || [string match "long_double*" $to] && [string match "*method" $from])) 287 || ([string match "*ftype" $to] && [string match "*array*" $from]) 288 || ([string match "*ftype2" $to] && [string match "*array*" $from]) 289 || ([string match "*ftype" $to] && [string match "*method" $from]) 290 || ([string match "*ftype2" $to] && [string match "*method" $from]) 291 || ([string match "*method_ptr*" $to] && [string match "*method" $from]) 292 || ([string match "*method_ptr*" $to] && [string match "*array*" $from])} { 293 gdb_test "whatis ($to) $from" "Invalid cast." "whatis ($to) $from (invalid)" 294 gdb_test "ptype ($to) $from" "Invalid cast." "ptype ($to) $from (invalid)" 295 } else { 296 gdb_test "whatis ($to) $from" "type = [string_to_regexp $to]" 297 gdb_test "ptype ($to) $from" "type = $ptype" 298 } 299 } 300 } 301 } 302} 303 304foreach_with_prefix lang {"c" "c++"} { 305 if { [prepare $lang] } then { 306 run_tests $lang 307 } 308} 309