void InitializeMethodSummaries();
bool isTrackedObjCObjectType(QualType T);
+ bool isTrackedCFObjectType(QualType T);
private:
return false;
}
+bool RetainSummaryManager::isTrackedCFObjectType(QualType T) {
+ return isRefType(T, "CF") || // Core Foundation.
+ isRefType(T, "CG") || // Core Graphics.
+ isRefType(T, "DADisk") || // Disk Arbitration API.
+ isRefType(T, "DADissenter") ||
+ isRefType(T, "DASessionRef");
+}
+
//===----------------------------------------------------------------------===//
// Summary creation for functions (largely uses of Core Foundation).
//===----------------------------------------------------------------------===//
assert(!str.empty());
if (CStrInCStrNoCase(&str[0], "delegate:")) ReceiverEff = StopTracking;
}
+
// Look for methods that return an owned object.
- if (!isTrackedObjCObjectType(RetTy)) {
- if (ScratchArgs.isEmpty() && ReceiverEff == DoNothing)
- return 0;
+ if (isTrackedObjCObjectType(RetTy)) {
+ // EXPERIMENTAL: Assume the Cocoa conventions for all objects returned
+ // by instance methods.
+
+ RetEffect E =
+ followsFundamentalRule(S.getIdentifierInfoForSlot(0)->getName())
+ ? (isGCEnabled() ? RetEffect::MakeGCNotOwned()
+ : RetEffect::MakeOwned(RetEffect::ObjC, true))
+ : RetEffect::MakeNotOwned(RetEffect::ObjC);
- return getPersistentSummary(RetEffect::MakeNoRet(), ReceiverEff,
- MayEscape);
+ return getPersistentSummary(E, ReceiverEff, MayEscape);
}
- // EXPERIMENTAL: Assume the Cocoa conventions for all objects returned
- // by instance methods.
+ // Look for methods that return an owned core foundation object.
+ if (isTrackedCFObjectType(RetTy)) {
+ RetEffect E =
+ followsFundamentalRule(S.getIdentifierInfoForSlot(0)->getName())
+ ? RetEffect::MakeOwned(RetEffect::CF, true)
+ : RetEffect::MakeNotOwned(RetEffect::CF);
+
+ return getPersistentSummary(E, ReceiverEff, MayEscape);
+ }
- RetEffect E =
- followsFundamentalRule(S.getIdentifierInfoForSlot(0)->getName())
- ? (isGCEnabled() ? RetEffect::MakeGCNotOwned()
- : RetEffect::MakeOwned(RetEffect::ObjC, true))
- : RetEffect::MakeNotOwned(RetEffect::ObjC);
+ if (ScratchArgs.isEmpty() && ReceiverEff == DoNothing)
+ return 0;
- return getPersistentSummary(E, ReceiverEff, MayEscape);
+ return getPersistentSummary(RetEffect::MakeNoRet(), ReceiverEff,
+ MayEscape);
}
RetainSummary*
[string release]; // expected-warning{{Incorrect decrement of the reference count}}
}
-// Test isTrackedObjectType()
+// Test isTrackedObjectType().
typedef NSString* WonkyTypedef;
@interface TestIsTracked
+ (WonkyTypedef)newString;
NSString *str = [TestIsTracked newString]; // expected-warning{{Potential leak}}
}
+// Test isTrackedCFObjectType().
+@interface TestIsCFTracked
++ (CFStringRef) badNewCFString;
++ (CFStringRef) newCFString;
+@end
+
+@implementation TestIsCFTracked
++ (CFStringRef) newCFString {
+ return CFStringCreateWithFormat(kCFAllocatorDefault, ((void*)0), ((CFStringRef) __builtin___CFStringMakeConstantString ("" "%d" "")), 100); // no-warning
+}
++ (CFStringRef) badNewCFString {
+ return CFStringCreateWithFormat(kCFAllocatorDefault, ((void*)0), ((CFStringRef) __builtin___CFStringMakeConstantString ("" "%d" "")), 100); // expected-warning{{leak}}
+}
+
+
+
// Test @synchronized
void test_synchronized(id x) {
@synchronized(x) {
}
}
+// Test return from method starting with 'new' or 'copy'