From 6041111f3749e76a1712ec58dd17449bd3177ddd Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Thu, 18 Feb 2010 00:06:12 +0000 Subject: [PATCH] Recognize attributes ns_returns_not_retained and cf_returns_not_retained in the static analyzer. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96539 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Checker/CFRefCount.cpp | 18 ++++++++++++++++-- test/Analysis/retain-release.m | 22 ++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/lib/Checker/CFRefCount.cpp b/lib/Checker/CFRefCount.cpp index 2eb9607bc9..ecb98a0496 100644 --- a/lib/Checker/CFRefCount.cpp +++ b/lib/Checker/CFRefCount.cpp @@ -1222,6 +1222,12 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ, else if (FD->getAttr()) { Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true)); } + else if (FD->getAttr()) { + Summ.setRetEffect(RetEffect::MakeNotOwned(RetEffect::ObjC)); + } + else if (FD->getAttr()) { + Summ.setRetEffect(RetEffect::MakeNotOwned(RetEffect::CF)); + } } else if (RetTy->getAs()) { if (FD->getAttr()) { @@ -1244,6 +1250,10 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ, Summ.setRetEffect(ObjCAllocRetE); return; } + if (MD->getAttr()) { + Summ.setRetEffect(RetEffect::MakeNotOwned(RetEffect::ObjC)); + return; + } isTrackedLoc = true; } @@ -1251,8 +1261,12 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ, if (!isTrackedLoc) isTrackedLoc = MD->getResultType()->getAs() != NULL; - if (isTrackedLoc && MD->getAttr()) - Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true)); + if (isTrackedLoc) { + if (MD->getAttr()) + Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true)); + else if (MD->getAttr()) + Summ.setRetEffect(RetEffect::MakeNotOwned(RetEffect::CF)); + } } RetainSummary* diff --git a/test/Analysis/retain-release.m b/test/Analysis/retain-release.m index 1c41d85d23..675e9a6702 100644 --- a/test/Analysis/retain-release.m +++ b/test/Analysis/retain-release.m @@ -7,6 +7,12 @@ #if __has_feature(attribute_cf_returns_retained) #define CF_RETURNS_RETAINED __attribute__((cf_returns_retained)) #endif +#if __has_feature(attribute_ns_returns_not_retained) +#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained)) +#endif +#if __has_feature(attribute_cf_returns_not_retained) +#define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained)) +#endif //===----------------------------------------------------------------------===// // The following code is reduced using delta-debugging from Mac OS X headers: @@ -1188,6 +1194,8 @@ typedef NSString* MyStringTy; - (NSString*) returnsAnOwnedString NS_RETURNS_RETAINED; // no-warning - (NSString*) returnsAnOwnedCFString CF_RETURNS_RETAINED; // no-warning - (MyStringTy) returnsAnOwnedTypedString NS_RETURNS_RETAINED; // no-warning +- (NSString*) newString NS_RETURNS_NOT_RETAINED; // no-warning +- (NSString*) newStringNoAttr; - (int) returnsAnOwnedInt NS_RETURNS_RETAINED; // expected-warning{{'ns_returns_retained' attribute only applies to functions or methods that return a pointer or Objective-C object}} @end @@ -1201,9 +1209,16 @@ void test_attr_1b(TestOwnershipAttr *X) { NSString *str = [X returnsAnOwnedCFString]; // expected-warning{{leak}} } +void test_attr1c(TestOwnershipAttr *X) { + NSString *str = [X newString]; // no-warning + NSString *str2 = [X newStringNoAttr]; // expected-warning{{leak}} +} + @interface MyClassTestCFAttr : NSObject {} - (NSDate*) returnsCFRetained CF_RETURNS_RETAINED; - (CFDateRef) returnsCFRetainedAsCF CF_RETURNS_RETAINED; +- (CFDateRef) newCFRetainedAsCF CF_RETURNS_NOT_RETAINED; +- (CFDateRef) newCFRetainedAsCFNoAttr; - (NSDate*) alsoReturnsRetained; - (CFDateRef) alsoReturnsRetainedAsCF; - (NSDate*) returnsNSRetained NS_RETURNS_RETAINED; @@ -1223,6 +1238,13 @@ CFDateRef returnsRetainedCFDate() { return returnsRetainedCFDate(); // No leak. } +- (CFDateRef) newCFRetainedAsCF { + return (CFDateRef)[(id)[self returnsCFRetainedAsCF] autorelease]; +} + +- (CFDateRef) newCFRetainedAsCFNoAttr { + return (CFDateRef)[(id)[self returnsCFRetainedAsCF] autorelease]; // expected-warning{{Object with +0 retain counts returned to caller where a +1 (owning) retain count is expected}} +} - (NSDate*) alsoReturnsRetained { return (NSDate*) returnsRetainedCFDate(); // expected-warning{{leak}} -- 2.40.0