xref: /aosp_15_r20/external/clang/test/CodeGenCXX/uncopyable-args.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li // RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s
2*67e74705SXin Li // RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-msvc -emit-llvm -o - %s | FileCheck %s -check-prefix=WIN64
3*67e74705SXin Li 
4*67e74705SXin Li namespace trivial {
5*67e74705SXin Li // Trivial structs should be passed directly.
6*67e74705SXin Li struct A {
7*67e74705SXin Li   void *p;
8*67e74705SXin Li };
9*67e74705SXin Li void foo(A);
bar()10*67e74705SXin Li void bar() {
11*67e74705SXin Li   foo({});
12*67e74705SXin Li }
13*67e74705SXin Li // CHECK-LABEL: define void @_ZN7trivial3barEv()
14*67e74705SXin Li // CHECK: alloca %"struct.trivial::A"
15*67e74705SXin Li // CHECK: load i8*, i8**
16*67e74705SXin Li // CHECK: call void @_ZN7trivial3fooENS_1AE(i8* %{{.*}})
17*67e74705SXin Li // CHECK-LABEL: declare void @_ZN7trivial3fooENS_1AE(i8*)
18*67e74705SXin Li 
19*67e74705SXin Li // WIN64-LABEL: declare void @"\01?foo@trivial@@YAXUA@1@@Z"(i64)
20*67e74705SXin Li }
21*67e74705SXin Li 
22*67e74705SXin Li namespace default_ctor {
23*67e74705SXin Li struct A {
24*67e74705SXin Li   A();
25*67e74705SXin Li   void *p;
26*67e74705SXin Li };
27*67e74705SXin Li void foo(A);
bar()28*67e74705SXin Li void bar() {
29*67e74705SXin Li   // Core issue 1590.  We can pass this type in registers, even though C++
30*67e74705SXin Li   // normally doesn't permit copies when using braced initialization.
31*67e74705SXin Li   foo({});
32*67e74705SXin Li }
33*67e74705SXin Li // CHECK-LABEL: define void @_ZN12default_ctor3barEv()
34*67e74705SXin Li // CHECK: alloca %"struct.default_ctor::A"
35*67e74705SXin Li // CHECK: call void @_Z{{.*}}C1Ev(
36*67e74705SXin Li // CHECK: load i8*, i8**
37*67e74705SXin Li // CHECK: call void @_ZN12default_ctor3fooENS_1AE(i8* %{{.*}})
38*67e74705SXin Li // CHECK-LABEL: declare void @_ZN12default_ctor3fooENS_1AE(i8*)
39*67e74705SXin Li 
40*67e74705SXin Li // WIN64-LABEL: declare void @"\01?foo@default_ctor@@YAXUA@1@@Z"(i64)
41*67e74705SXin Li }
42*67e74705SXin Li 
43*67e74705SXin Li namespace move_ctor {
44*67e74705SXin Li // The presence of a move constructor implicitly deletes the trivial copy ctor
45*67e74705SXin Li // and means that we have to pass this struct by address.
46*67e74705SXin Li struct A {
47*67e74705SXin Li   A();
48*67e74705SXin Li   A(A &&o);
49*67e74705SXin Li   void *p;
50*67e74705SXin Li };
51*67e74705SXin Li void foo(A);
bar()52*67e74705SXin Li void bar() {
53*67e74705SXin Li   foo({});
54*67e74705SXin Li }
55*67e74705SXin Li // FIXME: The copy ctor is implicitly deleted.
56*67e74705SXin Li // CHECK-DISABLED-LABEL: define void @_ZN9move_ctor3barEv()
57*67e74705SXin Li // CHECK-DISABLED: call void @_Z{{.*}}C1Ev(
58*67e74705SXin Li // CHECK-DISABLED-NOT: call
59*67e74705SXin Li // CHECK-DISABLED: call void @_ZN9move_ctor3fooENS_1AE(%"struct.move_ctor::A"* %{{.*}})
60*67e74705SXin Li // CHECK-DISABLED-LABEL: declare void @_ZN9move_ctor3fooENS_1AE(%"struct.move_ctor::A"*)
61*67e74705SXin Li 
62*67e74705SXin Li // WIN64-LABEL: declare void @"\01?foo@move_ctor@@YAXUA@1@@Z"(%"struct.move_ctor::A"*)
63*67e74705SXin Li }
64*67e74705SXin Li 
65*67e74705SXin Li namespace all_deleted {
66*67e74705SXin Li struct A {
67*67e74705SXin Li   A();
68*67e74705SXin Li   A(const A &o) = delete;
69*67e74705SXin Li   A(A &&o) = delete;
70*67e74705SXin Li   void *p;
71*67e74705SXin Li };
72*67e74705SXin Li void foo(A);
bar()73*67e74705SXin Li void bar() {
74*67e74705SXin Li   foo({});
75*67e74705SXin Li }
76*67e74705SXin Li // FIXME: The copy ctor is deleted.
77*67e74705SXin Li // CHECK-DISABLED-LABEL: define void @_ZN11all_deleted3barEv()
78*67e74705SXin Li // CHECK-DISABLED: call void @_Z{{.*}}C1Ev(
79*67e74705SXin Li // CHECK-DISABLED-NOT: call
80*67e74705SXin Li // CHECK-DISABLED: call void @_ZN11all_deleted3fooENS_1AE(%"struct.all_deleted::A"* %{{.*}})
81*67e74705SXin Li // CHECK-DISABLED-LABEL: declare void @_ZN11all_deleted3fooENS_1AE(%"struct.all_deleted::A"*)
82*67e74705SXin Li 
83*67e74705SXin Li // WIN64-LABEL: declare void @"\01?foo@all_deleted@@YAXUA@1@@Z"(%"struct.all_deleted::A"*)
84*67e74705SXin Li }
85*67e74705SXin Li 
86*67e74705SXin Li namespace implicitly_deleted {
87*67e74705SXin Li struct A {
88*67e74705SXin Li   A();
89*67e74705SXin Li   A &operator=(A &&o);
90*67e74705SXin Li   void *p;
91*67e74705SXin Li };
92*67e74705SXin Li void foo(A);
bar()93*67e74705SXin Li void bar() {
94*67e74705SXin Li   foo({});
95*67e74705SXin Li }
96*67e74705SXin Li // FIXME: The copy and move ctors are implicitly deleted.
97*67e74705SXin Li // CHECK-DISABLED-LABEL: define void @_ZN18implicitly_deleted3barEv()
98*67e74705SXin Li // CHECK-DISABLED: call void @_Z{{.*}}C1Ev(
99*67e74705SXin Li // CHECK-DISABLED-NOT: call
100*67e74705SXin Li // CHECK-DISABLED: call void @_ZN18implicitly_deleted3fooENS_1AE(%"struct.implicitly_deleted::A"* %{{.*}})
101*67e74705SXin Li // CHECK-DISABLED-LABEL: declare void @_ZN18implicitly_deleted3fooENS_1AE(%"struct.implicitly_deleted::A"*)
102*67e74705SXin Li 
103*67e74705SXin Li // WIN64-LABEL: declare void @"\01?foo@implicitly_deleted@@YAXUA@1@@Z"(%"struct.implicitly_deleted::A"*)
104*67e74705SXin Li }
105*67e74705SXin Li 
106*67e74705SXin Li namespace one_deleted {
107*67e74705SXin Li struct A {
108*67e74705SXin Li   A();
109*67e74705SXin Li   A(A &&o) = delete;
110*67e74705SXin Li   void *p;
111*67e74705SXin Li };
112*67e74705SXin Li void foo(A);
bar()113*67e74705SXin Li void bar() {
114*67e74705SXin Li   foo({});
115*67e74705SXin Li }
116*67e74705SXin Li // FIXME: The copy constructor is implicitly deleted.
117*67e74705SXin Li // CHECK-DISABLED-LABEL: define void @_ZN11one_deleted3barEv()
118*67e74705SXin Li // CHECK-DISABLED: call void @_Z{{.*}}C1Ev(
119*67e74705SXin Li // CHECK-DISABLED-NOT: call
120*67e74705SXin Li // CHECK-DISABLED: call void @_ZN11one_deleted3fooENS_1AE(%"struct.one_deleted::A"* %{{.*}})
121*67e74705SXin Li // CHECK-DISABLED-LABEL: declare void @_ZN11one_deleted3fooENS_1AE(%"struct.one_deleted::A"*)
122*67e74705SXin Li 
123*67e74705SXin Li // WIN64-LABEL: declare void @"\01?foo@one_deleted@@YAXUA@1@@Z"(%"struct.one_deleted::A"*)
124*67e74705SXin Li }
125*67e74705SXin Li 
126*67e74705SXin Li namespace copy_defaulted {
127*67e74705SXin Li struct A {
128*67e74705SXin Li   A();
129*67e74705SXin Li   A(const A &o) = default;
130*67e74705SXin Li   A(A &&o) = delete;
131*67e74705SXin Li   void *p;
132*67e74705SXin Li };
133*67e74705SXin Li void foo(A);
bar()134*67e74705SXin Li void bar() {
135*67e74705SXin Li   foo({});
136*67e74705SXin Li }
137*67e74705SXin Li // CHECK-LABEL: define void @_ZN14copy_defaulted3barEv()
138*67e74705SXin Li // CHECK: call void @_Z{{.*}}C1Ev(
139*67e74705SXin Li // CHECK: load i8*, i8**
140*67e74705SXin Li // CHECK: call void @_ZN14copy_defaulted3fooENS_1AE(i8* %{{.*}})
141*67e74705SXin Li // CHECK-LABEL: declare void @_ZN14copy_defaulted3fooENS_1AE(i8*)
142*67e74705SXin Li 
143*67e74705SXin Li // WIN64-LABEL: declare void @"\01?foo@copy_defaulted@@YAXUA@1@@Z"(i64)
144*67e74705SXin Li }
145*67e74705SXin Li 
146*67e74705SXin Li namespace move_defaulted {
147*67e74705SXin Li struct A {
148*67e74705SXin Li   A();
149*67e74705SXin Li   A(const A &o) = delete;
150*67e74705SXin Li   A(A &&o) = default;
151*67e74705SXin Li   void *p;
152*67e74705SXin Li };
153*67e74705SXin Li void foo(A);
bar()154*67e74705SXin Li void bar() {
155*67e74705SXin Li   foo({});
156*67e74705SXin Li }
157*67e74705SXin Li // CHECK-LABEL: define void @_ZN14move_defaulted3barEv()
158*67e74705SXin Li // CHECK: call void @_Z{{.*}}C1Ev(
159*67e74705SXin Li // CHECK: load i8*, i8**
160*67e74705SXin Li // CHECK: call void @_ZN14move_defaulted3fooENS_1AE(i8* %{{.*}})
161*67e74705SXin Li // CHECK-LABEL: declare void @_ZN14move_defaulted3fooENS_1AE(i8*)
162*67e74705SXin Li 
163*67e74705SXin Li // WIN64-LABEL: declare void @"\01?foo@move_defaulted@@YAXUA@1@@Z"(%"struct.move_defaulted::A"*)
164*67e74705SXin Li }
165*67e74705SXin Li 
166*67e74705SXin Li namespace trivial_defaulted {
167*67e74705SXin Li struct A {
168*67e74705SXin Li   A();
169*67e74705SXin Li   A(const A &o) = default;
170*67e74705SXin Li   void *p;
171*67e74705SXin Li };
172*67e74705SXin Li void foo(A);
bar()173*67e74705SXin Li void bar() {
174*67e74705SXin Li   foo({});
175*67e74705SXin Li }
176*67e74705SXin Li // CHECK-LABEL: define void @_ZN17trivial_defaulted3barEv()
177*67e74705SXin Li // CHECK: call void @_Z{{.*}}C1Ev(
178*67e74705SXin Li // CHECK: load i8*, i8**
179*67e74705SXin Li // CHECK: call void @_ZN17trivial_defaulted3fooENS_1AE(i8* %{{.*}})
180*67e74705SXin Li // CHECK-LABEL: declare void @_ZN17trivial_defaulted3fooENS_1AE(i8*)
181*67e74705SXin Li 
182*67e74705SXin Li // WIN64-LABEL: declare void @"\01?foo@trivial_defaulted@@YAXUA@1@@Z"(i64)
183*67e74705SXin Li }
184*67e74705SXin Li 
185*67e74705SXin Li namespace two_copy_ctors {
186*67e74705SXin Li struct A {
187*67e74705SXin Li   A();
188*67e74705SXin Li   A(const A &) = default;
189*67e74705SXin Li   A(const A &, int = 0);
190*67e74705SXin Li   void *p;
191*67e74705SXin Li };
192*67e74705SXin Li struct B : A {};
193*67e74705SXin Li 
194*67e74705SXin Li void foo(B);
bar()195*67e74705SXin Li void bar() {
196*67e74705SXin Li   foo({});
197*67e74705SXin Li }
198*67e74705SXin Li // FIXME: This class has a non-trivial copy ctor and a trivial copy ctor.  It's
199*67e74705SXin Li // not clear whether we should pass by address or in registers.
200*67e74705SXin Li // CHECK-DISABLED-LABEL: define void @_ZN14two_copy_ctors3barEv()
201*67e74705SXin Li // CHECK-DISABLED: call void @_Z{{.*}}C1Ev(
202*67e74705SXin Li // CHECK-DISABLED: call void @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"* %{{.*}})
203*67e74705SXin Li // CHECK-DISABLED-LABEL: declare void @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"*)
204*67e74705SXin Li 
205*67e74705SXin Li // WIN64-LABEL: declare void @"\01?foo@two_copy_ctors@@YAXUB@1@@Z"(%"struct.two_copy_ctors::B"*)
206*67e74705SXin Li }
207