diff options
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp | 11 | ||||
-rw-r--r-- | clang/test/Analysis/retain-release.m | 30 |
2 files changed, 39 insertions, 2 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp b/clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp index 3bbb4c7f9ab..0187ebaf3ae 100644 --- a/clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp @@ -204,6 +204,11 @@ const RetainSummary *RetainSummaryManager::getSummaryForObjCOrCFObject( AllowAnnotations = false; return RetTy->isObjCIdType() ? getUnarySummary(FT, cfmakecollectable) : getPersistentStopSummary(); + } else if (FName == "CMBufferQueueDequeueAndRetain" || + FName == "CMBufferQueueDequeueIfDataReadyAndRetain") { + // Part of: <rdar://problem/39390714>. + return getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF), DoNothing, + DoNothing); } else if (FName == "CFPlugInInstanceCreate") { return getPersistentSummary(RetEffect::MakeNoRet()); } else if (FName == "IORegistryEntrySearchCFProperty" || @@ -591,6 +596,12 @@ RetainSummaryManager::canEval(const CallExpr *CE, const FunctionDecl *FD, // Handle: (CF|CG|CV)Retain // CFAutorelease // It's okay to be a little sloppy here. + if (FName == "CMBufferQueueDequeueAndRetain" || + FName == "CMBufferQueueDequeueIfDataReadyAndRetain") { + // Part of: <rdar://problem/39390714>. + // These are not retain. They just return something and retain it. + return None; + } if (cocoa::isRefType(ResultTy, "CF", FName) || cocoa::isRefType(ResultTy, "CG", FName) || cocoa::isRefType(ResultTy, "CV", FName)) diff --git a/clang/test/Analysis/retain-release.m b/clang/test/Analysis/retain-release.m index 4694d6ca615..4a3695d42a8 100644 --- a/clang/test/Analysis/retain-release.m +++ b/clang/test/Analysis/retain-release.m @@ -1,9 +1,20 @@ // RUN: rm -f %t.objc.plist %t.objcpp.plist -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -fblocks -verify -Wno-objc-root-class %s -analyzer-output=plist -o %t.objc.plist -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -fblocks -verify -x objective-c++ -std=gnu++98 -Wno-objc-root-class %s -analyzer-output=plist -o %t.objcpp.plist +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10\ +// RUN: -analyzer-checker=core,osx.coreFoundation.CFRetainRelease\ +// RUN: -analyzer-checker=osx.cocoa.ClassRelease,osx.cocoa.RetainCount\ +// RUN: -analyzer-checker=debug.ExprInspection -fblocks -verify %s\ +// RUN: -Wno-objc-root-class -analyzer-output=plist -o %t.objcpp.plist +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10\ +// RUN: -analyzer-checker=core,osx.coreFoundation.CFRetainRelease\ +// RUN: -analyzer-checker=osx.cocoa.ClassRelease,osx.cocoa.RetainCount\ +// RUN: -analyzer-checker=debug.ExprInspection -fblocks -verify %s\ +// RUN: -Wno-objc-root-class -analyzer-output=plist -o %t.objcpp.plist\ +// RUN: -x objective-c++ -std=gnu++98 // FIXLATER: cat %t.objc.plist ; FileCheck --input-file=%t.objc.plist %s // FIXLATER: cat %t.objcpp.plist ; FileCheck --input-file=%t.objcpp.plist %s +void clang_analyzer_eval(int); + #if __has_feature(attribute_ns_returns_retained) #define NS_RETURNS_RETAINED __attribute__((ns_returns_retained)) #endif @@ -495,6 +506,21 @@ void testLeakWithReturnsRetainedOutParameter() { // status is returned. } +typedef CFTypeRef CMBufferRef; + +typedef CFTypeRef *CMBufferQueueRef; + +CMBufferRef CMBufferQueueDequeueAndRetain(CMBufferQueueRef); + +void testCMBufferQueueDequeueAndRetain(CMBufferQueueRef queue) { + CMBufferRef buffer = CMBufferQueueDequeueAndRetain(queue); // expected-warning{{Potential leak of an object stored into 'buffer'}} + // There's a state split due to the eagerly-assume behavior. + // The point here is that we don't treat CMBufferQueueDequeueAndRetain + // as some sort of CFRetain() that returns its argument. + clang_analyzer_eval((CMFooRef)buffer == (CMFooRef)queue); // expected-warning{{TRUE}} + // expected-warning@-1{{FALSE}} +} + // Test retain/release checker with CFString and CFMutableArray. void f11() { // Create the array. |