1// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -Wno-objc-root-class -Wno-incompatible-pointer-types -Wno-arc-unsafe-retained-assign -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-passes -o - %s | FileCheck %s 2// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -Wno-objc-root-class -Wno-incompatible-pointer-types -Wno-arc-unsafe-retained-assign -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-GLOBALS %s 3 4// Check both native/non-native arc platforms. Here we check that they treat 5// nonlazybind differently. 6// RUN: %clang_cc1 -fobjc-runtime=macosx-10.6.0 -triple x86_64-apple-darwin10 -Wno-objc-root-class -Wno-incompatible-pointer-types -Wno-arc-unsafe-retained-assign -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=ARC-ALIEN %s 7// RUN: %clang_cc1 -fobjc-runtime=macosx-10.7.0 -triple x86_64-apple-darwin11 -Wno-objc-root-class -Wno-incompatible-pointer-types -Wno-arc-unsafe-retained-assign -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=ARC-NATIVE %s 8 9// ARC-ALIEN: declare extern_weak void @llvm.objc.storeStrong(ptr, ptr) 10// ARC-ALIEN: declare extern_weak ptr @llvm.objc.retain(ptr returned) 11// ARC-ALIEN: declare extern_weak ptr @llvm.objc.autoreleaseReturnValue(ptr returned) 12// ARC-ALIEN: declare ptr @objc_msgSend(ptr, ptr, ...) [[NLB:#[0-9]+]] 13// ARC-ALIEN: declare extern_weak void @llvm.objc.release(ptr) 14// ARC-ALIEN: declare extern_weak ptr @llvm.objc.retainAutoreleasedReturnValue(ptr) 15// ARC-ALIEN: declare extern_weak ptr @llvm.objc.initWeak(ptr, ptr) 16// ARC-ALIEN: declare extern_weak ptr @llvm.objc.storeWeak(ptr, ptr) 17// ARC-ALIEN: declare extern_weak ptr @llvm.objc.loadWeakRetained(ptr) 18// ARC-ALIEN: declare extern_weak void @llvm.objc.destroyWeak(ptr) 19// ARC-ALIEN: declare extern_weak ptr @llvm.objc.autorelease(ptr returned) 20// ARC-ALIEN: declare extern_weak ptr @llvm.objc.retainAutorelease(ptr returned) 21 22// ARC-NATIVE: declare void @llvm.objc.storeStrong(ptr, ptr) 23// ARC-NATIVE: declare ptr @llvm.objc.retain(ptr returned) 24// ARC-NATIVE: declare ptr @llvm.objc.autoreleaseReturnValue(ptr returned) 25// ARC-NATIVE: declare ptr @objc_msgSend(ptr, ptr, ...) [[NLB:#[0-9]+]] 26// ARC-NATIVE: declare void @llvm.objc.release(ptr) 27// ARC-NATIVE: declare ptr @llvm.objc.retainAutoreleasedReturnValue(ptr) 28// ARC-NATIVE: declare ptr @llvm.objc.initWeak(ptr, ptr) 29// ARC-NATIVE: declare ptr @llvm.objc.storeWeak(ptr, ptr) 30// ARC-NATIVE: declare ptr @llvm.objc.loadWeakRetained(ptr) 31// ARC-NATIVE: declare void @llvm.objc.destroyWeak(ptr) 32// ARC-NATIVE: declare ptr @llvm.objc.autorelease(ptr returned) 33// ARC-NATIVE: declare ptr @llvm.objc.retainAutorelease(ptr returned) 34 35// CHECK-LABEL: define{{.*}} void @test0 36void test0(id x) { 37 // CHECK: [[X:%.*]] = alloca ptr 38 // CHECK-NEXT: [[PARM:%.*]] = call ptr @llvm.objc.retain(ptr {{.*}}) 39 // CHECK-NEXT: store ptr [[PARM]], ptr [[X]] 40 // CHECK-NEXT: [[TMP:%.*]] = load ptr, ptr [[X]] 41 // CHECK-NEXT: call void @llvm.objc.release(ptr [[TMP]]) 42 // CHECK-NEXT: ret void 43} 44 45// CHECK-LABEL: define{{.*}} ptr @test1(ptr 46id test1(id x) { 47 // CHECK: [[X:%.*]] = alloca ptr 48 // CHECK-NEXT: [[Y:%.*]] = alloca ptr 49 // CHECK-NEXT: [[PARM:%.*]] = call ptr @llvm.objc.retain(ptr {{%.*}}) 50 // CHECK-NEXT: store ptr [[PARM]], ptr [[X]] 51 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[Y]]) 52 // CHECK-NEXT: store ptr null, ptr [[Y]] 53 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[Y]] 54 // CHECK-NEXT: [[RET:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]]) 55 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[Y]] 56 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) 57 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[Y]]) 58 // CHECK-NEXT: [[T1:%.*]] = load ptr, ptr [[X]] 59 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]]) 60 // CHECK-NEXT: [[T1:%.*]] = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr [[RET]]) 61 // CHECK-NEXT: ret ptr [[T1]] 62 id y; 63 return y; 64} 65 66@interface Test2 67+ (void) class_method; 68- (void) inst_method; 69@end 70@implementation Test2 71 72// The self pointer of a class method is not retained. 73// CHECK: define internal void @"\01+[Test2 class_method]" 74// CHECK: alloca 75// CHECK-NEXT: alloca 76// CHECK-NEXT: store 77// CHECK-NEXT: store 78// CHECK-NEXT: ret void 79+ (void) class_method {} 80 81// The self pointer of an instance method is not retained. 82// CHECK: define internal void @"\01-[Test2 inst_method]" 83// CHECK: alloca 84// CHECK-NEXT: alloca 85// CHECK-NEXT: store 86// CHECK-NEXT: store 87// CHECK-NEXT: ret void 88- (void) inst_method {} 89@end 90 91@interface Test3 92+ (id) alloc; 93- (id) initWith: (int) x; 94- (id) copy; 95@end 96 97// CHECK-LABEL: define{{.*}} void @test3_unelided() 98void test3_unelided(void) { 99 extern void test3_helper(void); 100 101 // CHECK: [[X:%.*]] = alloca ptr 102 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]]) 103 // CHECK-NEXT: store ptr null, ptr [[X]], align 104 Test3 *x; 105 106 // Call to +alloc. 107 // CHECK-NEXT: load {{.*}}, ptr @"OBJC_CLASSLIST_REFERENCES_ 108 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_ 109 // CHECK-NEXT: [[ALLOC:%.*]] = call ptr @objc_msgSend 110 // CHECK-NEXT: call void @llvm.objc.release(ptr 111 [Test3 alloc]; 112 113 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]] 114 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_ 115 // CHECK-NEXT: [[COPY:%.*]] = call ptr @objc_msgSend(ptr noundef [[T0]], 116 // CHECK-NEXT: call void @llvm.objc.release(ptr [[COPY]]) [[NUW:#[0-9]+]] 117 [x copy]; 118 119 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]] 120 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]] 121 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[X]]) 122 // CHECK-NEXT: ret void 123} 124 125// CHECK-LABEL: define{{.*}} void @test3() 126void test3(void) { 127 // CHECK: [[X:%.*]] = alloca ptr 128 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]]) 129 130 id x = [[Test3 alloc] initWith: 5]; 131 132 // Call to +alloc. 133 // CHECK-NEXT: load {{.*}}, ptr @"OBJC_CLASSLIST_REFERENCES_ 134 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_ 135 // CHECK-NEXT: [[ALLOC:%.*]] = call ptr @objc_msgSend 136 137 // Call to -initWith: with elided retain of consumed argument. 138 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_ 139 // CHECK-NEXT: [[INIT:%.*]] = call ptr @objc_msgSend(ptr 140 // Assignment for initialization, retention elided. 141 // CHECK-NEXT: store ptr [[INIT]], ptr [[X]] 142 143 // Call to -copy. 144 // CHECK-NEXT: [[V:%.*]] = load ptr, ptr [[X]] 145 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_ 146 // CHECK-NEXT: [[COPY:%.*]] = call ptr @objc_msgSend(ptr noundef [[V]], 147 148 // Assignment to x. 149 // CHECK-NEXT: [[TMP:%.*]] = load ptr, ptr [[X]] 150 // CHECK-NEXT: store ptr [[COPY]], ptr [[X]] 151 // CHECK-NEXT: call void @llvm.objc.release(ptr [[TMP]]) [[NUW]] 152 153 x = [x copy]; 154 155 // Cleanup for x. 156 // CHECK-NEXT: [[TMP:%.*]] = load ptr, ptr [[X]] 157 // CHECK-NEXT: call void @llvm.objc.release(ptr [[TMP]]) [[NUW]] 158 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[X]]) 159 // CHECK-NEXT: ret void 160} 161 162// CHECK-LABEL: define{{.*}} ptr @test4() 163id test4(void) { 164 // Call to +alloc. 165 // CHECK: load {{.*}}, ptr @"OBJC_CLASSLIST_REFERENCES_ 166 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_ 167 // CHECK-NEXT: [[ALLOC:%.*]] = call ptr @objc_msgSend 168 169 // Call to -initWith: with elided retain of consumed argument. 170 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_ 171 // CHECK-NEXT: [[INIT:%.*]] = call ptr @objc_msgSend(ptr noundef [[ALLOC]], 172 173 // Initialization of return value, occurring within full-expression. 174 // Retain/release elided. 175 // CHECK-NEXT: [[RET:%.*]] = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr [[INIT]]) 176 177 // CHECK-NEXT: ret ptr [[RET]] 178 179 return [[Test3 alloc] initWith: 6]; 180} 181 182@interface Test5 { 183@public 184 id var; 185} 186@end 187 188// CHECK-LABEL: define{{.*}} void @test5 189void test5(Test5 *x, id y) { 190 // Prologue. 191 // CHECK: [[X:%.*]] = alloca ptr, 192 // CHECK-NEXT: [[Y:%.*]] = alloca ptr 193 // CHECK-NEXT: call ptr @llvm.objc.retain 194 // CHECK-NEXT: store ptr {{%.*}}, ptr [[X]] 195 // CHECK-NEXT: call ptr @llvm.objc.retain 196 // CHECK-NEXT: store 197 198 // CHECK-NEXT: load ptr, ptr [[X]] 199 // CHECK-NEXT: load i64, ptr @"OBJC_IVAR_$_Test5.var" 200 // CHECK-NEXT: [[VAR:%.*]] = getelementptr 201 // CHECK-NEXT: [[TMP:%.*]] = load ptr, ptr [[VAR]] 202 // CHECK-NEXT: store ptr null, ptr [[VAR]] 203 // CHECK-NEXT: call void @llvm.objc.release(ptr [[TMP]]) [[NUW]] 204 x->var = 0; 205 206 // CHECK-NEXT: [[YVAL:%.*]] = load ptr, ptr [[Y]] 207 // CHECK-NEXT: load ptr, ptr [[X]] 208 // CHECK-NEXT: load i64, ptr @"OBJC_IVAR_$_Test5.var" 209 // CHECK-NEXT: [[VAR:%.*]] = getelementptr 210 // CHECK-NEXT: [[T0:%.*]] = call ptr @llvm.objc.retain(ptr [[YVAL]]) [[NUW]] 211 // CHECK-NEXT: [[TMP:%.*]] = load ptr, ptr [[VAR]] 212 // CHECK-NEXT: store ptr [[T0]], ptr [[VAR]] 213 // CHECK-NEXT: call void @llvm.objc.release(ptr [[TMP]]) [[NUW]] 214 x->var = y; 215 216 // Epilogue. 217 // CHECK-NEXT: [[TMP:%.*]] = load ptr, ptr [[Y]] 218 // CHECK-NEXT: call void @llvm.objc.release(ptr [[TMP]]) [[NUW]] 219 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]] 220 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]] 221 // CHECK-NEXT: ret void 222} 223 224id test6_helper(void) __attribute__((ns_returns_retained)); 225// CHECK-LABEL: define{{.*}} void @test6() 226void test6(void) { 227 // CHECK: [[X:%.*]] = alloca ptr 228 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]]) 229 // CHECK-NEXT: [[CALL:%.*]] = call ptr @test6_helper() 230 // CHECK-NEXT: store ptr [[CALL]], ptr [[X]] 231 // CHECK-NEXT: [[T1:%.*]] = load ptr, ptr [[X]] 232 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]]) [[NUW]], !clang.imprecise_release 233 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[X]]) 234 // CHECK-NEXT: ret void 235 id x = test6_helper(); 236} 237 238void test7_helper(id __attribute__((ns_consumed))); 239// CHECK-LABEL: define{{.*}} void @test7() 240void test7(void) { 241 // CHECK: [[X:%.*]] = alloca ptr 242 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]]) 243 // CHECK-NEXT: store ptr null, ptr [[X]] 244 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]] 245 // CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]]) [[NUW]] 246 // CHECK-NEXT: call void @test7_helper(ptr noundef [[T1]]) 247 // CHECK-NEXT: [[T1:%.*]] = load ptr, ptr [[X]] 248 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]]) [[NUW]], !clang.imprecise_release 249 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[X]]) 250 // CHECK-NEXT: ret void 251 id x; 252 test7_helper(x); 253} 254 255id test8_helper(void) __attribute__((ns_returns_retained)); 256void test8(void) { 257 __unsafe_unretained id x = test8_helper(); 258 // CHECK: [[X:%.*]] = alloca ptr 259 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]]) 260 // CHECK-NEXT: [[T0:%.*]] = call ptr @test8_helper() 261 // CHECK-NEXT: store ptr [[T0]], ptr [[X]] 262 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]], !clang.imprecise_release 263 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[X]]) 264 // CHECK-NEXT: ret void 265} 266 267@interface Test10 268@property (retain) Test10 *me; 269@end 270void test10(void) { 271 Test10 *x; 272 id y = x.me.me; 273 274 // CHECK-LABEL: define{{.*}} void @test10() 275 // CHECK: [[X:%.*]] = alloca ptr, align 276 // CHECK-NEXT: [[Y:%.*]] = alloca ptr, align 277 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]]) 278 // CHECK-NEXT: store ptr null, ptr [[X]] 279 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[Y]]) 280 // CHECK-NEXT: load ptr, ptr [[X]], align 281 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_{{[0-9]*}} 282 // CHECK-NEXT: [[V:%.*]] = call ptr @objc_msgSend{{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ] 283 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[V]]) 284 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_{{[0-9]*}} 285 // CHECK-NEXT: [[T3:%.*]] = call ptr @objc_msgSend{{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ] 286 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T3]]) 287 // CHECK-NEXT: store ptr [[T3]], ptr [[Y]] 288 // CHECK-NEXT: call void @llvm.objc.release(ptr [[V]]) 289 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[Y]] 290 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) 291 // CHECK-NEXT: void @llvm.lifetime.end.p0(i64 8, ptr [[Y]]) 292 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]] 293 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) 294 // CHECK-NEXT: void @llvm.lifetime.end.p0(i64 8, ptr [[X]]) 295 // CHECK-NEXT: ret void 296} 297 298void test11(id (*f)(void) __attribute__((ns_returns_retained))) { 299 // CHECK-LABEL: define{{.*}} void @test11( 300 // CHECK: [[F:%.*]] = alloca ptr, align 301 // CHECK-NEXT: [[X:%.*]] = alloca ptr, align 302 // CHECK-NEXT: store ptr {{%.*}}, ptr [[F]], align 303 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]]) 304 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[F]], align 305 // CHECK-NEXT: [[T1:%.*]] = call ptr [[T0]]() 306 // CHECK-NEXT: store ptr [[T1]], ptr [[X]], align 307 // CHECK-NEXT: [[T3:%.*]] = load ptr, ptr [[X]] 308 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T3]]) [[NUW]], !clang.imprecise_release 309 // CHECK-NEXT: void @llvm.lifetime.end.p0(i64 8, ptr [[X]]) 310 // CHECK-NEXT: ret void 311 id x = f(); 312} 313 314void test12(void) { 315 extern id test12_helper(void); 316 317 // CHECK-LABEL: define{{.*}} void @test12() 318 // CHECK: [[X:%.*]] = alloca ptr, align 319 // CHECK-NEXT: [[Y:%.*]] = alloca ptr, align 320 321 __weak id x = test12_helper(); 322 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]]) 323 // CHECK-NEXT: [[T1:%.*]] = call ptr @test12_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ] 324 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]]) 325 // CHECK-NEXT: call ptr @llvm.objc.initWeak(ptr [[X]], ptr [[T1]]) 326 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]]) 327 328 x = test12_helper(); 329 // CHECK-NEXT: [[T1:%.*]] = call ptr @test12_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ] 330 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]]) 331 // CHECK-NEXT: call ptr @llvm.objc.storeWeak(ptr [[X]], ptr [[T1]]) 332 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]]) 333 334 id y = x; 335 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[Y]]) 336 // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.loadWeakRetained(ptr [[X]]) 337 // CHECK-NEXT: store ptr [[T2]], ptr [[Y]], align 338 339 // CHECK-NEXT: [[T4:%.*]] = load ptr, ptr [[Y]] 340 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T4]]) [[NUW]], !clang.imprecise_release 341 // CHECK-NEXT: void @llvm.lifetime.end.p0(i64 8, ptr [[Y]]) 342 // CHECK-NEXT: call void @llvm.objc.destroyWeak(ptr [[X]]) 343 // CHECK-NEXT: void @llvm.lifetime.end.p0(i64 8, ptr [[X]]) 344 // CHECK: ret void 345} 346 347// Indirect consuming calls. 348void test13(void) { 349 // CHECK-LABEL: define{{.*}} void @test13() 350 // CHECK: [[X:%.*]] = alloca ptr, align 351 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]]) 352 // CHECK-NEXT: store ptr null, ptr [[X]], align 353 id x; 354 355 typedef void fnty(id __attribute__((ns_consumed))); 356 extern fnty *test13_func; 357 // CHECK-NEXT: [[FN:%.*]] = load ptr, ptr @test13_func, align 358 // CHECK-NEXT: [[X_VAL:%.*]] = load ptr, ptr [[X]], align 359 // CHECK-NEXT: [[X_TMP:%.*]] = call ptr @llvm.objc.retain(ptr [[X_VAL]]) [[NUW]] 360 // CHECK-NEXT: call void [[FN]](ptr noundef [[X_TMP]]) 361 test13_func(x); 362 363 extern fnty ^test13_block; 364 // CHECK-NEXT: [[TMP:%.*]] = load ptr, ptr @test13_block, align 365 // CHECK-NEXT: [[BLOCK_FN_PTR:%.*]] = getelementptr inbounds nuw [[BLOCKTY:%.*]], ptr [[TMP]], i32 0, i32 3 366 // CHECK-NEXT: [[X_VAL:%.*]] = load ptr, ptr [[X]], align 367 // CHECK-NEXT: [[X_TMP:%.*]] = call ptr @llvm.objc.retain(ptr [[X_VAL]]) [[NUW]] 368 // CHECK-NEXT: [[BLOCK_FN_TMP:%.*]] = load ptr, ptr [[BLOCK_FN_PTR]] 369 // CHECK-NEXT: call void [[BLOCK_FN_TMP]](ptr noundef [[TMP]], ptr noundef [[X_TMP]]) 370 test13_block(x); 371 372 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]] 373 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]] 374 // CHECK-NEXT: void @llvm.lifetime.end.p0(i64 8, ptr [[X]]) 375 // CHECK-NEXT: ret void 376} 377 378@interface Test16_super @end 379@interface Test16 : Test16_super { 380 id z; 381} 382@property (assign) int x; 383@property (retain) id y; 384- (void) dealloc; 385@end 386@implementation Test16 387@synthesize x; 388@synthesize y; 389- (void) dealloc { 390 // CHECK: define internal void @"\01-[Test16 dealloc]"( 391 // CHECK: [[SELF:%.*]] = alloca ptr, align 392 // CHECK-NEXT: [[CMD:%.*]] = alloca ptr, align 393 // CHECK-NEXT: alloca 394 // CHECK-NEXT: store ptr {{%.*}}, ptr [[SELF]], align 395 // CHECK-NEXT: store ptr {{%.*}}, ptr [[CMD]] 396 // CHECK-NEXT: [[BASE:%.*]] = load ptr, ptr [[SELF]] 397 398 // Call super. 399 // CHECK-NEXT: [[T0:%.*]] = getelementptr 400 // CHECK-NEXT: store ptr [[BASE]], ptr [[T0]] 401 // CHECK-NEXT: load ptr, ptr @"OBJC_CLASSLIST_SUP_REFS_$_ 402 // CHECK-NEXT: getelementptr 403 // CHECK-NEXT: store 404 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_ 405 // CHECK-NEXT: call void @objc_msgSendSuper2( 406 // CHECK-NEXT: ret void 407} 408 409// .cxx_destruct 410 // CHECK: define internal void @"\01-[Test16 .cxx_destruct]"( 411 // CHECK: [[SELF:%.*]] = alloca ptr, align 412 // CHECK-NEXT: [[CMD:%.*]] = alloca ptr, align 413 // CHECK-NEXT: store ptr {{%.*}}, ptr [[SELF]], align 414 // CHECK-NEXT: store ptr {{%.*}}, ptr [[CMD]] 415 // CHECK-NEXT: [[BASE:%.*]] = load ptr, ptr [[SELF]] 416 417 // Destroy y. 418 // CHECK-NEXT: [[Y_OFF:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test16.y" 419 // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[Y_OFF]] 420 // CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[T1]], ptr null) [[NUW]] 421 422 // Destroy z. 423 // CHECK-NEXT: [[Z_OFF:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test16.z" 424 // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[Z_OFF]] 425 // CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[T1]], ptr null) [[NUW]] 426 427 // CHECK-NEXT: ret void 428 429@end 430 431// This shouldn't crash. 432@interface Test17A 433@property (assign) int x; 434@end 435@interface Test17B : Test17A 436@end 437@implementation Test17B 438- (int) x { return super.x + 1; } 439@end 440 441void test19(void) { 442 // CHECK-LABEL: define{{.*}} void @test19() 443 // CHECK: [[X:%.*]] = alloca [5 x ptr], align 16 444 // CHECK: call void @llvm.lifetime.start 445 // CHECK: call void @llvm.memset.p0.i64(ptr align 16 [[X]], i8 0, i64 40, i1 false) 446 id x[5]; 447 448 extern id test19_helper(void); 449 x[2] = test19_helper(); 450 451 // CHECK-NEXT: [[T1:%.*]] = call ptr @test19_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ] 452 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]]) 453 // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [5 x ptr], ptr [[X]], i64 0, i64 2 454 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SLOT]] 455 // CHECK-NEXT: store ptr [[T1]], ptr [[SLOT]] 456 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]] 457 458 // CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [5 x ptr], ptr [[X]], i32 0, i32 0 459 // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds ptr, ptr [[BEGIN]], i64 5 460 // CHECK-NEXT: br label 461 462 // CHECK: [[AFTER:%.*]] = phi ptr [ [[END]], {{%.*}} ], [ [[NEXT:%.*]], {{%.*}} ] 463 // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds ptr, ptr [[AFTER]], i64 -1 464 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[CUR]] 465 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]], !clang.imprecise_release 466 // CHECK-NEXT: [[EQ:%.*]] = icmp eq ptr [[CUR]], [[BEGIN]] 467 // CHECK-NEXT: br i1 [[EQ]], 468 469 // CHECK: ret void 470} 471 472void test20(unsigned n) { 473 // CHECK-LABEL: define{{.*}} void @test20 474 // CHECK: [[N:%.*]] = alloca i32, align 4 475 // CHECK-NEXT: [[SAVED_STACK:%.*]] = alloca ptr 476 // CHECK-NEXT: [[VLA_EXPR:%.*]] = alloca i64, align 8 477 // CHECK-NEXT: store i32 {{%.*}}, ptr [[N]], align 4 478 479 id x[n]; 480 481 // Capture the VLA size. 482 // CHECK-NEXT: [[T0:%.*]] = load i32, ptr [[N]], align 4 483 // CHECK-NEXT: [[DIM:%.*]] = zext i32 [[T0]] to i64 484 485 // Save the stack pointer. 486 // CHECK-NEXT: [[T0:%.*]] = call ptr @llvm.stacksave.p0() 487 // CHECK-NEXT: store ptr [[T0]], ptr [[SAVED_STACK]] 488 489 // Allocate the VLA. 490 // CHECK-NEXT: [[VLA:%.*]] = alloca ptr, i64 [[DIM]], align 16 491 492 // Store the VLA #elements expression. 493 // CHECK-NEXT: store i64 [[DIM]], ptr [[VLA_EXPR]], align 8 494 495 // Zero-initialize. 496 // CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[DIM]], 8 497 // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[VLA]], i8 0, i64 [[T1]], i1 false) 498 499 // Destroy. 500 // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds ptr, ptr [[VLA]], i64 [[DIM]] 501 // CHECK-NEXT: [[EMPTY:%.*]] = icmp eq ptr [[VLA]], [[END]] 502 // CHECK-NEXT: br i1 [[EMPTY]] 503 504 // CHECK: [[AFTER:%.*]] = phi ptr [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ] 505 // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds ptr, ptr [[AFTER]], i64 -1 506 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[CUR]] 507 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]], !clang.imprecise_release 508 // CHECK-NEXT: [[EQ:%.*]] = icmp eq ptr [[CUR]], [[VLA]] 509 // CHECK-NEXT: br i1 [[EQ]], 510 511 // CHECK: [[T0:%.*]] = load ptr, ptr [[SAVED_STACK]] 512 // CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[T0]]) 513 // CHECK-NEXT: ret void 514} 515 516void test21(unsigned n) { 517 // CHECK-LABEL: define{{.*}} void @test21 518 // CHECK: [[N:%.*]] = alloca i32, align 4 519 // CHECK-NEXT: [[SAVED_STACK:%.*]] = alloca ptr 520 // CHECK-NEXT: [[VLA_EXPR:%.*]] = alloca i64, align 8 521 // CHECK-NEXT: store i32 {{%.*}}, ptr [[N]], align 4 522 523 id x[2][n][3]; 524 525 // Capture the VLA size. 526 // CHECK-NEXT: [[T0:%.*]] = load i32, ptr [[N]], align 4 527 // CHECK-NEXT: [[DIM:%.*]] = zext i32 [[T0]] to i64 528 529 // CHECK-NEXT: [[T0:%.*]] = call ptr @llvm.stacksave.p0() 530 // CHECK-NEXT: store ptr [[T0]], ptr [[SAVED_STACK]] 531 532 533 // Allocate the VLA. 534 // CHECK-NEXT: [[T0:%.*]] = mul nuw i64 2, [[DIM]] 535 // CHECK-NEXT: [[VLA:%.*]] = alloca [3 x ptr], i64 [[T0]], align 16 536 537 // Store the VLA #elements expression. 538 // CHECK-NEXT: store i64 [[DIM]], ptr [[VLA_EXPR]], align 8 539 540 // Zero-initialize. 541 // CHECK-NEXT: [[T1:%.*]] = mul nuw i64 2, [[DIM]] 542 // CHECK-NEXT: [[T2:%.*]] = mul nuw i64 [[T1]], 24 543 // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[VLA]], i8 0, i64 [[T2]], i1 false) 544 545 // Destroy. 546 // CHECK-NEXT: [[T0:%.*]] = mul nuw i64 2, [[DIM]] 547 // CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [3 x ptr], ptr [[VLA]], i32 0, i32 0 548 // CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[T0]], 3 549 // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds ptr, ptr [[BEGIN]], i64 [[T1]] 550 // CHECK-NEXT: [[EMPTY:%.*]] = icmp eq ptr [[BEGIN]], [[END]] 551 // CHECK-NEXT: br i1 [[EMPTY]] 552 553 // CHECK: [[AFTER:%.*]] = phi ptr [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ] 554 // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds ptr, ptr [[AFTER]], i64 -1 555 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[CUR]] 556 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]], !clang.imprecise_release 557 // CHECK-NEXT: [[EQ:%.*]] = icmp eq ptr [[CUR]], [[BEGIN]] 558 // CHECK-NEXT: br i1 [[EQ]], 559 560 // CHECK: [[T0:%.*]] = load ptr, ptr [[SAVED_STACK]] 561 // CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[T0]]) 562 // CHECK-NEXT: ret void 563} 564 565// Note that we no longer emit .release_ivars flags. 566// Note that we set the flag saying that we need destruction *and* 567// the flag saying that we don't also need construction. 568// CHECK-GLOBALS: @"_OBJC_CLASS_RO_$_Test23" = internal global [[RO_T:%.*]] { i32 390, 569@interface Test23 { id x; } @end 570@implementation Test23 @end 571 572// CHECK-GLOBALS: @"_OBJC_CLASS_RO_$_Test24" = internal global [[RO_T:%.*]] { i32 130, 573@interface Test24 {} @end 574@implementation Test24 @end 575 576@interface Test26 { id x[4]; } @end 577@implementation Test26 @end 578// CHECK: define internal void @"\01-[Test26 .cxx_destruct]"( 579// CHECK: [[SELF:%.*]] = load ptr, ptr 580// CHECK-NEXT: [[OFFSET:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test26.x" 581// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i64 [[OFFSET]] 582// CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [4 x ptr], ptr [[T1]], i32 0, i32 0 583// CHECK-NEXT: [[END:%.*]] = getelementptr inbounds ptr, ptr [[BEGIN]], i64 4 584// CHECK-NEXT: br label 585// CHECK: [[PAST:%.*]] = phi ptr [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ] 586// CHECK-NEXT: [[CUR]] = getelementptr inbounds ptr, ptr [[PAST]], i64 -1 587// CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[CUR]], ptr null) 588// CHECK-NEXT: [[ISDONE:%.*]] = icmp eq ptr [[CUR]], [[BEGIN]] 589// CHECK-NEXT: br i1 [[ISDONE]], 590// CHECK: ret void 591 592// Check that 'init' retains self. 593@interface Test27 594- (id) init; 595@end 596@implementation Test27 597- (id) init { return self; } 598// CHECK: define internal ptr @"\01-[Test27 init]" 599// CHECK: [[SELF:%.*]] = alloca ptr, 600// CHECK-NEXT: [[CMD:%.*]] = alloca ptr, 601// CHECK-NEXT: store ptr {{%.*}}, ptr [[SELF]] 602// CHECK-NEXT: store ptr {{%.*}}, ptr [[CMD]] 603// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SELF]] 604// CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]]) 605// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SELF]] 606// CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) 607// CHECK-NEXT: ret ptr [[T2]] 608 609@end 610 611@interface Test28 612@property (copy) id prop; 613@end 614@implementation Test28 615@synthesize prop; 616@end 617// CHECK: define internal void @"\01-[Test28 .cxx_destruct]" 618// CHECK: [[SELF:%.*]] = load ptr, ptr 619// CHECK-NEXT: [[OFFSET:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test28.prop" 620// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i64 [[OFFSET]] 621// CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[T1]], ptr null) 622// CHECK-NEXT: ret void 623 624@interface Test29_super 625- (id) initWithAllocator: (id) allocator; 626@end 627@interface Test29 : Test29_super 628- (id) init; 629- (id) initWithAllocator: (id) allocator; 630@end 631@implementation Test29 632static id _test29_allocator = 0; 633- (id) init { 634// CHECK: define internal ptr @"\01-[Test29 init]"(ptr noundef {{%.*}}, 635// CHECK: [[SELF:%.*]] = alloca ptr, align 8 636// CHECK-NEXT: [[CMD:%.*]] = alloca ptr, align 8 637// CHECK-NEXT: store ptr {{%.*}}, ptr [[SELF]] 638// CHECK-NEXT: store ptr {{%.*}}, ptr [[CMD]] 639 640// Evaluate arguments. Note that the send argument is evaluated 641// before the zeroing of self. 642// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SELF]], align 8 643// CHECK-NEXT: [[T1:%.*]] = load ptr, ptr @_test29_allocator, align 8 644 645// Implicit null of 'self', i.e. direct transfer of ownership. 646// CHECK-NEXT: store ptr null, ptr [[SELF]] 647 648// Actual message send. 649// CHECK-NEXT: [[SEL:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_ 650// CHECK-NEXT: [[CALL:%.*]] = call ptr @objc_msgSend(ptr noundef [[T0]], ptr noundef [[SEL]], ptr noundef [[T1]]) 651 652// Implicit write of result back into 'self'. This is not supposed to 653// be detectable because we're supposed to ban accesses to the old 654// self value past the delegate init call. 655// CHECK-NEXT: store ptr [[CALL]], ptr [[SELF]] 656 657// Return statement. 658// CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.retain(ptr [[CALL]]) [[NUW]] 659 660// Cleanup. 661// CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[SELF]] 662// CHECK-NEXT: call void @llvm.objc.release(ptr [[T2]]) [[NUW]], !clang.imprecise_release 663 664// Return. 665// CHECK-NEXT: ret ptr [[T1]] 666 return [self initWithAllocator: _test29_allocator]; 667} 668- (id) initWithAllocator: (id) allocator { 669// CHECK: define internal ptr @"\01-[Test29 initWithAllocator:]"( 670// CHECK: [[SELF:%.*]] = alloca ptr, align 8 671// CHECK-NEXT: [[CMD:%.*]] = alloca ptr, align 8 672// CHECK-NEXT: [[ALLOCATOR:%.*]] = alloca ptr, align 8 673// CHECK-NEXT: alloca 674// CHECK-NEXT: store ptr {{%.*}}, ptr [[SELF]] 675// CHECK-NEXT: store ptr {{%.*}}, ptr [[CMD]] 676// CHECK-NEXT: [[T0:%.*]] = call ptr @llvm.objc.retain(ptr {{%.*}}) 677// CHECK-NEXT: store ptr [[T0]], ptr [[ALLOCATOR]] 678 679// Evaluate arguments. Note that the send argument is evaluated 680// before the zeroing of self. 681// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SELF]] 682// CHECK-NEXT: [[T1:%.*]] = load ptr, ptr [[ALLOCATOR]], align 8 683 684// Implicit null of 'self', i.e. direct transfer of ownership. 685// CHECK-NEXT: store ptr null, ptr [[SELF]] 686 687// Actual message send. 688// CHECK: [[CALL:%.*]] = call {{.*}} @objc_msgSendSuper2 689 690// Implicit write of result back into 'self'. This is not supposed to 691// be detectable because we're supposed to ban accesses to the old 692// self value past the delegate init call. 693// CHECK-NEXT: store ptr [[CALL]], ptr [[SELF]] 694 695// Assignment. 696// CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[CALL]]) [[NUW]] 697// CHECK-NEXT: [[T4:%.*]] = load ptr, ptr [[SELF]], align 698// CHECK-NEXT: store ptr [[T2]], ptr [[SELF]], align 699// CHECK-NEXT: call void @llvm.objc.release(ptr [[T4]]) 700 701// Return statement. 702// CHECK-NEXT: [[T3:%.*]] = load ptr, ptr [[SELF]] 703// CHECK-NEXT: [[T4:%.*]] = call ptr @llvm.objc.retain(ptr [[T3]]) [[NUW]] 704 705// Cleanup. 706// CHECK-NEXT: [[T5:%.*]] = load ptr, ptr [[ALLOCATOR]] 707// CHECK-NEXT: call void @llvm.objc.release(ptr [[T5]]) [[NUW]], !clang.imprecise_release 708 709// CHECK-NEXT: [[T6:%.*]] = load ptr, ptr [[SELF]] 710// CHECK-NEXT: call void @llvm.objc.release(ptr [[T6]]) [[NUW]], !clang.imprecise_release 711 712// Return. 713// CHECK-NEXT: ret ptr [[T4]] 714 self = [super initWithAllocator: allocator]; 715 return self; 716} 717@end 718 719typedef struct Test30_helper Test30_helper; 720@interface Test30 721- (id) init; 722- (Test30_helper*) initHelper; 723@end 724@implementation Test30 { 725char *helper; 726} 727- (id) init { 728// CHECK: define internal ptr @"\01-[Test30 init]"(ptr noundef {{%.*}}, 729// CHECK: [[RET:%.*]] = alloca ptr 730// CHECK-NEXT: alloca ptr 731// CHECK-NEXT: store ptr {{%.*}}, ptr [[SELF]] 732// CHECK-NEXT: store 733 734// Call. 735// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SELF]] 736// CHECK-NEXT: [[SEL:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_ 737// CHECK-NEXT: [[CALL:%.*]] = call ptr @objc_msgSend(ptr noundef [[T0]], ptr noundef [[SEL]]) 738 739// Assignment. 740// CHECK-NEXT: [[T1:%.*]] = load ptr, ptr [[SELF]] 741// CHECK-NEXT: [[IVAR:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test30.helper" 742// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T1]], i64 [[IVAR]] 743// CHECK-NEXT#: [[T5:%.*]] = load ptr, ptr [[T3]] 744// CHECK-NEXT#: [[T6:%.*]] = call ptr @llvm.objc.retain(ptr [[CALL]]) 745// CHECK-NEXT#: call void @llvm.objc.release(ptr [[T5]]) 746// CHECK-NEXT: store ptr [[CALL]], ptr [[T3]] 747 748// Return. 749// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SELF]] 750// CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]]) 751 752// Cleanup. 753// CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[SELF]] 754// CHECK-NEXT: call void @llvm.objc.release(ptr [[T2]]) 755 756// Epilogue. 757// CHECK-NEXT: ret ptr [[T1]] 758 self->helper = [self initHelper]; 759 return self; 760} 761- (Test30_helper*) initHelper { 762// CHECK: define internal ptr @"\01-[Test30 initHelper]"( 763// CHECK: alloca 764// CHECK-NEXT: alloca 765// CHECK-NEXT: store 766// CHECK-NEXT: store 767// CHECK-NEXT: ret ptr null 768 return 0; 769} 770 771@end 772 773__attribute__((ns_returns_retained)) id test32(void) { 774// CHECK-LABEL: define{{.*}} ptr @test32() 775// CHECK: [[T0:%.*]] = call ptr @test32_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ] 776// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]]) 777// CHECK-NEXT: ret ptr [[T0]] 778 extern id test32_helper(void); 779 return test32_helper(); 780} 781 782@class Test33_a; 783@interface Test33 784- (void) give: (Test33_a **) x; 785- (void) take: (Test33_a **) x; 786- (void) giveStrong: (out __strong Test33_a **) x; 787- (void) takeStrong: (inout __strong Test33_a **) x; 788- (void) giveOut: (out Test33_a **) x; 789@end 790void test33(Test33 *ptr) { 791 Test33_a *a; 792 [ptr give: &a]; 793 [ptr take: &a]; 794 [ptr giveStrong: &a]; 795 [ptr takeStrong: &a]; 796 [ptr giveOut: &a]; 797 798 // CHECK: define{{.*}} void @test33(ptr 799 // CHECK: [[PTR:%.*]] = alloca ptr 800 // CHECK-NEXT: [[A:%.*]] = alloca ptr 801 // CHECK-NEXT: [[TEMP0:%.*]] = alloca ptr 802 // CHECK-NEXT: [[TEMP1:%.*]] = alloca ptr 803 // CHECK-NEXT: [[TEMP2:%.*]] = alloca ptr 804 // CHECK-NEXT: llvm.objc.retain 805 // CHECK-NEXT: store 806 // CHECK-NEXT: call void @llvm.lifetime.start 807 // CHECK-NEXT: store ptr null, ptr [[A]] 808 809 // CHECK-NEXT: load ptr, ptr [[PTR]] 810 // CHECK-NEXT: [[W0:%.*]] = load ptr, ptr [[A]] 811 // CHECK-NEXT: store ptr [[W0]], ptr [[TEMP0]] 812 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_ 813 // CHECK-NEXT: objc_msgSend{{.*}}, ptr noundef [[TEMP0]]) 814 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[TEMP0]] 815 // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]]) 816 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use(ptr [[W0]]) [[NUW]] 817 // CHECK-NEXT: [[T4:%.*]] = load ptr, ptr [[A]] 818 // CHECK-NEXT: store ptr [[T2]], ptr [[A]] 819 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T4]]) 820 821 // CHECK-NEXT: load ptr, ptr [[PTR]] 822 // CHECK-NEXT: [[W0:%.*]] = load ptr, ptr [[A]] 823 // CHECK-NEXT: store ptr [[W0]], ptr [[TEMP1]] 824 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_ 825 // CHECK-NEXT: objc_msgSend{{.*}}, ptr noundef [[TEMP1]]) 826 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[TEMP1]] 827 // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]]) 828 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use(ptr [[W0]]) [[NUW]] 829 // CHECK-NEXT: [[T4:%.*]] = load ptr, ptr [[A]] 830 // CHECK-NEXT: store ptr [[T2]], ptr [[A]] 831 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T4]]) 832 833 // CHECK-NEXT: load ptr, ptr [[PTR]] 834 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_ 835 // CHECK-NEXT: objc_msgSend{{.*}}, ptr noundef [[A]]) 836 837 // CHECK-NEXT: load ptr, ptr [[PTR]] 838 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_ 839 // CHECK-NEXT: objc_msgSend{{.*}}, ptr noundef [[A]]) 840 841 // 'out' 842 // CHECK-NEXT: load ptr, ptr [[PTR]] 843 // CHECK-NEXT: store ptr null, ptr [[TEMP2]] 844 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_ 845 // CHECK-NEXT: objc_msgSend{{.*}}, ptr noundef [[TEMP2]]) 846 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[TEMP2]] 847 // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]]) 848 // CHECK-NEXT: [[T4:%.*]] = load ptr, ptr [[A]] 849 // CHECK-NEXT: store ptr [[T2]], ptr [[A]] 850 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T4]]) 851 852 // CHECK-NEXT: load 853 // CHECK-NEXT: llvm.objc.release 854 // CHECK-NEXT: call void @llvm.lifetime.end 855 // CHECK-NEXT: load 856 // CHECK-NEXT: llvm.objc.release 857 // CHECK-NEXT: ret void 858} 859 860 861// CHECK-LABEL: define{{.*}} void @test36 862void test36(id x) { 863 // CHECK: [[X:%.*]] = alloca ptr 864 865 // CHECK: call ptr @llvm.objc.retain 866 // CHECK: call ptr @llvm.objc.retain 867 // CHECK: call ptr @llvm.objc.retain 868 id array[3] = { @"A", x, @"y" }; 869 870 // CHECK: [[T0:%.*]] = load ptr, ptr [[X]] 871 // CHECK-NEXT: store ptr null, ptr [[X]] 872 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) 873 x = 0; 874 875 // CHECK: br label 876 // CHECK: call void @llvm.objc.release 877 // CHECK: br i1 878 879 // CHECK: call void @llvm.objc.release 880 // CHECK-NEXT: ret void 881} 882 883@class Test37; 884void test37(void) { 885 extern void test37_helper(id *); 886 Test37 *var; 887 test37_helper(&var); 888 889 // CHECK-LABEL: define{{.*}} void @test37() 890 // CHECK: [[VAR:%.*]] = alloca ptr, 891 // CHECK-NEXT: [[TEMP:%.*]] = alloca ptr 892 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[VAR]]) 893 // CHECK-NEXT: store ptr null, ptr [[VAR]] 894 895 // CHECK-NEXT: [[W0:%.*]] = load ptr, ptr [[VAR]] 896 // CHECK-NEXT: store ptr [[W0]], ptr [[TEMP]] 897 // CHECK-NEXT: call void @test37_helper(ptr noundef [[TEMP]]) 898 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[TEMP]] 899 // CHECK-NEXT: [[T3:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]]) 900 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use(ptr [[W0]]) [[NUW]] 901 // CHECK-NEXT: [[T5:%.*]] = load ptr, ptr [[VAR]] 902 // CHECK-NEXT: store ptr [[T3]], ptr [[VAR]] 903 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T5]]) 904 905 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[VAR]] 906 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) 907 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[VAR]]) 908 // CHECK-NEXT: ret void 909} 910 911@interface Test43 @end 912@implementation Test43 913- (id) test __attribute__((ns_returns_retained)) { 914 extern id test43_produce(void); 915 return test43_produce(); 916 // CHECK: call ptr @test43_produce(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ] 917 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use( 918 // CHECK-NEXT: ret 919} 920@end 921 922@interface Test45 923@property (retain) id x; 924@end 925@implementation Test45 926@synthesize x; 927@end 928// CHECK: define internal ptr @"\01-[Test45 x]"( 929// CHECK: [[CALL:%.*]] = tail call ptr @objc_getProperty( 930// CHECK-NEXT: ret ptr [[CALL]] 931 932void test46(__weak id *wp, __weak volatile id *wvp) { 933 extern id test46_helper(void); 934 935 // TODO: this is sub-optimal, we should retain at the actual call site. 936 937 // CHECK: [[T1:%.*]] = call ptr @test46_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ] 938 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]]) 939 // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr {{%.*}}, align 8 940 // CHECK-NEXT: [[T3:%.*]] = call ptr @llvm.objc.storeWeak(ptr [[T2]], ptr [[T1]]) 941 // CHECK-NEXT: [[T4:%.*]] = call ptr @llvm.objc.retain(ptr [[T3]]) 942 // CHECK-NEXT: store ptr [[T4]], ptr 943 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]]) 944 id x = *wp = test46_helper(); 945 946 // CHECK: [[T1:%.*]] = call ptr @test46_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ] 947 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]]) 948 // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr {{%.*}}, align 8 949 // CHECK-NEXT: [[T3:%.*]] = call ptr @llvm.objc.storeWeak(ptr [[T2]], ptr [[T1]]) 950 // CHECK-NEXT: [[T4:%.*]] = call ptr @llvm.objc.retain(ptr [[T3]]) 951 // CHECK-NEXT: store ptr [[T4]], ptr 952 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]]) 953 id y = *wvp = test46_helper(); 954} 955 956void test47(void) { 957 extern id test47_helper(void); 958 id x = x = test47_helper(); 959 960 // CHECK-LABEL: define{{.*}} void @test47() 961 // CHECK: [[X:%.*]] = alloca ptr 962 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]]) 963 // CHECK-NEXT: store ptr null, ptr [[X]] 964 // CHECK-NEXT: [[T0:%.*]] = call ptr @test47_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ] 965 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]]) 966 // CHECK-NEXT: [[T1:%.*]] = load ptr, ptr [[X]] 967 // CHECK-NEXT: store ptr [[T0]], ptr [[X]] 968 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]]) 969 // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]]) 970 // CHECK-NEXT: [[T3:%.*]] = load ptr, ptr [[X]] 971 // CHECK-NEXT: store ptr [[T2]], ptr [[X]] 972 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T3]]) 973 // CHECK-NEXT: [[T4:%.*]] = load ptr, ptr [[X]] 974 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T4]]) 975 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[X]]) 976 // CHECK-NEXT: ret void 977} 978 979void test48(void) { 980 extern id test48_helper(void); 981 __weak id x = x = test48_helper(); 982 // CHECK-LABEL: define{{.*}} void @test48() 983 // CHECK: [[X:%.*]] = alloca ptr 984 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]]) 985 // CHECK-NEXT: [[T0:%.*]] = call ptr @llvm.objc.initWeak(ptr [[X]], ptr null) 986 // CHECK-NEXT: [[T2:%.*]] = call ptr @test48_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ] 987 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T2]]) 988 // CHECK-NEXT: [[T3:%.*]] = call ptr @llvm.objc.storeWeak(ptr [[X]], ptr [[T2]]) 989 // CHECK-NEXT: [[T4:%.*]] = call ptr @llvm.objc.storeWeak(ptr [[X]], ptr [[T3]]) 990 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T2]]) 991 // CHECK-NEXT: call void @llvm.objc.destroyWeak(ptr [[X]]) 992 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[X]]) 993 // CHECK-NEXT: ret void 994} 995 996void test49(void) { 997 extern id test49_helper(void); 998 __autoreleasing id x = x = test49_helper(); 999 // CHECK-LABEL: define{{.*}} void @test49() 1000 // CHECK: [[X:%.*]] = alloca ptr 1001 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]]) 1002 // CHECK-NEXT: store ptr null, ptr [[X]] 1003 // CHECK-NEXT: [[T0:%.*]] = call ptr @test49_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ] 1004 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]]) 1005 // CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.autorelease(ptr [[T0]]) 1006 // CHECK-NEXT: store ptr [[T1]], ptr [[X]] 1007 // CHECK-NEXT: [[T3:%.*]] = call ptr @llvm.objc.retainAutorelease(ptr [[T1]]) 1008 // CHECK-NEXT: store ptr [[T3]], ptr [[X]] 1009 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[X]]) 1010 // CHECK-NEXT: ret void 1011} 1012 1013id x(void); 1014void test50(id y) { 1015 ({x();}); 1016// CHECK: [[T0:%.*]] = call ptr @llvm.objc.retain 1017// CHECK: call void @llvm.objc.release 1018} 1019 1020struct CGPoint { 1021 float x; 1022 float y; 1023}; 1024typedef struct CGPoint CGPoint; 1025 1026@interface Foo 1027@property (assign) CGPoint point; 1028@end 1029 1030@implementation Foo 1031@synthesize point; 1032@end 1033 1034id test52(void) { 1035 id test52_helper(int) __attribute__((ns_returns_retained)); 1036 return ({ int x = 5; test52_helper(x); }); 1037 1038// CHECK-LABEL: define{{.*}} ptr @test52() 1039// CHECK: [[X:%.*]] = alloca i32 1040// CHECK-NEXT: [[TMPALLOCA:%.*]] = alloca ptr 1041// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[X]]) 1042// CHECK-NEXT: store i32 5, ptr [[X]], 1043// CHECK-NEXT: [[T0:%.*]] = load i32, ptr [[X]], 1044// CHECK-NEXT: [[T1:%.*]] = call ptr @test52_helper(i32 noundef [[T0]]) 1045// CHECK-NEXT: store ptr [[T1]], ptr [[TMPALLOCA]] 1046// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[X]]) 1047// CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[TMPALLOCA]] 1048// CHECK-NEXT: [[T3:%.*]] = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr [[T2]]) 1049// CHECK-NEXT: ret ptr [[T3]] 1050} 1051 1052void test53(void) { 1053 id test53_helper(void); 1054 id x = ({ id y = test53_helper(); y; }); 1055 (void) x; 1056// CHECK-LABEL: define{{.*}} void @test53() 1057// CHECK: [[X:%.*]] = alloca ptr, 1058// CHECK-NEXT: [[Y:%.*]] = alloca ptr, 1059// CHECK-NEXT: [[TMPALLOCA:%.*]] = alloca ptr, 1060// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]]) 1061// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[Y]]) 1062// CHECK-NEXT: [[T1:%.*]] = call ptr @test53_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ] 1063// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]]) 1064// CHECK-NEXT: store ptr [[T1]], ptr [[Y]], 1065// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[Y]], 1066// CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]]) 1067// CHECK-NEXT: store ptr [[T1]], ptr [[TMPALLOCA]] 1068// CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[Y]] 1069// CHECK-NEXT: call void @llvm.objc.release(ptr [[T2]]) 1070// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[Y]]) 1071// CHECK-NEXT: [[T3:%.*]] = load ptr, ptr [[TMPALLOCA]] 1072// CHECK-NEXT: store ptr [[T3]], ptr [[X]], 1073// CHECK-NEXT: load ptr, ptr [[X]], 1074// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]] 1075// CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) 1076// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[X]]) 1077// CHECK-NEXT: ret void 1078} 1079 1080// CHECK-LABEL: define{{.*}} void @test54(i32 noundef %first, ...) 1081void test54(int first, ...) { 1082 __builtin_va_list arglist; 1083 // CHECK: call void @llvm.va_start 1084 __builtin_va_start(arglist, first); 1085 // CHECK: call ptr @llvm.objc.retain 1086 id obj = __builtin_va_arg(arglist, id); 1087 // CHECK: call void @llvm.va_end 1088 __builtin_va_end(arglist); 1089 // CHECK: call void @llvm.objc.release 1090 // CHECK: ret void 1091} 1092 1093// PR10228 1094@interface Test55Base @end 1095@interface Test55 : Test55Base @end 1096@implementation Test55 (Category) 1097- (void) dealloc {} 1098@end 1099// CHECK: define internal void @"\01-[Test55(Category) dealloc]"( 1100// CHECK-NOT: ret 1101// CHECK: call void @objc_msgSendSuper2( 1102 1103@protocol Test56Protocol 1104+ (id) make __attribute__((ns_returns_retained)); 1105@end 1106@interface Test56<Test56Protocol> @end 1107@implementation Test56 1108// CHECK: define internal ptr @"\01+[Test56 make]"( 1109+ (id) make { 1110 extern id test56_helper(void); 1111 // CHECK: [[T1:%.*]] = call ptr @test56_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ] 1112 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]]) 1113 // CHECK-NEXT: ret ptr [[T1]] 1114 return test56_helper(); 1115} 1116@end 1117void test56_test(void) { 1118 id x = [Test56 make]; 1119 // CHECK-LABEL: define{{.*}} void @test56_test() 1120 // CHECK: [[X:%.*]] = alloca ptr, align 8 1121 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]]) 1122 // CHECK: [[T0:%.*]] = call ptr @objc_msgSend( 1123 // CHECK-NEXT: store ptr [[T0]], ptr [[X]] 1124 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]] 1125 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) 1126 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[X]]) 1127 // CHECK-NEXT: ret void 1128} 1129 1130@interface Test57 1131@property (nonatomic, strong) id strong; 1132@property (nonatomic, weak) id weak; 1133@property (nonatomic, unsafe_unretained) id unsafe; 1134@end 1135@implementation Test57 1136@synthesize strong, weak, unsafe; 1137@end 1138// CHECK: define internal ptr @"\01-[Test57 strong]"( 1139// CHECK: [[T0:%.*]] = load ptr, ptr {{%.*}} 1140// CHECK-NEXT: [[T1:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test57.strong" 1141// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 [[T1]] 1142// CHECK-NEXT: [[T5:%.*]] = load ptr, ptr [[T3]] 1143// CHECK-NEXT: ret ptr [[T5]] 1144 1145// CHECK: define internal ptr @"\01-[Test57 weak]"( 1146// CHECK: [[T0:%.*]] = load ptr, ptr {{%.*}} 1147// CHECK-NEXT: [[T1:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test57.weak" 1148// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 [[T1]] 1149// CHECK-NEXT: [[T5:%.*]] = call ptr @llvm.objc.loadWeakRetained(ptr [[T3]]) 1150// CHECK-NEXT: [[T6:%.*]] = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr [[T5]]) 1151// CHECK-NEXT: ret ptr [[T6]] 1152 1153// CHECK: define internal ptr @"\01-[Test57 unsafe]"( 1154// CHECK: [[T0:%.*]] = load ptr, ptr {{%.*}} 1155// CHECK-NEXT: [[T1:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test57.unsafe" 1156// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 [[T1]] 1157// CHECK-NEXT: [[T5:%.*]] = load ptr, ptr [[T3]] 1158// CHECK-NEXT: ret ptr [[T5]] 1159 1160void test59(void) { 1161 extern id test59_getlock(void); 1162 extern void test59_body(void); 1163 @synchronized (test59_getlock()) { 1164 test59_body(); 1165 } 1166 1167 // CHECK-LABEL: define{{.*}} void @test59() 1168 // CHECK: [[T1:%.*]] = call ptr @test59_getlock(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ] 1169 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]]) 1170 // CHECK-NEXT: call i32 @objc_sync_enter(ptr [[T1]]) 1171 // CHECK-NEXT: call void @test59_body() 1172 // CHECK-NEXT: call i32 @objc_sync_exit(ptr [[T1]]) 1173 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]]) 1174 // CHECK-NEXT: ret void 1175} 1176 1177// Verify that we don't try to reclaim the result of performSelector. 1178@interface Test61 1179- (id) performSelector: (SEL) selector; 1180- (void) test61_void; 1181- (id) test61_id; 1182@end 1183void test61(void) { 1184 // CHECK-LABEL: define{{.*}} void @test61() 1185 // CHECK: [[Y:%.*]] = alloca ptr, align 8 1186 1187 extern id test61_make(void); 1188 1189 // CHECK-NEXT: [[T0:%.*]] = call ptr @test61_make(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ] 1190 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]]) 1191 // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_ 1192 // CHECK-NEXT: [[T3:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_ 1193 // CHECK-NEXT: [[T4:%.*]] = call ptr @objc_msgSend(ptr noundef [[T1]], ptr noundef [[T3]], ptr noundef [[T2]]) 1194 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]]) 1195 [test61_make() performSelector: @selector(test61_void)]; 1196 1197 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[Y]]) 1198 // CHECK-NEXT: [[T1:%.*]] = call ptr @test61_make(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ] 1199 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]]) 1200 // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_ 1201 // CHECK-NEXT: [[T3:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_ 1202 // CHECK-NEXT: [[T5:%.*]] = call ptr @objc_msgSend(ptr noundef [[T1]], ptr noundef [[T3]], ptr noundef [[T2]]){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ] 1203 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T5]]) 1204 // CHECK-NEXT: store ptr [[T5]], ptr [[Y]] 1205 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]]) 1206 id y = [test61_make() performSelector: @selector(test61_id)]; 1207 1208 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[Y]] 1209 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) 1210 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[Y]]) 1211 // CHECK-NEXT: ret void 1212} 1213 1214void test62(void) { 1215 // CHECK-LABEL: define{{.*}} void @test62() 1216 // CHECK: [[I:%.*]] = alloca i32, align 4 1217 // CHECK-NEXT: [[CLEANUP_VALUE:%.*]] = alloca ptr 1218 // CHECK-NEXT: [[CLEANUP_REQUIRED:%.*]] = alloca i1 1219 extern id test62_make(void); 1220 extern void test62_body(void); 1221 1222 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[I]]) 1223 // CHECK-NEXT: store i32 0, ptr [[I]], align 4 1224 // CHECK-NEXT: br label 1225 1226 // CHECK: [[T0:%.*]] = load i32, ptr [[I]], align 4 1227 // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 20 1228 // CHECK-NEXT: br i1 [[T1]], 1229 1230 for (unsigned i = 0; i != 20; ++i) { 1231 // CHECK: [[T0:%.*]] = load i32, ptr [[I]], align 4 1232 // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 0 1233 // CHECK-NEXT: store i1 false, ptr [[CLEANUP_REQUIRED]] 1234 // CHECK-NEXT: br i1 [[T1]], 1235 // CHECK: [[T1:%.*]] = call ptr @test62_make(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ] 1236 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]]) 1237 // CHECK-NEXT: store ptr [[T1]], ptr [[CLEANUP_VALUE]] 1238 // CHECK-NEXT: store i1 true, ptr [[CLEANUP_REQUIRED]] 1239 // CHECK-NEXT: [[T2:%.*]] = icmp ne ptr [[T1]], null 1240 // CHECK-NEXT: br label 1241 // CHECK: [[COND:%.*]] = phi i1 [ false, {{%.*}} ], [ [[T2]], {{%.*}} ] 1242 // CHECK-NEXT: [[T0:%.*]] = load i1, ptr [[CLEANUP_REQUIRED]] 1243 // CHECK-NEXT: br i1 [[T0]], 1244 // CHECK: [[T0:%.*]] = load ptr, ptr [[CLEANUP_VALUE]] 1245 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) 1246 // CHECK-NEXT: br label 1247 // CHECK: br i1 [[COND]] 1248 // CHECK: call void @test62_body() 1249 // CHECK-NEXT: br label 1250 // CHECK: br label 1251 if (i != 0 && test62_make() != 0) 1252 test62_body(); 1253 } 1254 1255 // CHECK: [[T0:%.*]] = load i32, ptr [[I]], align 4 1256 // CHECK-NEXT: [[T1:%.*]] = add i32 [[T0]], 1 1257 // CHECK-NEXT: store i32 [[T1]], ptr [[I]] 1258 // CHECK-NEXT: br label 1259 1260 // CHECK: ret void 1261} 1262 1263@class NSString; 1264 1265@interface Person { 1266 NSString *name; 1267} 1268@property NSString *address; 1269@end 1270 1271@implementation Person 1272@synthesize address; 1273@end 1274// CHECK: tail call ptr @objc_getProperty 1275// CHECK: call void @objc_setProperty 1276 1277// Verify that we successfully parse and preserve this attribute in 1278// this position. 1279@interface Test66 1280- (void) consume: (id __attribute__((ns_consumed))) ptr; 1281@end 1282void test66(void) { 1283 extern Test66 *test66_receiver(void); 1284 extern id test66_arg(void); 1285 [test66_receiver() consume: test66_arg()]; 1286} 1287// CHECK-LABEL: define{{.*}} void @test66() 1288// CHECK: [[T3:%.*]] = call ptr @test66_receiver(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ] 1289// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T3]]) 1290// CHECK-NEXT: [[T4:%.*]] = call ptr @test66_arg(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ] 1291// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T4]]) 1292// CHECK-NEXT: [[SIX:%.*]] = icmp eq ptr [[T3]], null 1293// CHECK-NEXT: br i1 [[SIX]], label [[NULINIT:%.*]], label %[[CALL:.*]] 1294// CHECK: [[CALL]]: 1295// CHECK-NEXT: [[SEL:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES 1296// CHECK-NEXT: call void @objc_msgSend(ptr noundef [[T3]], ptr noundef [[SEL]], ptr noundef [[T4]]) 1297// CHECK-NEXT: br label [[CONT:%.*]] 1298// CHECK: call void @llvm.objc.release(ptr [[T4]]) [[NUW]] 1299// CHECK-NEXT: br label [[CONT:%.*]] 1300// CHECK: call void @llvm.objc.release(ptr [[T3]]) 1301// CHECK-NEXT: ret void 1302 1303Class test67_helper(void); 1304void test67(void) { 1305 Class cl = test67_helper(); 1306} 1307// CHECK-LABEL: define{{.*}} void @test67() 1308// CHECK: [[CL:%.*]] = alloca ptr, align 8 1309// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[CL]]) 1310// CHECK-NEXT: [[T0:%.*]] = call ptr @test67_helper() 1311// CHECK-NEXT: store ptr [[T0]], ptr [[CL]], align 8 1312// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[CL]]) 1313// CHECK-NEXT: ret void 1314 1315Class test68_helper(void); 1316void test68(void) { 1317 __strong Class cl = test67_helper(); 1318} 1319// CHECK-LABEL: define{{.*}} void @test68() 1320// CHECK: [[CL:%.*]] = alloca ptr, align 8 1321// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[CL]]) 1322// CHECK-NEXT: [[T1:%.*]] = call ptr @test67_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ] 1323// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]]) 1324// CHECK-NEXT: store ptr [[T1]], ptr [[CL]], align 8 1325// CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[CL]] 1326// CHECK-NEXT: call void @llvm.objc.release(ptr [[T2]]) 1327// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[CL]]) 1328// CHECK-NEXT: ret void 1329 1330@interface Test69 @end 1331@implementation Test69 1332- (id) foo { return self; } 1333@end 1334// CHECK: define internal ptr @"\01-[Test69 foo]"( 1335// CHECK: [[SELF:%.*]] = alloca ptr, align 8 1336// CHECK: [[T0:%.*]] = load ptr, ptr [[SELF]], align 8 1337// CHECK-NEXT: ret ptr [[T0]] 1338 1339void test70(id i) { 1340 // CHECK-LABEL: define{{.*}} void @test70 1341 // CHECK: store ptr null, ptr 1342 // CHECK: store ptr null, ptr 1343 // CHECK: [[ID:%.*]] = call ptr @llvm.objc.retain(ptr 1344 // CHECK: store ptr [[ID]], ptr 1345 id x[3] = { 1346 [2] = i 1347 }; 1348} 1349 1350// Be sure that we emit lifetime intrinsics only after dtors 1351struct AggDtor { 1352 char cs[40]; 1353 id x; 1354}; 1355 1356struct AggDtor getAggDtor(void); 1357 1358// CHECK-LABEL: define{{.*}} void @test71 1359void test71(void) { 1360 // CHECK: call void @llvm.lifetime.start.p0({{[^,]+}}, ptr %[[T:.*]]) 1361 // CHECK: call void @getAggDtor(ptr dead_on_unwind writable sret(%struct.AggDtor) align 8 %[[T]]) 1362 // CHECK: call void @__destructor_8_s40(ptr %[[T]]) 1363 // CHECK: call void @llvm.lifetime.end.p0({{[^,]+}}, ptr %[[T]]) 1364 // CHECK: call void @llvm.lifetime.start.p0({{[^,]+}}, ptr %[[T2:.*]]) 1365 // CHECK: call void @getAggDtor(ptr dead_on_unwind writable sret(%struct.AggDtor) align 8 %[[T2]]) 1366 // CHECK: call void @__destructor_8_s40(ptr %[[T2]]) 1367 // CHECK: call void @llvm.lifetime.end.p0({{[^,]+}}, ptr %[[T2]]) 1368 getAggDtor(); 1369 getAggDtor(); 1370} 1371 1372// Check that no extra release calls are emitted to detruct the compond literal. 1373 1374// CHECK: define{{.*}} void @test72(ptr noundef %[[A:.*]], ptr noundef %[[B:.*]]) 1375// CHECK: %[[A_ADDR:.*]] = alloca ptr, align 8 1376// CHECK: %[[B_ADDR:.*]] = alloca ptr, align 8 1377// CHECK: %[[T:.*]] = alloca [2 x ptr], align 16 1378// CHECK: %[[V0:.*]] = call ptr @llvm.objc.retain(ptr %[[A]]) 1379// CHECK: %[[V1:.*]] = call ptr @llvm.objc.retain(ptr %[[B]]) #2 1380// CHECK: %[[V3:.*]] = load ptr, ptr %[[A_ADDR]], align 8, !tbaa !7 1381// CHECK: %[[V4:.*]] = call ptr @llvm.objc.retain(ptr %[[V3]]) #2 1382// CHECK: store ptr %[[V4]], ptr %[[T]], align 8, !tbaa !7 1383// CHECK: %[[ARRAYINIT_ELEMENT:.*]] = getelementptr inbounds ptr, ptr %[[T]], i64 1 1384// CHECK: %[[V5:.*]] = load ptr, ptr %[[B_ADDR]], align 8, !tbaa !7 1385// CHECK: %[[V6:.*]] = call ptr @llvm.objc.retain(ptr %[[V5]]) #2 1386// CHECK: store ptr %[[V6]], ptr %[[ARRAYINIT_ELEMENT]], align 8, !tbaa !7 1387// CHECK: %[[ARRAY_BEGIN:.*]] = getelementptr inbounds [2 x ptr], ptr %[[T]], i32 0, i32 0 1388// CHECK: %[[V7:.*]] = getelementptr inbounds ptr, ptr %[[ARRAY_BEGIN]], i64 2 1389 1390// CHECK-NOT: call void @llvm.objc.release 1391 1392// CHECK: %[[ARRAYDESTROY_ELEMENTPAST:.*]] = phi ptr [ %[[V7]], %{{.*}} ], [ %[[ARRAYDESTROY_ELEMENT:.*]], %{{.*}} ] 1393// CHECK: %[[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds ptr, ptr %[[ARRAYDESTROY_ELEMENTPAST]], i64 -1 1394// CHECK: %[[V8:.*]] = load ptr, ptr %[[ARRAYDESTROY_ELEMENT]], align 8 1395// CHECK: call void @llvm.objc.release(ptr %[[V8]]) #2, !clang.imprecise_release 1396 1397// CHECK-NOT: call void @llvm.objc.release 1398 1399// CHECK: %[[V10:.*]] = load ptr, ptr %[[B_ADDR]], align 8 1400// CHECK: call void @llvm.objc.release(ptr %[[V10]]) #2, !clang.imprecise_release 1401// CHECK: %[[V11:.*]] = load ptr, ptr %[[A_ADDR]], align 8 1402// CHECK: call void @llvm.objc.release(ptr %[[V11]]) #2, !clang.imprecise_release 1403 1404void test72(id a, id b) { 1405 __strong id t[] = (__strong id[]){a, b}; 1406} 1407 1408// ARC-ALIEN: attributes [[NLB]] = { nonlazybind } 1409// ARC-NATIVE: attributes [[NLB]] = { nonlazybind } 1410// CHECK: attributes [[NUW]] = { nounwind } 1411