[ObjC] Supress the 'implementing unavailable method' warning when
authorAlex Lorenz <arphaman@gmail.com>
Thu, 3 May 2018 01:12:06 +0000 (01:12 +0000)
committerAlex Lorenz <arphaman@gmail.com>
Thu, 3 May 2018 01:12:06 +0000 (01:12 +0000)
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
clang/lib/AST/DeclBase.cpp
clang/lib/Sema/SemaDeclObjC.cpp
clang/test/SemaObjC/avoid-unavailable-implementation-warning-in-app-extension.m [new file with mode: 0644]

index 1243a67..88f8216 100644 (file)
@@ -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.
index baf83a3..8d7291e 100644 (file)
@@ -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<FunctionTemplateDecl>(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;
index 5b8a9f3..e1eed82 100644 (file)
@@ -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<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();
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 (file)
index 0000000..06872a9
--- /dev/null
@@ -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