Commit | Line | Data |
---|---|---|
618f726f | 1 | # Copyright (C) 2008-2016 Free Software Foundation, Inc. |
ed3ef339 DE |
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 | # This file is part of the GDB testsuite. | |
17 | # It tests the mechanism exposing values to Guile. | |
18 | ||
19 | load_lib gdb-guile.exp | |
20 | ||
21 | standard_testfile | |
22 | ||
673dc4a0 YQ |
23 | set has_argv0 [gdb_has_argv0] |
24 | ||
ed3ef339 DE |
25 | # Build inferior to language specification. |
26 | # LANG is one of "c" or "c++". | |
27 | proc build_inferior {exefile lang} { | |
28 | global srcdir subdir srcfile testfile hex | |
29 | ||
30 | # Use different names for .o files based on the language. | |
31 | # For Fission, the debug info goes in foo.dwo and we don't want, | |
32 | # for example, a C++ compile to clobber the dwo of a C compile. | |
33 | # ref: http://gcc.gnu.org/wiki/DebugFission | |
34 | switch ${lang} { | |
35 | "c" { set filename ${testfile}.o } | |
36 | "c++" { set filename ${testfile}-cxx.o } | |
37 | } | |
38 | set objfile [standard_output_file $filename] | |
39 | ||
40 | if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objfile}" object "debug $lang"] != "" | |
41 | || [gdb_compile "${objfile}" "${exefile}" executable "debug $lang"] != "" } { | |
42 | untested "Couldn't compile ${srcfile} in $lang mode" | |
43 | return -1 | |
44 | } | |
45 | return 0 | |
46 | } | |
47 | ||
48 | proc test_value_in_inferior {} { | |
49 | global gdb_prompt | |
50 | global testfile | |
51 | ||
52 | gdb_breakpoint [gdb_get_line_number "break to inspect struct and union"] | |
53 | ||
54 | gdb_continue_to_breakpoint "break to inspect struct and union" | |
55 | ||
56 | # Just get inferior variable s in the value history, available to guile. | |
57 | gdb_test "print s" "= {a = 3, b = 5}" "" | |
58 | ||
59 | gdb_scm_test_silent_cmd "gu (define s (history-ref 0))" "set s" | |
60 | ||
61 | gdb_test "gu (print (value-field s \"a\"))" \ | |
62 | "= 3" "access element inside struct using string name" | |
63 | ||
7a5a839f LC |
64 | # Append value in the value history. |
65 | gdb_scm_test_silent_cmd "gu (define i (history-append! (make-value 42)))" \ | |
66 | "append 42" | |
67 | ||
68 | gdb_test "gu i" "\[0-9\]+" | |
69 | gdb_test "gu (history-ref i)" "#<gdb:value 42>" | |
70 | gdb_test "p \$" "= 42" | |
71 | ||
350e1a76 DE |
72 | # Verify the recorded history value survives a gc. |
73 | gdb_test_no_output "guile (gc)" | |
74 | gdb_test "p \$\$" "= 42" | |
75 | ||
fb934770 LC |
76 | # Make sure 'history-append!' rejects non-value objects. |
77 | gdb_test "gu (history-append! 123)" \ | |
78 | "ERROR:.* Wrong type argument.*" "history-append! type error" | |
79 | ||
ed3ef339 DE |
80 | # Test dereferencing the argv pointer. |
81 | ||
82 | # Just get inferior variable argv the value history, available to guile. | |
83 | gdb_test "print argv" "= \\(char \\*\\*\\) 0x.*" "" | |
84 | ||
85 | gdb_scm_test_silent_cmd "gu (define argv (history-ref 0))" \ | |
86 | "set argv" | |
87 | gdb_scm_test_silent_cmd "gu (define arg0 (value-dereference argv))" \ | |
88 | "set arg0" | |
89 | ||
90 | # Check that the dereferenced value is sane. | |
673dc4a0 YQ |
91 | global has_argv0 |
92 | set test "verify dereferenced value" | |
93 | if { $has_argv0 } { | |
c0ecb95f JK |
94 | gdb_test_no_output "set print elements unlimited" "" |
95 | gdb_test_no_output "set print repeats unlimited" "" | |
673dc4a0 YQ |
96 | gdb_test "gu (print arg0)" "0x.*$testfile\"" $test |
97 | } else { | |
98 | unsupported $test | |
ed3ef339 DE |
99 | } |
100 | ||
101 | # Smoke-test value-optimized-out?. | |
102 | gdb_test "gu (print (value-optimized-out? arg0))" \ | |
103 | "= #f" "Test value-optimized-out?" | |
104 | ||
105 | # Test address attribute. | |
106 | gdb_test "gu (print (value-address arg0))" \ | |
107 | "= 0x\[\[:xdigit:\]\]+" "Test address attribute" | |
108 | # Test address attribute is #f in a non-addressable value. | |
109 | gdb_test "gu (print (value-address (make-value 42)))" \ | |
110 | "= #f" "Test address attribute in non-addressable value" | |
111 | ||
112 | # Test displaying a variable that is temporarily at a bad address. | |
113 | # But if we can examine what's at memory address 0, then we'll also be | |
114 | # able to display it without error. Don't run the test in that case. | |
20c6f1e1 | 115 | set can_read_0 [is_address_zero_readable] |
ed3ef339 DE |
116 | |
117 | # Test memory error. | |
118 | set test "parse_and_eval with memory error" | |
119 | if {$can_read_0} { | |
120 | untested $test | |
121 | } else { | |
122 | gdb_test "gu (print (parse-and-eval \"*(int*)0\"))" \ | |
123 | "ERROR: Cannot access memory at address 0x0.*" $test | |
124 | } | |
125 | ||
126 | # Test Guile lazy value handling | |
127 | set test "memory error and lazy values" | |
128 | if {$can_read_0} { | |
129 | untested $test | |
130 | } else { | |
131 | gdb_test_no_output "gu (define inval (parse-and-eval \"*(int*)0\"))" | |
132 | gdb_test "gu (print (value-lazy? inval))" \ | |
133 | "#t" | |
134 | gdb_test "gu (define inval2 (value-add inval 1))" \ | |
135 | "ERROR: Cannot access memory at address 0x0.*" $test | |
136 | gdb_test "gu (value-fetch-lazy! inval))" \ | |
137 | "ERROR: Cannot access memory at address 0x0.*" $test | |
138 | } | |
139 | gdb_test_no_output "gu (define argc-lazy (parse-and-eval \"argc\"))" | |
140 | gdb_test_no_output "gu (define argc-notlazy (parse-and-eval \"argc\"))" | |
141 | gdb_test_no_output "gu (value-fetch-lazy! argc-notlazy)" | |
142 | gdb_test "gu (print (value-lazy? argc-lazy))" "= #t" | |
143 | gdb_test "gu (print (value-lazy? argc-notlazy))" "= #f" | |
144 | gdb_test "print argc" "= 1" "sanity check argc" | |
145 | gdb_test "gu (print (value-lazy? argc-lazy))" "= #t" | |
146 | gdb_test_no_output "set argc=2" | |
147 | gdb_test "gu (print argc-notlazy)" "= 1" | |
148 | gdb_test "gu (print argc-lazy)" "= 2" | |
149 | gdb_test "gu (print (value-lazy? argc-lazy))" "= #f" | |
150 | ||
151 | # Test string fetches, both partial and whole. | |
152 | gdb_test "print st" "\"divide et impera\"" | |
153 | gdb_scm_test_silent_cmd "gu (define st (history-ref 0))" \ | |
154 | "inf: get st value from history" | |
155 | gdb_test "gu (print (value->string st))" \ | |
156 | "= divide et impera" "Test string with no length" | |
157 | gdb_test "gu (print (value->string st #:length -1))" \ | |
158 | "= divide et impera" "Test string (length = -1) is all of the string" | |
159 | gdb_test "gu (print (value->string st #:length 6))" \ | |
160 | "= divide" | |
161 | gdb_test "gu (print (string-append \"---\" (value->string st #:length 0) \"---\"))" \ | |
162 | "= ------" "Test string (length = 0) is empty" | |
163 | gdb_test "gu (print (string-length (value->string st #:length 0)))" \ | |
164 | "= 0" "Test length is 0" | |
165 | ||
166 | # Fetch a string that has embedded nulls. | |
167 | gdb_test "print nullst" "\"divide\\\\000et\\\\000impera\".*" | |
168 | gdb_scm_test_silent_cmd "gu (define nullst (history-ref 0))" \ | |
169 | "inf: get nullst value from history" | |
170 | gdb_test "gu (print (value->string nullst))" \ | |
171 | "divide" "Test string to first null" | |
172 | gdb_scm_test_silent_cmd "gu (set! nullst (value->string nullst #:length 9))" \ | |
173 | "get string beyond null" | |
174 | gdb_test "gu (print nullst)" \ | |
175 | "= divide\\\\000et" | |
176 | } | |
177 | ||
178 | proc test_strings {} { | |
179 | gdb_test "gu (make-value \"test\")" "#<gdb:value \"test\">" "make string" | |
180 | ||
181 | # Test string conversion errors. | |
182 | set save_charset [get_target_charset] | |
183 | gdb_test_no_output "set target-charset UTF-8" | |
184 | ||
185 | gdb_test_no_output "gu (set-port-conversion-strategy! #f 'error)" | |
186 | gdb_test "gu (print (value->string (make-value (string #\\x1234)) #:encoding \"ASCII\"))" \ | |
187 | "ERROR.*decoding-error.*" \ | |
188 | "value->string with default #:errors = 'error" | |
189 | ||
190 | # There is no 'escape strategy for C->SCM string conversions, but it's | |
191 | # still a legitimate value for %default-port-conversion-strategy. | |
192 | # GDB handles this by, umm, substituting 'substitute. | |
193 | # Use this case to also handle "#:errors #f" which explicitly says | |
194 | # "use %default-port-conversion-strategy". | |
195 | gdb_test_no_output "gu (set-port-conversion-strategy! #f 'escape)" | |
196 | gdb_test "gu (print (value->string (make-value (string #\\x1234)) #:encoding \"ASCII\" #:errors #f))" \ | |
197 | "= \[?\]{3}" "value->string with default #:errors = 'escape" | |
198 | ||
199 | # This is last in the default conversion tests so that | |
200 | # %default-port-conversion-strategy ends up with the default value. | |
201 | gdb_test_no_output "gu (set-port-conversion-strategy! #f 'substitute)" | |
202 | gdb_test "gu (print (value->string (make-value (string #\\x1234)) #:encoding \"ASCII\"))" \ | |
203 | "= \[?\]{3}" "value->string with default #:errors = 'substitute" | |
204 | ||
205 | gdb_test "gu (print (value->string (make-value (string #\\x1234)) #:encoding \"ASCII\" #:errors 'error))" \ | |
206 | "ERROR.*decoding-error.*" "value->string #:errors 'error" | |
207 | gdb_test "gu (print (value->string (make-value (string #\\x1234)) #:encoding \"ASCII\" #:errors 'substitute))" \ | |
208 | "= \[?\]{3}" "value->string #:errors 'substitute" | |
209 | gdb_test "gu (print (value->string (make-value \"abc\") #:errors \"foo\"))" \ | |
210 | "ERROR.*invalid error kind.*" "bad value for #:errors" | |
211 | ||
212 | gdb_test_no_output "set target-charset $save_charset" \ | |
213 | "restore target-charset" | |
214 | } | |
215 | ||
216 | proc test_lazy_strings {} { | |
217 | global hex | |
218 | ||
219 | gdb_test "print sptr" "\"pointer\"" | |
220 | gdb_scm_test_silent_cmd "gu (define sptr (history-ref 0))" \ | |
221 | "lazy strings: get sptr value from history" | |
222 | ||
223 | gdb_scm_test_silent_cmd "gu (define lstr (value->lazy-string sptr))" \ | |
224 | "Aquire lazy string" | |
225 | gdb_test "gu (print (lazy-string-type lstr))" \ | |
226 | "= const char \*." "Test lazy-string type name equality" | |
227 | gdb_test "gu (print (value-type sptr))" \ | |
228 | "= const char \*." "Test string type name equality" | |
3881fb67 YQ |
229 | |
230 | # Prevent symbol on address 0x0 being printed. | |
231 | gdb_test_no_output "set print symbol off" | |
ed3ef339 | 232 | gdb_test "print sn" "0x0" |
3881fb67 | 233 | |
ed3ef339 DE |
234 | gdb_scm_test_silent_cmd "gu (define snptr (history-ref 0))" \ |
235 | "lazy strings: get snptr value from history" | |
236 | gdb_test "gu (define snstr (value->lazy-string snptr #:length 5))" \ | |
237 | ".*cannot create a lazy string with address.*" "Test lazy string" | |
238 | gdb_scm_test_silent_cmd "gu (define snstr (value->lazy-string snptr #:length 0))" \ | |
239 | "Successfully create a lazy string" | |
240 | gdb_test "gu (print (lazy-string-length snstr))" \ | |
241 | "= 0" "Test lazy string length" | |
242 | gdb_test "gu (print (lazy-string-address snstr))" \ | |
243 | "= 0" "Test lazy string address" | |
244 | } | |
245 | ||
246 | proc test_inferior_function_call {} { | |
247 | global gdb_prompt hex decimal | |
248 | ||
249 | # Correct inferior call without arguments. | |
250 | gdb_test "p/x fp1" "= $hex.*" | |
251 | gdb_scm_test_silent_cmd "gu (define fp1 (history-ref 0))" \ | |
252 | "get fp1 value from history" | |
253 | gdb_scm_test_silent_cmd "gu (set! fp1 (value-dereference fp1))" \ | |
254 | "dereference fp1" | |
255 | gdb_test "gu (print (value-call fp1 '()))" \ | |
256 | "= void" | |
257 | ||
258 | # Correct inferior call with arguments. | |
259 | gdb_test "p/x fp2" "= $hex.*" | |
260 | gdb_scm_test_silent_cmd "gu (define fp2 (history-ref 0))" \ | |
261 | "get fp2 value from history" | |
262 | gdb_scm_test_silent_cmd "gu (set! fp2 (value-dereference fp2))" \ | |
263 | "dereference fp2" | |
264 | gdb_test "gu (print (value-call fp2 (list 10 20)))" \ | |
265 | "= 30" | |
266 | ||
267 | # Incorrect to call an int value. | |
268 | gdb_test "p i" "= $decimal.*" | |
269 | gdb_scm_test_silent_cmd "gu (define i (history-ref 0))" \ | |
270 | "inf call: get i value from history" | |
271 | gdb_test "gu (print (value-call i '()))" \ | |
272 | "ERROR: .*: Wrong type argument in position 1 \\(expecting function \\(value of TYPE_CODE_FUNC\\)\\): .*" | |
273 | ||
274 | # Incorrect number of arguments. | |
275 | gdb_test "p/x fp2" "= $hex.*" | |
276 | gdb_scm_test_silent_cmd "gu (define fp3 (history-ref 0))" \ | |
277 | "get fp3 value from history" | |
278 | gdb_scm_test_silent_cmd "gu (set! fp3 (value-dereference fp3))" \ | |
279 | "dereference fp3" | |
280 | gdb_test "gu (print (value-call fp3 (list 10)))" \ | |
281 | "ERROR: Too few arguments in function call.*" | |
282 | } | |
283 | ||
284 | proc test_value_after_death {} { | |
285 | # Construct a type while the inferior is still running. | |
286 | gdb_scm_test_silent_cmd "gu (define ptrtype (lookup-type \"PTR\"))" \ | |
287 | "create PTR type" | |
288 | ||
289 | # Kill the inferior and remove the symbols. | |
290 | gdb_test "kill" "" "kill the inferior" \ | |
291 | "Kill the program being debugged. .y or n. $" \ | |
292 | "y" | |
293 | gdb_test "file" "" "Discard the symbols" \ | |
294 | "Discard symbol table from.*y or n. $" \ | |
295 | "y" | |
296 | ||
5a1e8c7a DE |
297 | # First do a garbage collect to delete anything unused. PR 16612. |
298 | gdb_scm_test_silent_cmd "gu (gc)" "garbage collect" | |
299 | ||
ed3ef339 DE |
300 | # Now create a value using that type. Relies on arg0, created by |
301 | # test_value_in_inferior. | |
302 | gdb_scm_test_silent_cmd "gu (define castval (value-cast arg0 (type-pointer ptrtype)))" \ | |
303 | "cast arg0 to PTR" | |
304 | ||
305 | # Make sure the type is deleted. | |
306 | gdb_scm_test_silent_cmd "gu (set! ptrtype #f)" \ | |
307 | "delete PTR type" | |
308 | ||
309 | # Now see if the value's type is still valid. | |
310 | gdb_test "gu (print (value-type castval))" \ | |
311 | "= PTR ." "print value's type" | |
312 | } | |
313 | ||
314 | # Regression test for invalid subscript operations. The bug was that | |
315 | # the type of the value was not being checked before allowing a | |
316 | # subscript operation to proceed. | |
317 | ||
318 | proc test_subscript_regression {exefile lang} { | |
319 | # Start with a fresh gdb. | |
320 | clean_restart ${exefile} | |
321 | ||
322 | if ![gdb_guile_runto_main ] { | |
323 | fail "Can't run to main" | |
324 | return | |
325 | } | |
326 | ||
327 | if {$lang == "c++"} { | |
328 | gdb_breakpoint [gdb_get_line_number "break to inspect pointer by reference"] | |
329 | gdb_continue_to_breakpoint "break to inspect pointer by reference" | |
330 | ||
331 | gdb_scm_test_silent_cmd "print rptr_int" \ | |
332 | "Obtain address" | |
333 | gdb_scm_test_silent_cmd "gu (define rptr (history-ref 0))" \ | |
334 | "set rptr" | |
335 | gdb_test "gu (print (value-subscript rptr 0))" \ | |
336 | "= 2" "Check pointer passed as reference" | |
337 | ||
338 | # Just the most basic test of dynamic_cast -- it is checked in | |
339 | # the C++ tests. | |
340 | gdb_test "gu (print (value->bool (value-dynamic-cast (parse-and-eval \"base\") (type-pointer (lookup-type \"Derived\")))))" \ | |
341 | "= #t" | |
342 | ||
343 | # Likewise. | |
344 | gdb_test "gu (print (value-dynamic-type (parse-and-eval \"base\")))" \ | |
345 | "= Derived \[*\]" | |
0be03e84 DE |
346 | gdb_test "gu (print (value-dynamic-type (parse-and-eval \"base_ref\")))" \ |
347 | "= Derived \[&\]" | |
ed3ef339 DE |
348 | # A static type case. |
349 | gdb_test "gu (print (value-dynamic-type (parse-and-eval \"5\")))" \ | |
350 | "= int" | |
351 | } | |
352 | ||
353 | gdb_breakpoint [gdb_get_line_number "break to inspect struct and union"] | |
354 | gdb_continue_to_breakpoint "break to inspect struct and union" | |
355 | ||
356 | gdb_scm_test_silent_cmd "gu (define intv (make-value 1))" \ | |
357 | "Create int value for subscript test" | |
358 | gdb_scm_test_silent_cmd "gu (define stringv (make-value \"foo\"))" \ | |
359 | "Create string value for subscript test" | |
360 | ||
361 | # Try to access an int with a subscript. This should fail. | |
362 | gdb_test "gu (print intv)" \ | |
363 | "= 1" "Baseline print of an int Guile value" | |
364 | gdb_test "gu (print (value-subscript intv 0))" \ | |
365 | "ERROR: Cannot subscript requested type.*" \ | |
366 | "Attempt to access an integer with a subscript" | |
367 | ||
368 | # Try to access a string with a subscript. This should pass. | |
369 | gdb_test "gu (print stringv)" \ | |
370 | "= \"foo\"" "Baseline print of a string Guile value" | |
371 | gdb_test "gu (print (value-subscript stringv 0))" \ | |
372 | "= 102 'f'" "Attempt to access a string with a subscript" | |
373 | ||
374 | # Try to access an int array via a pointer with a subscript. | |
375 | # This should pass. | |
376 | gdb_scm_test_silent_cmd "print p" "Build pointer to array" | |
377 | gdb_scm_test_silent_cmd "gu (define pointer (history-ref 0))" "set pointer" | |
378 | gdb_test "gu (print (value-subscript pointer 0))" \ | |
379 | "= 1" "Access array via pointer with int subscript" | |
380 | gdb_test "gu (print (value-subscript pointer intv))" \ | |
381 | "= 2" "Access array via pointer with value subscript" | |
382 | ||
383 | # Try to access a single dimension array with a subscript to the | |
384 | # result. This should fail. | |
385 | gdb_test "gu (print (value-subscript (value-subscript pointer intv) 0))" \ | |
386 | "ERROR: Cannot subscript requested type.*" \ | |
387 | "Attempt to access an integer with a subscript 2" | |
388 | ||
389 | # Lastly, test subscript access to an array with multiple | |
390 | # dimensions. This should pass. | |
391 | gdb_scm_test_silent_cmd "print {\"fu \",\"foo\",\"bar\"}" "Build array" | |
392 | gdb_scm_test_silent_cmd "gu (define marray (history-ref 0))" "" | |
393 | gdb_test "gu (print (value-subscript (value-subscript marray 1) 2))" \ | |
394 | "o." "Test multiple subscript" | |
395 | } | |
396 | ||
397 | # A few tests of gdb:parse-and-eval. | |
398 | ||
399 | proc test_parse_and_eval {} { | |
400 | gdb_test "gu (print (parse-and-eval \"23\"))" \ | |
401 | "= 23" "parse-and-eval constant test" | |
402 | gdb_test "gu (print (parse-and-eval \"5 + 7\"))" \ | |
403 | "= 12" "parse-and-eval simple expression test" | |
404 | gdb_test "gu (raw-print (parse-and-eval \"5 + 7\"))" \ | |
405 | "#<gdb:value 12>" "parse-and-eval type test" | |
406 | } | |
407 | ||
408 | # Test that values are hashable. | |
409 | # N.B.: While smobs are hashable, the hash is really non-existent, | |
410 | # they all get hashed to the same value. Guile may provide a hash function | |
411 | # for smobs in a future release. In the meantime one should use a custom | |
412 | # hash table that uses gdb:hash-gsmob. | |
413 | ||
414 | proc test_value_hash {} { | |
415 | gdb_test_multiline "Simple Guile value dictionary" \ | |
416 | "guile" "" \ | |
417 | "(define one (make-value 1))" "" \ | |
418 | "(define two (make-value 2))" "" \ | |
419 | "(define three (make-value 3))" "" \ | |
420 | "(define vdict (make-hash-table 5))" "" \ | |
421 | "(hash-set! vdict one \"one str\")" "" \ | |
422 | "(hash-set! vdict two \"two str\")" "" \ | |
423 | "(hash-set! vdict three \"three str\")" "" \ | |
424 | "end" | |
425 | gdb_test "gu (print (hash-ref vdict one))" \ | |
426 | "one str" "Test dictionary hash 1" | |
427 | gdb_test "gu (print (hash-ref vdict two))" \ | |
428 | "two str" "Test dictionary hash 2" | |
429 | gdb_test "gu (print (hash-ref vdict three))" \ | |
430 | "three str" "Test dictionary hash 3" | |
431 | } | |
432 | ||
433 | # Build C version of executable. C++ is built later. | |
434 | if { [build_inferior "${binfile}" "c"] < 0 } { | |
435 | return | |
436 | } | |
437 | ||
438 | # Start with a fresh gdb. | |
439 | clean_restart ${binfile} | |
440 | ||
441 | # Skip all tests if Guile scripting is not enabled. | |
442 | if { [skip_guile_tests] } { continue } | |
443 | ||
444 | gdb_install_guile_utils | |
445 | gdb_install_guile_module | |
446 | ||
447 | test_parse_and_eval | |
448 | test_value_hash | |
449 | ||
450 | # The following tests require execution. | |
451 | ||
452 | if ![gdb_guile_runto_main] { | |
453 | fail "Can't run to main" | |
454 | return | |
455 | } | |
456 | ||
457 | test_value_in_inferior | |
458 | test_inferior_function_call | |
459 | test_strings | |
460 | test_lazy_strings | |
461 | test_value_after_death | |
462 | ||
463 | # Test either C or C++ values. | |
464 | ||
465 | test_subscript_regression "${binfile}" "c" | |
466 | ||
467 | if ![skip_cplus_tests] { | |
468 | if { [build_inferior "${binfile}-cxx" "c++"] < 0 } { | |
469 | return | |
470 | } | |
471 | with_test_prefix "c++" { | |
472 | test_subscript_regression "${binfile}-cxx" "c++" | |
473 | } | |
474 | } |