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