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