Refine 'deprecated' checking for Objective-C classes/methods.
- 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>.
llvm-svn: 195259
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 4fe5576..cd64311 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -12994,5 +12994,22 @@
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();
}
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 22242a5..26c81ef 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -111,7 +111,8 @@
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:
diff --git a/clang/test/SemaObjC/attr-deprecated.m b/clang/test/SemaObjC/attr-deprecated.m
index aa4b479..cf2e063 100644
--- a/clang/test/SemaObjC/attr-deprecated.m
+++ b/clang/test/SemaObjC/attr-deprecated.m
@@ -154,3 +154,41 @@
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