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 
4 namespace trivial {
5 // Trivial structs should be passed directly.
6 struct A {
7   void *p;
8 };
9 void foo(A);
bar()10 void 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 
22 namespace default_ctor {
23 struct A {
24   A();
25   void *p;
26 };
27 void foo(A);
bar()28 void 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 
43 namespace 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.
46 struct A {
47   A();
48   A(A &&o);
49   void *p;
50 };
51 void foo(A);
bar()52 void 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 
65 namespace all_deleted {
66 struct A {
67   A();
68   A(const A &o) = delete;
69   A(A &&o) = delete;
70   void *p;
71 };
72 void foo(A);
bar()73 void 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 
86 namespace implicitly_deleted {
87 struct A {
88   A();
89   A &operator=(A &&o);
90   void *p;
91 };
92 void foo(A);
bar()93 void 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 
106 namespace one_deleted {
107 struct A {
108   A();
109   A(A &&o) = delete;
110   void *p;
111 };
112 void foo(A);
bar()113 void 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 
126 namespace copy_defaulted {
127 struct A {
128   A();
129   A(const A &o) = default;
130   A(A &&o) = delete;
131   void *p;
132 };
133 void foo(A);
bar()134 void 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 
146 namespace move_defaulted {
147 struct A {
148   A();
149   A(const A &o) = delete;
150   A(A &&o) = default;
151   void *p;
152 };
153 void foo(A);
bar()154 void 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 
166 namespace trivial_defaulted {
167 struct A {
168   A();
169   A(const A &o) = default;
170   void *p;
171 };
172 void foo(A);
bar()173 void 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 
185 namespace two_copy_ctors {
186 struct A {
187   A();
188   A(const A &) = default;
189   A(const A &, int = 0);
190   void *p;
191 };
192 struct B : A {};
193 
194 void foo(B);
bar()195 void 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