summaryrefslogtreecommitdiff
path: root/test/SemaObjCXX
diff options
context:
space:
mode:
authorAkira Hatanaka <ahatanaka@apple.com>2017-09-20 06:22:51 +0000
committerAkira Hatanaka <ahatanaka@apple.com>2017-09-20 06:22:51 +0000
commite077cfd4f9ada87940c24f0feb197492787e40f6 (patch)
tree96c3afc54ecd82000558a3017b242d752d34439c /test/SemaObjCXX
parentcb0d01de81d97f744ef81029b8e013a770b46936 (diff)
Add support for attribute 'noescape'.
The attribute informs the compiler that the annotated pointer parameter of a function cannot escape and enables IRGen to attach attribute 'nocapture' to parameters that are annotated with the attribute. That is the only optimization that currently takes advantage of 'noescape', but there are other optimizations that will be added later that improves IRGen for ObjC blocks. rdar://problem/19886775 Differential Revision: https://reviews.llvm.org/D32520 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@313720 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/SemaObjCXX')
-rw-r--r--test/SemaObjCXX/noescape.mm90
1 files changed, 90 insertions, 0 deletions
diff --git a/test/SemaObjCXX/noescape.mm b/test/SemaObjCXX/noescape.mm
new file mode 100644
index 0000000000..6c5d9897aa
--- /dev/null
+++ b/test/SemaObjCXX/noescape.mm
@@ -0,0 +1,90 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -std=c++11 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -std=c++1z %s
+
+typedef void (^BlockTy)();
+
+struct S {
+ int i;
+ void m();
+};
+
+void noescapeFunc0(id, __attribute__((noescape)) BlockTy);
+void noescapeFunc1(id, [[clang::noescape]] BlockTy);
+void noescapeFunc2(__attribute__((noescape)) int *); // expected-note {{previous declaration is here}}
+void noescapeFunc3(__attribute__((noescape)) id);
+void noescapeFunc4(__attribute__((noescape)) int &);
+void noescapeFunc2(int *); // expected-error {{conflicting types for 'noescapeFunc2'}}
+
+void invalidFunc0(int __attribute__((noescape))); // expected-warning {{'noescape' attribute only applies to pointer arguments}}
+void invalidFunc1(int __attribute__((noescape(0)))); // expected-error {{'noescape' attribute takes no arguments}}
+void invalidFunc2(int0 *__attribute__((noescape))); // expected-error {{use of undeclared identifier 'int0'; did you mean 'int'?}}
+void invalidFunc3(__attribute__((noescape)) int (S::*Ty)); // expected-warning {{'noescape' attribute only applies to pointer arguments}}
+void invalidFunc4(__attribute__((noescape)) void (S::*Ty)()); // expected-warning {{'noescape' attribute only applies to pointer arguments}}
+int __attribute__((noescape)) g; // expected-warning {{'noescape' attribute only applies to parameters}}
+
+struct S1 {
+ virtual void m0(int *__attribute__((noescape))); // expected-note {{parameter of overridden method is annotated with __attribute__((noescape))}}
+};
+
+struct S2 : S1 {
+ void m0(int *__attribute__((noescape))) override;
+};
+
+struct S3 : S1 {
+ void m0(int *) override; // expected-warning {{parameter of overriding method should be annotated with __attribute__((noescape))}}
+};
+
+__attribute__((objc_root_class))
+@interface C0
+-(void) m0:(int*)__attribute__((noescape)) p; // expected-note {{parameter of overridden method is annotated with __attribute__((noescape))}}
+@end
+
+@implementation C0
+-(void) m0:(int*)__attribute__((noescape)) p {}
+@end
+
+@interface C1 : C0
+-(void) m0:(int*)__attribute__((noescape)) p;
+@end
+
+@implementation C1 : C0
+-(void) m0:(int*)__attribute__((noescape)) p {}
+@end
+
+@interface C2 : C0
+-(void) m0:(int*) p; // expected-warning {{parameter of overriding method should be annotated with __attribute__((noescape))}}
+@end
+
+@implementation C2 : C0
+-(void) m0:(int*) p {}
+@end
+
+void func0(int *);
+void (*fnptr0)(int *);
+void (*fnptr1)(__attribute__((noescape)) int *);
+template<void (*fn)(int*)> struct S4 {};
+template<void (*fn)(int* __attribute__((noescape)))> struct S5 {};
+
+#if __cplusplus < 201406
+ // expected-note@-4 {{template parameter is declared here}}
+ // expected-note@-4 {{template parameter is declared here}}
+#endif
+
+void test0() {
+ fnptr0 = &func0;
+ fnptr0 = &noescapeFunc2;
+ fnptr1 = &func0; // expected-error {{assigning to 'void (*)(__attribute__((noescape)) int *)' from incompatible type 'void (*)(int *)'}}
+ fnptr1 = &noescapeFunc2;
+ S4<&func0> e0;
+ S4<&noescapeFunc2> e1;
+ S5<&func0> ne0;
+
+#if __cplusplus < 201406
+ // expected-error@-4 {{non-type template argument of type 'void (*)(__attribute__((noescape)) int *)' cannot be converted to a value of type 'void (*)(int *)'}}
+ // expected-error@-4 {{non-type template argument of type 'void (*)(int *)' cannot be converted to a value of type 'void (*)(__attribute__((noescape)) int *)'}}
+#else
+ // expected-error@-6 {{value of type 'void (*)(int *)' is not implicitly convertible to 'void (*)(__attribute__((noescape)) int *)'}}
+#endif
+
+ S5<&noescapeFunc2> ne1;
+}