1 # Copyright
2007-2022 Free Software Foundation
, Inc.
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.
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.
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
/>.
16 # Check that GDB can
call C
++ functions whose parameters have
17 # object type
, and are either passed by value or implicitly by reference.
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.
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.
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.
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
66 # The generated code is placed in the test output directory.
68 # The companion test file pass
-by
-ref
-2.exp also contains
69 # manually
-written cases.
71 if {[skip_cplus_tests
]} {
72 untested
"c++ test skipped"
76 # The
program source is generated in the output directory.
77 # We use standard_testfile here to
set convenience variables.
80 # Some constant
values used when generating the source
90 #
Return 1 if the class whose special function states are STATES
91 # is copyable. Otherwise
return 0.
93 proc is_copy_constructible
{ states
} {
94 set cctor
[lindex $states
0]
95 set dtor
[lindex $states
1]
96 set mctor
[lindex $states
2]
98 if {$cctor
== "deleted" || ($cctor == "absent" && $mctor != "absent")} {
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
108 proc generate_member_function
{ classname signature length state
} {
117 set declaration
"$signature;\n"
118 set definition
"$classname\:\:$signature
121 data\
[[expr $length
- 1]\
] = $CUSTOM
;
126 set declaration
"$signature = default;\n"
129 set declaration
"$signature;\n"
130 set definition
"$classname\:\:$signature = default;\n"
133 set declaration
"$signature = delete;\n"
136 # function is not user
-defined in this case
140 return [list $declaration $definition
]
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
147 # copy constructor
, destructor
, move constructor
149 proc generate_class
{ classname length states
} {
152 set classname
"${classname}_[join $states _]"
154 for {set i
0} {$i
< [llength $states
]} {incr i
} {
157 0 {set sig
"$classname (const $classname \&rhs)"}
158 1 {set sig
"\~$classname (void)"}
159 2 {set sig
"$classname ($classname \&\&rhs)"}
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]
171 /*** C
++ class $classname
***/
180 $classname\
:\
:$classname
(void
)
182 data\
[0\
] = $ORIGINAL
;
183 data\
[[expr $length
- 1]\
] = $ORIGINAL
;
188 $classname $
{classname
}_var
; /* global var
*/
190 template
int cbv
<$classname
> ($classname
arg);"
193 # Generate a small C
++ class
195 proc generate_small_class
{ states
} {
197 return [generate_class Small $SMALL $states
];
200 # Generate a large C
++ class
202 proc generate_large_class
{ states
} {
204 return [generate_class Large $LARGE $states
];
207 # Generate a class that derives from a small class
209 proc generate_derived_class
{ states
} {
210 set base
"Small_[join $states _]"
211 set classname
"Derived_[join $states _]"
214 /*** Class derived from $base
***/
215 class $classname
: public $base
{
219 $classname $
{classname
}_var
; /* global var
*/
221 template
int cbv
<$classname
> ($classname
arg);"
224 # Generate a class that contains a small class item
226 proc generate_container_class
{ states
} {
227 set contained
"Small_[join $states _]"
228 set classname
"Container_[join $states _]"
231 /*** Class that contains $contained
***/
237 $classname $
{classname
}_var
; /* global var
*/
239 template
int cbv_container
<$classname
> ($classname
arg);"
242 # Generate useful statements that use a class in the debugee
program
244 proc generate_stmts
{ classprefix states
{cbvfun
"cbv"}} {
245 set classname
"${classprefix}_[join $states _]"
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"
258 # Generate the complete debugee
program
260 proc generate_program
{ classes stmts
} {
264 /*** THIS FILE IS GENERATED BY THE TEST.
***/
266 static
int tracer
= 0;
268 /* The
call-by
-value function.
*/
273 arg.data\
[0\
] += $ADDED
; // intentionally modify the
arg
274 return arg.data\
[0\
];
279 cbv_container
(T
arg)
281 arg.item.data\
[0\
] += $ADDED
; // intentionally modify
282 return arg.item.data\
[0\
];
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.
304 set options_nodelete
[list absent explicit defaultedIn defaultedOut
]
305 set options
[concat $options_nodelete
{deleted
}]
306 set all_combinations
{}
308 foreach cctor $options
{
309 foreach dtor $options_nodelete
{
310 foreach mctor $options
{
311 lappend all_combinations
[list $cctor $dtor $mctor
]
316 # Generate the classes.
321 foreach state $all_combinations
{
322 append classes
[generate_small_class $state
]
323 append stmts
[generate_stmts
"Small" $state]
325 append classes
[generate_large_class $state
]
326 append stmts
[generate_stmts
"Large" $state]
328 append classes
[generate_derived_class $state
]
329 append stmts
[generate_stmts
"Derived" $state]
331 append classes
[generate_container_class $state
]
332 append stmts
[generate_stmts
"Container" $state "cbv_container"]
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
340 set options
{debug c
++ additional_flags
=-std
=c
++11}
341 if {[prepare_for_testing
"failed to prepare" $testfile $srcfile $options]} {
349 set bp_location
[gdb_get_line_number
"stop here"]
350 gdb_breakpoint $bp_location
351 gdb_continue_to_breakpoint
"end of main" ".*return .*;"
353 #
Do the checks
for a given class whose
name is prefixed with PREFIX
,
354 # and whose special functions have the states given in STATES.
355 # The
name of the
call-by
-value function and the expression to access
356 # the data field can be specified explicitly
if the default
values
359 proc test_for_class
{ prefix states cbvfun data_field length
} {
360 set name "${prefix}_[join $states _]"
362 set cctor
[lindex $states
0]
363 set dtor
[lindex $states
1]
364 set mctor
[lindex $states
2]
371 # GCC version
<= 6 and Clang
do not emit DW_AT_defaulted and DW_AT_deleted.
372 set is_gcc_6_or_older
[test_compiler_info
{gcc
-[0-6]-*}]
373 set is_clang
[test_compiler_info
{clang
-*}]
374 # But Clang version
>= 7 emits DW_AT_calling_convention
for types.
375 set is_clang_6_or_older
[test_compiler_info
{clang
-[0-6]-*}]
377 with_test_prefix $
name {
378 if {[is_copy_constructible $states
]} {
379 set expected
[expr
{$ORIGINAL
+ $ADDED
}]
380 if {$cctor
== "explicit"} {
381 set expected
[expr
{$CUSTOM
+ $ADDED
}]
383 if {$dtor
== "explicit"} {
384 gdb_test
"print tracer = 0" " = 0" "reset the tracer"
387 if {$cctor
== "defaultedIn" || $dtor == "defaultedIn"} {
388 if {$is_gcc_6_or_older || $is_clang_6_or_older
} {
390 } elseif
{$is_clang
} {
391 #
If this is a pass
-by
-value case
, Clang
>= 7's
392 # DW_AT_calling_convention leads to the right decision.
393 # Otherwise, it is expected to fail.
394 if {"defaultedOut" in $states || "explicit" in $states} {
399 gdb_test "print ${cbvfun}<$name> (${name}_var)" " = $expected" \
401 gdb_test "print ${name}_var.${data_field}\[0\]" " = $ORIGINAL" \
402 "cbv argument should not change (item 0)"
404 set last_index [expr $length - 1]
405 gdb_test "print ${name}_var.${data_field}\[$last_index\]" \
407 "cbv argument should not change (item $last_index)"
409 if {$dtor == "explicit"} {
410 if {$cctor == "defaultedIn"
411 && ($is_gcc_6_or_older || $is_clang)} {
414 gdb_test "print tracer" " = $TRACE" \
415 "destructor should be called"
418 if {$cctor == "deleted" && ($is_gcc_6_or_older || $is_clang)} {
421 gdb_test "print ${cbvfun}<$name> (${name}_var)" \
422 ".* cannot be evaluated .* '$
{name}' is not copy constructible" \
423 "calling '$cbvfun
' should be refused"
428 foreach state $all_combinations {
429 test_for_class "Small" $state "cbv" "data" $SMALL
430 test_for_class "Large" $state "cbv" "data" $LARGE
431 test_for_class "Derived" $state "cbv" "data" 1
432 test_for_class "Container" $state "cbv_container" "item.data" 1