1405 lines · plain
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 %s2// 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 %s3 4// Check both native/non-native arc platforms. Here we check that they treat5// 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 %s7// 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 %s8 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 @test036void test0(id x) {37 // CHECK: [[X:%.*]] = alloca ptr38 // 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 void43}44 45// CHECK-LABEL: define{{.*}} ptr @test1(ptr46id test1(id x) {47 // CHECK: [[X:%.*]] = alloca ptr48 // CHECK-NEXT: [[Y:%.*]] = alloca ptr49 // 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(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(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 Test267+ (void) class_method;68- (void) inst_method;69@end70@implementation Test271 72// The self pointer of a class method is not retained.73// CHECK: define internal void @"\01+[Test2 class_method]"74// CHECK: alloca75// CHECK-NEXT: alloca76// CHECK-NEXT: store77// CHECK-NEXT: store78// CHECK-NEXT: ret void79+ (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: alloca84// CHECK-NEXT: alloca85// CHECK-NEXT: store86// CHECK-NEXT: store87// CHECK-NEXT: ret void88- (void) inst_method {}89@end90 91@interface Test392+ (id) alloc;93- (id) initWith: (int) x;94- (id) copy;95@end96 97// CHECK-LABEL: define{{.*}} void @test3_unelided()98void test3_unelided(void) {99 extern void test3_helper(void);100 101 // CHECK: [[X:%.*]] = alloca ptr102 // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[X]])103 // CHECK-NEXT: store ptr null, ptr [[X]], align104 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_msgSend110 // CHECK-NEXT: call void @llvm.objc.release(ptr111 [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(ptr [[X]])122 // CHECK-NEXT: ret void123}124 125// CHECK-LABEL: define{{.*}} void @test3()126void test3(void) {127 // CHECK: [[X:%.*]] = alloca ptr128 // CHECK-NEXT: call void @llvm.lifetime.start.p0(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_msgSend136 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(ptr140 // 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(ptr [[X]])159 // CHECK-NEXT: ret void160}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_msgSend168 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@public184 id var;185}186@end187 188// CHECK-LABEL: define{{.*}} void @test5189void test5(Test5 *x, id y) {190 // Prologue.191 // CHECK: [[X:%.*]] = alloca ptr,192 // CHECK-NEXT: [[Y:%.*]] = alloca ptr193 // CHECK-NEXT: call ptr @llvm.objc.retain194 // CHECK-NEXT: store ptr {{%.*}}, ptr [[X]]195 // CHECK-NEXT: call ptr @llvm.objc.retain196 // CHECK-NEXT: store197 198 // CHECK-NEXT: load ptr, ptr [[X]]199 // CHECK-NEXT: load i64, ptr @"OBJC_IVAR_$_Test5.var"200 // CHECK-NEXT: [[VAR:%.*]] = getelementptr201 // 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:%.*]] = getelementptr210 // 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 void222}223 224id test6_helper(void) __attribute__((ns_returns_retained));225// CHECK-LABEL: define{{.*}} void @test6()226void test6(void) {227 // CHECK: [[X:%.*]] = alloca ptr228 // CHECK-NEXT: call void @llvm.lifetime.start.p0(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_release233 // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[X]])234 // CHECK-NEXT: ret void235 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 ptr242 // CHECK-NEXT: call void @llvm.lifetime.start.p0(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_release249 // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[X]])250 // CHECK-NEXT: ret void251 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 ptr259 // CHECK-NEXT: call void @llvm.lifetime.start.p0(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_release263 // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[X]])264 // CHECK-NEXT: ret void265}266 267@interface Test10268@property (retain) Test10 *me;269@end270void test10(void) {271 Test10 *x;272 id y = x.me.me;273 274 // CHECK-LABEL: define{{.*}} void @test10()275 // CHECK: [[X:%.*]] = alloca ptr, align276 // CHECK-NEXT: [[Y:%.*]] = alloca ptr, align277 // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[X]])278 // CHECK-NEXT: store ptr null, ptr [[X]]279 // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[Y]])280 // CHECK-NEXT: load ptr, ptr [[X]], align281 // 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(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(ptr [[X]])295 // CHECK-NEXT: ret void296}297 298void test11(id (*f)(void) __attribute__((ns_returns_retained))) {299 // CHECK-LABEL: define{{.*}} void @test11(300 // CHECK: [[F:%.*]] = alloca ptr, align301 // CHECK-NEXT: [[X:%.*]] = alloca ptr, align302 // CHECK-NEXT: store ptr {{%.*}}, ptr [[F]], align303 // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[X]])304 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[F]], align305 // CHECK-NEXT: [[T1:%.*]] = call ptr [[T0]]()306 // CHECK-NEXT: store ptr [[T1]], ptr [[X]], align307 // CHECK-NEXT: [[T3:%.*]] = load ptr, ptr [[X]]308 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T3]]) [[NUW]], !clang.imprecise_release309 // CHECK-NEXT: void @llvm.lifetime.end.p0(ptr [[X]])310 // CHECK-NEXT: ret void311 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, align319 // CHECK-NEXT: [[Y:%.*]] = alloca ptr, align320 321 __weak id x = test12_helper();322 // CHECK-NEXT: call void @llvm.lifetime.start.p0(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(ptr [[Y]])336 // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.loadWeakRetained(ptr [[X]])337 // CHECK-NEXT: store ptr [[T2]], ptr [[Y]], align338 339 // CHECK-NEXT: [[T4:%.*]] = load ptr, ptr [[Y]]340 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T4]]) [[NUW]], !clang.imprecise_release341 // CHECK-NEXT: void @llvm.lifetime.end.p0(ptr [[Y]])342 // CHECK-NEXT: call void @llvm.objc.destroyWeak(ptr [[X]])343 // CHECK-NEXT: void @llvm.lifetime.end.p0(ptr [[X]])344 // CHECK: ret void345}346 347// Indirect consuming calls.348void test13(void) {349 // CHECK-LABEL: define{{.*}} void @test13()350 // CHECK: [[X:%.*]] = alloca ptr, align351 // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[X]])352 // CHECK-NEXT: store ptr null, ptr [[X]], align353 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, align358 // CHECK-NEXT: [[X_VAL:%.*]] = load ptr, ptr [[X]], align359 // 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, align365 // CHECK-NEXT: [[BLOCK_FN_PTR:%.*]] = getelementptr inbounds nuw [[BLOCKTY:%.*]], ptr [[TMP]], i32 0, i32 3366 // CHECK-NEXT: [[X_VAL:%.*]] = load ptr, ptr [[X]], align367 // 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(ptr [[X]])375 // CHECK-NEXT: ret void376}377 378@interface Test16_super @end379@interface Test16 : Test16_super {380 id z;381}382@property (assign) int x;383@property (retain) id y;384- (void) dealloc;385@end386@implementation Test16387@synthesize x;388@synthesize y;389- (void) dealloc {390 // CHECK: define internal void @"\01-[Test16 dealloc]"(391 // CHECK: [[SELF:%.*]] = alloca ptr, align392 // CHECK-NEXT: [[CMD:%.*]] = alloca ptr, align393 // CHECK-NEXT: alloca394 // CHECK-NEXT: store ptr {{%.*}}, ptr [[SELF]], align395 // CHECK-NEXT: store ptr {{%.*}}, ptr [[CMD]]396 // CHECK-NEXT: [[BASE:%.*]] = load ptr, ptr [[SELF]]397 398 // Call super.399 // CHECK-NEXT: [[T0:%.*]] = getelementptr400 // CHECK-NEXT: store ptr [[BASE]], ptr [[T0]]401 // CHECK-NEXT: load ptr, ptr @"OBJC_CLASSLIST_SUP_REFS_$_402 // CHECK-NEXT: getelementptr403 // CHECK-NEXT: store404 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_405 // CHECK-NEXT: call void @objc_msgSendSuper2(406 // CHECK-NEXT: ret void407}408 409// .cxx_destruct410 // CHECK: define internal void @"\01-[Test16 .cxx_destruct]"(411 // CHECK: [[SELF:%.*]] = alloca ptr, align412 // CHECK-NEXT: [[CMD:%.*]] = alloca ptr, align413 // CHECK-NEXT: store ptr {{%.*}}, ptr [[SELF]], align414 // 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 void428 429@end430 431// This shouldn't crash.432@interface Test17A433@property (assign) int x;434@end435@interface Test17B : Test17A436@end437@implementation Test17B438- (int) x { return super.x + 1; }439@end440 441void test19(void) {442 // CHECK-LABEL: define{{.*}} void @test19()443 // CHECK: [[X:%.*]] = alloca [5 x ptr], align 16444 // CHECK: call void @llvm.lifetime.start445 // 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 2454 // 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 0459 // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds ptr, ptr [[BEGIN]], i64 5460 // CHECK-NEXT: br label461 462 // CHECK: [[AFTER:%.*]] = phi ptr [ [[END]], {{%.*}} ], [ [[NEXT:%.*]], {{%.*}} ]463 // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds ptr, ptr [[AFTER]], i64 -1464 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[CUR]]465 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]], !clang.imprecise_release466 // CHECK-NEXT: [[EQ:%.*]] = icmp eq ptr [[CUR]], [[BEGIN]]467 // CHECK-NEXT: br i1 [[EQ]],468 469 // CHECK: ret void470}471 472void test20(unsigned n) {473 // CHECK-LABEL: define{{.*}} void @test20474 // CHECK: [[N:%.*]] = alloca i32, align 4475 // CHECK-NEXT: [[SAVED_STACK:%.*]] = alloca ptr476 // CHECK-NEXT: [[VLA_EXPR:%.*]] = alloca i64, align 8477 // CHECK-NEXT: store i32 {{%.*}}, ptr [[N]], align 4478 479 id x[n];480 481 // Capture the VLA size.482 // CHECK-NEXT: [[T0:%.*]] = load i32, ptr [[N]], align 4483 // CHECK-NEXT: [[DIM:%.*]] = zext i32 [[T0]] to i64484 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 16491 492 // Store the VLA #elements expression.493 // CHECK-NEXT: store i64 [[DIM]], ptr [[VLA_EXPR]], align 8494 495 // Zero-initialize.496 // CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[DIM]], 8497 // 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 -1506 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[CUR]]507 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]], !clang.imprecise_release508 // 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 void514}515 516void test21(unsigned n) {517 // CHECK-LABEL: define{{.*}} void @test21518 // CHECK: [[N:%.*]] = alloca i32, align 4519 // CHECK-NEXT: [[SAVED_STACK:%.*]] = alloca ptr520 // CHECK-NEXT: [[VLA_EXPR:%.*]] = alloca i64, align 8521 // CHECK-NEXT: store i32 {{%.*}}, ptr [[N]], align 4522 523 id x[2][n][3];524 525 // Capture the VLA size.526 // CHECK-NEXT: [[T0:%.*]] = load i32, ptr [[N]], align 4527 // CHECK-NEXT: [[DIM:%.*]] = zext i32 [[T0]] to i64528 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 16536 537 // Store the VLA #elements expression.538 // CHECK-NEXT: store i64 [[DIM]], ptr [[VLA_EXPR]], align 8539 540 // Zero-initialize.541 // CHECK-NEXT: [[T1:%.*]] = mul nuw i64 2, [[DIM]]542 // CHECK-NEXT: [[T2:%.*]] = mul nuw i64 [[T1]], 24543 // 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 0548 // CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[T0]], 3549 // 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 -1555 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[CUR]]556 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]], !clang.imprecise_release557 // 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 void563}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; } @end570@implementation Test23 @end571 572// CHECK-GLOBALS: @"_OBJC_CLASS_RO_$_Test24" = internal global [[RO_T:%.*]] { i32 130,573@interface Test24 {} @end574@implementation Test24 @end575 576@interface Test26 { id x[4]; } @end577@implementation Test26 @end578// CHECK: define internal void @"\01-[Test26 .cxx_destruct]"(579// CHECK: [[SELF:%.*]] = load ptr, ptr580// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i64 0581// CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [4 x ptr], ptr [[T1]], i32 0, i32 0582// CHECK-NEXT: [[END:%.*]] = getelementptr inbounds ptr, ptr [[BEGIN]], i64 4583// CHECK-NEXT: br label584// CHECK: [[PAST:%.*]] = phi ptr [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ]585// CHECK-NEXT: [[CUR]] = getelementptr inbounds ptr, ptr [[PAST]], i64 -1586// CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[CUR]], ptr null)587// CHECK-NEXT: [[ISDONE:%.*]] = icmp eq ptr [[CUR]], [[BEGIN]]588// CHECK-NEXT: br i1 [[ISDONE]],589// CHECK: ret void590 591// Check that 'init' retains self.592@interface Test27593- (id) init;594@end595@implementation Test27596- (id) init { return self; }597// CHECK: define internal ptr @"\01-[Test27 init]"598// CHECK: [[SELF:%.*]] = alloca ptr,599// CHECK-NEXT: [[CMD:%.*]] = alloca ptr,600// CHECK-NEXT: store ptr {{%.*}}, ptr [[SELF]]601// CHECK-NEXT: store ptr {{%.*}}, ptr [[CMD]]602// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SELF]]603// CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])604// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SELF]]605// CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])606// CHECK-NEXT: ret ptr [[T2]]607 608@end609 610@interface Test28611@property (copy) id prop;612@end613@implementation Test28614@synthesize prop;615@end616// CHECK: define internal void @"\01-[Test28 .cxx_destruct]"617// CHECK: [[SELF:%.*]] = load ptr, ptr618// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i64 0619// CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[T1]], ptr null)620// CHECK-NEXT: ret void621 622@interface Test29_super623- (id) initWithAllocator: (id) allocator;624@end625@interface Test29 : Test29_super626- (id) init;627- (id) initWithAllocator: (id) allocator;628@end629@implementation Test29630static id _test29_allocator = 0;631- (id) init {632// CHECK: define internal ptr @"\01-[Test29 init]"(ptr noundef {{%.*}},633// CHECK: [[SELF:%.*]] = alloca ptr, align 8634// CHECK-NEXT: [[CMD:%.*]] = alloca ptr, align 8635// CHECK-NEXT: store ptr {{%.*}}, ptr [[SELF]]636// CHECK-NEXT: store ptr {{%.*}}, ptr [[CMD]]637 638// Evaluate arguments. Note that the send argument is evaluated639// before the zeroing of self.640// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SELF]], align 8641// CHECK-NEXT: [[T1:%.*]] = load ptr, ptr @_test29_allocator, align 8642 643// Implicit null of 'self', i.e. direct transfer of ownership.644// CHECK-NEXT: store ptr null, ptr [[SELF]]645 646// Actual message send.647// CHECK-NEXT: [[SEL:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_648// CHECK-NEXT: [[CALL:%.*]] = call ptr @objc_msgSend(ptr noundef [[T0]], ptr noundef [[SEL]], ptr noundef [[T1]])649 650// Implicit write of result back into 'self'. This is not supposed to651// be detectable because we're supposed to ban accesses to the old652// self value past the delegate init call.653// CHECK-NEXT: store ptr [[CALL]], ptr [[SELF]]654 655// Return statement.656// CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.retain(ptr [[CALL]]) [[NUW]]657 658// Cleanup.659// CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[SELF]]660// CHECK-NEXT: call void @llvm.objc.release(ptr [[T2]]) [[NUW]], !clang.imprecise_release661 662// Return.663// CHECK-NEXT: ret ptr [[T1]]664 return [self initWithAllocator: _test29_allocator];665}666- (id) initWithAllocator: (id) allocator {667// CHECK: define internal ptr @"\01-[Test29 initWithAllocator:]"(668// CHECK: [[SELF:%.*]] = alloca ptr, align 8669// CHECK-NEXT: [[CMD:%.*]] = alloca ptr, align 8670// CHECK-NEXT: [[ALLOCATOR:%.*]] = alloca ptr, align 8671// CHECK-NEXT: alloca672// CHECK-NEXT: store ptr {{%.*}}, ptr [[SELF]]673// CHECK-NEXT: store ptr {{%.*}}, ptr [[CMD]]674// CHECK-NEXT: [[T0:%.*]] = call ptr @llvm.objc.retain(ptr {{%.*}})675// CHECK-NEXT: store ptr [[T0]], ptr [[ALLOCATOR]]676 677// Evaluate arguments. Note that the send argument is evaluated678// before the zeroing of self.679// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SELF]]680// CHECK-NEXT: [[T1:%.*]] = load ptr, ptr [[ALLOCATOR]], align 8681 682// Implicit null of 'self', i.e. direct transfer of ownership.683// CHECK-NEXT: store ptr null, ptr [[SELF]]684 685// Actual message send.686// CHECK: [[CALL:%.*]] = call {{.*}} @objc_msgSendSuper2687 688// Implicit write of result back into 'self'. This is not supposed to689// be detectable because we're supposed to ban accesses to the old690// self value past the delegate init call.691// CHECK-NEXT: store ptr [[CALL]], ptr [[SELF]]692 693// Assignment.694// CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[CALL]]) [[NUW]]695// CHECK-NEXT: [[T4:%.*]] = load ptr, ptr [[SELF]], align696// CHECK-NEXT: store ptr [[T2]], ptr [[SELF]], align697// CHECK-NEXT: call void @llvm.objc.release(ptr [[T4]])698 699// Return statement.700// CHECK-NEXT: [[T3:%.*]] = load ptr, ptr [[SELF]]701// CHECK-NEXT: [[T4:%.*]] = call ptr @llvm.objc.retain(ptr [[T3]]) [[NUW]]702 703// Cleanup.704// CHECK-NEXT: [[T5:%.*]] = load ptr, ptr [[ALLOCATOR]]705// CHECK-NEXT: call void @llvm.objc.release(ptr [[T5]]) [[NUW]], !clang.imprecise_release706 707// CHECK-NEXT: [[T6:%.*]] = load ptr, ptr [[SELF]]708// CHECK-NEXT: call void @llvm.objc.release(ptr [[T6]]) [[NUW]], !clang.imprecise_release709 710// Return.711// CHECK-NEXT: ret ptr [[T4]]712 self = [super initWithAllocator: allocator];713 return self;714}715@end716 717typedef struct Test30_helper Test30_helper;718@interface Test30719- (id) init;720- (Test30_helper*) initHelper;721@end722@implementation Test30 {723char *helper;724}725- (id) init {726// CHECK: define internal ptr @"\01-[Test30 init]"(ptr noundef {{%.*}},727// CHECK: [[RET:%.*]] = alloca ptr728// CHECK-NEXT: alloca ptr729// CHECK-NEXT: store ptr {{%.*}}, ptr [[SELF]]730// CHECK-NEXT: store731 732// Call.733// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SELF]]734// CHECK-NEXT: [[SEL:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_735// CHECK-NEXT: [[CALL:%.*]] = call ptr @objc_msgSend(ptr noundef [[T0]], ptr noundef [[SEL]])736 737// Assignment.738// CHECK-NEXT: [[T1:%.*]] = load ptr, ptr [[SELF]]739// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T1]], i64 0740// CHECK-NEXT#: [[T5:%.*]] = load ptr, ptr [[T3]]741// CHECK-NEXT#: [[T6:%.*]] = call ptr @llvm.objc.retain(ptr [[CALL]])742// CHECK-NEXT#: call void @llvm.objc.release(ptr [[T5]])743// CHECK-NEXT: store ptr [[CALL]], ptr [[T3]]744 745// Return.746// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SELF]]747// CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])748 749// Cleanup.750// CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[SELF]]751// CHECK-NEXT: call void @llvm.objc.release(ptr [[T2]])752 753// Epilogue.754// CHECK-NEXT: ret ptr [[T1]]755 self->helper = [self initHelper];756 return self;757}758- (Test30_helper*) initHelper {759// CHECK: define internal ptr @"\01-[Test30 initHelper]"(760// CHECK: alloca761// CHECK-NEXT: alloca762// CHECK-NEXT: store763// CHECK-NEXT: store764// CHECK-NEXT: ret ptr null765 return 0;766}767 768@end769 770__attribute__((ns_returns_retained)) id test32(void) {771// CHECK-LABEL: define{{.*}} ptr @test32()772// CHECK: [[T0:%.*]] = call ptr @test32_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]773// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])774// CHECK-NEXT: ret ptr [[T0]]775 extern id test32_helper(void);776 return test32_helper();777}778 779@class Test33_a;780@interface Test33781- (void) give: (Test33_a **) x;782- (void) take: (Test33_a **) x;783- (void) giveStrong: (out __strong Test33_a **) x;784- (void) takeStrong: (inout __strong Test33_a **) x;785- (void) giveOut: (out Test33_a **) x;786@end787void test33(Test33 *ptr) {788 Test33_a *a;789 [ptr give: &a];790 [ptr take: &a];791 [ptr giveStrong: &a];792 [ptr takeStrong: &a];793 [ptr giveOut: &a];794 795 // CHECK: define{{.*}} void @test33(ptr796 // CHECK: [[PTR:%.*]] = alloca ptr797 // CHECK-NEXT: [[A:%.*]] = alloca ptr798 // CHECK-NEXT: [[TEMP0:%.*]] = alloca ptr799 // CHECK-NEXT: [[TEMP1:%.*]] = alloca ptr800 // CHECK-NEXT: [[TEMP2:%.*]] = alloca ptr801 // CHECK-NEXT: llvm.objc.retain802 // CHECK-NEXT: store803 // CHECK-NEXT: call void @llvm.lifetime.start804 // CHECK-NEXT: store ptr null, ptr [[A]]805 806 // CHECK-NEXT: load ptr, ptr [[PTR]]807 // CHECK-NEXT: [[W0:%.*]] = load ptr, ptr [[A]]808 // CHECK-NEXT: store ptr [[W0]], ptr [[TEMP0]]809 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_810 // CHECK-NEXT: objc_msgSend{{.*}}, ptr noundef [[TEMP0]])811 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[TEMP0]]812 // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])813 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use(ptr [[W0]]) [[NUW]]814 // CHECK-NEXT: [[T4:%.*]] = load ptr, ptr [[A]]815 // CHECK-NEXT: store ptr [[T2]], ptr [[A]]816 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T4]])817 818 // CHECK-NEXT: load ptr, ptr [[PTR]]819 // CHECK-NEXT: [[W0:%.*]] = load ptr, ptr [[A]]820 // CHECK-NEXT: store ptr [[W0]], ptr [[TEMP1]]821 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_822 // CHECK-NEXT: objc_msgSend{{.*}}, ptr noundef [[TEMP1]])823 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[TEMP1]]824 // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])825 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use(ptr [[W0]]) [[NUW]]826 // CHECK-NEXT: [[T4:%.*]] = load ptr, ptr [[A]]827 // CHECK-NEXT: store ptr [[T2]], ptr [[A]]828 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T4]])829 830 // CHECK-NEXT: load ptr, ptr [[PTR]]831 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_832 // CHECK-NEXT: objc_msgSend{{.*}}, ptr noundef [[A]])833 834 // CHECK-NEXT: load ptr, ptr [[PTR]]835 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_836 // CHECK-NEXT: objc_msgSend{{.*}}, ptr noundef [[A]])837 838 // 'out'839 // CHECK-NEXT: load ptr, ptr [[PTR]]840 // CHECK-NEXT: store ptr null, ptr [[TEMP2]]841 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_842 // CHECK-NEXT: objc_msgSend{{.*}}, ptr noundef [[TEMP2]])843 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[TEMP2]]844 // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])845 // CHECK-NEXT: [[T4:%.*]] = load ptr, ptr [[A]]846 // CHECK-NEXT: store ptr [[T2]], ptr [[A]]847 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T4]])848 849 // CHECK-NEXT: load850 // CHECK-NEXT: llvm.objc.release851 // CHECK-NEXT: call void @llvm.lifetime.end852 // CHECK-NEXT: load853 // CHECK-NEXT: llvm.objc.release854 // CHECK-NEXT: ret void855}856 857 858// CHECK-LABEL: define{{.*}} void @test36859void test36(id x) {860 // CHECK: [[X:%.*]] = alloca ptr861 862 // CHECK: call ptr @llvm.objc.retain863 // CHECK: call ptr @llvm.objc.retain864 // CHECK: call ptr @llvm.objc.retain865 id array[3] = { @"A", x, @"y" };866 867 // CHECK: [[T0:%.*]] = load ptr, ptr [[X]]868 // CHECK-NEXT: store ptr null, ptr [[X]]869 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])870 x = 0;871 872 // CHECK: br label873 // CHECK: call void @llvm.objc.release874 // CHECK: br i1875 876 // CHECK: call void @llvm.objc.release877 // CHECK-NEXT: ret void878}879 880@class Test37;881void test37(void) {882 extern void test37_helper(id *);883 Test37 *var;884 test37_helper(&var);885 886 // CHECK-LABEL: define{{.*}} void @test37()887 // CHECK: [[VAR:%.*]] = alloca ptr,888 // CHECK-NEXT: [[TEMP:%.*]] = alloca ptr889 // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[VAR]])890 // CHECK-NEXT: store ptr null, ptr [[VAR]]891 892 // CHECK-NEXT: [[W0:%.*]] = load ptr, ptr [[VAR]]893 // CHECK-NEXT: store ptr [[W0]], ptr [[TEMP]]894 // CHECK-NEXT: call void @test37_helper(ptr noundef [[TEMP]])895 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[TEMP]]896 // CHECK-NEXT: [[T3:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])897 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use(ptr [[W0]]) [[NUW]]898 // CHECK-NEXT: [[T5:%.*]] = load ptr, ptr [[VAR]]899 // CHECK-NEXT: store ptr [[T3]], ptr [[VAR]]900 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T5]])901 902 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[VAR]]903 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])904 // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[VAR]])905 // CHECK-NEXT: ret void906}907 908@interface Test43 @end909@implementation Test43910- (id) test __attribute__((ns_returns_retained)) {911 extern id test43_produce(void);912 return test43_produce();913 // CHECK: call ptr @test43_produce(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]914 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(915 // CHECK-NEXT: ret916}917@end918 919@interface Test45920@property (retain) id x;921@end922@implementation Test45923@synthesize x;924@end925// CHECK: define internal ptr @"\01-[Test45 x]"(926// CHECK: [[CALL:%.*]] = tail call ptr @objc_getProperty(927// CHECK-NEXT: ret ptr [[CALL]]928 929void test46(__weak id *wp, __weak volatile id *wvp) {930 extern id test46_helper(void);931 932 // TODO: this is sub-optimal, we should retain at the actual call site.933 934 // CHECK: [[T1:%.*]] = call ptr @test46_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]935 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])936 // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr {{%.*}}, align 8937 // CHECK-NEXT: [[T3:%.*]] = call ptr @llvm.objc.storeWeak(ptr [[T2]], ptr [[T1]])938 // CHECK-NEXT: [[T4:%.*]] = call ptr @llvm.objc.retain(ptr [[T3]])939 // CHECK-NEXT: store ptr [[T4]], ptr940 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]])941 id x = *wp = test46_helper();942 943 // CHECK: [[T1:%.*]] = call ptr @test46_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]944 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])945 // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr {{%.*}}, align 8946 // CHECK-NEXT: [[T3:%.*]] = call ptr @llvm.objc.storeWeak(ptr [[T2]], ptr [[T1]])947 // CHECK-NEXT: [[T4:%.*]] = call ptr @llvm.objc.retain(ptr [[T3]])948 // CHECK-NEXT: store ptr [[T4]], ptr949 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]])950 id y = *wvp = test46_helper();951}952 953void test47(void) {954 extern id test47_helper(void);955 id x = x = test47_helper();956 957 // CHECK-LABEL: define{{.*}} void @test47()958 // CHECK: [[X:%.*]] = alloca ptr959 // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[X]])960 // CHECK-NEXT: store ptr null, ptr [[X]]961 // CHECK-NEXT: [[T0:%.*]] = call ptr @test47_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]962 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])963 // CHECK-NEXT: [[T1:%.*]] = load ptr, ptr [[X]]964 // CHECK-NEXT: store ptr [[T0]], ptr [[X]]965 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]])966 // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])967 // CHECK-NEXT: [[T3:%.*]] = load ptr, ptr [[X]]968 // CHECK-NEXT: store ptr [[T2]], ptr [[X]]969 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T3]])970 // CHECK-NEXT: [[T4:%.*]] = load ptr, ptr [[X]]971 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T4]])972 // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[X]])973 // CHECK-NEXT: ret void974}975 976void test48(void) {977 extern id test48_helper(void);978 __weak id x = x = test48_helper();979 // CHECK-LABEL: define{{.*}} void @test48()980 // CHECK: [[X:%.*]] = alloca ptr981 // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[X]])982 // CHECK-NEXT: [[T0:%.*]] = call ptr @llvm.objc.initWeak(ptr [[X]], ptr null)983 // CHECK-NEXT: [[T2:%.*]] = call ptr @test48_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]984 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T2]])985 // CHECK-NEXT: [[T3:%.*]] = call ptr @llvm.objc.storeWeak(ptr [[X]], ptr [[T2]])986 // CHECK-NEXT: [[T4:%.*]] = call ptr @llvm.objc.storeWeak(ptr [[X]], ptr [[T3]])987 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T2]])988 // CHECK-NEXT: call void @llvm.objc.destroyWeak(ptr [[X]])989 // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[X]])990 // CHECK-NEXT: ret void991}992 993void test49(void) {994 extern id test49_helper(void);995 __autoreleasing id x = x = test49_helper();996 // CHECK-LABEL: define{{.*}} void @test49()997 // CHECK: [[X:%.*]] = alloca ptr998 // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[X]])999 // CHECK-NEXT: store ptr null, ptr [[X]]1000 // CHECK-NEXT: [[T0:%.*]] = call ptr @test49_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]1001 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])1002 // CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.autorelease(ptr [[T0]])1003 // CHECK-NEXT: store ptr [[T1]], ptr [[X]]1004 // CHECK-NEXT: [[T3:%.*]] = call ptr @llvm.objc.retainAutorelease(ptr [[T1]])1005 // CHECK-NEXT: store ptr [[T3]], ptr [[X]]1006 // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[X]])1007 // CHECK-NEXT: ret void1008}1009 1010id x(void);1011void test50(id y) {1012 ({x();});1013// CHECK: [[T0:%.*]] = call ptr @llvm.objc.retain1014// CHECK: call void @llvm.objc.release1015}1016 1017struct CGPoint {1018 float x;1019 float y;1020};1021typedef struct CGPoint CGPoint;1022 1023@interface Foo1024@property (assign) CGPoint point;1025@end1026 1027@implementation Foo1028@synthesize point;1029@end1030 1031id test52(void) {1032 id test52_helper(int) __attribute__((ns_returns_retained));1033 return ({ int x = 5; test52_helper(x); });1034 1035// CHECK-LABEL: define{{.*}} ptr @test52()1036// CHECK: [[X:%.*]] = alloca i321037// CHECK-NEXT: [[TMPALLOCA:%.*]] = alloca ptr1038// CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[X]])1039// CHECK-NEXT: store i32 5, ptr [[X]],1040// CHECK-NEXT: [[T0:%.*]] = load i32, ptr [[X]],1041// CHECK-NEXT: [[T1:%.*]] = call ptr @test52_helper(i32 noundef [[T0]])1042// CHECK-NEXT: store ptr [[T1]], ptr [[TMPALLOCA]]1043// CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[X]])1044// CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[TMPALLOCA]]1045// CHECK-NEXT: [[T3:%.*]] = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr [[T2]])1046// CHECK-NEXT: ret ptr [[T3]]1047}1048 1049void test53(void) {1050 id test53_helper(void);1051 id x = ({ id y = test53_helper(); y; });1052 (void) x;1053// CHECK-LABEL: define{{.*}} void @test53()1054// CHECK: [[X:%.*]] = alloca ptr,1055// CHECK-NEXT: [[Y:%.*]] = alloca ptr,1056// CHECK-NEXT: [[TMPALLOCA:%.*]] = alloca ptr,1057// CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[X]])1058// CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[Y]])1059// CHECK-NEXT: [[T1:%.*]] = call ptr @test53_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]1060// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])1061// CHECK-NEXT: store ptr [[T1]], ptr [[Y]],1062// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[Y]],1063// CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])1064// CHECK-NEXT: store ptr [[T1]], ptr [[TMPALLOCA]]1065// CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[Y]]1066// CHECK-NEXT: call void @llvm.objc.release(ptr [[T2]])1067// CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[Y]])1068// CHECK-NEXT: [[T3:%.*]] = load ptr, ptr [[TMPALLOCA]]1069// CHECK-NEXT: store ptr [[T3]], ptr [[X]],1070// CHECK-NEXT: load ptr, ptr [[X]],1071// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]]1072// CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])1073// CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[X]])1074// CHECK-NEXT: ret void1075}1076 1077// CHECK-LABEL: define{{.*}} void @test54(i32 noundef %first, ...)1078void test54(int first, ...) {1079 __builtin_va_list arglist;1080 // CHECK: call void @llvm.va_start1081 __builtin_va_start(arglist, first);1082 // CHECK: call ptr @llvm.objc.retain1083 id obj = __builtin_va_arg(arglist, id);1084 // CHECK: call void @llvm.va_end1085 __builtin_va_end(arglist);1086 // CHECK: call void @llvm.objc.release1087 // CHECK: ret void1088}1089 1090// PR102281091@interface Test55Base @end1092@interface Test55 : Test55Base @end1093@implementation Test55 (Category)1094- (void) dealloc {}1095@end1096// CHECK: define internal void @"\01-[Test55(Category) dealloc]"(1097// CHECK-NOT: ret1098// CHECK: call void @objc_msgSendSuper2(1099 1100@protocol Test56Protocol1101+ (id) make __attribute__((ns_returns_retained));1102@end1103@interface Test56<Test56Protocol> @end1104@implementation Test561105// CHECK: define internal ptr @"\01+[Test56 make]"(1106+ (id) make {1107 extern id test56_helper(void);1108 // CHECK: [[T1:%.*]] = call ptr @test56_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]1109 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])1110 // CHECK-NEXT: ret ptr [[T1]]1111 return test56_helper();1112}1113@end1114void test56_test(void) {1115 id x = [Test56 make];1116 // CHECK-LABEL: define{{.*}} void @test56_test()1117 // CHECK: [[X:%.*]] = alloca ptr, align 81118 // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[X]])1119 // CHECK: [[T0:%.*]] = call ptr @objc_msgSend(1120 // CHECK-NEXT: store ptr [[T0]], ptr [[X]]1121 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]]1122 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])1123 // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[X]])1124 // CHECK-NEXT: ret void1125}1126 1127@interface Test571128@property (nonatomic, strong) id strong;1129@property (nonatomic, weak) id weak;1130@property (nonatomic, unsafe_unretained) id unsafe;1131@end1132@implementation Test571133@synthesize strong, weak, unsafe;1134@end1135// CHECK: define internal ptr @"\01-[Test57 strong]"(1136// CHECK: [[T0:%.*]] = load ptr, ptr {{%.*}}1137// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 01138// CHECK-NEXT: [[T5:%.*]] = load ptr, ptr [[T3]]1139// CHECK-NEXT: ret ptr [[T5]]1140 1141// CHECK: define internal ptr @"\01-[Test57 weak]"(1142// CHECK: [[T0:%.*]] = load ptr, ptr {{%.*}}1143// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 81144// CHECK-NEXT: [[T5:%.*]] = call ptr @llvm.objc.loadWeakRetained(ptr [[T3]])1145// CHECK-NEXT: [[T6:%.*]] = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr [[T5]])1146// CHECK-NEXT: ret ptr [[T6]]1147 1148// CHECK: define internal ptr @"\01-[Test57 unsafe]"(1149// CHECK: [[T0:%.*]] = load ptr, ptr {{%.*}}1150// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 161151// CHECK-NEXT: [[T5:%.*]] = load ptr, ptr [[T3]]1152// CHECK-NEXT: ret ptr [[T5]]1153 1154void test59(void) {1155 extern id test59_getlock(void);1156 extern void test59_body(void);1157 @synchronized (test59_getlock()) {1158 test59_body();1159 }1160 1161 // CHECK-LABEL: define{{.*}} void @test59()1162 // CHECK: [[T1:%.*]] = call ptr @test59_getlock(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]1163 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])1164 // CHECK-NEXT: call i32 @objc_sync_enter(ptr [[T1]])1165 // CHECK-NEXT: call void @test59_body()1166 // CHECK-NEXT: call i32 @objc_sync_exit(ptr [[T1]])1167 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]])1168 // CHECK-NEXT: ret void1169}1170 1171// Verify that we don't try to reclaim the result of performSelector.1172@interface Test611173- (id) performSelector: (SEL) selector;1174- (void) test61_void;1175- (id) test61_id;1176@end1177void test61(void) {1178 // CHECK-LABEL: define{{.*}} void @test61()1179 // CHECK: [[Y:%.*]] = alloca ptr, align 81180 1181 extern id test61_make(void);1182 1183 // CHECK-NEXT: [[T0:%.*]] = call ptr @test61_make(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]1184 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])1185 // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_1186 // CHECK-NEXT: [[T3:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_1187 // CHECK-NEXT: [[T4:%.*]] = call ptr @objc_msgSend(ptr noundef [[T1]], ptr noundef [[T3]], ptr noundef [[T2]])1188 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]])1189 [test61_make() performSelector: @selector(test61_void)];1190 1191 // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[Y]])1192 // CHECK-NEXT: [[T1:%.*]] = call ptr @test61_make(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]1193 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])1194 // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_1195 // CHECK-NEXT: [[T3:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_1196 // CHECK-NEXT: [[T5:%.*]] = call ptr @objc_msgSend(ptr noundef [[T1]], ptr noundef [[T3]], ptr noundef [[T2]]){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]1197 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T5]])1198 // CHECK-NEXT: store ptr [[T5]], ptr [[Y]]1199 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]])1200 id y = [test61_make() performSelector: @selector(test61_id)];1201 1202 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[Y]]1203 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])1204 // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[Y]])1205 // CHECK-NEXT: ret void1206}1207 1208void test62(void) {1209 // CHECK-LABEL: define{{.*}} void @test62()1210 // CHECK: [[I:%.*]] = alloca i32, align 41211 // CHECK-NEXT: [[CLEANUP_VALUE:%.*]] = alloca ptr1212 // CHECK-NEXT: [[CLEANUP_REQUIRED:%.*]] = alloca i11213 extern id test62_make(void);1214 extern void test62_body(void);1215 1216 // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[I]])1217 // CHECK-NEXT: store i32 0, ptr [[I]], align 41218 // CHECK-NEXT: br label1219 1220 // CHECK: [[T0:%.*]] = load i32, ptr [[I]], align 41221 // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 201222 // CHECK-NEXT: br i1 [[T1]],1223 1224 for (unsigned i = 0; i != 20; ++i) {1225 // CHECK: [[T0:%.*]] = load i32, ptr [[I]], align 41226 // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 01227 // CHECK-NEXT: store i1 false, ptr [[CLEANUP_REQUIRED]]1228 // CHECK-NEXT: br i1 [[T1]],1229 // CHECK: [[T1:%.*]] = call ptr @test62_make(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]1230 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])1231 // CHECK-NEXT: store ptr [[T1]], ptr [[CLEANUP_VALUE]]1232 // CHECK-NEXT: store i1 true, ptr [[CLEANUP_REQUIRED]]1233 // CHECK-NEXT: [[T2:%.*]] = icmp ne ptr [[T1]], null1234 // CHECK-NEXT: br label1235 // CHECK: [[COND:%.*]] = phi i1 [ false, {{%.*}} ], [ [[T2]], {{%.*}} ]1236 // CHECK-NEXT: [[T0:%.*]] = load i1, ptr [[CLEANUP_REQUIRED]]1237 // CHECK-NEXT: br i1 [[T0]],1238 // CHECK: [[T0:%.*]] = load ptr, ptr [[CLEANUP_VALUE]]1239 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])1240 // CHECK-NEXT: br label1241 // CHECK: br i1 [[COND]]1242 // CHECK: call void @test62_body()1243 // CHECK-NEXT: br label1244 // CHECK: br label1245 if (i != 0 && test62_make() != 0)1246 test62_body();1247 }1248 1249 // CHECK: [[T0:%.*]] = load i32, ptr [[I]], align 41250 // CHECK-NEXT: [[T1:%.*]] = add i32 [[T0]], 11251 // CHECK-NEXT: store i32 [[T1]], ptr [[I]]1252 // CHECK-NEXT: br label1253 1254 // CHECK: ret void1255}1256 1257@class NSString;1258 1259@interface Person {1260 NSString *name;1261}1262@property NSString *address;1263@end1264 1265@implementation Person1266@synthesize address;1267@end1268// CHECK: tail call ptr @objc_getProperty1269// CHECK: call void @objc_setProperty1270 1271// Verify that we successfully parse and preserve this attribute in1272// this position.1273@interface Test661274- (void) consume: (id __attribute__((ns_consumed))) ptr;1275@end1276void test66(void) {1277 extern Test66 *test66_receiver(void);1278 extern id test66_arg(void);1279 [test66_receiver() consume: test66_arg()];1280}1281// CHECK-LABEL: define{{.*}} void @test66()1282// CHECK: [[T3:%.*]] = call ptr @test66_receiver(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]1283// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T3]])1284// CHECK-NEXT: [[T4:%.*]] = call ptr @test66_arg(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]1285// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T4]])1286// CHECK-NEXT: [[SIX:%.*]] = icmp eq ptr [[T3]], null1287// CHECK-NEXT: br i1 [[SIX]], label [[NULINIT:%.*]], label %[[CALL:.*]]1288// CHECK: [[CALL]]:1289// CHECK-NEXT: [[SEL:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES1290// CHECK-NEXT: call void @objc_msgSend(ptr noundef [[T3]], ptr noundef [[SEL]], ptr noundef [[T4]])1291// CHECK-NEXT: br label [[CONT:%.*]]1292// CHECK: call void @llvm.objc.release(ptr [[T4]]) [[NUW]]1293// CHECK-NEXT: br label [[CONT:%.*]]1294// CHECK: call void @llvm.objc.release(ptr [[T3]])1295// CHECK-NEXT: ret void1296 1297Class test67_helper(void);1298void test67(void) {1299 Class cl = test67_helper();1300}1301// CHECK-LABEL: define{{.*}} void @test67()1302// CHECK: [[CL:%.*]] = alloca ptr, align 81303// CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[CL]])1304// CHECK-NEXT: [[T0:%.*]] = call ptr @test67_helper()1305// CHECK-NEXT: store ptr [[T0]], ptr [[CL]], align 81306// CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[CL]])1307// CHECK-NEXT: ret void1308 1309Class test68_helper(void);1310void test68(void) {1311 __strong Class cl = test67_helper();1312}1313// CHECK-LABEL: define{{.*}} void @test68()1314// CHECK: [[CL:%.*]] = alloca ptr, align 81315// CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[CL]])1316// CHECK-NEXT: [[T1:%.*]] = call ptr @test67_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]1317// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])1318// CHECK-NEXT: store ptr [[T1]], ptr [[CL]], align 81319// CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[CL]]1320// CHECK-NEXT: call void @llvm.objc.release(ptr [[T2]])1321// CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[CL]])1322// CHECK-NEXT: ret void1323 1324@interface Test69 @end1325@implementation Test691326- (id) foo { return self; }1327@end1328// CHECK: define internal ptr @"\01-[Test69 foo]"(1329// CHECK: [[SELF:%.*]] = alloca ptr, align 81330// CHECK: [[T0:%.*]] = load ptr, ptr [[SELF]], align 81331// CHECK-NEXT: ret ptr [[T0]]1332 1333void test70(id i) {1334 // CHECK-LABEL: define{{.*}} void @test701335 // CHECK: store ptr null, ptr1336 // CHECK: store ptr null, ptr1337 // CHECK: [[ID:%.*]] = call ptr @llvm.objc.retain(ptr1338 // CHECK: store ptr [[ID]], ptr1339 id x[3] = {1340 [2] = i1341 };1342}1343 1344// Be sure that we emit lifetime intrinsics only after dtors1345struct AggDtor {1346 char cs[40];1347 id x;1348};1349 1350struct AggDtor getAggDtor(void);1351 1352// CHECK-LABEL: define{{.*}} void @test711353void test71(void) {1354 // CHECK: call void @llvm.lifetime.start.p0(ptr %[[T:.*]])1355 // CHECK: call void @getAggDtor(ptr dead_on_unwind writable sret(%struct.AggDtor) align 8 %[[T]])1356 // CHECK: call void @__destructor_8_s40(ptr %[[T]])1357 // CHECK: call void @llvm.lifetime.end.p0(ptr %[[T]])1358 // CHECK: call void @llvm.lifetime.start.p0(ptr %[[T2:.*]])1359 // CHECK: call void @getAggDtor(ptr dead_on_unwind writable sret(%struct.AggDtor) align 8 %[[T2]])1360 // CHECK: call void @__destructor_8_s40(ptr %[[T2]])1361 // CHECK: call void @llvm.lifetime.end.p0(ptr %[[T2]])1362 getAggDtor();1363 getAggDtor();1364}1365 1366// Check that no extra release calls are emitted to detruct the compond literal.1367 1368// CHECK: define{{.*}} void @test72(ptr noundef %[[A:.*]], ptr noundef %[[B:.*]])1369// CHECK: %[[A_ADDR:.*]] = alloca ptr, align 81370// CHECK: %[[B_ADDR:.*]] = alloca ptr, align 81371// CHECK: %[[T:.*]] = alloca [2 x ptr], align 161372// CHECK: %[[V0:.*]] = call ptr @llvm.objc.retain(ptr %[[A]])1373// CHECK: %[[V1:.*]] = call ptr @llvm.objc.retain(ptr %[[B]]) #21374// CHECK: %[[V3:.*]] = load ptr, ptr %[[A_ADDR]], align 8, !tbaa !{{[0-9]+}}1375// CHECK: %[[V4:.*]] = call ptr @llvm.objc.retain(ptr %[[V3]]) #21376// CHECK: store ptr %[[V4]], ptr %[[T]], align 8, !tbaa !{{[0-9]+}}1377// CHECK: %[[ARRAYINIT_ELEMENT:.*]] = getelementptr inbounds ptr, ptr %[[T]], i64 11378// CHECK: %[[V5:.*]] = load ptr, ptr %[[B_ADDR]], align 8, !tbaa !{{[0-9]+}}1379// CHECK: %[[V6:.*]] = call ptr @llvm.objc.retain(ptr %[[V5]]) #21380// CHECK: store ptr %[[V6]], ptr %[[ARRAYINIT_ELEMENT]], align 8, !tbaa !{{[0-9]+}}1381// CHECK: %[[ARRAY_BEGIN:.*]] = getelementptr inbounds [2 x ptr], ptr %[[T]], i32 0, i32 01382// CHECK: %[[V7:.*]] = getelementptr inbounds ptr, ptr %[[ARRAY_BEGIN]], i64 21383 1384// CHECK-NOT: call void @llvm.objc.release1385 1386// CHECK: %[[ARRAYDESTROY_ELEMENTPAST:.*]] = phi ptr [ %[[V7]], %{{.*}} ], [ %[[ARRAYDESTROY_ELEMENT:.*]], %{{.*}} ]1387// CHECK: %[[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds ptr, ptr %[[ARRAYDESTROY_ELEMENTPAST]], i64 -11388// CHECK: %[[V8:.*]] = load ptr, ptr %[[ARRAYDESTROY_ELEMENT]], align 81389// CHECK: call void @llvm.objc.release(ptr %[[V8]]) #2, !clang.imprecise_release1390 1391// CHECK-NOT: call void @llvm.objc.release1392 1393// CHECK: %[[V10:.*]] = load ptr, ptr %[[B_ADDR]], align 81394// CHECK: call void @llvm.objc.release(ptr %[[V10]]) #2, !clang.imprecise_release1395// CHECK: %[[V11:.*]] = load ptr, ptr %[[A_ADDR]], align 81396// CHECK: call void @llvm.objc.release(ptr %[[V11]]) #2, !clang.imprecise_release1397 1398void test72(id a, id b) {1399 __strong id t[] = (__strong id[]){a, b};1400}1401 1402// ARC-ALIEN: attributes [[NLB]] = { nonlazybind }1403// ARC-NATIVE: attributes [[NLB]] = { nonlazybind }1404// CHECK: attributes [[NUW]] = { nounwind }1405