summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/CodeGenObjC/externally-retained.m115
-rw-r--r--clang/test/Misc/pragma-attribute-supported-attributes-list.test1
-rw-r--r--clang/test/SemaObjC/externally-retained-no-arc.m7
-rw-r--r--clang/test/SemaObjC/externally-retained.m114
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
OpenPOWER on IntegriCloud