Author: dcoughlin Date: Sat Nov 25 06:57:42 2017 New Revision: 318979 URL: http://llvm.org/viewvc/llvm-project?rev=318979&view=rev Log: [analyzer] Teach RetainCountChecker about CoreMedia APIs
Teach the retain-count checker that CoreMedia reference types use CoreFoundation-style reference counting. This enables the checker to catch leaks and over releases of those types. rdar://problem/33599757 Modified: cfe/trunk/lib/Analysis/CocoaConventions.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp cfe/trunk/test/Analysis/retain-release.m Modified: cfe/trunk/lib/Analysis/CocoaConventions.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CocoaConventions.cpp?rev=318979&r1=318978&r2=318979&view=diff ============================================================================== --- cfe/trunk/lib/Analysis/CocoaConventions.cpp (original) +++ cfe/trunk/lib/Analysis/CocoaConventions.cpp Sat Nov 25 06:57:42 2017 @@ -47,12 +47,19 @@ bool cocoa::isRefType(QualType RetTy, St 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); } Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp?rev=318979&r1=318978&r2=318979&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp Sat Nov 25 06:57:42 2017 @@ -1201,10 +1201,10 @@ RetainSummaryManager::getFunctionSummary 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; } Modified: cfe/trunk/test/Analysis/retain-release.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/retain-release.m?rev=318979&r1=318978&r2=318979&view=diff ============================================================================== --- cfe/trunk/test/Analysis/retain-release.m (original) +++ cfe/trunk/test/Analysis/retain-release.m Sat Nov 25 06:57:42 2017 @@ -450,6 +450,51 @@ void f10(io_service_t media, DADiskRef d 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. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits