From: Ted Kremenek Date: Wed, 20 Nov 2013 17:24:03 +0000 (+0000) Subject: Refine 'deprecated' checking for Objective-C classes/methods. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1251e989207a838338d5057d3af9984ce1dcefe4;p=clang 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 and . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@195259 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 4fe55765d3..cd643118ee 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -12994,5 +12994,22 @@ Decl *Sema::getObjCDeclContext() const { AvailabilityResult Sema::getCurContextAvailability() const { const Decl *D = cast(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(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(D)) { + D = ID->getClassInterface(); + } return D->getAvailability(); } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 22242a5acc..26c81ef552 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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: diff --git a/test/SemaObjC/attr-deprecated.m b/test/SemaObjC/attr-deprecated.m index aa4b479e00..cf2e063762 100644 --- a/test/SemaObjC/attr-deprecated.m +++ b/test/SemaObjC/attr-deprecated.m @@ -154,3 +154,41 @@ typedef NewI DeprI __attribute__((deprecated("blah"))); // expected-note 4 {{'De return 0; } @end + +// and : +// - 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