[RISCV] Add shrinkwrap test cases showing gaps in current impl
[llvm-project.git] / clang / test / CodeGenObjCXX / objc-struct-cxx-abi.mm
blob4d76796d86d1ffefc0b94914cb5ef246599fa897
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
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 { ptr, ptr }
11 // CHECK: %[[STRUCT_STRONG:.*]] = type { ptr }
12 // CHECK: %[[STRUCT_CONTAINSNONTRIVIAL:.*]] = type { %{{.*}}, ptr }
13 // CHECK: %[[STRUCT_NONTRIVIAL:.*]] = type { ptr }
14 // CHECK: %[[STRUCT_CONTAINSSTRONGWEAK:.*]] = type { %[[STRUCT_STRONGWEAK]] }
15 // CHECK: %[[STRUCT_S:.*]] = type { ptr }
17 #ifdef TRIVIALABI
18 struct __attribute__((trivial_abi)) StrongWeak {
19 #else
20 struct StrongWeak {
21 #endif
22   id fstrong;
23   __weak id fweak;
26 #ifdef TRIVIALABI
27 struct __attribute__((trivial_abi)) ContainsStrongWeak {
28 #else
29 struct ContainsStrongWeak {
30 #endif
31   StrongWeak sw;
34 #ifdef TRIVIALABI
35 struct __attribute__((trivial_abi)) DerivedStrongWeak : StrongWeak {
36 #else
37 struct DerivedStrongWeak : StrongWeak {
38 #endif
41 #ifdef TRIVIALABI
42 struct __attribute__((trivial_abi)) Strong {
43 #else
44 struct Strong {
45 #endif
46   id fstrong;
49 template<class T>
50 #ifdef TRIVIALABI
51 struct __attribute__((trivial_abi)) S {
52 #else
53 struct S {
54 #endif
55   T a;
58 struct NonTrivial {
59   NonTrivial();
60   NonTrivial(const NonTrivial &);
61   ~NonTrivial();
62   int *a;
65 // This struct is not passed directly nor destructed in the callee because f0
66 // has type NonTrivial.
67 struct ContainsNonTrivial {
68   NonTrivial f0;
69   id f1;
72 @interface C
73 - (void)passStrong:(Strong)a;
74 - (void)passStrongWeak:(StrongWeak)a;
75 - (void)passNonTrivial:(NonTrivial)a;
76 @end
78 // CHECK: define{{.*}} void @_Z19testParamStrongWeak10StrongWeak(ptr noundef %{{.*}})
79 // CHECK: call noundef ptr @_ZN10StrongWeakD1Ev(
80 // CHECK-NEXT: ret void
82 void testParamStrongWeak(StrongWeak a) {
85 // CHECK: define{{.*}} void @_Z18testCallStrongWeakP10StrongWeak(ptr noundef %[[A:.*]])
86 // CHECK: %[[A_ADDR:.*]] = alloca ptr, align 8
87 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_STRONGWEAK]], align 8
88 // CHECK: store ptr %[[A]], ptr %[[A_ADDR]], align 8
89 // CHECK: %[[V0:.*]] = load ptr, ptr %[[A_ADDR]], align 8
90 // CHECK: %[[CALL:.*]] = call noundef ptr @_ZN10StrongWeakC1ERKS_(ptr {{[^,]*}} %[[AGG_TMP]], ptr noundef nonnull align 8 dereferenceable(16) %[[V0]])
91 // CHECK: call void @_Z19testParamStrongWeak10StrongWeak(ptr noundef %[[AGG_TMP]])
92 // CHECK-NOT: call
93 // CHECK: ret void
95 void testCallStrongWeak(StrongWeak *a) {
96   testParamStrongWeak(*a);
99 // CHECK: define{{.*}} void @_Z20testReturnStrongWeakP10StrongWeak(ptr dead_on_unwind noalias writable sret(%[[STRUCT_STRONGWEAK:.*]]) align 8 %[[AGG_RESULT:.*]], ptr noundef %[[A:.*]])
100 // CHECK: %[[A_ADDR:a.addr]] = alloca ptr, align 8
101 // CHECK: store ptr %[[A]], ptr %[[A_ADDR]], align 8
102 // CHECK: %[[V0:.*]] = load ptr, ptr %[[A_ADDR]], align 8
103 // CHECK: %[[CALL:.*]] = call noundef ptr @_ZN10StrongWeakC1ERKS_(ptr {{[^,]*}} %[[AGG_RESULT]], ptr noundef nonnull align 8 dereferenceable(16) %[[V0]])
104 // CHECK: ret void
106 StrongWeak testReturnStrongWeak(StrongWeak *a) {
107   return *a;
110 // CHECK: define{{.*}} void @_Z27testParamContainsStrongWeak18ContainsStrongWeak(ptr noundef %[[A:.*]])
111 // CHECK: call noundef ptr @_ZN18ContainsStrongWeakD1Ev(ptr {{[^,]*}} %[[A]])
113 void testParamContainsStrongWeak(ContainsStrongWeak a) {
116 // CHECK: define{{.*}} void @_Z26testParamDerivedStrongWeak17DerivedStrongWeak(ptr noundef %[[A:.*]])
117 // CHECK: call noundef ptr @_ZN17DerivedStrongWeakD1Ev(ptr {{[^,]*}} %[[A]])
119 void testParamDerivedStrongWeak(DerivedStrongWeak a) {
122 // CHECK: define{{.*}} void @_Z15testParamStrong6Strong(i64 %[[A_COERCE:.*]])
123 // CHECK: %[[A:.*]] = alloca %[[STRUCT_STRONG]], align 8
124 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONG]], ptr %[[A]], i32 0, i32 0
125 // CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[A_COERCE]] to ptr
126 // CHECK: store ptr %[[COERCE_VAL_IP]], ptr %[[COERCE_DIVE]], align 8
127 // CHECK: %[[CALL:.*]] = call noundef ptr @_ZN6StrongD1Ev(ptr {{[^,]*}} %[[A]])
128 // CHECK: ret void
130 // CHECK: define linkonce_odr noundef ptr @_ZN6StrongD1Ev(
132 void testParamStrong(Strong a) {
135 // CHECK: define{{.*}} void @_Z14testCallStrongP6Strong(ptr noundef %[[A:.*]])
136 // CHECK: %[[A_ADDR:.*]] = alloca ptr, align 8
137 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_STRONG]], align 8
138 // CHECK: store ptr %[[A]], ptr %[[A_ADDR]], align 8
139 // CHECK: %[[V0:.*]] = load ptr, ptr %[[A_ADDR]], align 8
140 // CHECK: %[[CALL:.*]] = call noundef ptr @_ZN6StrongC1ERKS_(ptr {{[^,]*}} %[[AGG_TMP]], ptr noundef nonnull align 8 dereferenceable(8) %[[V0]])
141 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONG]], ptr %[[AGG_TMP]], i32 0, i32 0
142 // CHECK: %[[V1:.*]] = load ptr, ptr %[[COERCE_DIVE]], align 8
143 // CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint ptr %[[V1]] to i64
144 // CHECK: call void @_Z15testParamStrong6Strong(i64 %[[COERCE_VAL_PI]])
145 // CHECK: ret void
147 void testCallStrong(Strong *a) {
148   testParamStrong(*a);
151 // CHECK: define{{.*}} i64 @_Z16testReturnStrongP6Strong(ptr noundef %[[A:.*]])
152 // CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_STRONG]], align 8
153 // CHECK: %[[A_ADDR:.*]] = alloca ptr, align 8
154 // CHECK: store ptr %[[A]], ptr %[[A_ADDR]], align 8
155 // CHECK: %[[V0:.*]] = load ptr, ptr %[[A_ADDR]], align 8
156 // CHECK: %[[CALL:.*]] = call noundef ptr @_ZN6StrongC1ERKS_(ptr {{[^,]*}} %[[RETVAL]], ptr noundef nonnull align 8 dereferenceable(8) %[[V0]])
157 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONG]], ptr %[[RETVAL]], i32 0, i32 0
158 // CHECK: %[[V1:.*]] = load ptr, ptr %[[COERCE_DIVE]], align 8
159 // CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint ptr %[[V1]] to i64
160 // CHECK: ret i64 %[[COERCE_VAL_PI]]
162 Strong testReturnStrong(Strong *a) {
163   return *a;
166 // CHECK: define{{.*}} void @_Z21testParamWeakTemplate1SIU6__weakP11objc_objectE(ptr noundef %{{.*}})
167 // CHECK: call noundef ptr @_ZN1SIU6__weakP11objc_objectED1Ev(
168 // CHECK-NEXT: ret void
170 void testParamWeakTemplate(S<__weak id> a) {
173 // CHECK: define{{.*}} void @_Z27testParamContainsNonTrivial18ContainsNonTrivial(ptr noundef %{{.*}})
174 // CHECK-NOT: call
175 // CHECK: ret void
177 void testParamContainsNonTrivial(ContainsNonTrivial a) {
180 // CHECK: define{{.*}} void @_Z26testCallContainsNonTrivialP18ContainsNonTrivial(
181 // CHECK: call void @_Z27testParamContainsNonTrivial18ContainsNonTrivial(ptr noundef %{{.*}})
182 // CHECK: call noundef ptr @_ZN18ContainsNonTrivialD1Ev(ptr {{[^,]*}} %{{.*}})
184 void testCallContainsNonTrivial(ContainsNonTrivial *a) {
185   testParamContainsNonTrivial(*a);
188 namespace testThunk {
190 // CHECK-LABEL: define{{.*}} i64 @_ZThn8_N9testThunk2D02m0Ev(
191 // CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_STRONG]], align 8
192 // CHECK: %[[CALL:.*]] = tail call i64 @_ZN9testThunk2D02m0Ev(
193 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONG]], ptr %[[RETVAL]], i32 0, i32 0
194 // CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[CALL]] to ptr
195 // CHECK: store ptr %[[COERCE_VAL_IP]], ptr %[[COERCE_DIVE]], align 8
196 // CHECK: %[[COERCE_DIVE2:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONG]], ptr %[[RETVAL]], i32 0, i32 0
197 // CHECK: %[[V3:.*]] = load ptr, ptr %[[COERCE_DIVE2]], align 8
198 // CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint ptr %[[V3]] to i64
199 // CHECK: ret i64 %[[COERCE_VAL_PI]]
201 struct B0 {
202   virtual Strong m0();
205 struct B1 {
206   virtual Strong m0();
209 struct D0 : B0, B1 {
210   Strong m0() override;
213 Strong D0::m0() { return {}; }
217 namespace testNullReceiver {
219 // CHECK-LABEL: define{{.*}} void @_ZN16testNullReceiver5test0EP1C(
220 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_STRONG]], align 8
221 // CHECK: br i1
223 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONG]], ptr %[[AGG_TMP]], i32 0, i32 0
224 // CHECK: %[[V7:.*]] = load ptr, ptr %[[COERCE_DIVE]], align 8
225 // CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint ptr %[[V7]] to i64
226 // CHECK: call void @objc_msgSend({{.*}}, i64 %[[COERCE_VAL_PI]])
227 // CHECK: br
229 // CHECK: %[[CALL1:.*]] = call noundef ptr @_ZN6StrongD1Ev(ptr noundef nonnull align 8 dereferenceable(8) %[[AGG_TMP]])
230 // CHECK: br
232 void test0(C *c) {
233   [c passStrong:Strong()];
236 // CHECK-LABEL: define{{.*}} void @_ZN16testNullReceiver5test1EP1C(
237 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_STRONGWEAK]], align 8
238 // CHECK: br i1
240 // CHECK: call void @objc_msgSend({{.*}}, ptr noundef %[[AGG_TMP]])
241 // CHECK: br
243 // CHECK: %[[CALL1:.*]] = call noundef ptr @_ZN10StrongWeakD1Ev(ptr noundef nonnull align 8 dereferenceable(16) %[[AGG_TMP]])
244 // CHECK: br
246 void test1(C *c) {
247   [c passStrongWeak:StrongWeak()];
250 // No null check needed.
252 // CHECK-LABEL: define{{.*}} void @_ZN16testNullReceiver5test2EP1C(
253 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_NONTRIVIAL]], align 8
254 // CHECK: call void @objc_msgSend({{.*}}, ptr noundef %[[AGG_TMP]])
255 // CHECK-NEXT: call noundef ptr @_ZN10NonTrivialD1Ev(ptr noundef nonnull align 8 dereferenceable(8) %[[AGG_TMP]])
257 void test2(C *c) {
258   [c passNonTrivial:NonTrivial()];