1 | // RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5 -emit-llvm -o - | FileCheck %s |
2 | // rdar://9208606 |
3 | |
4 | struct MyStruct { |
5 | int x; |
6 | int y; |
7 | int z; |
8 | }; |
9 | |
10 | @interface MyClass { |
11 | MyStruct _foo; |
12 | } |
13 | |
14 | @property (assign, readwrite) const MyStruct& foo; |
15 | |
16 | - (const MyStruct&) foo; |
17 | - (void) setFoo:(const MyStruct&)inFoo; |
18 | @end |
19 | |
20 | void test0() { |
21 | MyClass* myClass; |
22 | MyStruct myStruct; |
23 | |
24 | myClass.foo = myStruct; |
25 | |
26 | const MyStruct& currentMyStruct = myClass.foo; |
27 | } |
28 | |
29 | // CHECK: [[C:%.*]] = call dereferenceable({{[0-9]+}}) %struct.MyStruct* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend |
30 | // CHECK: store %struct.MyStruct* [[C]], %struct.MyStruct** [[D:%.*]] |
31 | |
32 | namespace test1 { |
33 | struct A { A(); A(const A&); A&operator=(const A&); ~A(); }; |
34 | } |
35 | @interface Test1 { |
36 | test1::A ivar; |
37 | } |
38 | @property (nonatomic) const test1::A &prop1; |
39 | @end |
40 | @implementation Test1 |
41 | @synthesize prop1 = ivar; |
42 | @end |
43 | // CHECK: define internal dereferenceable({{[0-9]+}}) [[A:%.*]]* @"\01-[Test1 prop1]"( |
44 | // CHECK: [[SELF:%.*]] = alloca [[TEST1:%.*]]*, align 8 |
45 | // CHECK: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]** [[SELF]] |
46 | // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* |
47 | // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds i8, i8* [[T1]], i64 0 |
48 | // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]* |
49 | // CHECK-NEXT: ret [[A]]* [[T3]] |
50 | |
51 | // CHECK: define internal void @"\01-[Test1 setProp1:]"( |
52 | // CHECK: call dereferenceable({{[0-9]+}}) [[A]]* @_ZN5test11AaSERKS0_( |
53 | // CHECK-NEXT: ret void |
54 | |
55 | // rdar://problem/10497174 |
56 | @interface Test2 |
57 | @property int prop; |
58 | @end |
59 | |
60 | // The fact that these are all non-dependent is critical. |
61 | template <class T> void test2(Test2 *a) { |
62 | int x = a.prop; |
63 | a.prop = x; |
64 | a.prop += x; |
65 | } |
66 | template void test2<int>(Test2*); |
67 | // CHECK-LABEL: define weak_odr void @_Z5test2IiEvP5Test2( |
68 | // CHECK: [[X:%.*]] = alloca i32, |
69 | // CHECK: @objc_msgSend |
70 | // CHECK: store i32 {{%.*}}, i32* [[X]], |
71 | // CHECK: load i32, i32* [[X]], |
72 | // CHECK: @objc_msgSend |
73 | // CHECK: @objc_msgSend |
74 | // CHECK: load i32, i32* [[X]], |
75 | // CHECK-NEXT: add nsw |
76 | // CHECK: @objc_msgSend |
77 | // CHECK-NEXT: ret void |
78 | |
79 | // Same as the previous test, but instantiation-dependent. |
80 | template <class T> void test3(Test2 *a) { |
81 | int x = (sizeof(T), a).prop; |
82 | a.prop = (sizeof(T), x); |
83 | a.prop += (sizeof(T), x); |
84 | } |
85 | template void test3<int>(Test2*); |
86 | // CHECK-LABEL: define weak_odr void @_Z5test3IiEvP5Test2( |
87 | // CHECK: [[X:%.*]] = alloca i32, |
88 | // CHECK: @objc_msgSend |
89 | // CHECK: store i32 {{%.*}}, i32* [[X]], |
90 | // CHECK: load i32, i32* [[X]], |
91 | // CHECK: @objc_msgSend |
92 | // CHECK: @objc_msgSend |
93 | // CHECK: load i32, i32* [[X]], |
94 | // CHECK-NEXT: add nsw |
95 | // CHECK: @objc_msgSend |
96 | // CHECK-NEXT: ret void |
97 | |