pass-by-ref.exp revision 1.1.1.8 1 # Copyright 2007-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 # Check that GDB can call C++ functions whose parameters have
17 # object type, and are either passed by value or implicitly by reference.
18 #
19 # Suppose F is a function that has a call-by-value parameter whose
20 # type is class C. When calling F with an argument A, a copy of A should
21 # be created and passed to F. If C is a trivially-copyable type, A can
22 # be copied by a straightforward memory copy. However, roughly speaking,
23 # if C has a user-defined copy constructor and/or a user-defined
24 # destructor, the copy ctor should be used to initialize the copy of A
25 # before calling F, and a reference to that copy is passed to F. After
26 # the function returns, the destructor should be called to destruct the
27 # copy. In this case, C is said to be a 'pass-by-reference' type.
28 # Determining whether C is pass-by-ref depends on
29 # how the copy ctor, destructor, and the move ctor of C are defined.
30 # First of all, C is not copy constructible if its copy constructor is
31 # explicitly or implicitly deleted. In this case, it would be illegal
32 # to pass values of type C to a function. C is pass-by-value, if all of
33 # its copy ctor, dtor, and move ctor are trivially defined.
34 # Otherwise, it is pass-by-ref.
35 #
36 # To cover the many possible combinations, this test generates classes
37 # that contain three special functions:
38 # (1) a copy constructor,
39 # (2) a destructor, and
40 # (3) a move constructor.
41 # A special function is in one of the following states:
42 # * explicit: The function is explicitly defined by the user.
43 # * defaultedIn: The function is defaulted inside the class decl,
44 # using the 'default' keyword.
45 # * defaultedOut: The function is declared inside the class decl,
46 # and defaulted outside using the 'default' keyword.
47 # * deleted: The function is explicitly deleted by the user,
48 # using the 'delete' keyword.
49 # * absent: The function is not declared by the user (i.e. it does not
50 # exist in the source. The compiler generates (or deletes) the
51 # definition in this case.
52 #
53 # The C++ ABI decides if a class is pass-by-value or pass-by-ref
54 # (i.e. trivially copyable or not) first at the language level, based
55 # on the state of the special functions. Then, at the target level, a
56 # class may be determined to be pass-by-ref because of its size
57 # (e.g. if it is too large to fit on registers). For this reason, this
58 # test generates both a small and a large version for the same
59 # combination of special function states.
60 #
61 # A class is not trivially-copyable if a base class or a field is not
62 # trivially-copyable, even though the class definition itself seems
63 # trivial. To test these cases, we also generate derived classes and
64 # container classes.
65 #
66 # The generated code is placed in the test output directory.
67 #
68 # The companion test file pass-by-ref-2.exp also contains
69 # manually-written cases.
70
71 require allow_cplus_tests
72
73 # The program source is generated in the output directory.
74 # We use standard_testfile here to set convenience variables.
75 standard_testfile .cc
76
77 # Some constant values used when generating the source
78
79 set SMALL 2
80 set LARGE 150
81 set ORIGINAL 2
82 set CUSTOM 3
83 set ADDED 4
84 set TRACE 5
85
86
87 # Return 1 if the class whose special function states are STATES
88 # is copyable. Otherwise return 0.
89
90 proc is_copy_constructible { states } {
91 set cctor [lindex $states 0]
92 set dtor [lindex $states 1]
93 set mctor [lindex $states 2]
94
95 if {$cctor == "deleted" || ($cctor == "absent" && $mctor != "absent")} {
96 return 0
97 }
98 return 1
99 }
100
101 # Generate a declaration and an out-of-class definition for a function
102 # with the provided signature. The STATE should be one of the following:
103 # - explicit, defaultedIn, defaultedOut, deleted, absent
104
105 proc generate_member_function { classname signature length state } {
106 set declaration ""
107 set definition ""
108
109 global CUSTOM
110 global TRACE
111
112 switch $state {
113 explicit {
114 set declaration "$signature;\n"
115 set definition "$classname\:\:$signature
116 {
117 data\[0\] = $CUSTOM;
118 data\[[expr $length - 1]\] = $CUSTOM;
119 tracer = $TRACE;
120 }\n"
121 }
122 defaultedIn {
123 set declaration "$signature = default;\n"
124 }
125 defaultedOut {
126 set declaration "$signature;\n"
127 set definition "$classname\:\:$signature = default;\n"
128 }
129 deleted {
130 set declaration "$signature = delete;\n"
131 }
132 default {
133 # function is not user-defined in this case
134 }
135 }
136
137 return [list $declaration $definition]
138 }
139
140 # Generate a C++ class with the given CLASSNAME and LENGTH-many
141 # integer elements. The STATES is an array of 3 items
142 # containing the desired state of the special functions
143 # in this order:
144 # copy constructor, destructor, move constructor
145
146 proc generate_class { classname length states } {
147 set declarations ""
148 set definitions ""
149 set classname "${classname}_[join $states _]"
150
151 for {set i 0} {$i < [llength $states]} {incr i} {
152 set sig ""
153 switch $i {
154 0 {set sig "$classname (const $classname \&rhs)"}
155 1 {set sig "\~$classname (void)"}
156 2 {set sig "$classname ($classname \&\&rhs)"}
157 }
158
159 set state [lindex $states $i]
160 set code [generate_member_function $classname $sig $length $state]
161 append declarations [lindex $code 0]
162 append definitions [lindex $code 1]
163 }
164
165 global ORIGINAL
166
167 return "
168 /*** C++ class $classname ***/
169 class ${classname} {
170 public:
171 $classname (void);
172 $declarations
173
174 int data\[$length\];
175 };
176
177 $classname\:\:$classname (void)
178 {
179 data\[0\] = $ORIGINAL;
180 data\[[expr $length - 1]\] = $ORIGINAL;
181 }
182
183 $definitions
184
185 $classname ${classname}_var; /* global var */
186
187 template int cbv<$classname> ($classname arg);"
188 }
189
190 # Generate a small C++ class
191
192 proc generate_small_class { states } {
193 global SMALL
194 return [generate_class Small $SMALL $states];
195 }
196
197 # Generate a large C++ class
198
199 proc generate_large_class { states } {
200 global LARGE
201 return [generate_class Large $LARGE $states];
202 }
203
204 # Generate a class that derives from a small class
205
206 proc generate_derived_class { states } {
207 set base "Small_[join $states _]"
208 set classname "Derived_[join $states _]"
209
210 return "
211 /*** Class derived from $base ***/
212 class $classname : public $base {
213 public:
214 };
215
216 $classname ${classname}_var; /* global var */
217
218 template int cbv<$classname> ($classname arg);"
219 }
220
221 # Generate a class that contains a small class item
222
223 proc generate_container_class { states } {
224 set contained "Small_[join $states _]"
225 set classname "Container_[join $states _]"
226
227 return "
228 /*** Class that contains $contained ***/
229 class $classname {
230 public:
231 $contained item;
232 };
233
234 $classname ${classname}_var; /* global var */
235
236 template int cbv_container<$classname> ($classname arg);"
237 }
238
239 # Generate useful statements that use a class in the debugee program
240
241 proc generate_stmts { classprefix states {cbvfun "cbv"}} {
242 set classname "${classprefix}_[join $states _]"
243
244 # Having an explicit call to the cbv function in the debugee program
245 # ensures that the compiler will emit necessary function in the binary.
246 if {[is_copy_constructible $states]} {
247 set cbvcall "$cbvfun<$classname> (${classname}_var);\n"
248 } else {
249 set cbvcall ""
250 }
251
252 return "$cbvcall"
253 }
254
255 # Generate the complete debugee program
256
257 proc generate_program { classes stmts } {
258 global ADDED
259
260 return "
261 /*** THIS FILE IS GENERATED BY THE TEST. ***/
262
263 static int tracer = 0;
264
265 /* The call-by-value function. */
266 template <class T>
267 int
268 cbv (T arg)
269 {
270 arg.data\[0\] += $ADDED; // intentionally modify the arg
271 return arg.data\[0\];
272 }
273
274 template <class T>
275 int
276 cbv_container (T arg)
277 {
278 arg.item.data\[0\] += $ADDED; // intentionally modify
279 return arg.item.data\[0\];
280 }
281
282 $classes
283
284 int
285 main (void)
286 {
287 $stmts
288
289 /* stop here */
290
291 return 0;
292 }"
293 }
294
295 # Compute all the combinations of special function states.
296 # We do not contain the 'deleted' state for the destructor,
297 # because it is illegal to have stack-allocated objects
298 # whose destructor have been deleted. This case is covered
299 # in pass-by-ref-2 via heap-allocated objects.
300
301 set options_nodelete [list absent explicit defaultedIn defaultedOut]
302 set options [concat $options_nodelete {deleted}]
303 set all_combinations {}
304
305 foreach cctor $options {
306 foreach dtor $options_nodelete {
307 foreach mctor $options {
308 lappend all_combinations [list $cctor $dtor $mctor]
309 }
310 }
311 }
312
313 # Generate the classes.
314
315 set classes ""
316 set stmts ""
317
318 foreach state $all_combinations {
319 append classes [generate_small_class $state]
320 append stmts [generate_stmts "Small" $state]
321
322 append classes [generate_large_class $state]
323 append stmts [generate_stmts "Large" $state]
324
325 append classes [generate_derived_class $state]
326 append stmts [generate_stmts "Derived" $state]
327
328 append classes [generate_container_class $state]
329 append stmts [generate_stmts "Container" $state "cbv_container"]
330 }
331
332 # Generate the program code and compile
333 set program [generate_program $classes $stmts]
334 set srcfile [standard_output_file ${srcfile}]
335 gdb_produce_source $srcfile $program
336
337 set options {debug c++ additional_flags=-std=c++11}
338 if {[prepare_for_testing "failed to prepare" $testfile $srcfile $options]} {
339 return -1
340 }
341
342 if {![runto_main]} {
343 return -1
344 }
345
346 set bp_location [gdb_get_line_number "stop here"]
347 gdb_breakpoint $bp_location
348 gdb_continue_to_breakpoint "end of main" ".*return .*;"
349
350 # Do the checks for a given class whose name is prefixed with PREFIX,
351 # and whose special functions have the states given in STATES.
352 # The name of the call-by-value function and the expression to access
353 # the data field can be specified explicitly if the default values
354 # do not work.
355
356 proc test_for_class { prefix states cbvfun data_field length} {
357 set name "${prefix}_[join $states _]"
358
359 set cctor [lindex $states 0]
360 set dtor [lindex $states 1]
361 set mctor [lindex $states 2]
362
363 global ORIGINAL
364 global CUSTOM
365 global ADDED
366 global TRACE
367
368 # GCC version <= 6 and Clang do not emit DW_AT_defaulted and DW_AT_deleted.
369 set is_gcc_6_or_older [test_compiler_info {gcc-[0-6]-*}]
370 set is_clang [test_compiler_info {clang-*}]
371 # But Clang version >= 7 emits DW_AT_calling_convention for types.
372 set is_clang_6_or_older [test_compiler_info {clang-[0-6]-*}]
373
374 with_test_prefix $name {
375 if {[is_copy_constructible $states]} {
376 set expected [expr {$ORIGINAL + $ADDED}]
377 if {$cctor == "explicit"} {
378 set expected [expr {$CUSTOM + $ADDED}]
379 }
380 if {$dtor == "explicit"} {
381 gdb_test "print tracer = 0" " = 0" "reset the tracer"
382 }
383
384 if {$cctor == "defaultedIn" || $dtor == "defaultedIn"} {
385 if {$is_gcc_6_or_older || $is_clang_6_or_older} {
386 setup_xfail "*-*-*"
387 } elseif {$is_clang} {
388 # If this is a pass-by-value case, Clang >= 7's
389 # DW_AT_calling_convention leads to the right decision.
390 # Otherwise, it is expected to fail.
391 if {"defaultedOut" in $states || "explicit" in $states} {
392 setup_xfail "*-*-*"
393 }
394 }
395 }
396 gdb_test "print ${cbvfun}<$name> (${name}_var)" " = $expected" \
397 "call '$cbvfun'"
398 gdb_test "print ${name}_var.${data_field}\[0\]" " = $ORIGINAL" \
399 "cbv argument should not change (item 0)"
400 if {$length > 1} {
401 set last_index [expr $length - 1]
402 gdb_test "print ${name}_var.${data_field}\[$last_index\]" \
403 " = $ORIGINAL" \
404 "cbv argument should not change (item $last_index)"
405 }
406 if {$dtor == "explicit"} {
407 if {$cctor == "defaultedIn"
408 && ($is_gcc_6_or_older || $is_clang)} {
409 setup_xfail "*-*-*"
410 }
411 gdb_test "print tracer" " = $TRACE" \
412 "destructor should be called"
413 }
414 } else {
415 if {$cctor == "deleted" && ($is_gcc_6_or_older || $is_clang)} {
416 setup_xfail "*-*-*"
417 }
418 gdb_test "print ${cbvfun}<$name> (${name}_var)" \
419 ".* cannot be evaluated .* '${name}' is not copy constructible" \
420 "calling '$cbvfun' should be refused"
421 }
422 }
423 }
424
425 foreach state $all_combinations {
426 test_for_class "Small" $state "cbv" "data" $SMALL
427 test_for_class "Large" $state "cbv" "data" $LARGE
428 test_for_class "Derived" $state "cbv" "data" 1
429 test_for_class "Container" $state "cbv_container" "item.data" 1
430 }
431