// RUN: %clang_cc1 -triple x86_64-apple-macosx-10.9 -Wunguarded-availability -fblocks -fsyntax-only -verify %s
// RUN: %clang_cc1 -xobjective-c++ -std=c++11 -DOBJCPP -triple x86_64-apple-macosx-10.9 -Wunguarded-availability -fblocks -fsyntax-only -verify %s
#define AVAILABLE_10_0 __attribute__((availability(macos, introduced = 10.0)))
#define AVAILABLE_10_11 __attribute__((availability(macos, introduced = 10.11)))
#define AVAILABLE_10_12 __attribute__((availability(macos, introduced = 10.12)))
typedef int AVAILABLE_10_12 new_int; // expected-note + {{marked partial here}}
int func_10_11() AVAILABLE_10_11; // expected-note 8 {{'func_10_11' has been explicitly marked partial here}}
#ifdef OBJCPP
// expected-note@+2 6 {{marked partial here}}
#endif
int func_10_12() AVAILABLE_10_12; // expected-note 7 {{'func_10_12' has been explicitly marked partial here}}
int func_10_0() AVAILABLE_10_0;
void use_func() {
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}}
if (@available(macos 10.11, *))
func_10_11();
else
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}}
}
void defn_10_11() AVAILABLE_10_11;
void defn_10_11() {
func_10_11();
}
void nested_ifs() {
if (@available(macos 10.12, *)) {
if (@available(macos 10.10, *)) {
func_10_12();
} else {
func_10_12();
}
} else {
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}}
}
}
void star_case() {
if (@available(ios 9, *)) {
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}}
func_10_0();
} else
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}}
if (@available(macOS 10.11, *)) {
if (@available(ios 8, *)) {
func_10_11();
func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{enclose}}
} else {
func_10_11();
func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{enclose}}
}
}
}
typedef int int_10_11 AVAILABLE_10_11; // expected-note {{'int_10_11' has been explicitly marked partial here}}
#ifdef OBJCPP
// expected-note@+2 {{marked partial here}}
#endif
typedef int int_10_12 AVAILABLE_10_12; // expected-note 2 {{'int_10_12' has been explicitly marked partial here}}
void use_typedef() {
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}}
}
__attribute__((objc_root_class))
AVAILABLE_10_11 @interface Class_10_11 { // expected-note{{annotate 'Class_10_11' with an availability attribute to silence}}
int_10_11 foo;
int_10_12 bar; // expected-warning {{'int_10_12' is only available on macOS 10.12 or newer}}
}
- (void)method1;
- (void)method2;
@end
@implementation Class_10_11
- (void) method1 {
func_10_11();
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}}
}
- (void)method2 AVAILABLE_10_12 {
func_10_12();
}
@end
int protected_scope() {
if (@available(macos 10.20, *)) { // expected-note 2 {{jump enters controlled statement of if available}}
label1:
return 0;
} else {
label2:
goto label1; // expected-error{{cannot jump from this goto statement to its label}}
}
goto label2; // expected-error{{cannot jump from this goto statement to its label}}
}
struct S {
int m1;
int m2 __attribute__((availability(macos, introduced = 10.12))); // expected-note{{marked partial here}}
struct Nested {
int nested_member __attribute__((availability(macos, introduced = 10.12))); // expected-note{{marked partial here}}
} n;
};
int test_members() {
struct S s;
(void)s.m1;
(void)s.m2; // expected-warning{{'m2' is only available on macOS 10.12 or newer}} expected-note{{@available}}
(void)s.n.nested_member; // expected-warning{{'nested_member' is only available on macOS 10.12 or newer}} expected-note{{@available}}
}
void test_blocks() {
(void) ^{
func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{@available}}
};
}
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}}
void test_params2(int_10_12 x) AVAILABLE_10_12; // no warn
void (^topLevelBlockDecl)() = ^ {
func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{@available}}
if (@available(macos 10.12, *))
func_10_12();
};
AVAILABLE_10_12
__attribute__((objc_root_class))
@interface InterWithProp // expected-note 2 {{marked partial here}}
@property(class) int x;
+ (void) setX: (int)newX AVAILABLE_10_12; // expected-note{{marked partial here}}
@end
void test_property(void) {
int y = InterWithProp.x; // expected-warning{{'InterWithProp' is only available on macOS 10.12 or newer}} expected-note{{@available}}
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}}
}
__attribute__((objc_root_class))
@interface Subscriptable
- (id)objectAtIndexedSubscript:(int)sub AVAILABLE_10_12; // expected-note{{marked partial here}}
@end
void test_at(Subscriptable *x) {
id y = x[42]; // expected-warning{{'objectAtIndexedSubscript:' is only available on macOS 10.12 or newer}} expected-note{{@available}}
}
void uncheckAtAvailable() {
if (@available(macOS 10.12, *) || 0) // expected-warning {{@available does not guard availability here; use if (@available) instead}}
func_10_12(); // expected-warning {{'func_10_12' is only available on macOS 10.12 or newer}}
// expected-note@-1 {{enclose 'func_10_12' in an @available check to silence this warning}}
}
void justAtAvailable() {
int availability = @available(macOS 10.12, *); // expected-warning {{@available does not guard availability here; use if (@available) instead}}
}
#ifdef OBJCPP
int f(char) AVAILABLE_10_12;
int f(int);
template <class T> int use_f() {
// FIXME: We should warn here!
return f(T());
}
int a = use_f<int>();
int b = use_f<char>();
template <class> int use_at_available() {
if (@available(macos 10.12, *))
return func_10_12();
else
return func_10_12(); // expected-warning {{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{enclose}}
}
int instantiate_template() {
if (@available(macos 10.12, *)) {
use_at_available<char>();
} else {
use_at_available<float>();
}
}
template <class>
int with_availability_attr() AVAILABLE_10_11 { // expected-note 2 {{marked partial here}}
return 0;
}
int instantiate_with_availability_attr() {
if (@available(macos 10.12, *))
with_availability_attr<char>();
else
with_availability_attr<int>(); // expected-warning {{'with_availability_attr<int>' is only available on macOS 10.11 or newer}} expected-note {{enclose}}
}
int instantiate_availability() {
if (@available(macOS 10.12, *))
with_availability_attr<int_10_12>();
else
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}}
}
auto topLevelLambda = [] () {
func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{@available}}
if (@available(macos 10.12, *))
func_10_12();
};
void functionInFunction() {
func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{@available}}
struct DontWarnTwice {
void f() {
func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{@available}}
}
};
void([] () {
func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{@available}}
});
(void)(^ {
func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{@available}}
});
}
#endif
struct InStruct { // expected-note{{annotate 'InStruct' with an availability attribute to silence}}
new_int mem; // expected-warning{{'new_int' is only available on macOS 10.12 or newer}}
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}}
};
#ifdef OBJCPP
static constexpr int AVAILABLE_10_12 SomeConstexprValue = 2; // expected-note{{marked partial here}}
typedef enum { // expected-note{{annotate anonymous enum with an availability attribute}}
SomeValue = SomeConstexprValue // expected-warning{{'SomeConstexprValue' is only available on macOS 10.12 or newer}}
} SomeEnum;
#endif
@interface InInterface
-(new_int)meth; // expected-warning{{'new_int' is only available on macOS 10.12 or newer}} expected-note{{annotate 'meth' with an availability attribute}}
@end
@interface Proper // expected-note{{annotate 'Proper' with an availability attribute}}
@property (class) new_int x; // expected-warning{{'new_int' is only available}}
@end
void with_local_struct() {
struct local { // expected-note{{annotate 'local' with an availability attribute}}
new_int x; // expected-warning{{'new_int' is only available}}
};
}
// rdar://33156429:
// Avoid the warning on protocol requirements.
AVAILABLE_10_12
@protocol NewProtocol // expected-note {{'NewProtocol' has been explicitly marked partial here}}
@end
@protocol ProtocolWithNewProtocolRequirement <NewProtocol> // expected-note {{annotate 'ProtocolWithNewProtocolRequirement' with an availability attribute to silence}}
@property(copy) id<NewProtocol> prop; // expected-warning {{'NewProtocol' is only available on macOS 10.12 or newer}}
@end
@interface BaseClass
@end
@interface ClassWithNewProtocolRequirement : BaseClass <NewProtocol>
@end
@interface BaseClass (CategoryWithNewProtocolRequirement) <NewProtocol>
@end
typedef enum {
AK_Dodo __attribute__((availability(macos, deprecated=10.3))), // expected-note 3 {{marked deprecated here}}
AK_Cat __attribute__((availability(macos, introduced=10.4))),
AK_CyborgCat __attribute__((availability(macos, introduced=10.12))), // expected-note {{marked partial here}}
} Animals;
void switchAnimals(Animals a) {
switch (a) {
case AK_Dodo: break; // expected-warning{{'AK_Dodo' is deprecated}}
case AK_Cat: break;
case AK_Cat|AK_CyborgCat: break; // expected-warning{{case value not in enum}}
case AK_CyborgCat: break; // no warn
}
switch (a) {
case AK_Dodo...AK_CyborgCat: // expected-warning {{'AK_Dodo' is depr}}
break;
}
(void)AK_Dodo; // expected-warning{{'AK_Dodo' is deprecated}}
(void)AK_Cat; // no warning
(void)AK_CyborgCat; // expected-warning{{'AK_CyborgCat' is only available on macOS 10.12 or newer}} expected-note {{@available}}
}
// test static initializers has the same availability as the deployment target and it cannot be overwritten.
@interface HasStaticInitializer : BaseClass
+ (void)load AVAILABLE_10_11; // expected-warning{{ignoring availability attribute on '+load' method}}
@end
@implementation HasStaticInitializer
+ (void)load {
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}}
}
@end
// test availability from interface is ignored when checking the unguarded availability in +load method.
AVAILABLE_10_11
@interface HasStaticInitializer1 : BaseClass
+ (void)load;
+ (void)load: (int)x; // no warning.
@end
@implementation HasStaticInitializer1
+ (void)load {
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}}
}
+ (void)load: (int)x {
func_10_11(); // no warning.
}
@end
__attribute__((constructor))
void is_constructor();
AVAILABLE_10_11 // expected-warning{{ignoring availability attribute with constructor attribute}}
void is_constructor() {
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}}
}
AVAILABLE_10_11 // expected-warning{{ignoring availability attribute with destructor attribute}}
__attribute__((destructor))
void is_destructor() {
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}}
}