aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2009-06-05 23:00:33 +0000
committerTed Kremenek <kremenek@apple.com>2009-06-05 23:00:33 +0000
commitb9d8db86ab1d9c95c09083d8e9792414ae9fcd6d (patch)
tree100497a538344682703bf79780b3686f2e913ae2
parent2968b7741da535810250b919c95d12105882d19f (diff)
Enhance attribute cf_returns_retained to also work (in the analyzer)
for non-Objctive-C pointer types. This implicitly documents that the return type is a CF object reference. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72968 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Analysis/CFRefCount.cpp11
-rw-r--r--test/Analysis/retain-release-gc-only.m24
-rw-r--r--test/Analysis/retain-release.m28
3 files changed, 60 insertions, 3 deletions
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index 30ff67f4a5..56ab0eb4f6 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -1168,12 +1168,19 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ,
if (!FD)
return;
+ QualType RetTy = FD->getResultType();
+
// Determine if there is a special return effect for this method.
- if (isTrackedObjCObjectType(FD->getResultType())) {
+ if (isTrackedObjCObjectType(RetTy)) {
if (FD->getAttr<NSReturnsRetainedAttr>()) {
Summ.setRetEffect(ObjCAllocRetE);
}
- else if (FD->getAttr<CFReturnsRetainedAttr>()) {
+ else if (FD->getAttr<CFReturnsRetainedAttr>()) {
+ Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
+ }
+ }
+ else if (RetTy->getAsPointerType()) {
+ if (FD->getAttr<CFReturnsRetainedAttr>()) {
Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
}
}
diff --git a/test/Analysis/retain-release-gc-only.m b/test/Analysis/retain-release-gc-only.m
index cc4a40db09..26765c3ac6 100644
--- a/test/Analysis/retain-release-gc-only.m
+++ b/test/Analysis/retain-release-gc-only.m
@@ -189,3 +189,27 @@ void test_attr_1b(TestOwnershipAttr *X) {
NSString *str = [X returnsAnOwnedCFString]; // expected-warning{{leak}}
}
+@interface MyClassTestCFAttr : NSObject {}
+- (NSDate*) returnsCFRetained __attribute__((cf_returns_retained));
+- (NSDate*) alsoReturnsRetained;
+- (NSDate*) returnsNSRetained __attribute__((ns_returns_retained));
+@end
+
+__attribute__((cf_returns_retained))
+CFDateRef returnsRetainedCFDate() {
+ return CFDateCreate(0, CFAbsoluteTimeGetCurrent());
+}
+
+@implementation MyClassTestCFAttr
+- (NSDate*) returnsCFRetained {
+ return (NSDate*) returnsRetainedCFDate(); // No leak.
+}
+
+- (NSDate*) alsoReturnsRetained {
+ return (NSDate*) returnsRetainedCFDate(); // expected-warning{{leak}}
+}
+
+- (NSDate*) returnsNSRetained {
+ return (NSDate*) returnsRetainedCFDate(); // expected-warning{{leak}}
+}
+@end \ No newline at end of file
diff --git a/test/Analysis/retain-release.m b/test/Analysis/retain-release.m
index 3ff007ed8b..c7c5e2488b 100644
--- a/test/Analysis/retain-release.m
+++ b/test/Analysis/retain-release.m
@@ -704,5 +704,31 @@ void test_attr_1(TestOwnershipAttr *X) {
void test_attr_1b(TestOwnershipAttr *X) {
NSString *str = [X returnsAnOwnedCFString]; // expected-warning{{leak}}
}
-//<<SLICER
+
+@interface MyClassTestCFAttr : NSObject {}
+- (NSDate*) returnsCFRetained __attribute__((cf_returns_retained));
+- (NSDate*) alsoReturnsRetained;
+- (NSDate*) returnsNSRetained __attribute__((ns_returns_retained));
+@end
+
+__attribute__((cf_returns_retained))
+CFDateRef returnsRetainedCFDate() {
+ return CFDateCreate(0, CFAbsoluteTimeGetCurrent());
+}
+
+@implementation MyClassTestCFAttr
+- (NSDate*) returnsCFRetained {
+ return (NSDate*) returnsRetainedCFDate(); // No leak.
+}
+
+- (NSDate*) alsoReturnsRetained {
+ return (NSDate*) returnsRetainedCFDate(); // expected-warning{{leak}}
+}
+
+- (NSDate*) returnsNSRetained {
+ return (NSDate*) returnsRetainedCFDate(); // no-warning
+}
+@end
+
+