r231553 - [analyzer] RetainCountChecker: CF properties are always manually retain-counted.
Jordan Rose
jordan_rose at apple.com
Fri Mar 6 21:47:25 PST 2015
Author: jrose
Date: Fri Mar 6 23:47:24 2015
New Revision: 231553
URL: http://llvm.org/viewvc/llvm-project?rev=231553&view=rev
Log:
[analyzer] RetainCountChecker: CF properties are always manually retain-counted.
In theory we could assume a CF property is stored at +0 if there's not a custom
setter, but that's not really worth the complexity. What we do know is that a
CF property can't have ownership attributes, and so we shouldn't assume anything
about the ownership of the ivar.
rdar://problem/20076963
Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
cfe/trunk/test/Analysis/properties.m
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp?rev=231553&r1=231552&r2=231553&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp Fri Mar 6 23:47:24 2015
@@ -2882,9 +2882,10 @@ void RetainCountChecker::checkPostStmt(c
// Also don't do anything if the ivar is unretained. If so, we know that
// there's no outstanding retain count for the value.
- if (const ObjCPropertyDecl *Prop = findPropForIvar(IRE->getDecl()))
- if (!Prop->isRetaining())
- return;
+ if (Kind == RetEffect::ObjC)
+ if (const ObjCPropertyDecl *Prop = findPropForIvar(IRE->getDecl()))
+ if (!Prop->isRetaining())
+ return;
// Note that this value has been loaded from an ivar.
C.addTransition(setRefBinding(State, Sym, RV->withIvarAccess()));
@@ -2900,12 +2901,16 @@ void RetainCountChecker::checkPostStmt(c
}
// Try to find the property associated with this ivar.
- const ObjCPropertyDecl *Prop = findPropForIvar(IRE->getDecl());
-
- if (Prop && !Prop->isRetaining())
- State = setRefBinding(State, Sym, PlusZero);
- else
+ if (Kind != RetEffect::ObjC) {
State = setRefBinding(State, Sym, PlusZero.withIvarAccess());
+ } else {
+ const ObjCPropertyDecl *Prop = findPropForIvar(IRE->getDecl());
+
+ if (Prop && !Prop->isRetaining())
+ State = setRefBinding(State, Sym, PlusZero);
+ else
+ State = setRefBinding(State, Sym, PlusZero.withIvarAccess());
+ }
C.addTransition(State);
}
Modified: cfe/trunk/test/Analysis/properties.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/properties.m?rev=231553&r1=231552&r2=231553&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/properties.m (original)
+++ cfe/trunk/test/Analysis/properties.m Fri Mar 6 23:47:24 2015
@@ -3,6 +3,10 @@
void clang_analyzer_eval(int);
+typedef const void * CFTypeRef;
+extern CFTypeRef CFRetain(CFTypeRef cf);
+void CFRelease(CFTypeRef cf);
+
typedef signed char BOOL;
typedef unsigned int NSUInteger;
typedef struct _NSZone NSZone;
@@ -352,6 +356,7 @@ void testOpaqueConsistency(OpaqueIntWrap
@property (strong) id ownedProp;
@property (unsafe_unretained) id unownedProp;
@property (nonatomic, strong) id manualProp;
+ at property CFTypeRef cfProp;
@end
@implementation RetainCountTesting {
@@ -382,6 +387,13 @@ void testOpaqueConsistency(OpaqueIntWrap
[_ivarOnly release]; // expected-warning{{used after it is released}}
}
+- (void)testOverreleaseCF {
+ CFRetain(_cfProp);
+ CFRelease(_cfProp);
+ CFRelease(_cfProp);
+ CFRelease(_cfProp); // expected-warning{{used after it is released}}
+}
+
- (void)testOverreleaseOwnedIvarUse {
[_ownedProp retain];
[_ownedProp release];
@@ -396,6 +408,15 @@ void testOpaqueConsistency(OpaqueIntWrap
[_ivarOnly myMethod]; // expected-warning{{used after it is released}}
}
+- (void)testOverreleaseCFUse {
+ CFRetain(_cfProp);
+ CFRelease(_cfProp);
+ CFRelease(_cfProp);
+
+ extern void CFUse(CFTypeRef);
+ CFUse(_cfProp); // expected-warning{{used after it is released}}
+}
+
- (void)testOverreleaseOwnedIvarAutoreleaseOkay {
[_ownedProp retain];
[_ownedProp release];
@@ -465,6 +486,21 @@ void testOpaqueConsistency(OpaqueIntWrap
[fromIvar release]; // no-warning
}
+- (void)testPropertyAccessThenReleaseCF {
+ CFTypeRef owned = CFRetain(self.cfProp);
+ CFRelease(owned);
+ CFRelease(_cfProp); // no-warning
+ clang_analyzer_eval(owned == _cfProp); // expected-warning{{TRUE}}
+}
+
+- (void)testPropertyAccessThenReleaseCF2 {
+ CFTypeRef fromIvar = _cfProp;
+ CFTypeRef owned = CFRetain(self.cfProp);
+ CFRelease(owned);
+ CFRelease(fromIvar);
+ clang_analyzer_eval(owned == fromIvar); // expected-warning{{TRUE}}
+}
+
- (id)getUnownedFromProperty {
[_ownedProp retain];
[_ownedProp autorelease];
@@ -498,6 +534,11 @@ void testOpaqueConsistency(OpaqueIntWrap
[_ivarOnly release]; // FIXME: no-warning{{not owned}}
}
+- (void)testAssignCF:(CFTypeRef)newValue {
+ _cfProp = newValue;
+ CFRelease(_cfProp); // FIXME: no-warning{{not owned}}
+}
+
- (void)testAssignOwnedOkay:(id)newValue {
_ownedProp = [newValue retain];
[_ownedProp release]; // no-warning
@@ -513,6 +554,11 @@ void testOpaqueConsistency(OpaqueIntWrap
[_ivarOnly release]; // no-warning
}
+- (void)testAssignCFOkay:(CFTypeRef)newValue {
+ _cfProp = CFRetain(newValue);
+ CFRelease(_cfProp); // no-warning
+}
+
// rdar://problem/19862648
- (void)establishIvarIsNilDuringLoops {
extern id getRandomObject();
More information about the cfe-commits
mailing list