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