[cfe-commits] r49509 - in /cfe/trunk: lib/Analysis/CFRefCount.cpp lib/Analysis/GRExprEngine.cpp test/Analysis-Apple/CFDate.c
Ted Kremenek
kremenek at apple.com
Thu Apr 10 16:44:06 PDT 2008
Author: kremenek
Date: Thu Apr 10 18:44:06 2008
New Revision: 49509
URL: http://llvm.org/viewvc/llvm-project?rev=49509&view=rev
Log:
Fixed some logic errors in the CF ref count checker; we now can detect simple
use-after-release errors. Added test case.
Added:
cfe/trunk/test/Analysis-Apple/CFDate.c
Modified:
cfe/trunk/lib/Analysis/CFRefCount.cpp
cfe/trunk/lib/Analysis/GRExprEngine.cpp
Modified: cfe/trunk/lib/Analysis/CFRefCount.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFRefCount.cpp?rev=49509&r1=49508&r2=49509&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CFRefCount.cpp (original)
+++ cfe/trunk/lib/Analysis/CFRefCount.cpp Thu Apr 10 18:44:06 2008
@@ -48,7 +48,8 @@
class RetEffect {
public:
- enum Kind { Alias = 0x0, OwnedSymbol = 0x1, NotOwnedSymbol = 0x2 };
+ enum Kind { NoRet = 0x0, Alias = 0x1, OwnedSymbol = 0x2,
+ NotOwnedSymbol = 0x3 };
private:
unsigned Data;
@@ -69,6 +70,8 @@
static RetEffect MakeNotOwned() { return RetEffect(NotOwnedSymbol, 0); }
+ static RetEffect MakeNoRet() { return RetEffect(NoRet, 0); }
+
operator Kind() const { return getKind(); }
void Profile(llvm::FoldingSetNodeID& ID) const { ID.AddInteger(Data); }
@@ -133,6 +136,10 @@
CFRefSummary* getPersistentSummary(ArgEffects* AE, RetEffect RE);
+ CFRefSummary* getDoNothingSummary(unsigned Args);
+ void FillDoNothing(unsigned Args);
+
+
public:
CFRefSummaryManager(ASTContext& ctx) : Ctx(ctx) {}
~CFRefSummaryManager();
@@ -158,8 +165,6 @@
ArgEffects* CFRefSummaryManager::getArgEffects() {
- assert (!ScratchArgs.empty());
-
llvm::FoldingSetNodeID profile;
profile.Add(ScratchArgs);
void* InsertPos;
@@ -314,20 +319,22 @@
// CFRetain: the return type should also be "CFTypeRef".
if (RetTy.getTypePtr() != ArgT)
return NULL;
+
+ // The function's interface checks out. Generate a canned summary.
+ assert (ScratchArgs.empty());
+ ScratchArgs.push_back(IncRef);
+ return getPersistentSummary(getArgEffects(), RetEffect::MakeAlias(0));
}
else {
// CFRelease: the return type should be void.
if (RetTy != Ctx.VoidTy)
return NULL;
- }
- // The function's interface checks out. Generate a canned summary.
-
- assert (ScratchArgs.empty());
- ScratchArgs.push_back(isRetain ? IncRef : DecRef);
-
- return getPersistentSummary(getArgEffects(), RetEffect::MakeAlias(0));
+ assert (ScratchArgs.empty());
+ ScratchArgs.push_back(DecRef);
+ return getPersistentSummary(getArgEffects(), RetEffect::MakeNoRet());
+ }
}
static bool isCFRefType(QualType T) {
@@ -354,21 +361,28 @@
return true;
}
+void CFRefSummaryManager::FillDoNothing(unsigned Args) {
+ for (unsigned i = 0; i != Args; ++i)
+ 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 NULL;
+ return getDoNothingSummary(FT->getNumArgs());
assert (ScratchArgs.empty());
// FIXME: Add special-cases for functions that retain/release. For now
// just handle the default case.
- for (unsigned i = 0, n = FT->getNumArgs(); i != n; ++i)
- ScratchArgs.push_back(DoNothing);
-
+ FillDoNothing(FT->getNumArgs());
return getPersistentSummary(getArgEffects(), RetEffect::MakeOwned());
}
@@ -376,16 +390,14 @@
CFRefSummaryManager::getCFSummaryGetRule(FunctionTypeProto* FT) {
if (!isCFRefType(FT->getResultType()))
- return NULL;
+ return getDoNothingSummary(FT->getNumArgs());
assert (ScratchArgs.empty());
// FIXME: Add special-cases for functions that retain/release. For now
// just handle the default case.
- for (unsigned i = 0, n = FT->getNumArgs(); i != n; ++i)
- ScratchArgs.push_back(DoNothing);
-
+ FillDoNothing(FT->getNumArgs());
return getPersistentSummary(getArgEffects(), RetEffect::MakeNotOwned());
}
@@ -711,11 +723,11 @@
if (hasError) {
St = StateMgr.getPersistentState(StVals);
- GRExprEngine::NodeTy* N = Builder.generateNode(CE, St, Pred);
+
+ Builder.BuildSinks = true;
+ GRExprEngine::NodeTy* N = Builder.MakeNode(Dst, CE, Pred, St);
if (N) {
- N->markAsSink();
-
switch (hasError) {
default: assert(false);
case RefVal::ErrorUseAfterRelease:
@@ -741,6 +753,9 @@
default:
assert (false && "Unhandled RetEffect."); break;
+ case RetEffect::NoRet:
+ break;
+
case RetEffect::Alias: {
unsigned idx = RE.getValue();
assert (idx < CE->getNumArgs());
@@ -810,7 +825,8 @@
assert(false);
case RefVal::Owned:
- V = RefVal::makeOwned(V.getCount()+1); break;
+ V = RefVal::makeOwned(V.getCount()+1);
+ break;
case RefVal::NotOwned:
V = RefVal::makeNotOwned(V.getCount()+1);
@@ -822,6 +838,8 @@
break;
}
+ break;
+
case DecRef:
switch (V.getKind()) {
default:
@@ -851,6 +869,8 @@
hasError = V.getKind();
break;
}
+
+ break;
}
return RefBFactory.Add(B, sym, V);
Modified: cfe/trunk/lib/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngine.cpp?rev=49509&r1=49508&r2=49509&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Thu Apr 10 18:44:06 2008
@@ -678,6 +678,8 @@
unsigned size = Dst.size();
+ SaveAndRestore<bool> OldSink(Builder->BuildSinks);
+
EvalCall(Dst, CE, cast<LVal>(L), *DI);
if (!Builder->BuildSinks && Dst.size() == size)
Added: cfe/trunk/test/Analysis-Apple/CFDate.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis-Apple/CFDate.c?rev=49509&view=auto
==============================================================================
--- cfe/trunk/test/Analysis-Apple/CFDate.c (added)
+++ cfe/trunk/test/Analysis-Apple/CFDate.c Thu Apr 10 18:44:06 2008
@@ -0,0 +1,15 @@
+// RUN: clang -checker-cfref -verify %s
+
+#include <CoreFoundation/CFDate.h>
+
+CFAbsoluteTime f1() {
+ CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
+ CFDateRef date = CFDateCreate(NULL, t);
+ CFRetain(date);
+ CFRelease(date);
+ t = CFDateGetAbsoluteTime(date);
+ CFRelease(date);
+ t = CFDateGetAbsoluteTime(date); // expected-warning{{Reference-counted object is used after it is released.}}
+ return t;
+}
+
More information about the cfe-commits
mailing list