// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -fobjc-fragile-abi -emit-llvm -o - | FileCheck %s // rdar://9208606 struct MyStruct { int x; int y; int z; }; @interface MyClass { MyStruct _foo; } @property (assign, readwrite) const MyStruct& foo; - (const MyStruct&) foo; - (void) setFoo:(const MyStruct&)inFoo; @end void test0() { MyClass* myClass; MyStruct myStruct; myClass.foo = myStruct; const MyStruct& currentMyStruct = myClass.foo; } // CHECK: [[C:%.*]] = call %struct.MyStruct* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend // CHECK: store %struct.MyStruct* [[C]], %struct.MyStruct** [[D:%.*]] namespace test1 { struct A { A(); A(const A&); A&operator=(const A&); ~A(); }; } @interface Test1 { test1::A ivar; } @property (nonatomic) const test1::A &prop1; @end @implementation Test1 @synthesize prop1 = ivar; @end // CHECK: define internal [[A:%.*]]* @"\01-[Test1 prop1]"( // CHECK: [[SELF:%.*]] = alloca [[TEST1:%.*]]*, align 8 // CHECK: [[T0:%.*]] = load [[TEST1]]** [[SELF]] // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds i8* [[T1]], i64 0 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]* // CHECK-NEXT: ret [[A]]* [[T3]] // CHECK: define internal void @"\01-[Test1 setProp1:]"( // CHECK: call [[A]]* @_ZN5test11AaSERKS0_( // CHECK-NEXT: ret void // rdar://problem/10497174 @interface Test2 @property int prop; @end // The fact that these are all non-dependent is critical. template void test2(Test2 *a) { int x = a.prop; a.prop = x; a.prop += x; } template void test2(Test2*); // CHECK: define weak_odr void @_Z5test2IiEvP5Test2( // CHECK: [[X:%.*]] = alloca i32, // CHECK: @objc_msgSend // CHECK: store i32 {{%.*}}, i32* [[X]], // CHECK: load i32* [[X]], // CHECK: @objc_msgSend // CHECK: @objc_msgSend // CHECK: load i32* [[X]], // CHECK-NEXT: add nsw // CHECK: @objc_msgSend // CHECK-NEXT: ret void // Same as the previous test, but instantiation-dependent. template void test3(Test2 *a) { int x = (sizeof(T), a).prop; a.prop = (sizeof(T), x); a.prop += (sizeof(T), x); } template void test3(Test2*); // CHECK: define weak_odr void @_Z5test3IiEvP5Test2( // CHECK: [[X:%.*]] = alloca i32, // CHECK: @objc_msgSend // CHECK: store i32 {{%.*}}, i32* [[X]], // CHECK: load i32* [[X]], // CHECK: @objc_msgSend // CHECK: @objc_msgSend // CHECK: load i32* [[X]], // CHECK-NEXT: add nsw // CHECK: @objc_msgSend // CHECK-NEXT: ret void