]>
Commit | Line | Data |
---|---|---|
42a4f53d | 1 | # Copyright 2017-2019 Free Software Foundation, Inc. |
c973d0aa PA |
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 | ||
26 | standard_testfile | |
27 | ||
28 | # Prepare for testing in language LANG. Lang can be "c" or "c++". | |
29 | ||
30 | proc 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] } { | |
cbcdb1aa | 48 | return 0 |
c973d0aa PA |
49 | } |
50 | ||
51 | if ![runto_main] then { | |
52 | fail "can't run to main" | |
53 | return 0 | |
54 | } | |
cbcdb1aa AB |
55 | |
56 | return 1 | |
c973d0aa PA |
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 | |
83 | set 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 | ||
73fcf641 PA |
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 | ||
c973d0aa PA |
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. | |
158 | proc 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 | ||
173 | proc 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 | ||
73fcf641 PA |
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 | ||
c973d0aa PA |
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 | # | |
73fcf641 | 261 | # float <-> array [iff sizeof pointer != sizeof float] |
c973d0aa PA |
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]) | |
73fcf641 PA |
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])) | |
c973d0aa PA |
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 | ||
304 | foreach_with_prefix lang {"c" "c++"} { | |
cbcdb1aa AB |
305 | if { [prepare $lang] } then { |
306 | run_tests $lang | |
307 | } | |
c973d0aa | 308 | } |