[analyzer] Move RetainReleaseChecker to the Checkers library and rename it to RetainCountChecker...and clean up the file while I'm at it.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139002 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index d8e982b..3e0d094 100644
--- a/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -45,6 +45,7 @@
PointerArithChecker.cpp
PointerSubChecker.cpp
PthreadLockChecker.cpp
+ RetainCountChecker.cpp
ReturnPointerRangeChecker.cpp
ReturnUndefChecker.cpp
StackAddrEscapeChecker.cpp
diff --git a/lib/StaticAnalyzer/Core/CFRefCount.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
similarity index 94%
rename from lib/StaticAnalyzer/Core/CFRefCount.cpp
rename to lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
index 7a1c73f..fce2cc3 100644
--- a/lib/StaticAnalyzer/Core/CFRefCount.cpp
+++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
@@ -1,4 +1,4 @@
-// CFRefCount.cpp - Transfer functions for tracking simple values -*- C++ -*--//
+//==-- RetainCountChecker.cpp - Checks for leaks and other issues -*- C++ -*--//
//
// The LLVM Compiler Infrastructure
//
@@ -7,26 +7,24 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines the methods for CFRefCount, which implements
-// a reference count checker for Core Foundation (Mac OS X).
+// This file defines the methods for RetainCountChecker, which implements
+// a reference count checker for Core Foundation and Cocoa on (Mac OS X).
//
//===----------------------------------------------------------------------===//
-#include "clang/StaticAnalyzer/Core/Checker.h"
-#include "clang/StaticAnalyzer/Core/CheckerManager.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "ClangSACheckers.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclCXX.h"
-#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
-#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
-#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngineBuilders.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
@@ -41,6 +39,8 @@
using llvm::StrInStrNoCase;
namespace {
+/// Wrapper around different kinds of node builder, so that helper functions
+/// can have a common interface.
class GenericNodeBuilderRefCount {
StmtNodeBuilder *SNB;
const Stmt *S;
@@ -258,7 +258,7 @@
Out << "Tracked " << T.getAsString() << '/';
switch (getKind()) {
- default: assert(false);
+ default: llvm_unreachable("Invalid RefVal kind");
case Owned: {
Out << "Owned";
unsigned cnt = getCount();
@@ -354,7 +354,7 @@
}
//===----------------------------------------------------------------------===//
-// Summaries
+// Function/Method behavior summaries.
//===----------------------------------------------------------------------===//
namespace {
@@ -733,8 +733,6 @@
InitializeMethodSummaries();
}
- ~RetainSummaryManager();
-
RetainSummary* getSummary(const FunctionDecl *FD);
RetainSummary *getInstanceMethodSummary(const ObjCMessage &msg,
@@ -842,8 +840,6 @@
// Implementation of checker data structures.
//===----------------------------------------------------------------------===//
-RetainSummaryManager::~RetainSummaryManager() {}
-
ArgEffects RetainSummaryManager::getArgEffects() {
ArgEffects AE = ScratchArgs;
ScratchArgs = AF.getEmptyMap();
@@ -1578,28 +1574,6 @@
}
//===----------------------------------------------------------------------===//
-// Transfer functions.
-//===----------------------------------------------------------------------===//
-
-namespace {
-
-class CFRefCount : public TransferFuncs {
-public:
- const LangOptions& LOpts;
- const bool GCEnabled;
-
-public:
- CFRefCount(ASTContext &Ctx, bool gcenabled, const LangOptions& lopts)
- : LOpts(lopts), GCEnabled(gcenabled) {}
-
- void RegisterChecks(ExprEngine &Eng);
-
- const LangOptions& getLangOptions() const { return LOpts; }
-};
-
-} // end anonymous namespace
-
-//===----------------------------------------------------------------------===//
// Error reporting.
//===----------------------------------------------------------------------===//
namespace {
@@ -1826,6 +1800,7 @@
addExtraText(GCModeDescription);
}
+// FIXME: This should be a method on SmallVector.
static inline bool contains(const SmallVectorImpl<ArgEffect>& V,
ArgEffect X) {
for (SmallVectorImpl<ArgEffect>::const_iterator I=V.begin(), E=V.end();
@@ -2291,40 +2266,8 @@
// Main checker logic.
//===----------------------------------------------------------------------===//
-/// GetReturnType - Used to get the return type of a message expression or
-/// function call with the intention of affixing that type to a tracked symbol.
-/// While the the return type can be queried directly from RetEx, when
-/// invoking class methods we augment to the return type to be that of
-/// a pointer to the class (as opposed it just being id).
-static QualType GetReturnType(const Expr *RetE, ASTContext &Ctx) {
- QualType RetTy = RetE->getType();
- // If RetE is not a message expression just return its type.
- // If RetE is a message expression, return its types if it is something
- /// more specific than id.
- if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(RetE))
- if (const ObjCObjectPointerType *PT = RetTy->getAs<ObjCObjectPointerType>())
- if (PT->isObjCQualifiedIdType() || PT->isObjCIdType() ||
- PT->isObjCClassType()) {
- // At this point we know the return type of the message expression is
- // id, id<...>, or Class. If we have an ObjCInterfaceDecl, we know this
- // is a call to a class method whose type we can resolve. In such
- // cases, promote the return type to XXX* (where XXX is the class).
- const ObjCInterfaceDecl *D = ME->getReceiverInterface();
- return !D ? RetTy :
- Ctx.getObjCObjectPointerType(Ctx.getObjCInterfaceType(D));
- }
-
- return RetTy;
-}
-
-//===----------------------------------------------------------------------===//
-// Pieces of the retain/release checker implemented using a CheckerVisitor.
-// More pieces of the retain/release checker will be migrated to this interface
-// (ideally, all of it some day).
-//===----------------------------------------------------------------------===//
-
namespace {
-class RetainReleaseChecker
+class RetainCountChecker
: public Checker< check::Bind,
check::DeadSymbols,
check::EndAnalysis,
@@ -2358,9 +2301,9 @@
mutable bool ShouldResetSummaryLog;
public:
- RetainReleaseChecker() : ShouldResetSummaryLog(false) {}
+ RetainCountChecker() : ShouldResetSummaryLog(false) {}
- virtual ~RetainReleaseChecker() {
+ virtual ~RetainCountChecker() {
DeleteContainerSeconds(DeadSymbolTags);
}
@@ -2545,108 +2488,14 @@
};
} // end anonymous namespace
+//===----------------------------------------------------------------------===//
+// Handle statements that may have an effect on refcounts.
+//===----------------------------------------------------------------------===//
-void RetainReleaseChecker::checkBind(SVal loc, SVal val,
- CheckerContext &C) const {
- // Are we storing to something that causes the value to "escape"?
- bool escapes = true;
+void RetainCountChecker::checkPostStmt(const BlockExpr *BE,
+ CheckerContext &C) const {
- // A value escapes in three possible cases (this may change):
- //
- // (1) we are binding to something that is not a memory region.
- // (2) we are binding to a memregion that does not have stack storage
- // (3) we are binding to a memregion with stack storage that the store
- // does not understand.
- const ProgramState *state = C.getState();
-
- if (loc::MemRegionVal *regionLoc = dyn_cast<loc::MemRegionVal>(&loc)) {
- escapes = !regionLoc->getRegion()->hasStackStorage();
-
- if (!escapes) {
- // To test (3), generate a new state with the binding added. If it is
- // the same state, then it escapes (since the store cannot represent
- // the binding).
- escapes = (state == (state->bindLoc(*regionLoc, val)));
- }
- }
-
- // If our store can represent the binding and we aren't storing to something
- // that doesn't have local storage then just return and have the simulation
- // state continue as is.
- if (!escapes)
- return;
-
- // Otherwise, find all symbols referenced by 'val' that we are tracking
- // and stop tracking them.
- state = state->scanReachableSymbols<StopTrackingCallback>(val).getState();
- C.addTransition(state);
-}
-
-// Assumptions.
-
-const ProgramState *RetainReleaseChecker::evalAssume(const ProgramState *state,
- SVal Cond,
- bool Assumption) const {
-
- // FIXME: We may add to the interface of evalAssume the list of symbols
- // whose assumptions have changed. For now we just iterate through the
- // bindings and check if any of the tracked symbols are NULL. This isn't
- // too bad since the number of symbols we will track in practice are
- // probably small and evalAssume is only called at branches and a few
- // other places.
- RefBindings B = state->get<RefBindings>();
-
- if (B.isEmpty())
- return state;
-
- bool changed = false;
- RefBindings::Factory &RefBFactory = state->get_context<RefBindings>();
-
- for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
- // Check if the symbol is null (or equal to any constant).
- // If this is the case, stop tracking the symbol.
- if (state->getSymVal(I.getKey())) {
- changed = true;
- B = RefBFactory.remove(B, I.getKey());
- }
- }
-
- if (changed)
- state = state->set<RefBindings>(B);
-
- return state;
-}
-
-const ProgramState *
-RetainReleaseChecker::checkRegionChanges(const ProgramState *state,
- const StoreManager::InvalidatedSymbols *invalidated,
- ArrayRef<const MemRegion *> ExplicitRegions,
- ArrayRef<const MemRegion *> Regions) const {
- if (!invalidated)
- return state;
-
- llvm::SmallPtrSet<SymbolRef, 8> WhitelistedSymbols;
- for (ArrayRef<const MemRegion *>::iterator I = ExplicitRegions.begin(),
- E = ExplicitRegions.end(); I != E; ++I) {
- if (const SymbolicRegion *SR = (*I)->StripCasts()->getAs<SymbolicRegion>())
- WhitelistedSymbols.insert(SR->getSymbol());
- }
-
- for (StoreManager::InvalidatedSymbols::const_iterator I=invalidated->begin(),
- E = invalidated->end(); I!=E; ++I) {
- SymbolRef sym = *I;
- if (WhitelistedSymbols.count(sym))
- continue;
- // Remove any existing reference-count binding.
- state = state->remove<RefBindings>(sym);
- }
- return state;
-}
-
-void RetainReleaseChecker::checkPostStmt(const BlockExpr *BE,
- CheckerContext &C) const {
-
- // Scan the BlockDecRefExprs for any object the retain/release checker
+ // Scan the BlockDecRefExprs for any object the retain count checker
// may be tracking.
if (!BE->getBlockDecl()->hasCaptures())
return;
@@ -2682,8 +2531,8 @@
C.addTransition(state);
}
-void RetainReleaseChecker::checkPostStmt(const CastExpr *CE,
- CheckerContext &C) const {
+void RetainCountChecker::checkPostStmt(const CastExpr *CE,
+ CheckerContext &C) const {
const ObjCBridgedCastExpr *BE = dyn_cast<ObjCBridgedCastExpr>(CE);
if (!BE)
return;
@@ -2722,8 +2571,8 @@
C.generateNode(state);
}
-void RetainReleaseChecker::checkPostStmt(const CallExpr *CE,
- CheckerContext &C) const {
+void RetainCountChecker::checkPostStmt(const CallExpr *CE,
+ CheckerContext &C) const {
// Get the callee.
const ProgramState *state = C.getState();
const Expr *Callee = CE->getCallee();
@@ -2751,8 +2600,8 @@
checkSummary(*Summ, CallOrObjCMessage(CE, state), C);
}
-void RetainReleaseChecker::checkPostStmt(const CXXConstructExpr *CE,
- CheckerContext &C) const {
+void RetainCountChecker::checkPostStmt(const CXXConstructExpr *CE,
+ CheckerContext &C) const {
const CXXConstructorDecl *Ctor = CE->getConstructor();
if (!Ctor)
return;
@@ -2768,8 +2617,8 @@
checkSummary(*Summ, CallOrObjCMessage(CE, state), C);
}
-void RetainReleaseChecker::checkPostObjCMessage(const ObjCMessage &Msg,
- CheckerContext &C) const {
+void RetainCountChecker::checkPostObjCMessage(const ObjCMessage &Msg,
+ CheckerContext &C) const {
const ProgramState *state = C.getState();
ExplodedNode *Pred = C.getPredecessor();
@@ -2790,9 +2639,37 @@
checkSummary(*Summ, CallOrObjCMessage(Msg, state), C);
}
-void RetainReleaseChecker::checkSummary(const RetainSummary &Summ,
- const CallOrObjCMessage &CallOrMsg,
- CheckerContext &C) const {
+/// GetReturnType - Used to get the return type of a message expression or
+/// function call with the intention of affixing that type to a tracked symbol.
+/// While the the return type can be queried directly from RetEx, when
+/// invoking class methods we augment to the return type to be that of
+/// a pointer to the class (as opposed it just being id).
+// FIXME: We may be able to do this with related result types instead.
+// This function is probably overestimating.
+static QualType GetReturnType(const Expr *RetE, ASTContext &Ctx) {
+ QualType RetTy = RetE->getType();
+ // If RetE is not a message expression just return its type.
+ // If RetE is a message expression, return its types if it is something
+ /// more specific than id.
+ if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(RetE))
+ if (const ObjCObjectPointerType *PT = RetTy->getAs<ObjCObjectPointerType>())
+ if (PT->isObjCQualifiedIdType() || PT->isObjCIdType() ||
+ PT->isObjCClassType()) {
+ // At this point we know the return type of the message expression is
+ // id, id<...>, or Class. If we have an ObjCInterfaceDecl, we know this
+ // is a call to a class method whose type we can resolve. In such
+ // cases, promote the return type to XXX* (where XXX is the class).
+ const ObjCInterfaceDecl *D = ME->getReceiverInterface();
+ return !D ? RetTy :
+ Ctx.getObjCObjectPointerType(Ctx.getObjCInterfaceType(D));
+ }
+
+ return RetTy;
+}
+
+void RetainCountChecker::checkSummary(const RetainSummary &Summ,
+ const CallOrObjCMessage &CallOrMsg,
+ CheckerContext &C) const {
const ProgramState *state = C.getState();
// Evaluate the effect of the arguments.
@@ -2921,10 +2798,11 @@
const ProgramState *
-RetainReleaseChecker::updateSymbol(const ProgramState *state, SymbolRef sym,
- RefVal V, ArgEffect E, RefVal::Kind &hasErr,
- CheckerContext &C) const {
+RetainCountChecker::updateSymbol(const ProgramState *state, SymbolRef sym,
+ RefVal V, ArgEffect E, RefVal::Kind &hasErr,
+ CheckerContext &C) const {
// In GC mode [... release] and [... retain] do nothing.
+ // In ARC mode they shouldn't exist at all, but we just ignore them.
bool IgnoreRetainMsg = C.isObjCGCEnabled();
if (!IgnoreRetainMsg)
IgnoreRetainMsg = (bool)C.getASTContext().getLangOptions().ObjCAutoRefCount;
@@ -3060,11 +2938,11 @@
return state->set<RefBindings>(sym, V);
}
-void RetainReleaseChecker::processNonLeakError(const ProgramState *St,
- SourceRange ErrorRange,
- RefVal::Kind ErrorKind,
- SymbolRef Sym,
- CheckerContext &C) const {
+void RetainCountChecker::processNonLeakError(const ProgramState *St,
+ SourceRange ErrorRange,
+ RefVal::Kind ErrorKind,
+ SymbolRef Sym,
+ CheckerContext &C) const {
ExplodedNode *N = C.generateSink(St);
if (!N)
return;
@@ -3104,8 +2982,11 @@
C.EmitReport(report);
}
-bool RetainReleaseChecker::evalCall(const CallExpr *CE,
- CheckerContext &C) const {
+//===----------------------------------------------------------------------===//
+// Handle the return values of retain-count-related functions.
+//===----------------------------------------------------------------------===//
+
+bool RetainCountChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
// Get the callee. We're only interested in simple C functions.
const ProgramState *state = C.getState();
const Expr *Callee = CE->getCallee();
@@ -3182,10 +3063,12 @@
return true;
}
- // Return statements.
+//===----------------------------------------------------------------------===//
+// Handle return statements.
+//===----------------------------------------------------------------------===//
-void RetainReleaseChecker::checkPreStmt(const ReturnStmt *S,
- CheckerContext &C) const {
+void RetainCountChecker::checkPreStmt(const ReturnStmt *S,
+ CheckerContext &C) const {
const Expr *RetE = S->getRetValue();
if (!RetE)
return;
@@ -3242,7 +3125,7 @@
// Update the autorelease counts.
static SimpleProgramPointTag
- AutoreleaseTag("RetainReleaseChecker : Autorelease");
+ AutoreleaseTag("RetainCountChecker : Autorelease");
GenericNodeBuilderRefCount Bd(C.getNodeBuilder(), S, &AutoreleaseTag);
llvm::tie(Pred, state) = handleAutoreleaseCounts(state, Bd, Pred,
C.getEngine(), Sym, X);
@@ -3277,11 +3160,11 @@
}
}
-void RetainReleaseChecker::checkReturnWithRetEffect(const ReturnStmt *S,
- CheckerContext &C,
- ExplodedNode *Pred,
- RetEffect RE, RefVal X,
- SymbolRef Sym,
+void RetainCountChecker::checkReturnWithRetEffect(const ReturnStmt *S,
+ CheckerContext &C,
+ ExplodedNode *Pred,
+ RetEffect RE, RefVal X,
+ SymbolRef Sym,
const ProgramState *state) const {
// Any leaks or other errors?
if (X.isReturnedOwned() && X.getCount() == 0) {
@@ -3309,7 +3192,7 @@
StmtNodeBuilder &Builder = C.getNodeBuilder();
static SimpleProgramPointTag
- ReturnOwnLeakTag("RetainReleaseChecker : ReturnsOwnLeak");
+ ReturnOwnLeakTag("RetainCountChecker : ReturnsOwnLeak");
ExplodedNode *N = Builder.generateNode(S, state, Pred,
&ReturnOwnLeakTag);
if (N) {
@@ -3331,7 +3214,7 @@
StmtNodeBuilder &Builder = C.getNodeBuilder();
static SimpleProgramPointTag
- ReturnNotOwnedTag("RetainReleaseChecker : ReturnNotOwnedForOwned");
+ ReturnNotOwnedTag("RetainCountChecker : ReturnNotOwnedForOwned");
ExplodedNode *N = Builder.generateNode(S, state, Pred,
&ReturnNotOwnedTag);
if (N) {
@@ -3349,15 +3232,113 @@
}
//===----------------------------------------------------------------------===//
+// Check various ways a symbol can be invalidated.
+//===----------------------------------------------------------------------===//
+
+void RetainCountChecker::checkBind(SVal loc, SVal val,
+ CheckerContext &C) const {
+ // Are we storing to something that causes the value to "escape"?
+ bool escapes = true;
+
+ // A value escapes in three possible cases (this may change):
+ //
+ // (1) we are binding to something that is not a memory region.
+ // (2) we are binding to a memregion that does not have stack storage
+ // (3) we are binding to a memregion with stack storage that the store
+ // does not understand.
+ const ProgramState *state = C.getState();
+
+ if (loc::MemRegionVal *regionLoc = dyn_cast<loc::MemRegionVal>(&loc)) {
+ escapes = !regionLoc->getRegion()->hasStackStorage();
+
+ if (!escapes) {
+ // To test (3), generate a new state with the binding added. If it is
+ // the same state, then it escapes (since the store cannot represent
+ // the binding).
+ escapes = (state == (state->bindLoc(*regionLoc, val)));
+ }
+ }
+
+ // If our store can represent the binding and we aren't storing to something
+ // that doesn't have local storage then just return and have the simulation
+ // state continue as is.
+ if (!escapes)
+ return;
+
+ // Otherwise, find all symbols referenced by 'val' that we are tracking
+ // and stop tracking them.
+ state = state->scanReachableSymbols<StopTrackingCallback>(val).getState();
+ C.addTransition(state);
+}
+
+const ProgramState *RetainCountChecker::evalAssume(const ProgramState *state,
+ SVal Cond,
+ bool Assumption) const {
+
+ // FIXME: We may add to the interface of evalAssume the list of symbols
+ // whose assumptions have changed. For now we just iterate through the
+ // bindings and check if any of the tracked symbols are NULL. This isn't
+ // too bad since the number of symbols we will track in practice are
+ // probably small and evalAssume is only called at branches and a few
+ // other places.
+ RefBindings B = state->get<RefBindings>();
+
+ if (B.isEmpty())
+ return state;
+
+ bool changed = false;
+ RefBindings::Factory &RefBFactory = state->get_context<RefBindings>();
+
+ for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
+ // Check if the symbol is null (or equal to any constant).
+ // If this is the case, stop tracking the symbol.
+ if (state->getSymVal(I.getKey())) {
+ changed = true;
+ B = RefBFactory.remove(B, I.getKey());
+ }
+ }
+
+ if (changed)
+ state = state->set<RefBindings>(B);
+
+ return state;
+}
+
+const ProgramState *
+RetainCountChecker::checkRegionChanges(const ProgramState *state,
+ const StoreManager::InvalidatedSymbols *invalidated,
+ ArrayRef<const MemRegion *> ExplicitRegions,
+ ArrayRef<const MemRegion *> Regions) const {
+ if (!invalidated)
+ return state;
+
+ llvm::SmallPtrSet<SymbolRef, 8> WhitelistedSymbols;
+ for (ArrayRef<const MemRegion *>::iterator I = ExplicitRegions.begin(),
+ E = ExplicitRegions.end(); I != E; ++I) {
+ if (const SymbolicRegion *SR = (*I)->StripCasts()->getAs<SymbolicRegion>())
+ WhitelistedSymbols.insert(SR->getSymbol());
+ }
+
+ for (StoreManager::InvalidatedSymbols::const_iterator I=invalidated->begin(),
+ E = invalidated->end(); I!=E; ++I) {
+ SymbolRef sym = *I;
+ if (WhitelistedSymbols.count(sym))
+ continue;
+ // Remove any existing reference-count binding.
+ state = state->remove<RefBindings>(sym);
+ }
+ return state;
+}
+
+//===----------------------------------------------------------------------===//
// Handle dead symbols and end-of-path.
//===----------------------------------------------------------------------===//
std::pair<ExplodedNode *, const ProgramState *>
-RetainReleaseChecker::handleAutoreleaseCounts(const ProgramState *state,
- GenericNodeBuilderRefCount Bd,
- ExplodedNode *Pred,
- ExprEngine &Eng, SymbolRef Sym,
- RefVal V) const {
+RetainCountChecker::handleAutoreleaseCounts(const ProgramState *state,
+ GenericNodeBuilderRefCount Bd,
+ ExplodedNode *Pred, ExprEngine &Eng,
+ SymbolRef Sym, RefVal V) const {
unsigned ACnt = V.getAutoreleaseCount();
// No autorelease counts? Nothing to be done.
@@ -3419,8 +3400,8 @@
}
const ProgramState *
-RetainReleaseChecker::handleSymbolDeath(const ProgramState *state,
- SymbolRef sid, RefVal V,
+RetainCountChecker::handleSymbolDeath(const ProgramState *state,
+ SymbolRef sid, RefVal V,
SmallVectorImpl<SymbolRef> &Leaked) const {
bool hasLeak = false;
if (V.isOwned())
@@ -3436,12 +3417,10 @@
}
ExplodedNode *
-RetainReleaseChecker::processLeaks(const ProgramState *state,
- SmallVectorImpl<SymbolRef> &Leaked,
- GenericNodeBuilderRefCount &Builder,
- ExprEngine &Eng,
- ExplodedNode *Pred) const {
-
+RetainCountChecker::processLeaks(const ProgramState *state,
+ SmallVectorImpl<SymbolRef> &Leaked,
+ GenericNodeBuilderRefCount &Builder,
+ ExprEngine &Eng, ExplodedNode *Pred) const {
if (Leaked.empty())
return Pred;
@@ -3467,8 +3446,8 @@
return N;
}
-void RetainReleaseChecker::checkEndPath(EndOfFunctionNodeBuilder &Builder,
- ExprEngine &Eng) const {
+void RetainCountChecker::checkEndPath(EndOfFunctionNodeBuilder &Builder,
+ ExprEngine &Eng) const {
const ProgramState *state = Builder.getState();
GenericNodeBuilderRefCount Bd(Builder);
RefBindings B = state->get<RefBindings>();
@@ -3491,19 +3470,19 @@
}
const ProgramPointTag *
-RetainReleaseChecker::getDeadSymbolTag(SymbolRef sym) const {
+RetainCountChecker::getDeadSymbolTag(SymbolRef sym) const {
const SimpleProgramPointTag *&tag = DeadSymbolTags[sym];
if (!tag) {
llvm::SmallString<64> buf;
llvm::raw_svector_ostream out(buf);
- out << "RetainReleaseChecker : Dead Symbol : " << sym->getSymbolID();
+ out << "RetainCountChecker : Dead Symbol : " << sym->getSymbolID();
tag = new SimpleProgramPointTag(out.str());
}
return tag;
}
-void RetainReleaseChecker::checkDeadSymbols(SymbolReaper &SymReaper,
- CheckerContext &C) const {
+void RetainCountChecker::checkDeadSymbols(SymbolReaper &SymReaper,
+ CheckerContext &C) const {
StmtNodeBuilder &Builder = C.getNodeBuilder();
ExprEngine &Eng = C.getEngine();
const Stmt *S = C.getStmt();
@@ -3584,9 +3563,8 @@
state->get<AutoreleasePoolContents>(SymbolRef());
}
-void RetainReleaseChecker::printState(raw_ostream &Out,
- const ProgramState *State,
- const char *NL, const char *Sep) const {
+void RetainCountChecker::printState(raw_ostream &Out, const ProgramState *State,
+ const char *NL, const char *Sep) const {
RefBindings B = State->get<RefBindings>();
@@ -3613,36 +3591,10 @@
}
//===----------------------------------------------------------------------===//
-// Transfer function creation for external clients.
+// Checker registration.
//===----------------------------------------------------------------------===//
-void CFRefCount::RegisterChecks(ExprEngine& Eng) {
- // Register the RetainReleaseChecker with the ExprEngine object.
- // Functionality in CFRefCount will be migrated to RetainReleaseChecker
- // over time.
- // FIXME: HACK! Remove TransferFuncs and turn all of CFRefCount into fully
- // using the checker mechanism.
- RetainReleaseChecker *checker =
- Eng.getCheckerManager().registerChecker<RetainReleaseChecker>();
- assert(checker);
- //checker->setGCMode(GCEnabled ? LangOptions::GCOnly : LangOptions::NonGC);
-}
-
-TransferFuncs* ento::MakeCFRefCountTF(ASTContext &Ctx, bool GCEnabled,
- const LangOptions& lopts) {
- return new CFRefCount(Ctx, GCEnabled, lopts);
-}
-
-
-// FIXME: This will be unnecessary once RetainReleaseChecker is moved to
-// the Checkers library (...and renamed to RetainCountChecker).
-namespace clang {
-namespace ento {
- void registerRetainCountChecker(CheckerManager &Mgr);
-}
-}
-
void ento::registerRetainCountChecker(CheckerManager &Mgr) {
- Mgr.registerChecker<RetainReleaseChecker>();
+ Mgr.registerChecker<RetainCountChecker>();
}
diff --git a/lib/StaticAnalyzer/Core/CMakeLists.txt b/lib/StaticAnalyzer/Core/CMakeLists.txt
index 950c7bc..391a781 100644
--- a/lib/StaticAnalyzer/Core/CMakeLists.txt
+++ b/lib/StaticAnalyzer/Core/CMakeLists.txt
@@ -10,7 +10,6 @@
BlockCounter.cpp
BugReporter.cpp
BugReporterVisitors.cpp
- CFRefCount.cpp
Checker.cpp
CheckerContext.cpp
CheckerHelpers.cpp