From: Ted Kremenek Date: Fri, 11 Apr 2008 20:11:19 +0000 (+0000) Subject: Changed behavior of how we handle "NULL" summaries: just call X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a0df99ff6fb7f86fbb55ebac52f64ab35497924a;p=clang Changed behavior of how we handle "NULL" summaries: just call GRSimpleVals::EvalCal(), and don't change reference counts. Remove "getDoNothingSummary()", as a NULL summary does the same thing. Added temporary hack for the "Get" rule for objects that return a pointer type: treat them as non-owned CF objects. Added test case to detect the release of a non-owned object. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49555 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index 1748e450a3..a115a71a2a 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -136,7 +136,6 @@ class CFRefSummaryManager { CFRefSummary* getPersistentSummary(ArgEffects* AE, RetEffect RE); - CFRefSummary* getDoNothingSummary(unsigned Args); void FillDoNothing(unsigned Args); @@ -366,16 +365,12 @@ void CFRefSummaryManager::FillDoNothing(unsigned Args) { ScratchArgs.push_back(DoNothing); } -CFRefSummary* CFRefSummaryManager::getDoNothingSummary(unsigned Args) { - FillDoNothing(Args); - return getPersistentSummary(getArgEffects(), RetEffect::MakeNoRet()); -} CFRefSummary* CFRefSummaryManager::getCFSummaryCreateRule(FunctionTypeProto* FT) { if (!isCFRefType(FT->getResultType())) - return getDoNothingSummary(FT->getNumArgs()); + return NULL; assert (ScratchArgs.empty()); @@ -389,8 +384,16 @@ CFRefSummaryManager::getCFSummaryCreateRule(FunctionTypeProto* FT) { CFRefSummary* CFRefSummaryManager::getCFSummaryGetRule(FunctionTypeProto* FT) { - if (!isCFRefType(FT->getResultType())) - return getDoNothingSummary(FT->getNumArgs()); + QualType RetTy = FT->getResultType(); + + // FIXME: For now we assume that all pointer types returned are referenced + // counted. Since this is the "Get" rule, we assume non-ownership, which + // works fine for things that are not reference counted. We do this because + // some generic data structures return "void*". We need something better + // in the future. + + if (!isCFRefType(RetTy) && !RetTy->isPointerType()) + return NULL; assert (ScratchArgs.empty()); @@ -659,7 +662,7 @@ void CFRefCount::EvalCall(ExplodedNodeSet& Dst, RefVal::Kind hasError = (RefVal::Kind) 0; if (!Summ) { - +#if 0 // This function has no summary. Invalidate all reference-count state // for arguments passed to this function, and also nuke the values of // arguments passed-by-reference. @@ -698,6 +701,10 @@ void CFRefCount::EvalCall(ExplodedNodeSet& Dst, Builder.MakeNode(Dst, CE, Pred, St); return; +#else + GRSimpleVals::EvalCall(Dst, Eng, Builder, CE, L, Pred); + return; +#endif } // This function has a summary. Evaluate the effect of the arguments. diff --git a/test/Analysis-Apple/CFString.c b/test/Analysis-Apple/CFString.c new file mode 100644 index 0000000000..ebd9275e10 --- /dev/null +++ b/test/Analysis-Apple/CFString.c @@ -0,0 +1,30 @@ +// RUN: clang -checker-cfref -verify %s + +#include +#include + +void f1() { + + // Create the array. + CFMutableArrayRef A = CFArrayCreateMutable(NULL, 10, &kCFTypeArrayCallBacks); + + // Create a string. + CFStringRef s1 = CFStringCreateWithCString(NULL, "hello world", + kCFStringEncodingUTF8); + + // Add the string to the array. + CFArrayAppendValue(A, s1); + + // Decrement the reference count. + CFRelease(s1); // no-warning + + // Get the string. We don't own it. + s1 = (CFStringRef) CFArrayGetValueAtIndex(A, 0); + + // Release the array. + CFRelease(A); // no-warning + + // Release the string. This is a bug. + CFRelease(s1); // expected-warning{{Incorrect decrement of the reference count}} +} +