xref: /llvm-project/clang/test/CodeGenObjC/externally-retained.m (revision c5de4dd1eab00df76c1a68c5f397304ceacb71f2)
1// RUN: %clang_cc1 -triple x86_64-apple-macosx10.13.0 -fobjc-arc -fblocks -Wno-objc-root-class -O0 %s -emit-llvm -o - | FileCheck %s
2// RUN: %clang_cc1 -triple x86_64-apple-macosx10.13.0 -fobjc-arc -fblocks -Wno-objc-root-class -O0 -xobjective-c++ -std=c++11 %s -emit-llvm -o - | FileCheck %s --check-prefix CHECKXX
3
4#define EXT_RET __attribute__((objc_externally_retained))
5
6@interface ObjTy @end
7
8ObjTy *global;
9
10#if __cplusplus
11// Suppress name mangling in C++ mode for the sake of check lines.
12extern "C" void param(ObjTy *p);
13extern "C" void local();
14extern "C" void in_init();
15extern "C" void anchor();
16extern "C" void block_capture(ObjTy *);
17extern "C" void esc(void (^)());
18extern "C" void escp(void (^)(ObjTy *));
19extern "C" void block_param();
20#endif
21
22void param(ObjTy *p) EXT_RET {
23  // CHECK-LABEL: define{{.*}} void @param
24  // CHECK-NOT: llvm.objc.
25  // CHECK: ret
26}
27
28void local(void) {
29  EXT_RET ObjTy *local = global;
30  // CHECK-LABEL: define{{.*}} void @local
31  // CHECK-NOT: llvm.objc.
32  // CHECK: ret
33}
34
35void in_init(void) {
36  // Test that we do the right thing when a variable appears in it's own
37  // initializer. Here, we release the value stored in 'wat' after overwriting
38  // it, in case it was somehow set to point to a non-null object while it's
39  // initializer is being evaluated.
40  EXT_RET ObjTy *wat = 0 ? wat : global;
41
42  // CHECK-LABEL: define{{.*}} void @in_init
43  // CHECK: [[WAT:%.*]] = alloca
44  // CHECK-NEXT: store {{.*}} null, {{.*}} [[WAT]]
45  // CHECK-NEXT: [[GLOBAL:%.*]] = load {{.*}} @global
46  // CHECK-NEXT: [[WAT_LOAD:%.*]] = load {{.*}} [[WAT]]
47  // CHECK-NEXT: store {{.*}} [[GLOBAL]], {{.*}} [[WAT]]
48  // CHECK-NEXT: call void @llvm.objc.release(ptr [[WAT_LOAD]])
49
50  // CHECK-NOT: llvm.objc.
51  // CHECK: ret
52}
53
54void esc(void (^)(void));
55
56void block_capture(ObjTy *obj) EXT_RET {
57  esc(^{ (void)obj; });
58
59  // CHECK-LABEL: define{{.*}} void @block_capture
60  // CHECK-NOT: llvm.objc.
61  // CHECK: call ptr @llvm.objc.retain
62  // CHECK-NOT: llvm.objc.
63  // CHECK: call void @esc
64  // CHECK-NOT: llvm.objc.
65  // CHECK: call void @llvm.objc.storeStrong({{.*}} null)
66  // CHECK-NOT: llvm.objc.
67  // CHECK: ret
68
69  // CHECK-LABEL: define {{.*}} void @__copy_helper_block_
70  // CHECK-NOT: llvm.objc.
71  // CHECK: llvm.objc.storeStrong
72  // CHECK-NOT: llvm.objc.
73  // CHECK: ret
74
75  // CHECK-LABEL: define {{.*}} void @__destroy_helper_block_
76  // CHECK-NOT: llvm.objc.
77  // CHECK: llvm.objc.storeStrong({{.*}} null)
78  // CHECK-NOT: llvm.objc.
79  // CHECK: ret
80}
81
82void escp(void (^)(ObjTy *));
83
84void block_param(void) {
85  escp(^(ObjTy *p) EXT_RET {});
86
87  // CHECK-LABEL: define internal void @__block_param_block_invoke
88  // CHECK-NOT: llvm.objc.
89  // CHECK: ret
90}
91
92@interface Inter
93-(void)m1: (ObjTy *)w;
94@end
95
96@implementation Inter
97-(void)m1: (ObjTy *) w EXT_RET {
98  // CHECK-LABEL: define internal void @"\01-[Inter m1:]"
99  // CHECK-NOT: llvm.objc.
100  // CHECK: ret
101}
102-(void)m2: (ObjTy *) w EXT_RET {
103  // CHECK-LABEL: define internal void @"\01-[Inter m2:]"
104  // CHECK-NOT: llvm.objc.
105  // CHECK: ret
106}
107@end
108
109#if __cplusplus
110// Verify that the decltype(p) is resolved before 'p' is made implicitly const.
111__attribute__((objc_externally_retained))
112void foo(ObjTy *p, decltype(p) *) {}
113// CHECKXX: _Z3fooP5ObjTyPU8__strongS0_
114#endif
115