1// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fobjc-arc  -fobjc-weak -fobjc-runtime-has-weak -emit-llvm -o - %s | FileCheck %s
2// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fobjc-arc  -fobjc-weak -fobjc-runtime-has-weak -fclang-abi-compat=4.0 -emit-llvm -o - %s | FileCheck %s
3// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fobjc-arc  -fobjc-weak -fobjc-runtime-has-weak -emit-llvm -o - -DTRIVIALABI %s | FileCheck %s
4// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fobjc-arc  -fobjc-weak -fobjc-runtime-has-weak -fclang-abi-compat=4.0 -emit-llvm -o - -DTRIVIALABI %s | FileCheck %s
5
6// Check that structs consisting solely of __strong or __weak pointer fields are
7// destructed in the callee function and structs consisting solely of __strong
8// pointer fields are passed directly.
9
10// CHECK: %[[STRUCT_STRONGWEAK:.*]] = type { i8*, i8* }
11// CHECK: %[[STRUCT_CONTAINSSTRONGWEAK:.*]] = type { %[[STRUCT_STRONGWEAK]] }
12// CHECK: %[[STRUCT_DERIVEDSTRONGWEAK:.*]] = type { %[[STRUCT_STRONGWEAK]] }
13// CHECK: %[[STRUCT_STRONG:.*]] = type { i8* }
14// CHECK: %[[STRUCT_S:.*]] = type { i8* }
15// CHECK: %[[STRUCT_CONTAINSNONTRIVIAL:.*]] = type { %{{.*}}, i8* }
16// CHECK: %[[STRUCT_NONTRIVIAL:.*]] = type { i32* }
17
18#ifdef TRIVIALABI
19struct __attribute__((trivial_abi)) StrongWeak {
20#else
21struct StrongWeak {
22#endif
23  id fstrong;
24  __weak id fweak;
25};
26
27#ifdef TRIVIALABI
28struct __attribute__((trivial_abi)) ContainsStrongWeak {
29#else
30struct ContainsStrongWeak {
31#endif
32  StrongWeak sw;
33};
34
35#ifdef TRIVIALABI
36struct __attribute__((trivial_abi)) DerivedStrongWeak : StrongWeak {
37#else
38struct DerivedStrongWeak : StrongWeak {
39#endif
40};
41
42#ifdef TRIVIALABI
43struct __attribute__((trivial_abi)) Strong {
44#else
45struct Strong {
46#endif
47  id fstrong;
48};
49
50template<class T>
51#ifdef TRIVIALABI
52struct __attribute__((trivial_abi)) S {
53#else
54struct S {
55#endif
56  T a;
57};
58
59struct NonTrivial {
60  NonTrivial();
61  NonTrivial(const NonTrivial &);
62  ~NonTrivial();
63  int *a;
64};
65
66// This struct is not passed directly nor destructed in the callee because f0
67// has type NonTrivial.
68struct ContainsNonTrivial {
69  NonTrivial f0;
70  id f1;
71};
72
73@interface C
74- (void)passStrong:(Strong)a;
75- (void)passStrongWeak:(StrongWeak)a;
76- (void)passNonTrivial:(NonTrivial)a;
77@end
78
79// CHECK: define{{.*}} void @_Z19testParamStrongWeak10StrongWeak(%[[STRUCT_STRONGWEAK]]* %{{.*}})
80// CHECK: call %struct.StrongWeak* @_ZN10StrongWeakD1Ev(
81// CHECK-NEXT: ret void
82
83void testParamStrongWeak(StrongWeak a) {
84}
85
86// CHECK: define{{.*}} void @_Z18testCallStrongWeakP10StrongWeak(%[[STRUCT_STRONGWEAK]]* %[[A:.*]])
87// CHECK: %[[A_ADDR:.*]] = alloca %[[STRUCT_STRONGWEAK]]*, align 8
88// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_STRONGWEAK]], align 8
89// CHECK: store %[[STRUCT_STRONGWEAK]]* %[[A]], %[[STRUCT_STRONGWEAK]]** %[[A_ADDR]], align 8
90// CHECK: %[[V0:.*]] = load %[[STRUCT_STRONGWEAK]]*, %[[STRUCT_STRONGWEAK]]** %[[A_ADDR]], align 8
91// CHECK: %[[CALL:.*]] = call %[[STRUCT_STRONGWEAK]]* @_ZN10StrongWeakC1ERKS_(%[[STRUCT_STRONGWEAK]]* {{[^,]*}} %[[AGG_TMP]], %[[STRUCT_STRONGWEAK]]* nonnull align 8 dereferenceable(16) %[[V0]])
92// CHECK: call void @_Z19testParamStrongWeak10StrongWeak(%[[STRUCT_STRONGWEAK]]* %[[AGG_TMP]])
93// CHECK-NOT: call
94// CHECK: ret void
95
96void testCallStrongWeak(StrongWeak *a) {
97  testParamStrongWeak(*a);
98}
99
100// CHECK: define{{.*}} void @_Z20testReturnStrongWeakP10StrongWeak(%[[STRUCT_STRONGWEAK:.*]]* noalias sret(%[[STRUCT_STRONGWEAK]]) align 8 %[[AGG_RESULT:.*]], %[[STRUCT_STRONGWEAK]]* %[[A:.*]])
101// CHECK: %[[A_ADDR:.*]] = alloca %[[STRUCT_STRONGWEAK]]*, align 8
102// CHECK: store %[[STRUCT_STRONGWEAK]]* %[[A]], %[[STRUCT_STRONGWEAK]]** %[[A_ADDR]], align 8
103// CHECK: %[[V0:.*]] = load %[[STRUCT_STRONGWEAK]]*, %[[STRUCT_STRONGWEAK]]** %[[A_ADDR]], align 8
104// CHECK: %[[CALL:.*]] = call %[[STRUCT_STRONGWEAK]]* @_ZN10StrongWeakC1ERKS_(%[[STRUCT_STRONGWEAK]]* {{[^,]*}} %[[AGG_RESULT]], %[[STRUCT_STRONGWEAK]]* nonnull align 8 dereferenceable(16) %[[V0]])
105// CHECK: ret void
106
107StrongWeak testReturnStrongWeak(StrongWeak *a) {
108  return *a;
109}
110
111// CHECK: define{{.*}} void @_Z27testParamContainsStrongWeak18ContainsStrongWeak(%[[STRUCT_CONTAINSSTRONGWEAK]]* %[[A:.*]])
112// CHECK: call %[[STRUCT_CONTAINSSTRONGWEAK]]* @_ZN18ContainsStrongWeakD1Ev(%[[STRUCT_CONTAINSSTRONGWEAK]]* {{[^,]*}} %[[A]])
113
114void testParamContainsStrongWeak(ContainsStrongWeak a) {
115}
116
117// CHECK: define{{.*}} void @_Z26testParamDerivedStrongWeak17DerivedStrongWeak(%[[STRUCT_DERIVEDSTRONGWEAK]]* %[[A:.*]])
118// CHECK: call %[[STRUCT_DERIVEDSTRONGWEAK]]* @_ZN17DerivedStrongWeakD1Ev(%[[STRUCT_DERIVEDSTRONGWEAK]]* {{[^,]*}} %[[A]])
119
120void testParamDerivedStrongWeak(DerivedStrongWeak a) {
121}
122
123// CHECK: define{{.*}} void @_Z15testParamStrong6Strong(i64 %[[A_COERCE:.*]])
124// CHECK: %[[A:.*]] = alloca %[[STRUCT_STRONG]], align 8
125// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[A]], i32 0, i32 0
126// CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[A_COERCE]] to i8*
127// CHECK: store i8* %[[COERCE_VAL_IP]], i8** %[[COERCE_DIVE]], align 8
128// CHECK: %[[CALL:.*]] = call %[[STRUCT_STRONG]]* @_ZN6StrongD1Ev(%[[STRUCT_STRONG]]* {{[^,]*}} %[[A]])
129// CHECK: ret void
130
131// CHECK: define linkonce_odr %[[STRUCT_STRONG]]* @_ZN6StrongD1Ev(
132
133void testParamStrong(Strong a) {
134}
135
136// CHECK: define{{.*}} void @_Z14testCallStrongP6Strong(%[[STRUCT_STRONG]]* %[[A:.*]])
137// CHECK: %[[A_ADDR:.*]] = alloca %[[STRUCT_STRONG]]*, align 8
138// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_STRONG]], align 8
139// CHECK: store %[[STRUCT_STRONG]]* %[[A]], %[[STRUCT_STRONG]]** %[[A_ADDR]], align 8
140// CHECK: %[[V0:.*]] = load %[[STRUCT_STRONG]]*, %[[STRUCT_STRONG]]** %[[A_ADDR]], align 8
141// CHECK: %[[CALL:.*]] = call %[[STRUCT_STRONG]]* @_ZN6StrongC1ERKS_(%[[STRUCT_STRONG]]* {{[^,]*}} %[[AGG_TMP]], %[[STRUCT_STRONG]]* nonnull align 8 dereferenceable(8) %[[V0]])
142// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[AGG_TMP]], i32 0, i32 0
143// CHECK: %[[V1:.*]] = load i8*, i8** %[[COERCE_DIVE]], align 8
144// CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i8* %[[V1]] to i64
145// CHECK: call void @_Z15testParamStrong6Strong(i64 %[[COERCE_VAL_PI]])
146// CHECK: ret void
147
148void testCallStrong(Strong *a) {
149  testParamStrong(*a);
150}
151
152// CHECK: define{{.*}} i64 @_Z16testReturnStrongP6Strong(%[[STRUCT_STRONG]]* %[[A:.*]])
153// CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_STRONG]], align 8
154// CHECK: %[[A_ADDR:.*]] = alloca %[[STRUCT_STRONG]]*, align 8
155// CHECK: store %[[STRUCT_STRONG]]* %[[A]], %[[STRUCT_STRONG]]** %[[A_ADDR]], align 8
156// CHECK: %[[V0:.*]] = load %[[STRUCT_STRONG]]*, %[[STRUCT_STRONG]]** %[[A_ADDR]], align 8
157// CHECK: %[[CALL:.*]] = call %[[STRUCT_STRONG]]* @_ZN6StrongC1ERKS_(%[[STRUCT_STRONG]]* {{[^,]*}} %[[RETVAL]], %[[STRUCT_STRONG]]* nonnull align 8 dereferenceable(8) %[[V0]])
158// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[RETVAL]], i32 0, i32 0
159// CHECK: %[[V1:.*]] = load i8*, i8** %[[COERCE_DIVE]], align 8
160// CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i8* %[[V1]] to i64
161// CHECK: ret i64 %[[COERCE_VAL_PI]]
162
163Strong testReturnStrong(Strong *a) {
164  return *a;
165}
166
167// CHECK: define{{.*}} void @_Z21testParamWeakTemplate1SIU6__weakP11objc_objectE(%[[STRUCT_S]]* %{{.*}})
168// CHECK: call %struct.S* @_ZN1SIU6__weakP11objc_objectED1Ev(
169// CHECK-NEXT: ret void
170
171void testParamWeakTemplate(S<__weak id> a) {
172}
173
174// CHECK: define{{.*}} void @_Z27testParamContainsNonTrivial18ContainsNonTrivial(%[[STRUCT_CONTAINSNONTRIVIAL]]* %{{.*}})
175// CHECK-NOT: call
176// CHECK: ret void
177
178void testParamContainsNonTrivial(ContainsNonTrivial a) {
179}
180
181// CHECK: define{{.*}} void @_Z26testCallContainsNonTrivialP18ContainsNonTrivial(
182// CHECK: call void @_Z27testParamContainsNonTrivial18ContainsNonTrivial(%[[STRUCT_CONTAINSNONTRIVIAL]]* %{{.*}})
183// CHECK: call %struct.ContainsNonTrivial* @_ZN18ContainsNonTrivialD1Ev(%[[STRUCT_CONTAINSNONTRIVIAL]]* {{[^,]*}} %{{.*}})
184
185void testCallContainsNonTrivial(ContainsNonTrivial *a) {
186  testParamContainsNonTrivial(*a);
187}
188
189namespace testThunk {
190
191// CHECK-LABEL: define{{.*}} i64 @_ZThn8_N9testThunk2D02m0Ev(
192// CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_STRONG]], align 8
193// CHECK: %[[CALL:.*]] = tail call i64 @_ZN9testThunk2D02m0Ev(
194// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[RETVAL]], i32 0, i32 0
195// CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[CALL]] to i8*
196// CHECK: store i8* %[[COERCE_VAL_IP]], i8** %[[COERCE_DIVE]], align 8
197// CHECK: %[[COERCE_DIVE2:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[RETVAL]], i32 0, i32 0
198// CHECK: %[[V3:.*]] = load i8*, i8** %[[COERCE_DIVE2]], align 8
199// CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i8* %[[V3]] to i64
200// CHECK: ret i64 %[[COERCE_VAL_PI]]
201
202struct B0 {
203  virtual Strong m0();
204};
205
206struct B1 {
207  virtual Strong m0();
208};
209
210struct D0 : B0, B1 {
211  Strong m0() override;
212};
213
214Strong D0::m0() { return {}; }
215
216}
217
218namespace testNullReceiver {
219
220// CHECK-LABEL: define{{.*}} void @_ZN16testNullReceiver5test0EP1C(
221// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_STRONG]], align 8
222// CHECK: br i1
223
224// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[AGG_TMP]], i32 0, i32 0
225// CHECK: %[[V7:.*]] = load i8*, i8** %[[COERCE_DIVE]], align 8
226// CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i8* %[[V7]] to i64
227// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i64)*)({{.*}}, i64 %[[COERCE_VAL_PI]])
228// CHECK: br
229
230// CHECK: %[[CALL1:.*]] = call %[[STRUCT_STRONG]]* @_ZN6StrongD1Ev(%[[STRUCT_STRONG]]* nonnull align 8 dereferenceable(8) %[[AGG_TMP]])
231// CHECK: br
232
233void test0(C *c) {
234  [c passStrong:Strong()];
235}
236
237// CHECK-LABEL: define{{.*}} void @_ZN16testNullReceiver5test1EP1C(
238// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_STRONGWEAK]], align 8
239// CHECK: br i1
240
241// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void ({{.*}}, %[[STRUCT_STRONGWEAK]]* %[[AGG_TMP]])
242// CHECK: br
243
244// CHECK: %[[CALL1:.*]] = call %[[STRUCT_STRONGWEAK]]* @_ZN10StrongWeakD1Ev(%[[STRUCT_STRONGWEAK]]* nonnull align 8 dereferenceable(16) %[[AGG_TMP]])
245// CHECK: br
246
247void test1(C *c) {
248  [c passStrongWeak:StrongWeak()];
249}
250
251// No null check needed.
252
253// CHECK-LABEL: define{{.*}} void @_ZN16testNullReceiver5test2EP1C(
254// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_NONTRIVIAL]], align 8
255// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, %[[STRUCT_NONTRIVIAL]]*)*)({{.*}}, %[[STRUCT_NONTRIVIAL]]* %[[AGG_TMP]])
256// CHECK-NEXT: call %[[STRUCT_NONTRIVIAL]]* @_ZN10NonTrivialD1Ev(%[[STRUCT_NONTRIVIAL]]* nonnull align 8 dereferenceable(8) %[[AGG_TMP]])
257
258void test2(C *c) {
259  [c passNonTrivial:NonTrivial()];
260}
261
262}
263