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