r232750 - Add -Wpartial-availability.

Nico Weber nicolasweber at gmx.de
Thu Mar 19 12:18:23 PDT 2015


Author: nico
Date: Thu Mar 19 14:18:22 2015
New Revision: 232750

URL: http://llvm.org/viewvc/llvm-project?rev=232750&view=rev
Log:
Add -Wpartial-availability.

This warns when using decls that are not available on all deployment targets.
For example, a call to

  - (void)ppartialMethod __attribute__((availability(macosx,introduced=10.8)));

will warn if -mmacosx-version-min is set to less than 10.8.

To silence the warning, one has to explicitly redeclare the method like so:

  @interface Whatever(MountainLionAPI)
  - (void)ppartialMethod;
  @end

This way, one cannot accidentally call a function that isn't available
everywhere.  Having to add the redeclaration will hopefully remind the user
to add an explicit respondsToSelector: call as well.

Some projects build against old SDKs to get this effect, but building against
old SDKs suppresses some bug fixes -- see http://crbug.com/463171 for examples.
The hope is that SDK headers are annotated well enough with availability
attributes that new SDK + this warning offers the same amount of protection
as using an old SDK.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticGroups.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/DelayedDiagnostic.cpp
    cfe/trunk/lib/Sema/SemaDeclAttr.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/test/Sema/attr-availability.c
    cfe/trunk/test/SemaObjC/attr-availability.m
    cfe/trunk/test/SemaObjC/property-deprecated-warning.m

Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=232750&r1=232749&r2=232750&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Thu Mar 19 14:18:22 2015
@@ -80,6 +80,7 @@ def CXX11CompatDeprecatedWritableStr :
 
 def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">;
 def UnavailableDeclarations : DiagGroup<"unavailable-declarations">;
+def PartialAvailability : DiagGroup<"partial-availability">;
 def DeprecatedImplementations :DiagGroup<"deprecated-implementations">;
 def DeprecatedIncrementBool : DiagGroup<"deprecated-increment-bool">;
 def DeprecatedRegister : DiagGroup<"deprecated-register">;

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=232750&r1=232749&r2=232750&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Mar 19 14:18:22 2015
@@ -731,7 +731,7 @@ def warn_accessor_property_type_mismatch
 def not_conv_function_declared_at : Note<"type conversion function declared here">;
 def note_method_declared_at : Note<"method %0 declared here">;
 def note_property_attribute : Note<"property %0 is declared "
-  "%select{deprecated|unavailable}1 here">;
+  "%select{deprecated|unavailable|partial}1 here">;
 def err_setter_type_void : Error<"type of setter must be void">;
 def err_duplicate_method_decl : Error<"duplicate declaration of method %0">;
 def warn_duplicate_method_decl : 
@@ -3867,6 +3867,15 @@ def err_not_found_by_two_phase_lookup :
 def note_not_found_by_two_phase_lookup : Note<"%0 should be declared prior to the "
     "call site%select{| or in %2| or in an associated namespace of one of its arguments}1">;
 def err_undeclared_use : Error<"use of undeclared %0">;
+def warn_partial_availability : Warning<"%0 is only available conditionally">,
+    InGroup<PartialAvailability>, DefaultIgnore;
+def note_partial_availability_silence : Note<
+  "explicitly redeclare %0 to silence this warning">;
+def warn_partial_message : Warning<"%0 is partial: %1">,
+    InGroup<PartialAvailability>, DefaultIgnore;
+def warn_partial_fwdclass_message : Warning<
+    "%0 may be partial because the receiver type is unknown">,
+    InGroup<PartialAvailability>, DefaultIgnore;
 def warn_deprecated : Warning<"%0 is deprecated">,
     InGroup<DeprecatedDeclarations>;
 def warn_property_method_deprecated :
@@ -3892,7 +3901,7 @@ def warn_unavailable_fwdclass_message :
     InGroup<UnavailableDeclarations>;
 def note_availability_specified_here : Note<
   "%0 has been explicitly marked "
-  "%select{unavailable|deleted|deprecated}1 here">;
+  "%select{unavailable|deleted|deprecated|partial}1 here">;
 def note_implicitly_deleted : Note<
   "explicitly defaulted function was implicitly deleted here">;
 def note_inherited_deleted_here : Note<

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=232750&r1=232749&r2=232750&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Mar 19 14:18:22 2015
@@ -3272,7 +3272,7 @@ public:
 
   void redelayDiagnostics(sema::DelayedDiagnosticPool &pool);
 
-  enum AvailabilityDiagnostic { AD_Deprecation, AD_Unavailable };
+  enum AvailabilityDiagnostic { AD_Deprecation, AD_Unavailable, AD_Partial };
 
   void EmitAvailabilityWarning(AvailabilityDiagnostic AD,
                                NamedDecl *D, StringRef Message,

Modified: cfe/trunk/lib/Sema/DelayedDiagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/DelayedDiagnostic.cpp?rev=232750&r1=232749&r2=232750&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/DelayedDiagnostic.cpp (original)
+++ cfe/trunk/lib/Sema/DelayedDiagnostic.cpp Thu Mar 19 14:18:22 2015
@@ -35,6 +35,8 @@ DelayedDiagnostic::makeAvailability(Sema
     case Sema::AD_Unavailable:
       DD.Kind = Unavailable;
       break;
+    case Sema::AD_Partial:
+      llvm_unreachable("AD_Partial diags should not be delayed");
   }
   DD.Triggered = false;
   DD.Loc = Loc;

Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=232750&r1=232749&r2=232750&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Thu Mar 19 14:18:22 2015
@@ -5117,7 +5117,7 @@ static bool isDeclUnavailable(Decl *D) {
   return false;
 }
 
-static void DoEmitAvailabilityWarning(Sema &S, DelayedDiagnostic::DDKind K,
+static void DoEmitAvailabilityWarning(Sema &S, Sema::AvailabilityDiagnostic K,
                                       Decl *Ctx, const NamedDecl *D,
                                       StringRef Message, SourceLocation Loc,
                                       const ObjCInterfaceDecl *UnknownObjCClass,
@@ -5134,7 +5134,7 @@ static void DoEmitAvailabilityWarning(Se
 
   // Don't warn if our current context is deprecated or unavailable.
   switch (K) {
-  case DelayedDiagnostic::Deprecation:
+  case Sema::AD_Deprecation:
     if (isDeclDeprecated(Ctx))
       return;
     diag = !ObjCPropertyAccess ? diag::warn_deprecated
@@ -5145,7 +5145,7 @@ static void DoEmitAvailabilityWarning(Se
     available_here_select_kind = /* deprecated */ 2;
     break;
 
-  case DelayedDiagnostic::Unavailable:
+  case Sema::AD_Unavailable:
     if (isDeclUnavailable(Ctx))
       return;
     diag = !ObjCPropertyAccess ? diag::err_unavailable
@@ -5156,8 +5156,13 @@ static void DoEmitAvailabilityWarning(Se
     available_here_select_kind = /* unavailable */ 0;
     break;
 
-  default:
-    llvm_unreachable("Neither a deprecation or unavailable kind");
+  case Sema::AD_Partial:
+    diag = diag::warn_partial_availability;
+    diag_message = diag::warn_partial_message;
+    diag_fwdclass_message = diag::warn_partial_fwdclass_message;
+    property_note_select = /* partial */ 2;
+    available_here_select_kind = /* partial */ 3;
+    break;
   }
 
   if (!Message.empty()) {
@@ -5177,15 +5182,21 @@ static void DoEmitAvailabilityWarning(Se
 
   S.Diag(D->getLocation(), diag::note_availability_specified_here)
       << D << available_here_select_kind;
+  if (K == Sema::AD_Partial)
+    S.Diag(Loc, diag::note_partial_availability_silence) << D;
 }
 
 static void handleDelayedAvailabilityCheck(Sema &S, DelayedDiagnostic &DD,
                                            Decl *Ctx) {
+  assert(DD.Kind == DelayedDiagnostic::Deprecation ||
+         DD.Kind == DelayedDiagnostic::Unavailable);
+  Sema::AvailabilityDiagnostic AD = DD.Kind == DelayedDiagnostic::Deprecation
+                                        ? Sema::AD_Deprecation
+                                        : Sema::AD_Unavailable;
   DD.Triggered = true;
-  DoEmitAvailabilityWarning(S, (DelayedDiagnostic::DDKind)DD.Kind, Ctx,
-                            DD.getDeprecationDecl(), DD.getDeprecationMessage(),
-                            DD.Loc, DD.getUnknownObjCClass(),
-                            DD.getObjCProperty(), false);
+  DoEmitAvailabilityWarning(
+      S, AD, Ctx, DD.getDeprecationDecl(), DD.getDeprecationMessage(), DD.Loc,
+      DD.getUnknownObjCClass(), DD.getObjCProperty(), false);
 }
 
 void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) {
@@ -5251,7 +5262,7 @@ void Sema::EmitAvailabilityWarning(Avail
                                    const ObjCPropertyDecl  *ObjCProperty,
                                    bool ObjCPropertyAccess) {
   // Delay if we're currently parsing a declaration.
-  if (DelayedDiagnostics.shouldDelayDiagnostics()) {
+  if (DelayedDiagnostics.shouldDelayDiagnostics() && AD != AD_Partial) {
     DelayedDiagnostics.add(DelayedDiagnostic::makeAvailability(
         AD, Loc, D, UnknownObjCClass, ObjCProperty, Message,
         ObjCPropertyAccess));
@@ -5259,16 +5270,6 @@ void Sema::EmitAvailabilityWarning(Avail
   }
 
   Decl *Ctx = cast<Decl>(getCurLexicalContext());
-  DelayedDiagnostic::DDKind K;
-  switch (AD) {
-    case AD_Deprecation:
-      K = DelayedDiagnostic::Deprecation;
-      break;
-    case AD_Unavailable:
-      K = DelayedDiagnostic::Unavailable;
-      break;
-  }
-
-  DoEmitAvailabilityWarning(*this, K, Ctx, D, Message, Loc,
-                            UnknownObjCClass, ObjCProperty, ObjCPropertyAccess);
+  DoEmitAvailabilityWarning(*this, AD, Ctx, D, Message, Loc, UnknownObjCClass,
+                            ObjCProperty, ObjCPropertyAccess);
 }

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=232750&r1=232749&r2=232750&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Mar 19 14:18:22 2015
@@ -82,10 +82,26 @@ static void DiagnoseUnusedOfDecl(Sema &S
   }
 }
 
-static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S,
-                              NamedDecl *D, SourceLocation Loc,
-                              const ObjCInterfaceDecl *UnknownObjCClass,
-                              bool ObjCPropertyAccess) {
+static bool HasRedeclarationWithoutAvailabilityInCategory(const Decl *D) {
+  const auto *OMD = dyn_cast<ObjCMethodDecl>(D);
+  if (!OMD)
+    return false;
+  const ObjCInterfaceDecl *OID = OMD->getClassInterface();
+  if (!OID)
+    return false;
+
+  for (const ObjCCategoryDecl *Cat : OID->visible_categories())
+    if (ObjCMethodDecl *CatMeth =
+            Cat->getMethod(OMD->getSelector(), OMD->isInstanceMethod()))
+      if (!CatMeth->hasAttr<AvailabilityAttr>())
+        return true;
+  return false;
+}
+
+static AvailabilityResult
+DiagnoseAvailabilityOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc,
+                           const ObjCInterfaceDecl *UnknownObjCClass,
+                           bool ObjCPropertyAccess) {
   // See if this declaration is unavailable or deprecated.
   std::string Message;
     
@@ -103,7 +119,8 @@ static AvailabilityResult DiagnoseAvaila
     }
 
   const ObjCPropertyDecl *ObjCPDecl = nullptr;
-  if (Result == AR_Deprecated || Result == AR_Unavailable) {
+  if (Result == AR_Deprecated || Result == AR_Unavailable ||
+      AR_NotYetIntroduced) {
     if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
       if (const ObjCPropertyDecl *PD = MD->findPropertyDecl()) {
         AvailabilityResult PDeclResult = PD->getAvailability(nullptr);
@@ -115,7 +132,6 @@ static AvailabilityResult DiagnoseAvaila
   
   switch (Result) {
     case AR_Available:
-    case AR_NotYetIntroduced:
       break;
 
     case AR_Deprecated:
@@ -125,6 +141,34 @@ static AvailabilityResult DiagnoseAvaila
                                   ObjCPropertyAccess);
       break;
 
+    case AR_NotYetIntroduced: {
+      // Don't do this for enums, they can't be redeclared.
+      if (isa<EnumConstantDecl>(D) || isa<EnumDecl>(D))
+        break;
+ 
+      bool Warn = !D->getAttr<AvailabilityAttr>()->isInherited();
+      // Objective-C method declarations in categories are not modelled as
+      // redeclarations, so manually look for a redeclaration in a category
+      // if necessary.
+      if (Warn && HasRedeclarationWithoutAvailabilityInCategory(D))
+        Warn = false;
+      // In general, D will point to the most recent redeclaration. However,
+      // for `@class A;` decls, this isn't true -- manually go through the
+      // redecl chain in that case.
+      if (Warn && isa<ObjCInterfaceDecl>(D))
+        for (Decl *Redecl = D->getMostRecentDecl(); Redecl && Warn;
+             Redecl = Redecl->getPreviousDecl())
+          if (!Redecl->hasAttr<AvailabilityAttr>() ||
+              Redecl->getAttr<AvailabilityAttr>()->isInherited())
+            Warn = false;
+ 
+      if (Warn)
+        S.EmitAvailabilityWarning(Sema::AD_Partial, D, Message, Loc,
+                                  UnknownObjCClass, ObjCPDecl,
+                                  ObjCPropertyAccess);
+      break;
+    }
+
     case AR_Unavailable:
       if (S.getCurContextAvailability() != AR_Unavailable)
         S.EmitAvailabilityWarning(Sema::AD_Unavailable,
@@ -307,7 +351,8 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *
         DeduceReturnType(FD, Loc))
       return true;
   }
-  DiagnoseAvailabilityOfDecl(*this, D, Loc, UnknownObjCClass, ObjCPropertyAccess);
+  DiagnoseAvailabilityOfDecl(*this, D, Loc, UnknownObjCClass,
+                             ObjCPropertyAccess);
 
   DiagnoseUnusedOfDecl(*this, D, Loc);
 

Modified: cfe/trunk/test/Sema/attr-availability.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/attr-availability.c?rev=232750&r1=232749&r2=232750&view=diff
==============================================================================
--- cfe/trunk/test/Sema/attr-availability.c (original)
+++ cfe/trunk/test/Sema/attr-availability.c Thu Mar 19 14:18:22 2015
@@ -1,4 +1,6 @@
 // RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fsyntax-only -fblocks -verify %s
+// RUN: %clang_cc1 -D WARN_PARTIAL -Wpartial-availability -triple x86_64-apple-darwin9 -fsyntax-only -fblocks -verify %s
+// 
 
 void f0() __attribute__((availability(macosx,introduced=10.4,deprecated=10.2))); // expected-warning{{feature cannot be deprecated in OS X version 10.2 before it was introduced in version 10.4; attribute ignored}}
 void f1() __attribute__((availability(ios,obsoleted=2.1,deprecated=3.0)));  // expected-warning{{feature cannot be obsoleted in iOS version 2.1 before it was deprecated in version 3.0; attribute ignored}}
@@ -13,9 +15,32 @@ ATSFontGetName(const char *oName) __attr
 extern void
 ATSFontGetPostScriptName(int flags) __attribute__((availability(macosx,introduced=8.0,obsoleted=9.0, message="use ATSFontGetFullPostScriptName"))); // expected-note {{'ATSFontGetPostScriptName' has been explicitly marked unavailable here}}
 
+#if defined(WARN_PARTIAL)
+// expected-note at +3 {{has been explicitly marked partial here}}
+#endif
+extern void
+PartiallyAvailable() __attribute__((availability(macosx,introduced=10.8)));
+
+enum __attribute__((availability(macosx,introduced=10.8))) PartialEnum {
+  kPartialEnumConstant,
+};
+
 void test_10095131() {
   ATSFontGetName("Hello"); // expected-warning {{'ATSFontGetName' is deprecated: first deprecated in OS X 9.0 - use CTFontCopyFullName}}
   ATSFontGetPostScriptName(100); // expected-error {{'ATSFontGetPostScriptName' is unavailable: obsoleted in OS X 9.0 - use ATSFontGetFullPostScriptName}}
+
+#if defined(WARN_PARTIAL)
+  // expected-warning at +2 {{is partial: introduced in OS X 10.8}} expected-note at +2 {{explicitly redeclare 'PartiallyAvailable' to silence this warning}}
+#endif
+  PartiallyAvailable();
+}
+
+extern void PartiallyAvailable() ;
+void with_redeclaration() {
+  PartiallyAvailable();  // Don't warn.
+
+  // enums should never warn.
+  enum PartialEnum p = kPartialEnumConstant;
 }
 
 // rdar://10711037

Modified: cfe/trunk/test/SemaObjC/attr-availability.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/attr-availability.m?rev=232750&r1=232749&r2=232750&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/attr-availability.m (original)
+++ cfe/trunk/test/SemaObjC/attr-availability.m Thu Mar 19 14:18:22 2015
@@ -1,11 +1,21 @@
 // RUN: %clang_cc1 -triple x86_64-apple-darwin9.0.0 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -D WARN_PARTIAL -Wpartial-availability -triple x86_64-apple-darwin9.0.0 -fsyntax-only -verify %s
 
 @protocol P
 - (void)proto_method __attribute__((availability(macosx,introduced=10.1,deprecated=10.2))); // expected-note 2 {{'proto_method' has been explicitly marked deprecated here}}
+
+#if defined(WARN_PARTIAL)
+  // expected-note at +2 2 {{'partial_proto_method' has been explicitly marked partial here}}
+#endif
+- (void)partial_proto_method __attribute__((availability(macosx,introduced=10.8)));
 @end
 
 @interface A <P>
 - (void)method __attribute__((availability(macosx,introduced=10.1,deprecated=10.2))); // expected-note {{'method' has been explicitly marked deprecated here}}
+#if defined(WARN_PARTIAL)
+  // expected-note at +2 {{'partialMethod' has been explicitly marked partial here}}
+#endif
+- (void)partialMethod __attribute__((availability(macosx,introduced=10.8)));
 
 - (void)overridden __attribute__((availability(macosx,introduced=10.3))); // expected-note{{overridden method is here}}
 - (void)overridden2 __attribute__((availability(macosx,introduced=10.3)));
@@ -18,6 +28,7 @@
 // rdar://11475360
 @interface B : A
 - (void)method; // NOTE: we expect 'method' to *not* inherit availability.
+- (void)partialMethod; // Likewise.
 - (void)overridden __attribute__((availability(macosx,introduced=10.4))); // expected-warning{{overriding method introduced after overridden method on OS X (10.4 vs. 10.3)}}
 - (void)overridden2 __attribute__((availability(macosx,introduced=10.2)));
 - (void)overridden3 __attribute__((availability(macosx,deprecated=10.4)));
@@ -31,6 +42,32 @@ void f(A *a, B *b) {
   [b method]; // no-warning
   [a proto_method]; // expected-warning{{'proto_method' is deprecated: first deprecated in OS X 10.2}}
   [b proto_method]; // expected-warning{{'proto_method' is deprecated: first deprecated in OS X 10.2}}
+
+#if defined(WARN_PARTIAL)
+  // expected-warning at +2 {{'partialMethod' is partial: introduced in OS X 10.8}} expected-note at +2 {{explicitly redeclare 'partialMethod' to silence this warning}}
+#endif
+  [a partialMethod];
+  [b partialMethod];  // no warning
+#if defined(WARN_PARTIAL)
+  // expected-warning at +2 {{'partial_proto_method' is partial: introduced in OS X 10.8}} expected-note at +2 {{explicitly redeclare 'partial_proto_method' to silence this warning}}
+#endif
+  [a partial_proto_method];
+#if defined(WARN_PARTIAL)
+  // expected-warning at +2 {{'partial_proto_method' is partial: introduced in OS X 10.8}} expected-note at +2 {{explicitly redeclare 'partial_proto_method' to silence this warning}}
+#endif
+  [b partial_proto_method];
+}
+
+ at interface A (NewAPI)
+- (void)partialMethod;
+- (void)partial_proto_method;
+ at end
+
+void f_after_redecl(A *a, B *b) {
+  [a partialMethod]; // no warning
+  [b partialMethod]; // no warning
+  [a partial_proto_method]; // no warning
+  [b partial_proto_method]; // no warning
 }
 
 // Test case for <rdar://problem/11627873>.  Warn about
@@ -87,3 +124,69 @@ id NSNibOwner, topNibObjects;
 }
 
 @end
+
+ at protocol PartialProt
+- (void)ppartialMethod __attribute__((availability(macosx,introduced=10.8)));
++ (void)ppartialMethod __attribute__((availability(macosx,introduced=10.8)));
+ at end
+
+ at interface PartialI <PartialProt>
+- (void)partialMethod __attribute__((availability(macosx,introduced=10.8)));
++ (void)partialMethod __attribute__((availability(macosx,introduced=10.8)));
+ at end
+
+ at interface PartialI ()
+- (void)ipartialMethod1 __attribute__((availability(macosx,introduced=10.8)));
+#if defined(WARN_PARTIAL)
+  // expected-note at +2 {{'ipartialMethod2' has been explicitly marked partial here}}
+#endif
+- (void)ipartialMethod2 __attribute__((availability(macosx,introduced=10.8)));
++ (void)ipartialMethod1 __attribute__((availability(macosx,introduced=10.8)));
+#if defined(WARN_PARTIAL)
+  // expected-note at +2 {{'ipartialMethod2' has been explicitly marked partial here}}
+#endif
++ (void)ipartialMethod2 __attribute__((availability(macosx,introduced=10.8)));
+ at end
+
+ at interface PartialI (Redecls)
+- (void)partialMethod;
+- (void)ipartialMethod1;
+- (void)ppartialMethod;
++ (void)partialMethod;
++ (void)ipartialMethod1;
++ (void)ppartialMethod;
+ at end
+
+void partialfun(PartialI* a) {
+  [a partialMethod]; // no warning
+  [a ipartialMethod1]; // no warning
+#if defined(WARN_PARTIAL)
+  // expected-warning at +2 {{'ipartialMethod2' is partial: introduced in OS X 10.8}} expected-note at +2 {{explicitly redeclare 'ipartialMethod2' to silence this warning}}
+#endif
+  [a ipartialMethod2];
+  [a ppartialMethod]; // no warning
+  [PartialI partialMethod]; // no warning
+  [PartialI ipartialMethod1]; // no warning
+#if defined(WARN_PARTIAL)
+  // expected-warning at +2 {{'ipartialMethod2' is partial: introduced in OS X 10.8}} expected-note at +2 {{explicitly redeclare 'ipartialMethod2' to silence this warning}}
+#endif
+  [PartialI ipartialMethod2];
+  [PartialI ppartialMethod]; // no warning
+}
+
+#if defined(WARN_PARTIAL)
+  // expected-note at +2 {{'PartialI2' has been explicitly marked partial here}}
+#endif
+__attribute__((availability(macosx, introduced = 10.8))) @interface PartialI2
+ at end
+
+#if defined(WARN_PARTIAL)
+  // expected-warning at +2 {{'PartialI2' is partial: introduced in OS X 10.8}} expected-note at +2 {{explicitly redeclare 'PartialI2' to silence this warning}}
+#endif
+void partialinter1(PartialI2* p) {
+}
+
+ at class PartialI2;
+
+void partialinter2(PartialI2* p) { // no warning
+}

Modified: cfe/trunk/test/SemaObjC/property-deprecated-warning.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-deprecated-warning.m?rev=232750&r1=232749&r2=232750&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/property-deprecated-warning.m (original)
+++ cfe/trunk/test/SemaObjC/property-deprecated-warning.m Thu Mar 19 14:18:22 2015
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1  -fsyntax-only -triple thumbv6-apple-ios3.0 -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -D WARN_PARTIAL -Wpartial-availability -fsyntax-only -triple thumbv6-apple-ios3.0 -verify -Wno-objc-root-class %s
 // RUN: %clang_cc1 -x objective-c++ -fsyntax-only -triple thumbv6-apple-ios3.0 -verify -Wno-objc-root-class %s
 // rdar://12324295
 
@@ -6,29 +7,47 @@ typedef signed char BOOL;
 
 @protocol P
 @property(nonatomic,assign) id ptarget __attribute__((availability(ios,introduced=2.0,deprecated=3.0))); // expected-note {{property 'ptarget' is declared deprecated here}} expected-note {{'ptarget' has been explicitly marked deprecated here}}
+
+#if defined(WARN_PARTIAL)
+// expected-note at +2 {{property 'partialPtarget' is declared partial here}} expected-note at +2 {{'partialPtarget' has been explicitly marked partial here}}
+#endif
+ at property(nonatomic,assign) id partialPtarget __attribute__((availability(ios,introduced=5.0)));
 @end
 
 @protocol P1<P>
 - (void)setPtarget:(id)arg;
+- (void)setPartialPtarget:(id)arg;
 @end
 
 
 @interface UITableViewCell<P1>
 @property(nonatomic,assign) id target __attribute__((availability(ios,introduced=2.0,deprecated=3.0))); // expected-note {{property 'target' is declared deprecated here}} expected-note {{'setTarget:' has been explicitly marked deprecated here}}
+
+#if defined(WARN_PARTIAL)
+// expected-note at +2 {{property 'partialTarget' is declared partial here}} expected-note at +2 {{'setPartialTarget:' has been explicitly marked partial here}}
+#endif
+ at property(nonatomic,assign) id partialTarget __attribute__((availability(ios,introduced=5.0)));
 @end
 
 @interface PSTableCell : UITableViewCell
  - (void)setTarget:(id)target;
+ - (void)setPartialTarget:(id)target;
 @end
 
 @interface UITableViewCell(UIDeprecated)
 @property(nonatomic,assign) id dep_target  __attribute__((availability(ios,introduced=2.0,deprecated=3.0))); // expected-note 2 {{'dep_target' has been explicitly marked deprecated here}} \
                                                                                     // expected-note 4 {{property 'dep_target' is declared deprecated here}} \
                                                                                     // expected-note 2 {{'setDep_target:' has been explicitly marked deprecated here}}
+
+#if defined(WARN_PARTIAL)
+// expected-note at +2 4 {{property 'partial_dep_target' is declared partial here}} expected-note at +2 2 {{'partial_dep_target' has been explicitly marked partial here}} expected-note at +2 2 {{'setPartial_dep_target:' has been explicitly marked partial here}}
+#endif
+ at property(nonatomic,assign) id partial_dep_target  __attribute__((availability(ios,introduced=5.0)));
 @end
 
 @implementation PSTableCell
 - (void)setTarget:(id)target {};
+- (void)setPartialTarget:(id)target {};
 - (void)setPtarget:(id)val {};
 - (void) Meth {
   [self setTarget: (id)0]; // no-warning
@@ -36,20 +55,41 @@ typedef signed char BOOL;
                                            // expected-warning {{'setDep_target:' is deprecated: first deprecated in iOS 3.0}}
 					   
   [self setPtarget: (id)0]; // no-warning
+  [self setPartialTarget: (id)0]; // no-warning
+#if defined(WARN_PARTIAL)
+  // expected-warning at +2 {{'partial_dep_target' is partial: introduced in iOS 5.0}} expected-warning at +2 {{'setPartial_dep_target:' is partial: introduced in iOS 5.0}} expected-note at +2 {{explicitly redeclare 'partial_dep_target' to silence this warning}} expected-note at +2 {{explicitly redeclare 'setPartial_dep_target:' to silence this warning}}
+#endif
+  [self setPartial_dep_target: [self partial_dep_target]];
+
+  [self setPartialPtarget: (id)0]; // no-warning
 }
 @end
 
 @implementation UITableViewCell
 @synthesize target;
+ at synthesize partialTarget;
 @synthesize ptarget;
+ at synthesize partialPtarget;
 - (void)setPtarget:(id)val {};
+- (void)setPartialPtarget:(id)val {};
 - (void)setTarget:(id)target {};
+- (void)setPartialTarget:(id)target {};
 - (void) Meth {
   [self setTarget: (id)0]; // expected-warning {{'setTarget:' is deprecated: first deprecated in iOS 3.0}}
   [self setDep_target: [self dep_target]]; // expected-warning {{'dep_target' is deprecated: first deprecated in iOS 3.0}} \
                                            // expected-warning {{'setDep_target:' is deprecated: first deprecated in iOS 3.0}}
-					   
+
   [self setPtarget: (id)0]; // no-warning
+
+#if defined(WARN_PARTIAL)
+  // expected-warning at +2 {{'setPartialTarget:' is partial: introduced in iOS 5.0}} expected-note at +2 {{explicitly redeclare 'setPartialTarget:' to silence this warning}}
+#endif
+  [self setPartialTarget: (id)0];
+#if defined(WARN_PARTIAL)
+  // expected-warning at +2 {{'partial_dep_target' is partial: introduced in iOS 5.0}} expected-warning at +2 {{'setPartial_dep_target:' is partial: introduced in iOS 5.0}} expected-note at +2 {{explicitly redeclare 'partial_dep_target' to silence this warning}} expected-note at +2 {{explicitly redeclare 'setPartial_dep_target:' to silence this warning}}
+#endif
+  [self setPartial_dep_target: [self partial_dep_target]];
+  [self setPartialPtarget: (id)0]; // no-warning
 }
 @end
 
@@ -58,11 +98,27 @@ typedef signed char BOOL;
 @property(getter=isEnabled,assign) BOOL enabled __attribute__((availability(ios,introduced=2.0,deprecated=3.0))); // expected-note {{'isEnabled' has been explicitly marked deprecated here}} expected-note {{property 'enabled' is declared deprecated here}}
 
 @property(setter=setNewDelegate:,assign) id delegate __attribute__((availability(ios,introduced=2.0,deprecated=3.0))); // expected-note {{'setNewDelegate:' has been explicitly marked deprecated here}} expected-note {{property 'delegate' is declared deprecated here}}
+
+#if defined(WARN_PARTIAL)
+// expected-note at +2 {{property 'partialEnabled' is declared partial here}} expected-note at +2 {{'partialIsEnabled' has been explicitly marked partial here}}
+#endif
+ at property(getter=partialIsEnabled,assign) BOOL partialEnabled __attribute__((availability(ios,introduced=5.0)));
+
+#if defined(WARN_PARTIAL)
+// expected-note at +2 {{property 'partialDelegate' is declared partial here}} expected-note at +2 {{'partialSetNewDelegate:' has been explicitly marked partial here}}
+#endif
+ at property(setter=partialSetNewDelegate:,assign) id partialDelegate __attribute__((availability(ios,introduced=5.0)));
 @end
 
 void testCustomAccessorNames(CustomAccessorNames *obj) {
   if ([obj isEnabled]) // expected-warning {{'isEnabled' is deprecated: first deprecated in iOS 3.0}}
     [obj setNewDelegate:0]; // expected-warning {{'setNewDelegate:' is deprecated: first deprecated in iOS 3.0}}
+
+#if defined(WARN_PARTIAL)
+// expected-warning at +2 {{'partialIsEnabled' is partial: introduced in iOS 5.0}} expected-warning at +3 {{'partialSetNewDelegate:' is partial: introduced in iOS 5.0}} expected-note at +2 {{explicitly redeclare 'partialIsEnabled' to silence this warning}} expected-note at +3 {{explicitly redeclare 'partialSetNewDelegate:' to silence this warning}}
+#endif
+  if ([obj partialIsEnabled])
+    [obj partialSetNewDelegate:0];
 }
 
 
@@ -71,12 +127,20 @@ void testCustomAccessorNames(CustomAcces
 
 @interface ProtocolInCategory (TheCategory) <P1>
 - (id)ptarget;
+- (id)partialPtarget;
 @end
 
 id useDeprecatedProperty(ProtocolInCategory *obj, id<P> obj2, int flag) {
   if (flag)
     return [obj ptarget];  // no-warning
   return [obj2 ptarget];   // expected-warning {{'ptarget' is deprecated: first deprecated in iOS 3.0}}
+
+  if (flag)
+    return [obj partialPtarget];  // no-warning
+#if defined(WARN_PARTIAL)
+// expected-warning at +2 {{'partialPtarget' is partial: introduced in iOS 5.0}} expected-note at +2 {{explicitly redeclare 'partialPtarget' to silence this warning}}
+#endif
+  return [obj2 partialPtarget];
 }
 
 // rdar://15951801





More information about the cfe-commits mailing list