[gdb/testsuite] Factor out lib/valgrind.exp
[external/binutils.git] / gdb / testsuite / gdb.base / whatis-ptype-typedefs.exp
1 # Copyright 2017-2018 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
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] } {
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
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
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.
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
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
304 foreach_with_prefix lang {"c" "c++"} {
305     if { [prepare $lang] } then {
306         run_tests $lang
307     }
308 }