diff options
Diffstat (limited to 'clang/test')
-rw-r--r-- | clang/test/CodeGenObjC/externally-retained.m | 115 | ||||
-rw-r--r-- | clang/test/Misc/pragma-attribute-supported-attributes-list.test | 1 | ||||
-rw-r--r-- | clang/test/SemaObjC/externally-retained-no-arc.m | 7 | ||||
-rw-r--r-- | clang/test/SemaObjC/externally-retained.m | 114 |
4 files changed, 237 insertions, 0 deletions
diff --git a/clang/test/CodeGenObjC/externally-retained.m b/clang/test/CodeGenObjC/externally-retained.m new file mode 100644 index 00000000000..0b4d0d648b4 --- /dev/null +++ b/clang/test/CodeGenObjC/externally-retained.m @@ -0,0 +1,115 @@ +// 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 --dump-input-on-failure +// 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 --dump-input-on-failure + +#define EXT_RET __attribute__((objc_externally_retained)) + +@interface ObjTy @end + +ObjTy *global; + +#if __cplusplus +// Suppress name mangling in C++ mode for the sake of check lines. +extern "C" void param(ObjTy *p); +extern "C" void local(); +extern "C" void in_init(); +extern "C" void anchor(); +extern "C" void block_capture(ObjTy *); +extern "C" void esc(void (^)()); +extern "C" void escp(void (^)(ObjTy *)); +extern "C" void block_param(); +#endif + +void param(ObjTy *p) EXT_RET { + // CHECK-LABEL: define void @param + // CHECK-NOT: llvm.objc. + // CHECK ret +} + +void local() { + EXT_RET ObjTy *local = global; + // CHECK-LABEL: define void @local + // CHECK-NOT: llvm.objc. + // CHECK: ret +} + +void in_init() { + // Test that we do the right thing when a variable appears in it's own + // initializer. Here, we release the value stored in 'wat' after overwriting + // it, in case it was somehow set to point to a non-null object while it's + // initializer is being evaluated. + EXT_RET ObjTy *wat = 0 ? wat : global; + + // CHECK-LABEL: define void @in_init + // CHECK: [[WAT:%.*]] = alloca + // CHECK-NEXT: store {{.*}} null, {{.*}} [[WAT]] + // CHECK-NEXT: [[GLOBAL:%.*]] = load {{.*}} @global + // CHECK-NEXT: [[WAT_LOAD:%.*]] = load {{.*}} [[WAT]] + // CHECK-NEXT: store {{.*}} [[GLOBAL]], {{.*}} [[WAT]] + // CHECK-NEXT: [[CASTED:%.*]] = bitcast {{.*}} [[WAT_LOAD]] to + // CHECK-NEXT: call void @llvm.objc.release(i8* [[CASTED]]) + + // CHECK-NOT: llvm.objc. + // CHECK: ret +} + +void esc(void (^)()); + +void block_capture(ObjTy *obj) EXT_RET { + esc(^{ (void)obj; }); + + // CHECK-LABEL: define void @block_capture + // CHECK-NOT: llvm.objc. + // CHECK: call i8* @llvm.objc.retain + // CHECK-NOT: llvm.objc. + // CHECK: call void @esc + // CHECK-NOT: llvm.objc. + // CHECK: call void @llvm.objc.storeStrong({{.*}} null) + // CHECK-NOT: llvm.objc. + // CHECK: ret + + // CHECK-LABEL: define {{.*}} void @__copy_helper_block_ + // CHECK-NOT: llvm.objc. + // CHECK: llvm.objc.storeStrong + // CHECK-NOT: llvm.objc. + // CHECK: ret + + // CHECK-LABEL: define {{.*}} void @__destroy_helper_block_ + // CHECK-NOT: llvm.objc. + // CHECK: llvm.objc.storeStrong({{.*}} null) + // CHECK-NOT: llvm.objc. + // CHECK: ret +} + +void escp(void (^)(ObjTy *)); + +void block_param() { + escp(^(ObjTy *p) EXT_RET {}); + + // CHECK-LABEL: define internal void @__block_param_block_invoke + // CHECK-NOT: llvm.objc. + // CHECK: ret +} + +@interface Inter +-(void)m1: (ObjTy *)w; +@end + +@implementation Inter +-(void)m1: (ObjTy *) w EXT_RET { + // CHECK-LABEL: define internal void @"\01-[Inter m1:]" + // CHECK-NOT: llvm.objc. + // CHECK: ret +} +-(void)m2: (ObjTy *) w EXT_RET { + // CHECK-LABEL: define internal void @"\01-[Inter m2:]" + // CHECK-NOT: llvm.objc. + // CHECK: ret +} +@end + +#if __cplusplus +// Verify that the decltype(p) is resolved before 'p' is made implicitly const. +__attribute__((objc_externally_retained)) +void foo(ObjTy *p, decltype(p) *) {} +// CHECKXX: _Z3fooP5ObjTyPU8__strongS0_ +#endif diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 48a6bac1875..2f4aaa200c5 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -94,6 +94,7 @@ // CHECK-NEXT: ObjCBridgeRelated (SubjectMatchRule_record) // CHECK-NEXT: ObjCException (SubjectMatchRule_objc_interface) // CHECK-NEXT: ObjCExplicitProtocolImpl (SubjectMatchRule_objc_protocol) +// CHECK-NEXT: ObjCExternallyRetained (SubjectMatchRule_variable_not_is_parameter, SubjectMatchRule_function, SubjectMatchRule_block, SubjectMatchRule_objc_method) // CHECK-NEXT: ObjCMethodFamily (SubjectMatchRule_objc_method) // CHECK-NEXT: ObjCPreciseLifetime (SubjectMatchRule_variable) // CHECK-NEXT: ObjCRequiresPropertyDefs (SubjectMatchRule_objc_interface) diff --git a/clang/test/SemaObjC/externally-retained-no-arc.m b/clang/test/SemaObjC/externally-retained-no-arc.m new file mode 100644 index 00000000000..a548d6b88dd --- /dev/null +++ b/clang/test/SemaObjC/externally-retained-no-arc.m @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 %s -verify + +@interface NSWidget @end + +__attribute__((objc_externally_retained)) void f(NSWidget *p) { // expected-warning{{'objc_externally_retained' attribute ignored}} + __attribute__((objc_externally_retained)) NSWidget *w; // expected-warning{{'objc_externally_retained' attribute ignored}} +} diff --git a/clang/test/SemaObjC/externally-retained.m b/clang/test/SemaObjC/externally-retained.m new file mode 100644 index 00000000000..2708fc8eefe --- /dev/null +++ b/clang/test/SemaObjC/externally-retained.m @@ -0,0 +1,114 @@ +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.13.0 -fobjc-runtime=macosx-10.13.0 -fblocks -fobjc-arc %s -verify +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.13.0 -fobjc-runtime=macosx-10.13.0 -fblocks -fobjc-arc -xobjective-c++ %s -verify + +#define EXT_RET __attribute__((objc_externally_retained)) + +@interface ObjCTy +@end + +void test1() { + EXT_RET int a; // expected-warning{{'objc_externally_retained' can only be applied to}} + EXT_RET __weak ObjCTy *b; // expected-warning{{'objc_externally_retained' can only be applied to}} + EXT_RET __weak int (^c)(); // expected-warning{{'objc_externally_retained' can only be applied to}} + + EXT_RET int (^d)() = ^{return 0;}; + EXT_RET ObjCTy *e = 0; + EXT_RET __strong ObjCTy *f = 0; + + e = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}} + f = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}} + d = ^{ return 0; }; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}} +} + +void test2(ObjCTy *a); + +void test2(ObjCTy *a) EXT_RET { + a = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}} +} + +EXT_RET ObjCTy *test3; // expected-warning{{'objc_externally_retained' can only be applied to}} + +@interface X // expected-warning{{defined without specifying a base class}} expected-note{{add a super class}} +-(void)m: (ObjCTy *) p; +@end +@implementation X +-(void)m: (ObjCTy *) p EXT_RET { + p = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}} +} +@end + +void test4() { + __attribute__((objc_externally_retained(0))) ObjCTy *a; // expected-error{{'objc_externally_retained' attribute takes no arguments}} +} + +void test5(ObjCTy *first, __strong ObjCTy *second) EXT_RET { + first = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}} + second = 0; // fine +} + +void test6(ObjCTy *first, + __strong ObjCTy *second) EXT_RET { + first = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}} + second = 0; +} + +__attribute__((objc_root_class)) @interface Y @end + +@implementation Y +- (void)test7:(__strong ObjCTy *)first + withThird:(ObjCTy *)second EXT_RET { + first = 0; + second = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}} +} +@end + +void (^blk)(ObjCTy *, ObjCTy *) = + ^(__strong ObjCTy *first, ObjCTy *second) EXT_RET { + first = 0; + second = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}} +}; + +void test8(EXT_RET ObjCTy *x) {} // expected-warning{{'objc_externally_retained' attribute only applies to variables}} + +#pragma clang attribute ext_ret.push(__attribute__((objc_externally_retained)), apply_to=any(function, block, objc_method)) +void test9(ObjCTy *first, __strong ObjCTy *second) { + first = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}} + second = 0; +} +void (^test10)(ObjCTy *first, ObjCTy *second) = ^(ObjCTy *first, __strong ObjCTy *second) { + first = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}} + second = 0; +}; +__attribute__((objc_root_class)) @interface Test11 @end +@implementation Test11 +-(void)meth: (ObjCTy *)first withSecond:(__strong ObjCTy *)second { + first = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}} + second = 0; +} ++(void)othermeth: (ObjCTy *)first withSecond:(__strong ObjCTy *)second { + first = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}} + second = 0; +} +@end + +#if __cplusplus +class Test12 { + void inline_member(ObjCTy *first, __strong ObjCTy *second) { + first = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}} + second = 0; + } + static void static_inline_member(ObjCTy *first, __strong ObjCTy *second) { + first = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}} + second = 0; + } +}; +#endif + +void test13(ObjCTy *first, __weak ObjCTy *second, __unsafe_unretained ObjCTy *third, __strong ObjCTy *fourth) { + first = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}} + second = 0; + third = 0; + fourth = 0; +} + +#pragma clang attribute ext_ret.pop |