diff options
| -rw-r--r-- | clang/lib/Analysis/CocoaConventions.cpp | 13 | ||||
| -rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp | 8 | ||||
| -rw-r--r-- | clang/test/Analysis/retain-release.m | 45 |
3 files changed, 59 insertions, 7 deletions
diff --git a/clang/lib/Analysis/CocoaConventions.cpp b/clang/lib/Analysis/CocoaConventions.cpp index be1262dc991..4d57623e216 100644 --- a/clang/lib/Analysis/CocoaConventions.cpp +++ b/clang/lib/Analysis/CocoaConventions.cpp @@ -47,12 +47,19 @@ bool cocoa::isRefType(QualType RetTy, StringRef Prefix, return Name.startswith(Prefix); } +/// Returns true when the passed-in type is a CF-style reference-counted +/// type from the DiskArbitration framework. +static bool isDiskArbitrationAPIRefType(QualType T) { + return cocoa::isRefType(T, "DADisk") || + cocoa::isRefType(T, "DADissenter") || + cocoa::isRefType(T, "DASessionRef"); +} + bool coreFoundation::isCFObjectRef(QualType T) { return cocoa::isRefType(T, "CF") || // Core Foundation. cocoa::isRefType(T, "CG") || // Core Graphics. - cocoa::isRefType(T, "DADisk") || // Disk Arbitration API. - cocoa::isRefType(T, "DADissenter") || - cocoa::isRefType(T, "DASessionRef"); + cocoa::isRefType(T, "CM") || // Core Media. + isDiskArbitrationAPIRefType(T); } diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp index 4db83af17f3..e47494a3e90 100644 --- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp @@ -1201,10 +1201,10 @@ RetainSummaryManager::getFunctionSummary(const FunctionDecl *FD) { break; } - // For the Disk Arbitration API (DiskArbitration/DADisk.h) - if (cocoa::isRefType(RetTy, "DADisk") || - cocoa::isRefType(RetTy, "DADissenter") || - cocoa::isRefType(RetTy, "DASessionRef")) { + // For all other CF-style types, use the Create/Get + // rule for summaries but don't support Retain functions + // with framework-specific prefixes. + if (coreFoundation::isCFObjectRef(RetTy)) { S = getCFCreateGetRuleSummary(FD); break; } diff --git a/clang/test/Analysis/retain-release.m b/clang/test/Analysis/retain-release.m index a1cc62cb359..4add50eb5d0 100644 --- a/clang/test/Analysis/retain-release.m +++ b/clang/test/Analysis/retain-release.m @@ -450,6 +450,51 @@ void f10(io_service_t media, DADiskRef d, CFStringRef s) { if (session) NSLog(@"ok"); } + +// Handle CoreMedia API + +struct CMFoo; +typedef struct CMFoo *CMFooRef; + +CMFooRef CMCreateFooRef(); +CMFooRef CMGetFooRef(); + +typedef signed long SInt32; +typedef SInt32 OSStatus; +OSStatus CMCreateFooAndReturnViaOutParameter(CMFooRef * CF_RETURNS_RETAINED fooOut); + +void testLeakCoreMediaReferenceType() { + CMFooRef f = CMCreateFooRef(); // expected-warning{{leak}} +} + +void testOverReleaseMediaReferenceType() { + CMFooRef f = CMGetFooRef(); + CFRelease(f); // expected-warning{{Incorrect decrement of the reference count}} +} + +void testOkToReleaseReturnsRetainedOutParameter() { + CMFooRef foo = 0; + OSStatus status = CMCreateFooAndReturnViaOutParameter(&foo); + + if (status != 0) + return; + + CFRelease(foo); // no-warning +} + +void testLeakWithReturnsRetainedOutParameter() { + CMFooRef foo = 0; + OSStatus status = CMCreateFooAndReturnViaOutParameter(&foo); + + if (status != 0) + return; + + // FIXME: Ideally we would report a leak here since it is the caller's + // responsibility to release 'foo'. However, we don't currently have + // a mechanism in this checker to only require a release when a successful + // status is returned. +} + // Test retain/release checker with CFString and CFMutableArray. void f11() { // Create the array. |

