1// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-arc -emit-llvm %s -o - | FileCheck %s 2 3@interface Test0 4- (void) setValue: (id) x; 5@end 6void test0(Test0 *t0, id value) { 7 t0.value = value; 8} 9// CHECK-LABEL: define{{.*}} void @test0( 10// CHECK: call void @llvm.objc.storeStrong 11// CHECK: call void @llvm.objc.storeStrong 12// CHECK: @objc_msgSend 13// CHECK: call void @llvm.objc.storeStrong( 14// CHECK: call void @llvm.objc.storeStrong( 15 16struct S1 { Class isa; }; 17@interface Test1 18@property (nonatomic, strong) __attribute__((NSObject)) struct S1 *pointer; 19@end 20@implementation Test1 21@synthesize pointer; 22@end 23// The getter should be a simple load. 24// CHECK: define internal ptr @"\01-[Test1 pointer]"( 25// CHECK: [[OFFSET:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test1.pointer" 26// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr {{%.*}}, i64 [[OFFSET]] 27// CHECK-NEXT: [[T3:%.*]] = load ptr, ptr [[T1]], align 8 28// CHECK-NEXT: ret ptr [[T3]] 29 30// The setter should be using objc_setProperty. 31// CHECK: define internal void @"\01-[Test1 setPointer:]"( 32// CHECK: [[OFFSET:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test1.pointer" 33// CHECK-NEXT: [[T1:%.*]] = load ptr, ptr {{%.*}} 34// CHECK-NEXT: call void @objc_setProperty(ptr noundef {{%.*}}, ptr noundef {{%.*}}, i64 noundef [[OFFSET]], ptr noundef [[T1]], i1 noundef zeroext false, i1 noundef zeroext false) 35// CHECK-NEXT: ret void 36 37 38@interface Test2 { 39@private 40 Class _theClass; 41} 42@property (copy) Class theClass; 43@end 44 45static Class theGlobalClass; 46@implementation Test2 47@synthesize theClass = _theClass; 48- (void) test { 49 _theClass = theGlobalClass; 50} 51@end 52// CHECK: define internal void @"\01-[Test2 test]"( 53// CHECK: [[T0:%.*]] = load ptr, ptr @theGlobalClass, align 8 54// CHECK-NEXT: [[T1:%.*]] = load ptr, ptr 55// CHECK-NEXT: [[OFFSET:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test2._theClass" 56// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T1]], i64 [[OFFSET]] 57// CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[T3]], ptr [[T0]]) [[NUW:#[0-9]+]] 58// CHECK-NEXT: ret void 59 60// CHECK: define internal ptr @"\01-[Test2 theClass]"( 61// CHECK: [[OFFSET:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test2._theClass" 62// CHECK-NEXT: [[T0:%.*]] = tail call ptr @objc_getProperty(ptr noundef {{.*}}, ptr noundef {{.*}}, i64 noundef [[OFFSET]], i1 noundef zeroext true) 63// CHECK-NEXT: ret ptr [[T0]] 64 65// CHECK: define internal void @"\01-[Test2 setTheClass:]"( 66// CHECK: [[OFFSET:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test2._theClass" 67// CHECK-NEXT: [[T1:%.*]] = load ptr, ptr {{%.*}} 68// CHECK-NEXT: call void @objc_setProperty(ptr noundef {{%.*}}, ptr noundef {{%.*}}, i64 noundef [[OFFSET]], ptr noundef [[T1]], i1 noundef zeroext true, i1 noundef zeroext true) 69// CHECK-NEXT: ret void 70 71// CHECK: define internal void @"\01-[Test2 .cxx_destruct]"( 72// CHECK: [[T0:%.*]] = load ptr, ptr 73// CHECK-NEXT: [[OFFSET:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test2._theClass" 74// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 [[OFFSET]] 75// CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[T2]], ptr null) [[NUW]] 76// CHECK-NEXT: ret void 77 78@interface Test3 79@property id copyMachine; 80@end 81 82void test3(Test3 *t) { 83 id x = t.copyMachine; 84 x = [t copyMachine]; 85} 86// CHECK: define{{.*}} void @test3(ptr 87// Prologue. 88// CHECK: [[T:%.*]] = alloca ptr, 89// CHECK-NEXT: [[X:%.*]] = alloca ptr, 90// Property access. 91// CHECK: [[T0:%.*]] = load ptr, ptr [[T]], 92// CHECK-NEXT: [[SEL:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES 93// CHECK-NEXT: [[T2:%.*]] = call ptr @objc_msgSend(ptr noundef [[T0]], ptr noundef [[SEL]]) 94// CHECK-NEXT: store ptr [[T2]], ptr [[X]], 95// Message send. 96// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[T]], 97// CHECK-NEXT: [[SEL:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES 98// CHECK-NEXT: [[T2:%.*]] = call ptr @objc_msgSend(ptr noundef [[T0]], ptr noundef [[SEL]]) 99// CHECK-NEXT: [[T3:%.*]] = load ptr, ptr [[X]], 100// CHECK-NEXT: store ptr [[T2]], ptr [[X]], 101// CHECK-NEXT: call void @llvm.objc.release(ptr [[T3]]) 102// Epilogue. 103// CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[X]], ptr null) 104// CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[T]], ptr null) 105// CHECK-NEXT: ret void 106 107@implementation Test3 108- (id) copyMachine { 109 extern id test3_helper(void); 110 return test3_helper(); 111} 112// CHECK: define internal ptr @"\01-[Test3 copyMachine]"( 113// CHECK: [[T0:%.*]] = call ptr @test3_helper() 114// CHECK-NEXT: [[T1:%.*]] = notail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[T0]]) 115// CHECK-NEXT: ret ptr [[T1]] 116- (void) setCopyMachine: (id) x {} 117@end 118 119// When synthesizing a property that's declared in multiple protocols, ensure 120// that the setter is emitted if any of these declarations is readwrite. 121@protocol ABC 122@property (copy, nonatomic, readonly) Test3 *someId; 123@end 124@protocol ABC__Mutable <ABC> 125@property (copy, nonatomic, readwrite) Test3 *someId; 126@end 127 128@interface ABC_Class <ABC, ABC__Mutable> 129@end 130 131@implementation ABC_Class 132@synthesize someId = _someId; 133// CHECK: define internal ptr @"\01-[ABC_Class someId]" 134// CHECK: define internal void @"\01-[ABC_Class setSomeId:]"( 135@end 136 137 138// CHECK: attributes [[NUW]] = { nounwind } 139