the method declaration is unavailable for an app extension platform
Rationale:
Classes are often shared between an app extension code and
non-app extension code. There's no way to remove the implementation
using preprocessor when building the app extension, so we should not warn here.
rdar://
38150617
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@331421
91177308-0d34-0410-b5e6-
96231b3b80d8
///
/// \param EnclosingVersion The version to compare with. If empty, assume the
/// deployment target version.
+ ///
+ /// \param RealizedPlatform If non-NULL and the availability result is found
+ /// in an available attribute it will set to the platform which is written in
+ /// the available attribute.
AvailabilityResult
getAvailability(std::string *Message = nullptr,
- VersionTuple EnclosingVersion = VersionTuple()) const;
+ VersionTuple EnclosingVersion = VersionTuple(),
+ StringRef *RealizedPlatform = nullptr) const;
/// \brief Retrieve the version of the target platform in which this
/// declaration was introduced.
}
AvailabilityResult Decl::getAvailability(std::string *Message,
- VersionTuple EnclosingVersion) const {
+ VersionTuple EnclosingVersion,
+ StringRef *RealizedPlatform) const {
if (auto *FTD = dyn_cast<FunctionTemplateDecl>(this))
- return FTD->getTemplatedDecl()->getAvailability(Message, EnclosingVersion);
+ return FTD->getTemplatedDecl()->getAvailability(Message, EnclosingVersion,
+ RealizedPlatform);
AvailabilityResult Result = AR_Available;
std::string ResultMessage;
AvailabilityResult AR = CheckAvailability(getASTContext(), Availability,
Message, EnclosingVersion);
- if (AR == AR_Unavailable)
+ if (AR == AR_Unavailable) {
+ if (RealizedPlatform)
+ *RealizedPlatform = Availability->getPlatform()->getName();
return AR_Unavailable;
+ }
if (AR > Result) {
Result = AR;
if (!ND)
return;
bool IsCategory = false;
- AvailabilityResult Availability = ND->getAvailability();
+ StringRef RealizedPlatform;
+ AvailabilityResult Availability = ND->getAvailability(
+ /*Message=*/nullptr, /*EnclosingVersion=*/VersionTuple(),
+ &RealizedPlatform);
if (Availability != AR_Deprecated) {
if (isa<ObjCMethodDecl>(ND)) {
if (Availability != AR_Unavailable)
return;
- // Warn about implementing unavailable methods.
+ if (RealizedPlatform.empty())
+ RealizedPlatform = S.Context.getTargetInfo().getPlatformName();
+ // Warn about implementing unavailable methods, unless the unavailable
+ // is for an app extension.
+ if (RealizedPlatform.endswith("_app_extension"))
+ return;
S.Diag(ImplLoc, diag::warn_unavailable_def);
S.Diag(ND->getLocation(), diag::note_method_declared_at)
<< ND->getDeclName();
--- /dev/null
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -fapplication-extension -Wdeprecated-implementations -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -triple arm64-apple-tvos11 -fapplication-extension -Wdeprecated-implementations -verify -Wno-objc-root-class %s
+// Declarations marked as 'unavailable' in an app extension should not generate a
+// warning on implementation.
+
+@interface Parent
+- (void)ok __attribute__((availability(ios_app_extension,unavailable,message="not available")));
+- (void)reallyUnavail __attribute__((availability(ios,unavailable))); // expected-note {{method 'reallyUnavail' declared here}}
+- (void)reallyUnavail2 __attribute__((unavailable)); // expected-note {{method 'reallyUnavail2' declared here}}
+@end
+
+@interface Child : Parent
+@end
+
+@implementation Child
+
+- (void)ok { // no warning.
+}
+- (void)reallyUnavail { // expected-warning {{implementing unavailable method}}
+}
+- (void)reallyUnavail2 { // expected-warning {{implementing unavailable method}}
+}
+
+@end