]> granicus.if.org Git - clang/commitdiff
Refine 'deprecated' checking for Objective-C classes/methods.
authorTed Kremenek <kremenek@apple.com>
Wed, 20 Nov 2013 17:24:03 +0000 (17:24 +0000)
committerTed Kremenek <kremenek@apple.com>
Wed, 20 Nov 2013 17:24:03 +0000 (17:24 +0000)
- If a deprecated class refers to another deprecated class, do not warn.
- @implementations of a deprecated class can refer to other deprecated things.

Fixes <rdar://problem/15407366> and <rdar://problem/15466783>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@195259 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDecl.cpp
lib/Sema/SemaExpr.cpp
test/SemaObjC/attr-deprecated.m

index 4fe55765d34b224638b252c2118c2065bd061164..cd643118ee968fdba6c8529a54304acf6675a1e4 100644 (file)
@@ -12994,5 +12994,22 @@ Decl *Sema::getObjCDeclContext() const {
 
 AvailabilityResult Sema::getCurContextAvailability() const {
   const Decl *D = cast<Decl>(getCurObjCLexicalContext());
+  // If we are within an Objective-C method, we should consult
+  // both the availability of the method as well as the
+  // enclosing class.  If the class is (say) deprecated,
+  // the entire method is considered deprecated from the
+  // purpose of checking if the current context is deprecated.
+  if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+    AvailabilityResult R = MD->getAvailability();
+    if (R != AR_Available)
+      return R;
+    D = MD->getClassInterface();
+  }
+  // If we are within an Objective-c @implementation, it
+  // gets the same availability context as the @interface.
+  else if (const ObjCImplementationDecl *ID =
+            dyn_cast<ObjCImplementationDecl>(D)) {
+    D = ID->getClassInterface();
+  }
   return D->getAvailability();
 }
index 22242a5acc9e10ce5fb167a31181e31f8e43de59..26c81ef552ca50316f92d8200b21dc082f7d486b 100644 (file)
@@ -111,7 +111,8 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S,
       break;
             
     case AR_Deprecated:
-      S.EmitDeprecationWarning(D, Message, Loc, UnknownObjCClass, ObjCPDecl);
+      if (S.getCurContextAvailability() != AR_Deprecated)
+        S.EmitDeprecationWarning(D, Message, Loc, UnknownObjCClass, ObjCPDecl);
       break;
             
     case AR_Unavailable:
index aa4b479e002285f2d6164a280da07fcfc942852d..cf2e063762c2009cc2ff21ed52c3bee11195f0aa 100644 (file)
@@ -154,3 +154,41 @@ typedef NewI DeprI __attribute__((deprecated("blah"))); // expected-note 4 {{'De
   return 0;
 }
 @end
+
+// <rdar://problem/15407366> and <rdar://problem/15466783>:
+// - Using deprecated class name inside class should not warn about deprecation.
+// - Implementations of deprecated classes should not result in deprecation warnings.
+__attribute__((deprecated))
+@interface DeprecatedClassA
+@end
+
+__attribute__((deprecated))
+@interface DeprecatedClassB
+// The self-reference return value should not be
+// flagged as the use of a deprecated declaration.
++ (DeprecatedClassB *)sharedInstance; // no-warning
+
+// Since this class is deprecated, returning a reference
+// to another deprecated class is fine as they may
+// have been deprecated together.  From a user's
+// perspective they are all deprecated.
++ (DeprecatedClassA *)somethingElse; // no-warning
+@end
+
+@implementation DeprecatedClassB
++ (DeprecatedClassB *)sharedInstance
+{
+  // This self-reference should not
+  // be flagged as a use of a deprecated
+  // declaration.
+  static DeprecatedClassB *x; // no-warning
+  return x;
+}
++ (DeprecatedClassA *)somethingElse {
+  // Since this class is deprecated, referencing
+  // another deprecated class is also OK.
+  static DeprecatedClassA *x; // no-warning
+  return x;
+}
+
+@end