Clang Project

clang_source_code/test/SemaObjCXX/noescape.mm
1// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -std=c++11 %s
2// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -std=c++1z %s
3
4typedef void (^BlockTy)();
5
6struct S {
7  int i;
8  void m();
9};
10
11void escapingFunc0(BlockTy);
12void noescapeFunc0(id, __attribute__((noescape)) BlockTy);
13void noescapeFunc1(id, [[clang::noescape]] BlockTy);
14void noescapeFunc2(__attribute__((noescape)) int *); // expected-note {{previous declaration is here}}
15void noescapeFunc3(__attribute__((noescape)) id);
16void noescapeFunc4(__attribute__((noescape)) int &);
17void noescapeFunc2(int *); // expected-error {{conflicting types for 'noescapeFunc2'}}
18
19void invalidFunc0(int __attribute__((noescape))); // expected-warning {{'noescape' attribute only applies to pointer arguments}}
20void invalidFunc1(int __attribute__((noescape(0)))); // expected-error {{'noescape' attribute takes no arguments}}
21void invalidFunc2(int0 *__attribute__((noescape))); // expected-error {{use of undeclared identifier 'int0'; did you mean 'int'?}}
22void invalidFunc3(__attribute__((noescape)) int (S::*Ty)); // expected-warning {{'noescape' attribute only applies to pointer arguments}}
23void invalidFunc4(__attribute__((noescape)) void (S::*Ty)()); // expected-warning {{'noescape' attribute only applies to pointer arguments}}
24int __attribute__((noescape)) g; // expected-warning {{'noescape' attribute only applies to parameters}}
25
26struct S1 {
27  virtual void m0(int *__attribute__((noescape))); // expected-note {{parameter of overridden method is annotated with __attribute__((noescape))}}
28};
29
30struct S2 : S1 {
31  void m0(int *__attribute__((noescape))) override;
32};
33
34struct S3 : S1 {
35  void m0(int *) override; // expected-warning {{parameter of overriding method should be annotated with __attribute__((noescape))}}
36};
37
38__attribute__((objc_root_class))
39@interface C0
40-(void) m0:(int*)__attribute__((noescape)) p; // expected-note {{parameter of overridden method is annotated with __attribute__((noescape))}}
41@end
42
43@implementation C0
44-(void) m0:(int*)__attribute__((noescape)) p {}
45@end
46
47@interface C1 : C0
48-(void) m0:(int*)__attribute__((noescape)) p;
49@end
50
51@implementation C1 : C0
52-(void) m0:(int*)__attribute__((noescape)) p {}
53@end
54
55@interface C2 : C0
56-(void) m0:(int*) p; // expected-warning {{parameter of overriding method should be annotated with __attribute__((noescape))}}
57@end
58
59@implementation C2 : C0
60-(void) m0:(int*) p {}
61@end
62
63void func0(int *);
64void (*fnptr0)(int *);
65void (*fnptr1)(__attribute__((noescape)) int *);
66template<void (*fn)(int*)> struct S4 {};
67template<void (*fn)(int* __attribute__((noescape)))> struct S5 {};
68
69#if __cplusplus < 201406
70  // expected-note@-4 {{template parameter is declared here}}
71  // expected-note@-4 {{template parameter is declared here}}
72#endif
73
74void test0() {
75  fnptr0 = &func0;
76  fnptr0 = &noescapeFunc2;
77  fnptr1 = &func0; // expected-error {{assigning to 'void (*)(__attribute__((noescape)) int *)' from incompatible type 'void (*)(int *)'}}
78  fnptr1 = &noescapeFunc2;
79  S4<&func0> e0;
80  S4<&noescapeFunc2> e1;
81  S5<&func0> ne0;
82
83#if __cplusplus < 201406
84  // expected-error@-4 {{non-type template argument of type 'void (*)(__attribute__((noescape)) int *)' cannot be converted to a value of type 'void (*)(int *)'}}
85  // expected-error@-4 {{non-type template argument of type 'void (*)(int *)' cannot be converted to a value of type 'void (*)(__attribute__((noescape)) int *)'}}
86#else
87  // expected-error@-6 {{value of type 'void (*)(int *)' is not implicitly convertible to 'void (*)(__attribute__((noescape)) int *)'}}
88#endif
89
90  S5<&noescapeFunc2> ne1;
91}
92
93@protocol NoescapeProt
94-(void) m0:(int*)__attribute__((noescape)) p; // expected-note 2 {{parameter of overridden method is annotated with __attribute__((noescape))}}
95+(void) m1:(int*)__attribute__((noescape)) p;
96-(void) m1:(int*) p;
97@end
98
99__attribute__((objc_root_class))
100@interface C3
101-(void) m0:(int*) p;
102+(void) m1:(int*)__attribute__((noescape)) p;
103-(void) m1:(int*) p;
104@end
105
106@interface C3 () <NoescapeProt> // expected-note {{class extension conforms to protocol 'NoescapeProt' which defines method 'm0:'}}
107@end
108
109@implementation C3
110-(void) m0:(int*) p { // expected-warning {{parameter of overriding method should be annotated with __attribute__((noescape))}}
111}
112+(void) m1:(int*)__attribute__((noescape)) p {
113}
114-(void) m1:(int*) p {
115}
116@end
117
118__attribute__((objc_root_class))
119@interface C4 <NoescapeProt>
120-(void) m0:(int*) p; // expected-warning {{parameter of overriding method should be annotated with __attribute__((noescape))}}
121@end
122
123@implementation C4
124-(void) m0:(int*) p {
125}
126+(void) m1:(int*)__attribute__((noescape)) p {
127}
128-(void) m1:(int*) p {
129}
130@end
131
132struct S6 {
133  S6();
134  S6(const S6 &) = delete; // expected-note 3 {{'S6' has been explicitly marked deleted here}}
135  int f;
136};
137
138void test1() {
139  id a;
140  // __block variables that are not captured by escaping blocks don't
141  // necessitate having accessible copy constructors.
142  __block S6 b0;
143  __block S6 b1; // expected-error {{call to deleted constructor of 'S6'}}
144  __block S6 b2; // expected-error {{call to deleted constructor of 'S6'}}
145  __block S6 b3; // expected-error {{call to deleted constructor of 'S6'}}
146
147  noescapeFunc0(a, ^{ (void)b0; });
148  escapingFunc0(^{ (void)b1; });
149  {
150    noescapeFunc0(a, ^{ (void)b0; (void)b1; });
151  }
152  noescapeFunc0(a, ^{ escapingFunc0(^{ (void)b2; }); });
153  escapingFunc0(^{ noescapeFunc0(a, ^{ (void)b3; }); });
154}
155