xref: /llvm-project/clang/test/SemaObjC/unguarded-availability.m (revision d07362f7a9fc06e2445f5c4bc62c10a339bf68a5)
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}}
9
10int func_10_11(void) 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}}
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}}
14#endif
15int func_10_12(void) 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}}
16
17int func_10_0(void) AVAILABLE_10_0;
18
19void use_func(void) {
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(void) AVAILABLE_10_11;
29
30void defn_10_11(void) {
31  func_10_11();
32}
33
34void nested_ifs(void) {
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(void) {
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}}
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}}
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}}
69
70void use_typedef(void) {
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(void) {
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}}
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}}
113  } n;
114};
115
116int test_members(void) {
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(void) {
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  if (@available(macos 10.12, *))
130    (void) ^{
131      func_10_12();
132      (void) ^{
133        func_10_12();
134      };
135    };
136}
137
138void 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}}
139
140void test_params2(int_10_12 x) AVAILABLE_10_12; // no warn
141
142void (^topLevelBlockDecl)(void) = ^ {
143  func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{@available}}
144  if (@available(macos 10.12, *))
145    func_10_12();
146};
147
148AVAILABLE_10_12
149__attribute__((objc_root_class))
150@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}}
151@property(class) int x;
152+ (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}}
153@end
154void test_property(void) {
155  int y = InterWithProp.x; // expected-warning{{'InterWithProp' is only available on macOS 10.12 or newer}} expected-note{{@available}}
156  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}}
157}
158
159__attribute__((objc_root_class))
160@interface Subscriptable
161- (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}}
162@end
163
164void test_at(Subscriptable *x) {
165  id y = x[42]; // expected-warning{{'objectAtIndexedSubscript:' is only available on macOS 10.12 or newer}} expected-note{{@available}}
166}
167
168void uncheckAtAvailable(void) {
169  if (@available(macOS 10.12, *) || 0) // expected-warning {{@available does not guard availability here; use if (@available) instead}}
170    func_10_12(); // expected-warning {{'func_10_12' is only available on macOS 10.12 or newer}}
171  // expected-note@-1 {{enclose 'func_10_12' in an @available check to silence this warning}}
172}
173
174void justAtAvailable(void) {
175  int availability = @available(macOS 10.12, *); // expected-warning {{@available does not guard availability here; use if (@available) instead}}
176}
177
178#ifdef OBJCPP
179
180int f(char) AVAILABLE_10_12; // #f_char_def
181int f(int);
182
183template <class T> int use_f() {
184  if (@available(macos 10.12, *)) {
185    return f(T()); // no warning expected
186  } else {
187  // expected-warning@#f_call {{'f' is only available on macOS 10.12 or newer}}
188  // expected-note@#f_char_inst {{in instantiation of function template specialization 'use_f<char>' requested here}}
189  // expected-note@#f_char_def {{'f' has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9}}
190  // expected-note@#f_call {{enclose 'f' in an @available check to silence this warning}}
191    return f(T()); // #f_call
192  }
193}
194
195int a = use_f<int>();
196int b = use_f<char>(); // #f_char_inst
197
198int use_f2() AVAILABLE_10_12 {
199  int c = use_f<int>();
200  int d = use_f<char>(); // no warning expected
201}
202
203template <class> int use_at_available() {
204  if (@available(macos 10.12, *))
205    return func_10_12();
206  else
207    return func_10_12(); // expected-warning {{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{enclose}}
208}
209
210int instantiate_template() {
211  if (@available(macos 10.12, *)) {
212    use_at_available<char>();
213  } else {
214    use_at_available<float>();
215  }
216}
217
218template <class>
219int 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}}
220  return 0;
221}
222
223int instantiate_with_availability_attr() {
224  if (@available(macos 10.12, *))
225    with_availability_attr<char>();
226  else
227    with_availability_attr<int>(); // expected-warning {{'with_availability_attr<int>' is only available on macOS 10.11 or newer}} expected-note {{enclose}}
228}
229
230int instantiate_availability() {
231  if (@available(macOS 10.12, *))
232    with_availability_attr<int_10_12>();
233  else
234    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}}
235}
236
237auto topLevelLambda = [] () {
238  func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{@available}}
239  if (@available(macos 10.12, *))
240    func_10_12();
241};
242
243void functionInFunction() {
244  func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{@available}}
245  struct DontWarnTwice {
246    void f() {
247      func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{@available}}
248    }
249  };
250  void([] () {
251    func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{@available}}
252  });
253  (void)(^ {
254    func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{@available}}
255  });
256
257  if (@available(macos 10.12, *)) {
258    void([]() {
259      func_10_12();
260      void([] () {
261        func_10_12();
262      });
263      struct DontWarn {
264        void f() {
265          func_10_12();
266        }
267      };
268    });
269  }
270
271  if (@available(macos 10.12, *)) {
272    struct DontWarn {
273      void f() {
274        func_10_12();
275        void([] () {
276          func_10_12();
277        });
278        struct DontWarn2 {
279          void f() {
280            func_10_12();
281          }
282        };
283      }
284    };
285  }
286}
287
288#endif
289
290struct InStruct { // expected-note{{annotate 'InStruct' with an availability attribute to silence}}
291  new_int mem; // expected-warning{{'new_int' is only available on macOS 10.12 or newer}}
292
293  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}}
294};
295
296#ifdef OBJCPP
297static 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}}
298typedef enum { // expected-note{{annotate anonymous enum with an availability attribute}}
299  SomeValue = SomeConstexprValue // expected-warning{{'SomeConstexprValue' is only available on macOS 10.12 or newer}}
300} SomeEnum;
301#endif
302
303@interface InInterface
304-(new_int)meth; // expected-warning{{'new_int' is only available on macOS 10.12 or newer}} expected-note{{annotate 'meth' with an availability attribute}}
305@end
306
307@interface Proper // expected-note{{annotate 'Proper' with an availability attribute}}
308@property (class) new_int x; // expected-warning{{'new_int' is only available}}
309@end
310
311void with_local_struct(void) {
312  struct local {
313    new_int x; // expected-warning{{'new_int' is only available}} expected-note{{enclose 'new_int' in an @available check}}
314  };
315  if (@available(macos 10.12, *)) {
316    struct DontWarn {
317      new_int x;
318    };
319  }
320}
321
322// Avoid the warning on protocol requirements.
323
324AVAILABLE_10_12
325@protocol NewProtocol // expected-note {{'NewProtocol' has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9}}
326@end
327
328@protocol ProtocolWithNewProtocolRequirement <NewProtocol> // expected-note {{annotate 'ProtocolWithNewProtocolRequirement' with an availability attribute to silence}}
329
330@property(copy) id<NewProtocol> prop; // expected-warning {{'NewProtocol' is only available on macOS 10.12 or newer}}
331
332@end
333
334@interface BaseClass
335@end
336
337@interface ClassWithNewProtocolRequirement : BaseClass <NewProtocol>
338
339@end
340
341@interface BaseClass (CategoryWithNewProtocolRequirement) <NewProtocol>
342
343@end
344
345typedef enum {
346  AK_Dodo __attribute__((availability(macos, deprecated=10.3))), // expected-note 3 {{marked deprecated here}}
347  AK_Cat __attribute__((availability(macos, introduced=10.4))),
348  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}}
349} Animals;
350
351void switchAnimals(Animals a) {
352  switch (a) {
353  case AK_Dodo: break; // expected-warning{{'AK_Dodo' is deprecated}}
354  case AK_Cat: break;
355  case AK_Cat|AK_CyborgCat: break; // expected-warning{{case value not in enum}}
356  case AK_CyborgCat: break; // no warn
357  }
358
359  switch (a) {
360  case AK_Dodo...AK_CyborgCat: // expected-warning {{'AK_Dodo' is depr}}
361    break;
362  }
363
364  (void)AK_Dodo; // expected-warning{{'AK_Dodo' is deprecated}}
365  (void)AK_Cat; // no warning
366  (void)AK_CyborgCat; // expected-warning{{'AK_CyborgCat' is only available on macOS 10.12 or newer}} expected-note {{@available}}
367}
368
369
370// test static initializers has the same availability as the deployment target and it cannot be overwritten.
371@interface HasStaticInitializer : BaseClass
372+ (void)load AVAILABLE_10_11; // expected-warning{{ignoring availability attribute on '+load' method}}
373@end
374
375@implementation HasStaticInitializer
376+ (void)load {
377  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}}
378}
379@end
380
381// test availability from interface is ignored when checking the unguarded availability in +load method.
382AVAILABLE_10_11
383@interface HasStaticInitializer1 : BaseClass
384+ (void)load;
385+ (void)load: (int)x; // no warning.
386@end
387
388@implementation HasStaticInitializer1
389+ (void)load {
390  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}}
391}
392+ (void)load: (int)x {
393  func_10_11(); // no warning.
394}
395@end
396
397__attribute__((constructor))
398void is_constructor(void);
399
400AVAILABLE_10_11 // expected-warning{{ignoring availability attribute with constructor attribute}}
401void is_constructor(void) {
402  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}}
403}
404
405AVAILABLE_10_11 // expected-warning{{ignoring availability attribute with destructor attribute}}
406__attribute__((destructor))
407void is_destructor(void) {
408  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}}
409}
410