Clang Project

clang_source_code/test/SemaObjC/unguarded-availability.m
1// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -Wunguarded-availability -fblocks -fsyntax-only -verify %s
2// RUN: %clang_cc1 -xobjective-c++ -std=c++11 -DOBJCPP -triple x86_64-apple-macosx10.9 -Wunguarded-availability -fblocks -fsyntax-only -verify %s
3
4#define AVAILABLE_10_0  __attribute__((availability(macos, introduced = 10.0)))
5#define AVAILABLE_10_11 __attribute__((availability(macos, introduced = 10.11)))
6#define AVAILABLE_10_12 __attribute__((availability(macos, introduced = 10.12)))
7
8typedef int AVAILABLE_10_12 new_int; // expected-note + {{'new_int' has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9.0}}
9
10int func_10_11() AVAILABLE_10_11; // expected-note 8 {{'func_10_11' has been marked as being introduced in macOS 10.11 here, but the deployment target is macOS 10.9.0}}
11
12#ifdef OBJCPP
13// expected-note@+2 6 {{'func_10_12' has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9.0}}
14#endif
15int func_10_12() AVAILABLE_10_12; // expected-note 7 {{'func_10_12' has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9.0}}
16
17int func_10_0() AVAILABLE_10_0;
18
19void use_func() {
20  func_10_11(); // expected-warning{{'func_10_11' is only available on macOS 10.11 or newer}} expected-note{{enclose 'func_10_11' in an @available check to silence this warning}}
21
22  if (@available(macos 10.11, *))
23    func_10_11();
24  else
25    func_10_11(); // expected-warning{{'func_10_11' is only available on macOS 10.11 or newer}} expected-note{{enclose 'func_10_11' in an @available check to silence this warning}}
26}
27
28void defn_10_11() AVAILABLE_10_11;
29
30void defn_10_11() {
31  func_10_11();
32}
33
34void nested_ifs() {
35  if (@available(macos 10.12, *)) {
36    if (@available(macos 10.10, *)) {
37      func_10_12();
38    } else {
39      func_10_12();
40    }
41  } else {
42    func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{enclose 'func_10_12' in an @available check to silence this warning}}
43  }
44}
45
46void star_case() {
47  if (@available(ios 9, *)) {
48    func_10_11(); // expected-warning{{'func_10_11' is only available on macOS 10.11 or newer}} expected-note{{enclose 'func_10_11' in an @available check to silence this warning}}
49    func_10_0();
50  } else
51    func_10_11(); // expected-warning{{'func_10_11' is only available on macOS 10.11 or newer}} expected-note{{enclose 'func_10_11' in an @available check to silence this warning}}
52
53  if (@available(macOS 10.11, *)) {
54    if (@available(ios 8, *)) {
55      func_10_11();
56      func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{enclose}}
57    } else {
58      func_10_11();
59      func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{enclose}}
60    }
61  }
62}
63
64typedef int int_10_11 AVAILABLE_10_11; // expected-note {{'int_10_11' has been marked as being introduced in macOS 10.11 here, but the deployment target is macOS 10.9.0}}
65#ifdef OBJCPP
66// expected-note@+2 {{'int_10_12' has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9.0}}
67#endif
68typedef int int_10_12 AVAILABLE_10_12; // expected-note 2 {{'int_10_12' has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9.0}}
69
70void use_typedef() {
71  int_10_11 x; // expected-warning{{'int_10_11' is only available on macOS 10.11 or newer}} expected-note{{enclose 'int_10_11' in an @available check to silence this warning}}
72}
73
74__attribute__((objc_root_class))
75AVAILABLE_10_11 @interface Class_10_11 { // expected-note{{annotate 'Class_10_11' with an availability attribute to silence}}
76  int_10_11 foo;
77  int_10_12 bar; // expected-warning {{'int_10_12' is only available on macOS 10.12 or newer}}
78}
79- (void)method1;
80- (void)method2;
81@end
82
83@implementation Class_10_11
84- (void) method1 {
85  func_10_11();
86  func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{enclose 'func_10_12' in an @available check to silence this warning}}
87}
88
89- (void)method2 AVAILABLE_10_12 {
90  func_10_12();
91}
92
93@end
94
95int protected_scope() {
96  if (@available(macos 10.20, *)) { // expected-note 2 {{jump enters controlled statement of if available}}
97  label1:
98    return 0;
99  } else {
100  label2:
101    goto label1; // expected-error{{cannot jump from this goto statement to its label}}
102  }
103
104  goto label2; // expected-error{{cannot jump from this goto statement to its label}}
105}
106
107struct S {
108  int m1;
109  int m2 __attribute__((availability(macos, introduced = 10.12))); // expected-note{{has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9.0}}
110
111  struct Nested {
112    int nested_member __attribute__((availability(macos, introduced = 10.12))); // expected-note{{'nested_member' has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9.0}}
113  } n;
114};
115
116int test_members() {
117  struct S s;
118  (void)s.m1;
119  (void)s.m2; // expected-warning{{'m2' is only available on macOS 10.12 or newer}} expected-note{{@available}}
120
121  (void)s.n.nested_member; // expected-warning{{'nested_member' is only available on macOS 10.12 or newer}} expected-note{{@available}}
122}
123
124void test_blocks() {
125  (void) ^{
126    func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{@available}}
127  };
128}
129
130void test_params(int_10_12 x); // expected-warning {{'int_10_12' is only available on macOS 10.12 or newer}} expected-note{{annotate 'test_params' with an availability attribute to silence this warning}}
131
132void test_params2(int_10_12 x) AVAILABLE_10_12; // no warn
133
134void (^topLevelBlockDecl)() = ^ {
135  func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{@available}}
136  if (@available(macos 10.12, *))
137    func_10_12();
138};
139
140AVAILABLE_10_12
141__attribute__((objc_root_class))
142@interface InterWithProp // expected-note 2 {{'InterWithProp' has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9.0}}
143@property(class) int x;
144+ (void) setX: (int)newX AVAILABLE_10_12; // expected-note{{'setX:' has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9.0}}
145@end
146void test_property(void) {
147  int y = InterWithProp.x; // expected-warning{{'InterWithProp' is only available on macOS 10.12 or newer}} expected-note{{@available}}
148  InterWithProp.x = y; // expected-warning{{'InterWithProp' is only available on macOS 10.12 or newer}} expected-note{{@available}} expected-warning{{'setX:' is only available on macOS 10.12 or newer}} expected-note{{@available}}
149}
150
151__attribute__((objc_root_class))
152@interface Subscriptable
153- (id)objectAtIndexedSubscript:(int)sub AVAILABLE_10_12; // expected-note{{'objectAtIndexedSubscript:' has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9.0}}
154@end
155
156void test_at(Subscriptable *x) {
157  id y = x[42]; // expected-warning{{'objectAtIndexedSubscript:' is only available on macOS 10.12 or newer}} expected-note{{@available}}
158}
159
160void uncheckAtAvailable() {
161  if (@available(macOS 10.12, *) || 0) // expected-warning {{@available does not guard availability here; use if (@available) instead}}
162    func_10_12(); // expected-warning {{'func_10_12' is only available on macOS 10.12 or newer}}
163  // expected-note@-1 {{enclose 'func_10_12' in an @available check to silence this warning}}
164}
165
166void justAtAvailable() {
167  int availability = @available(macOS 10.12, *); // expected-warning {{@available does not guard availability here; use if (@available) instead}}
168}
169
170#ifdef OBJCPP
171
172int f(char) AVAILABLE_10_12;
173int f(int);
174
175template <class T> int use_f() {
176  // FIXME: We should warn here!
177  return f(T());
178}
179
180int a = use_f<int>();
181int b = use_f<char>();
182
183template <class> int use_at_available() {
184  if (@available(macos 10.12, *))
185    return func_10_12();
186  else
187    return func_10_12(); // expected-warning {{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{enclose}}
188}
189
190int instantiate_template() {
191  if (@available(macos 10.12, *)) {
192    use_at_available<char>();
193  } else {
194    use_at_available<float>();
195  }
196}
197
198template <class>
199int with_availability_attr() AVAILABLE_10_11 { // expected-note 2 {{'with_availability_attr<int>' has been marked as being introduced in macOS 10.11 here, but the deployment target is macOS 10.9.0}}
200  return 0;
201}
202
203int instantiate_with_availability_attr() {
204  if (@available(macos 10.12, *))
205    with_availability_attr<char>();
206  else
207    with_availability_attr<int>(); // expected-warning {{'with_availability_attr<int>' is only available on macOS 10.11 or newer}} expected-note {{enclose}}
208}
209
210int instantiate_availability() {
211  if (@available(macOS 10.12, *))
212    with_availability_attr<int_10_12>();
213  else
214    with_availability_attr<int_10_12>(); // expected-warning{{'with_availability_attr<int>' is only available on macOS 10.11 or newer}} expected-warning{{'int_10_12' is only available on macOS 10.12 or newer}} expected-note 2 {{enclose}}
215}
216
217auto topLevelLambda = [] () {
218  func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{@available}}
219  if (@available(macos 10.12, *))
220    func_10_12();
221};
222
223void functionInFunction() {
224  func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{@available}}
225  struct DontWarnTwice {
226    void f() {
227      func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{@available}}
228    }
229  };
230  void([] () {
231    func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{@available}}
232  });
233  (void)(^ {
234    func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{@available}}
235  });
236}
237
238#endif
239
240struct InStruct { // expected-note{{annotate 'InStruct' with an availability attribute to silence}}
241  new_int mem; // expected-warning{{'new_int' is only available on macOS 10.12 or newer}}
242
243  struct { new_int mem; } anon; // expected-warning{{'new_int' is only available on macOS 10.12 or newer}} expected-note{{annotate anonymous struct with an availability attribute to silence}}
244};
245
246#ifdef OBJCPP
247static constexpr int AVAILABLE_10_12 SomeConstexprValue = 2; // expected-note{{'SomeConstexprValue' has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9.0}}
248typedef enum { // expected-note{{annotate anonymous enum with an availability attribute}}
249  SomeValue = SomeConstexprValue // expected-warning{{'SomeConstexprValue' is only available on macOS 10.12 or newer}} 
250} SomeEnum;
251#endif
252
253@interface InInterface
254-(new_int)meth; // expected-warning{{'new_int' is only available on macOS 10.12 or newer}} expected-note{{annotate 'meth' with an availability attribute}}
255@end
256
257@interface Proper // expected-note{{annotate 'Proper' with an availability attribute}}
258@property (class) new_int x; // expected-warning{{'new_int' is only available}}
259@end
260
261void with_local_struct() {
262  struct local { // expected-note{{annotate 'local' with an availability attribute}}
263    new_int x; // expected-warning{{'new_int' is only available}}
264  };
265}
266
267// rdar://33156429:
268// Avoid the warning on protocol requirements.
269
270AVAILABLE_10_12
271@protocol NewProtocol // expected-note {{'NewProtocol' has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9.0}}
272@end
273
274@protocol ProtocolWithNewProtocolRequirement <NewProtocol> // expected-note {{annotate 'ProtocolWithNewProtocolRequirement' with an availability attribute to silence}}
275
276@property(copy) id<NewProtocol> prop; // expected-warning {{'NewProtocol' is only available on macOS 10.12 or newer}}
277
278@end
279
280@interface BaseClass
281@end
282
283@interface ClassWithNewProtocolRequirement : BaseClass <NewProtocol>
284
285@end
286
287@interface BaseClass (CategoryWithNewProtocolRequirement) <NewProtocol>
288
289@end
290
291typedef enum {
292  AK_Dodo __attribute__((availability(macos, deprecated=10.3))), // expected-note 3 {{marked deprecated here}}
293  AK_Cat __attribute__((availability(macos, introduced=10.4))),
294  AK_CyborgCat __attribute__((availability(macos, introduced=10.12))), // expected-note {{'AK_CyborgCat' has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9.0}}
295} Animals;
296
297void switchAnimals(Animals a) {
298  switch (a) {
299  case AK_Dodo: break; // expected-warning{{'AK_Dodo' is deprecated}}
300  case AK_Cat: break;
301  case AK_Cat|AK_CyborgCat: break; // expected-warning{{case value not in enum}}
302  case AK_CyborgCat: break; // no warn
303  }
304
305  switch (a) {
306  case AK_Dodo...AK_CyborgCat: // expected-warning {{'AK_Dodo' is depr}}
307    break;
308  }
309
310  (void)AK_Dodo; // expected-warning{{'AK_Dodo' is deprecated}}
311  (void)AK_Cat; // no warning
312  (void)AK_CyborgCat; // expected-warning{{'AK_CyborgCat' is only available on macOS 10.12 or newer}} expected-note {{@available}}
313}
314
315
316// test static initializers has the same availability as the deployment target and it cannot be overwritten.
317@interface HasStaticInitializer : BaseClass
318+ (void)load AVAILABLE_10_11; // expected-warning{{ignoring availability attribute on '+load' method}}
319@end
320
321@implementation HasStaticInitializer
322+ (void)load {
323  func_10_11(); // expected-warning{{'func_10_11' is only available on macOS 10.11 or newer}} expected-note{{enclose 'func_10_11' in an @available check to silence this warning}}
324}
325@end
326
327// test availability from interface is ignored when checking the unguarded availability in +load method.
328AVAILABLE_10_11
329@interface HasStaticInitializer1 : BaseClass
330+ (void)load;
331+ (void)load: (int)x; // no warning.
332@end
333
334@implementation HasStaticInitializer1
335+ (void)load {
336  func_10_11(); // expected-warning{{'func_10_11' is only available on macOS 10.11 or newer}} expected-note{{enclose 'func_10_11' in an @available check to silence this warning}}
337}
338+ (void)load: (int)x {
339  func_10_11(); // no warning.
340}
341@end
342
343__attribute__((constructor))
344void is_constructor();
345
346AVAILABLE_10_11 // expected-warning{{ignoring availability attribute with constructor attribute}}
347void is_constructor() {
348  func_10_11(); // expected-warning{{'func_10_11' is only available on macOS 10.11 or newer}} expected-note{{enclose 'func_10_11' in an @available check to silence this warning}}
349}
350
351AVAILABLE_10_11 // expected-warning{{ignoring availability attribute with destructor attribute}}
352__attribute__((destructor))
353void is_destructor() {
354  func_10_11(); // expected-warning{{'func_10_11' is only available on macOS 10.11 or newer}} expected-note{{enclose 'func_10_11' in an @available check to silence this warning}}
355}
356