From f4d4cfbefa4c1e61a69f47ac41790cd15a65fb07 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Thu, 3 May 2018 01:12:06 +0000 Subject: [PATCH] [ObjC] Supress the 'implementing unavailable method' warning when 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 llvm-svn: 331421 --- clang/include/clang/AST/DeclBase.h | 7 ++++++- clang/lib/AST/DeclBase.cpp | 11 +++++++--- clang/lib/Sema/SemaDeclObjC.cpp | 12 +++++++++-- ...lable-implementation-warning-in-app-extension.m | 24 ++++++++++++++++++++++ 4 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 clang/test/SemaObjC/avoid-unavailable-implementation-warning-in-app-extension.m diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 1243a67..88f8216 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -644,9 +644,14 @@ public: /// /// \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. diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index baf83a3..8d7291e 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -590,9 +590,11 @@ static AvailabilityResult CheckAvailability(ASTContext &Context, } AvailabilityResult Decl::getAvailability(std::string *Message, - VersionTuple EnclosingVersion) const { + VersionTuple EnclosingVersion, + StringRef *RealizedPlatform) const { if (auto *FTD = dyn_cast(this)) - return FTD->getTemplatedDecl()->getAvailability(Message, EnclosingVersion); + return FTD->getTemplatedDecl()->getAvailability(Message, EnclosingVersion, + RealizedPlatform); AvailabilityResult Result = AR_Available; std::string ResultMessage; @@ -619,8 +621,11 @@ AvailabilityResult Decl::getAvailability(std::string *Message, 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; diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 5b8a9f3..e1eed82 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -266,12 +266,20 @@ static void DiagnoseObjCImplementedDeprecations(Sema &S, const NamedDecl *ND, 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(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(); diff --git a/clang/test/SemaObjC/avoid-unavailable-implementation-warning-in-app-extension.m b/clang/test/SemaObjC/avoid-unavailable-implementation-warning-in-app-extension.m new file mode 100644 index 0000000..06872a9 --- /dev/null +++ b/clang/test/SemaObjC/avoid-unavailable-implementation-warning-in-app-extension.m @@ -0,0 +1,24 @@ +// 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 -- 2.7.4