[clang] Handle __declspec() attributes in using
[llvm-project.git] / clang / test / CodeGenObjCXX / objc-struct-cxx-abi.mm
blobe7119f9ec1067fdd83000c245f8de7b4a146155f
1 // RUN: %clang_cc1 -no-opaque-pointers -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 -no-opaque-pointers -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 -no-opaque-pointers -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 -no-opaque-pointers -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
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.
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* }
18 #ifdef TRIVIALABI
19 struct __attribute__((trivial_abi)) StrongWeak {
20 #else
21 struct StrongWeak {
22 #endif
23   id fstrong;
24   __weak id fweak;
27 #ifdef TRIVIALABI
28 struct __attribute__((trivial_abi)) ContainsStrongWeak {
29 #else
30 struct ContainsStrongWeak {
31 #endif
32   StrongWeak sw;
35 #ifdef TRIVIALABI
36 struct __attribute__((trivial_abi)) DerivedStrongWeak : StrongWeak {
37 #else
38 struct DerivedStrongWeak : StrongWeak {
39 #endif
42 #ifdef TRIVIALABI
43 struct __attribute__((trivial_abi)) Strong {
44 #else
45 struct Strong {
46 #endif
47   id fstrong;
50 template<class T>
51 #ifdef TRIVIALABI
52 struct __attribute__((trivial_abi)) S {
53 #else
54 struct S {
55 #endif
56   T a;
59 struct NonTrivial {
60   NonTrivial();
61   NonTrivial(const NonTrivial &);
62   ~NonTrivial();
63   int *a;
66 // This struct is not passed directly nor destructed in the callee because f0
67 // has type NonTrivial.
68 struct ContainsNonTrivial {
69   NonTrivial f0;
70   id f1;
73 @interface C
74 - (void)passStrong:(Strong)a;
75 - (void)passStrongWeak:(StrongWeak)a;
76 - (void)passNonTrivial:(NonTrivial)a;
77 @end
79 // CHECK: define{{.*}} void @_Z19testParamStrongWeak10StrongWeak(%[[STRUCT_STRONGWEAK]]* noundef %{{.*}})
80 // CHECK: call noundef %struct.StrongWeak* @_ZN10StrongWeakD1Ev(
81 // CHECK-NEXT: ret void
83 void testParamStrongWeak(StrongWeak a) {
86 // CHECK: define{{.*}} void @_Z18testCallStrongWeakP10StrongWeak(%[[STRUCT_STRONGWEAK]]* noundef %[[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 noundef %[[STRUCT_STRONGWEAK]]* @_ZN10StrongWeakC1ERKS_(%[[STRUCT_STRONGWEAK]]* {{[^,]*}} %[[AGG_TMP]], %[[STRUCT_STRONGWEAK]]* noundef nonnull align 8 dereferenceable(16) %[[V0]])
92 // CHECK: call void @_Z19testParamStrongWeak10StrongWeak(%[[STRUCT_STRONGWEAK]]* noundef %[[AGG_TMP]])
93 // CHECK-NOT: call
94 // CHECK: ret void
96 void testCallStrongWeak(StrongWeak *a) {
97   testParamStrongWeak(*a);
100 // CHECK: define{{.*}} void @_Z20testReturnStrongWeakP10StrongWeak(%[[STRUCT_STRONGWEAK:.*]]* noalias sret(%[[STRUCT_STRONGWEAK]]) align 8 %[[AGG_RESULT:.*]], %[[STRUCT_STRONGWEAK]]* noundef %[[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 noundef %[[STRUCT_STRONGWEAK]]* @_ZN10StrongWeakC1ERKS_(%[[STRUCT_STRONGWEAK]]* {{[^,]*}} %[[AGG_RESULT]], %[[STRUCT_STRONGWEAK]]* noundef nonnull align 8 dereferenceable(16) %[[V0]])
105 // CHECK: ret void
107 StrongWeak testReturnStrongWeak(StrongWeak *a) {
108   return *a;
111 // CHECK: define{{.*}} void @_Z27testParamContainsStrongWeak18ContainsStrongWeak(%[[STRUCT_CONTAINSSTRONGWEAK]]* noundef %[[A:.*]])
112 // CHECK: call noundef %[[STRUCT_CONTAINSSTRONGWEAK]]* @_ZN18ContainsStrongWeakD1Ev(%[[STRUCT_CONTAINSSTRONGWEAK]]* {{[^,]*}} %[[A]])
114 void testParamContainsStrongWeak(ContainsStrongWeak a) {
117 // CHECK: define{{.*}} void @_Z26testParamDerivedStrongWeak17DerivedStrongWeak(%[[STRUCT_DERIVEDSTRONGWEAK]]* noundef %[[A:.*]])
118 // CHECK: call noundef %[[STRUCT_DERIVEDSTRONGWEAK]]* @_ZN17DerivedStrongWeakD1Ev(%[[STRUCT_DERIVEDSTRONGWEAK]]* {{[^,]*}} %[[A]])
120 void testParamDerivedStrongWeak(DerivedStrongWeak a) {
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 noundef %[[STRUCT_STRONG]]* @_ZN6StrongD1Ev(%[[STRUCT_STRONG]]* {{[^,]*}} %[[A]])
129 // CHECK: ret void
131 // CHECK: define linkonce_odr noundef %[[STRUCT_STRONG]]* @_ZN6StrongD1Ev(
133 void testParamStrong(Strong a) {
136 // CHECK: define{{.*}} void @_Z14testCallStrongP6Strong(%[[STRUCT_STRONG]]* noundef %[[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 noundef %[[STRUCT_STRONG]]* @_ZN6StrongC1ERKS_(%[[STRUCT_STRONG]]* {{[^,]*}} %[[AGG_TMP]], %[[STRUCT_STRONG]]* noundef 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
148 void testCallStrong(Strong *a) {
149   testParamStrong(*a);
152 // CHECK: define{{.*}} i64 @_Z16testReturnStrongP6Strong(%[[STRUCT_STRONG]]* noundef %[[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 noundef %[[STRUCT_STRONG]]* @_ZN6StrongC1ERKS_(%[[STRUCT_STRONG]]* {{[^,]*}} %[[RETVAL]], %[[STRUCT_STRONG]]* noundef 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]]
163 Strong testReturnStrong(Strong *a) {
164   return *a;
167 // CHECK: define{{.*}} void @_Z21testParamWeakTemplate1SIU6__weakP11objc_objectE(%[[STRUCT_S]]* noundef %{{.*}})
168 // CHECK: call noundef %struct.S* @_ZN1SIU6__weakP11objc_objectED1Ev(
169 // CHECK-NEXT: ret void
171 void testParamWeakTemplate(S<__weak id> a) {
174 // CHECK: define{{.*}} void @_Z27testParamContainsNonTrivial18ContainsNonTrivial(%[[STRUCT_CONTAINSNONTRIVIAL]]* noundef %{{.*}})
175 // CHECK-NOT: call
176 // CHECK: ret void
178 void testParamContainsNonTrivial(ContainsNonTrivial a) {
181 // CHECK: define{{.*}} void @_Z26testCallContainsNonTrivialP18ContainsNonTrivial(
182 // CHECK: call void @_Z27testParamContainsNonTrivial18ContainsNonTrivial(%[[STRUCT_CONTAINSNONTRIVIAL]]* noundef %{{.*}})
183 // CHECK: call noundef %struct.ContainsNonTrivial* @_ZN18ContainsNonTrivialD1Ev(%[[STRUCT_CONTAINSNONTRIVIAL]]* {{[^,]*}} %{{.*}})
185 void testCallContainsNonTrivial(ContainsNonTrivial *a) {
186   testParamContainsNonTrivial(*a);
189 namespace testThunk {
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]]
202 struct B0 {
203   virtual Strong m0();
206 struct B1 {
207   virtual Strong m0();
210 struct D0 : B0, B1 {
211   Strong m0() override;
214 Strong D0::m0() { return {}; }
218 namespace testNullReceiver {
220 // CHECK-LABEL: define{{.*}} void @_ZN16testNullReceiver5test0EP1C(
221 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_STRONG]], align 8
222 // CHECK: br i1
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
230 // CHECK: %[[CALL1:.*]] = call noundef %[[STRUCT_STRONG]]* @_ZN6StrongD1Ev(%[[STRUCT_STRONG]]* noundef nonnull align 8 dereferenceable(8) %[[AGG_TMP]])
231 // CHECK: br
233 void test0(C *c) {
234   [c passStrong:Strong()];
237 // CHECK-LABEL: define{{.*}} void @_ZN16testNullReceiver5test1EP1C(
238 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_STRONGWEAK]], align 8
239 // CHECK: br i1
241 // CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void ({{.*}}, %[[STRUCT_STRONGWEAK]]* noundef %[[AGG_TMP]])
242 // CHECK: br
244 // CHECK: %[[CALL1:.*]] = call noundef %[[STRUCT_STRONGWEAK]]* @_ZN10StrongWeakD1Ev(%[[STRUCT_STRONGWEAK]]* noundef nonnull align 8 dereferenceable(16) %[[AGG_TMP]])
245 // CHECK: br
247 void test1(C *c) {
248   [c passStrongWeak:StrongWeak()];
251 // No null check needed.
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]]* noundef %[[AGG_TMP]])
256 // CHECK-NEXT: call noundef %[[STRUCT_NONTRIVIAL]]* @_ZN10NonTrivialD1Ev(%[[STRUCT_NONTRIVIAL]]* noundef nonnull align 8 dereferenceable(8) %[[AGG_TMP]])
258 void test2(C *c) {
259   [c passNonTrivial:NonTrivial()];