/// Merge availability attributes for an implementation of
/// a protocol requirement.
AMK_ProtocolImplementation,
+ /// Merge availability attributes for an implementation of
+ /// an optional protocol requirement.
+ AMK_OptionalProtocolImplementation
};
/// Describes the kind of priority given to an availability attribute.
NewAttr = nullptr;
else if ((isa<DeprecatedAttr>(Attr) || isa<UnavailableAttr>(Attr)) &&
(AMK == Sema::AMK_Override ||
- AMK == Sema::AMK_ProtocolImplementation))
+ AMK == Sema::AMK_ProtocolImplementation ||
+ AMK == Sema::AMK_OptionalProtocolImplementation))
NewAttr = nullptr;
else if (const auto *UA = dyn_cast<UuidAttr>(Attr))
NewAttr = S.mergeUuidAttr(D, *UA, UA->getGuid(), UA->getGuidDecl());
case AMK_Redeclaration:
case AMK_Override:
case AMK_ProtocolImplementation:
+ case AMK_OptionalProtocolImplementation:
LocalAMK = AMK;
break;
}
ObjCMethodDecl *oldMethod) {
// Merge the attributes, including deprecated/unavailable
AvailabilityMergeKind MergeKind =
- isa<ObjCProtocolDecl>(oldMethod->getDeclContext())
- ? AMK_ProtocolImplementation
- : isa<ObjCImplDecl>(newMethod->getDeclContext()) ? AMK_Redeclaration
- : AMK_Override;
+ isa<ObjCProtocolDecl>(oldMethod->getDeclContext())
+ ? (oldMethod->isOptional() ? AMK_OptionalProtocolImplementation
+ : AMK_ProtocolImplementation)
+ : isa<ObjCImplDecl>(newMethod->getDeclContext()) ? AMK_Redeclaration
+ : AMK_Override;
mergeDeclAttributes(newMethod, oldMethod, MergeKind);
case AMK_Override:
case AMK_ProtocolImplementation:
+ case AMK_OptionalProtocolImplementation:
OverrideOrImpl = true;
break;
}
diag::warn_mismatched_availability_override_unavail)
<< AvailabilityAttr::getPrettyPlatformName(Platform->getName())
<< (AMK == AMK_Override);
+ } else if (Which != 1 && AMK == AMK_OptionalProtocolImplementation) {
+ // Allow different 'introduced' / 'obsoleted' availability versions
+ // on a method that implements an optional protocol requirement. It
+ // makes less sense to allow this for 'deprecated' as the user can't
+ // see if the method is 'deprecated' as 'respondsToSelector' will
+ // still return true when the method is deprecated.
+ ++i;
+ continue;
} else {
Diag(OldAA->getLocation(),
diag::warn_mismatched_availability_override)
// inherited be implementations of those protocol methods.
@protocol AvailabilityP2
@optional
--(void)methodA __attribute__((availability(macosx,introduced=10.1,deprecated=10.2))); // expected-note 4{{'methodA' has been explicitly marked deprecated here}} \
-// expected-note 2{{protocol method is here}}
+-(void)methodA __attribute__((availability(macosx,introduced=10.1,deprecated=10.2))); // expected-note 4{{'methodA' has been explicitly marked deprecated here}}
-(void)methodB __attribute__((unavailable)); // expected-note 4{{'methodB' has been explicitly marked unavailable here}}
-(void)methodC;
@end
__attribute__((objc_root_class))
@interface ImplementsAvailabilityP2c <AvailabilityP2>
--(void)methodA __attribute__((availability(macosx,introduced=10.2))); // expected-warning{{method introduced after the protocol method it implements on macOS (10.2 vs. 10.1)}}
+-(void)methodA __attribute__((availability(macosx,introduced=10.2)));
-(void)methodB __attribute__((unavailable));
@end
@end
@implementation ImplementsAvailabilityP2d
--(void)methodA __attribute__((availability(macosx,introduced=10.2))) // expected-warning{{method introduced after the protocol method it implements on macOS (10.2 vs. 10.1)}}
+-(void)methodA __attribute__((availability(macosx,introduced=10.2)))
{
}
-(void)methodB __attribute__((unavailable)) {
--- /dev/null
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -fsyntax-only -verify %s
+
+@protocol P
+
+@property (nonatomic) int reqProp __attribute__((availability(ios, introduced=12.0))); // expected-note 2 {{is here}}
+
+
+
+@optional
+@property (nonatomic) int myProp __attribute__((availability(ios, introduced=12.0))); // expected-note {{has been marked as being introduced in}}
+
+@optional
+@property (nonatomic, readonly) int depProp __attribute__((availability(ios, introduced=8.0, deprecated=12.0))); // expected-note {{protocol method is here}}
+
+@optional
+@property (nonatomic) int obsProp __attribute__((availability(ios, introduced=8.0, obsoleted=12.0)));
+
+@optional
+- (void) unavaibleInClass __attribute__((availability(ios, introduced=12.0))); // expected-note {{method is here}}
+
+@end
+
+@interface X <P>
+
+@property (nonatomic) int myProp __attribute__((availability(ios, introduced=13.0))); // expected-note 2 {{has been marked as being introduced in}}
+
+@property (nonatomic) int reqProp __attribute__((availability(ios, introduced=13.0))); // expected-warning 2 {{method introduced after the protocol method it implements on iOS}}
+
+@property (nonatomic, readonly) int depProp __attribute__((availability(ios, introduced=8.0, deprecated=10.0))); // expected-warning {{method deprecated before the protocol method it implements on iOS (12.0 vs. 10.0)}} expected-note {{been explicitly marked deprecated here}}
+
+@property (nonatomic) int obsProp __attribute__((availability(ios, introduced=8.0, obsoleted=10.0))); // expected-note {{been explicitly marked unavailable here}}
+
+- (void) unavaibleInClass __attribute__((availability(ios, unavailable))); // expected-warning {{method cannot be unavailable on iOS when the protocol method it implements is available}}
+
+@end
+
+
+void test(X *x) {
+ int i = x.myProp; // expected-warning {{'myProp' is only available on iOS 13.0 or newer}} expected-note {{enclose}}
+ x.myProp = i; // expected-warning {{'setMyProp:' is only available on iOS 13.0 or newer}} expected-note {{enclose}}
+ int i2 = x.depProp; // expected-warning {{'depProp' is deprecated: first deprecated in iOS 10.0}}
+ int i3 = x.obsProp; // expected-error {{'obsProp' is unavailable: obsoleted in iOS 10.0}}
+}
+
+void testProto(id<P> x) {
+ int i = x.myProp; // expected-warning {{'myProp' is only available on iOS 12.0 or newer}} expected-note {{enclose}}
+}