| 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 | |
| 8 | typedef 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 | |
| 10 | int 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 |
| 15 | int 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 | |
| 17 | int func_10_0() AVAILABLE_10_0; |
| 18 | |
| 19 | void 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 | |
| 28 | void defn_10_11() AVAILABLE_10_11; |
| 29 | |
| 30 | void defn_10_11() { |
| 31 | func_10_11(); |
| 32 | } |
| 33 | |
| 34 | void 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 | |
| 46 | void 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 | |
| 64 | typedef 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 |
| 68 | typedef 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 | |
| 70 | void 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)) |
| 75 | AVAILABLE_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 | |
| 95 | int 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 | |
| 107 | struct 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 | |
| 116 | int 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 | |
| 124 | void 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 | |
| 130 | void 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 | |
| 132 | void test_params2(int_10_12 x) AVAILABLE_10_12; // no warn |
| 133 | |
| 134 | void (^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 | |
| 140 | AVAILABLE_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 |
| 146 | void 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 | |
| 156 | void 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 | |
| 160 | void 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 | |
| 166 | void 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 | |
| 172 | int f(char) AVAILABLE_10_12; |
| 173 | int f(int); |
| 174 | |
| 175 | template <class T> int use_f() { |
| 176 | // FIXME: We should warn here! |
| 177 | return f(T()); |
| 178 | } |
| 179 | |
| 180 | int a = use_f<int>(); |
| 181 | int b = use_f<char>(); |
| 182 | |
| 183 | template <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 | |
| 190 | int instantiate_template() { |
| 191 | if (@available(macos 10.12, *)) { |
| 192 | use_at_available<char>(); |
| 193 | } else { |
| 194 | use_at_available<float>(); |
| 195 | } |
| 196 | } |
| 197 | |
| 198 | template <class> |
| 199 | int 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 | |
| 203 | int 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 | |
| 210 | int 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 | |
| 217 | auto 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 | |
| 223 | void 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 | |
| 240 | struct 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 |
| 247 | static 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}} |
| 248 | typedef 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 | |
| 261 | void 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 | |
| 270 | AVAILABLE_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 | |
| 291 | typedef 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 | |
| 297 | void 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. |
| 328 | AVAILABLE_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)) |
| 344 | void is_constructor(); |
| 345 | |
| 346 | AVAILABLE_10_11 // expected-warning{{ignoring availability attribute with constructor attribute}} |
| 347 | void 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 | |
| 351 | AVAILABLE_10_11 // expected-warning{{ignoring availability attribute with destructor attribute}} |
| 352 | __attribute__((destructor)) |
| 353 | void 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 | |