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