1// RUN: %clang_cc1 -triple x86_64-apple-macosx10.13.0 -fobjc-arc -fblocks -Wno-objc-root-class -O0 %s -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 -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() { 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() { 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: [[CASTED:%.*]] = bitcast {{.*}} [[WAT_LOAD]] to 49 // CHECK-NEXT: call void @llvm.objc.release(i8* [[CASTED]]) 50 51 // CHECK-NOT: llvm.objc. 52 // CHECK: ret 53} 54 55void esc(void (^)()); 56 57void block_capture(ObjTy *obj) EXT_RET { 58 esc(^{ (void)obj; }); 59 60 // CHECK-LABEL: define void @block_capture 61 // CHECK-NOT: llvm.objc. 62 // CHECK: call i8* @llvm.objc.retain 63 // CHECK-NOT: llvm.objc. 64 // CHECK: call void @esc 65 // CHECK-NOT: llvm.objc. 66 // CHECK: call void @llvm.objc.storeStrong({{.*}} null) 67 // CHECK-NOT: llvm.objc. 68 // CHECK: ret 69 70 // CHECK-LABEL: define {{.*}} void @__copy_helper_block_ 71 // CHECK-NOT: llvm.objc. 72 // CHECK: llvm.objc.storeStrong 73 // CHECK-NOT: llvm.objc. 74 // CHECK: ret 75 76 // CHECK-LABEL: define {{.*}} void @__destroy_helper_block_ 77 // CHECK-NOT: llvm.objc. 78 // CHECK: llvm.objc.storeStrong({{.*}} null) 79 // CHECK-NOT: llvm.objc. 80 // CHECK: ret 81} 82 83void escp(void (^)(ObjTy *)); 84 85void block_param() { 86 escp(^(ObjTy *p) EXT_RET {}); 87 88 // CHECK-LABEL: define internal void @__block_param_block_invoke 89 // CHECK-NOT: llvm.objc. 90 // CHECK: ret 91} 92 93@interface Inter 94-(void)m1: (ObjTy *)w; 95@end 96 97@implementation Inter 98-(void)m1: (ObjTy *) w EXT_RET { 99 // CHECK-LABEL: define internal void @"\01-[Inter m1:]" 100 // CHECK-NOT: llvm.objc. 101 // CHECK: ret 102} 103-(void)m2: (ObjTy *) w EXT_RET { 104 // CHECK-LABEL: define internal void @"\01-[Inter m2:]" 105 // CHECK-NOT: llvm.objc. 106 // CHECK: ret 107} 108@end 109 110#if __cplusplus 111// Verify that the decltype(p) is resolved before 'p' is made implicitly const. 112__attribute__((objc_externally_retained)) 113void foo(ObjTy *p, decltype(p) *) {} 114// CHECKXX: _Z3fooP5ObjTyPU8__strongS0_ 115#endif 116