[analyzer] Improved checker naming in CFG dump.

This implements FIXME from Checker.cpp (FIXME: We want to return the package + name of the checker here.) and replaces hardcoded checker names with the new ones obtained via getCheckName().getName().

llvm-svn: 201525
This commit is contained in:
Anton Yartsev 2014-02-17 18:25:34 +00:00
parent 06bd44b3e8
commit 6a61922239
11 changed files with 64 additions and 34 deletions

View File

@ -658,11 +658,11 @@ protected:
private:
const void *TagKind;
};
class SimpleProgramPointTag : public ProgramPointTag {
std::string desc;
std::string Desc;
public:
SimpleProgramPointTag(StringRef description);
SimpleProgramPointTag(StringRef MsgProvider, StringRef Msg);
StringRef getTagDescription() const;
};

View File

@ -465,6 +465,17 @@ public:
const char *NL, const char *Sep) const { }
};
/// Dump checker name to stream.
raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker);
/// Tag that can use a checker name as a message provider
/// (see SimpleProgramPointTag).
class CheckerProgramPointTag : public SimpleProgramPointTag {
public:
CheckerProgramPointTag(StringRef CheckerName, StringRef Msg);
CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg);
};
template <typename CHECK1, typename CHECK2=check::_VoidCheck,
typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck,
typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck,

View File

@ -43,9 +43,10 @@ ProgramPoint ProgramPoint::getProgramPoint(const Stmt *S, ProgramPoint::Kind K,
}
}
SimpleProgramPointTag::SimpleProgramPointTag(StringRef description)
: desc(description) {}
SimpleProgramPointTag::SimpleProgramPointTag(StringRef MsgProvider,
StringRef Msg)
: Desc((MsgProvider + " : " + Msg).str()) {}
StringRef SimpleProgramPointTag::getTagDescription() const {
return desc;
return Desc;
}

View File

@ -455,7 +455,7 @@ void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C,
ProgramStateRef state,
const ObjCMethodCall &Msg) const {
ASTContext &Ctx = C.getASTContext();
static SimpleProgramPointTag Tag("CallAndMessageChecker : NilReceiver");
static CheckerProgramPointTag Tag(this, "NilReceiver");
// Check the return type of the message expression. A message to nil will
// return different values depending on the return type and the architecture.

View File

@ -575,7 +575,7 @@ void MacOSKeychainAPIChecker::checkDeadSymbols(SymbolReaper &SR,
return;
}
static SimpleProgramPointTag Tag("MacOSKeychainAPIChecker : DeadSymbolsLeak");
static CheckerProgramPointTag Tag(this, "DeadSymbolsLeak");
ExplodedNode *N = C.addTransition(C.getState(), C.getPredecessor(), &Tag);
// Generate the error reports.

View File

@ -1738,7 +1738,7 @@ void MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper,
// Generate leak node.
ExplodedNode *N = C.getPredecessor();
if (!Errors.empty()) {
static SimpleProgramPointTag Tag("MallocChecker : DeadSymbolsLeak");
static CheckerProgramPointTag Tag("MallocChecker", "DeadSymbolsLeak");
N = C.addTransition(C.getState(), C.getPredecessor(), &Tag);
for (SmallVectorImpl<SymbolRef>::iterator
I = Errors.begin(), E = Errors.end(); I != E; ++I) {
@ -2251,11 +2251,17 @@ void MallocChecker::printState(raw_ostream &Out, ProgramStateRef State,
RegionStateTy RS = State->get<RegionState>();
if (!RS.isEmpty()) {
Out << Sep << "MallocChecker:" << NL;
Out << Sep << "MallocChecker :" << NL;
for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
const RefState *RefS = State->get<RegionState>(I.getKey());
AllocationFamily Family = RefS->getAllocationFamily();
Optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(Family);
I.getKey()->dumpToStream(Out);
Out << " : ";
I.getData().dump(Out);
if (CheckKind.hasValue())
Out << " (" << CheckNames[*CheckKind].getName() << ")";
Out << NL;
}
}
@ -2269,11 +2275,8 @@ void ento::registerNewDeleteLeaksChecker(CheckerManager &mgr) {
mgr.getCurrentCheckName();
// We currently treat NewDeleteLeaks checker as a subchecker of NewDelete
// checker.
if (!checker->ChecksEnabled[MallocChecker::CK_NewDeleteChecker]) {
if (!checker->ChecksEnabled[MallocChecker::CK_NewDeleteChecker])
checker->ChecksEnabled[MallocChecker::CK_NewDeleteChecker] = true;
checker->CheckNames[MallocChecker::CK_NewDeleteChecker] =
mgr.getCurrentCheckName();
}
}
#define REGISTER_CHECKER(name) \

View File

@ -350,7 +350,7 @@ void ObjCSelfInitChecker::printState(raw_ostream &Out, ProgramStateRef State,
if (FlagMap.isEmpty() && !DidCallInit && !PreCallFlags)
return;
Out << Sep << NL << "ObjCSelfInitChecker:" << NL;
Out << Sep << NL << *this << " :" << NL;
if (DidCallInit)
Out << " An init method has been called." << NL;

View File

@ -2344,7 +2344,7 @@ class RetainCountChecker
mutable OwningPtr<CFRefBug> leakWithinFunction, leakAtReturn;
mutable OwningPtr<CFRefBug> leakWithinFunctionGC, leakAtReturnGC;
typedef llvm::DenseMap<SymbolRef, const SimpleProgramPointTag *> SymbolTagMap;
typedef llvm::DenseMap<SymbolRef, const CheckerProgramPointTag *> SymbolTagMap;
// This map is only used to ensure proper deletion of any allocated tags.
mutable SymbolTagMap DeadSymbolTags;
@ -3258,8 +3258,7 @@ void RetainCountChecker::checkPreStmt(const ReturnStmt *S,
return;
// Update the autorelease counts.
static SimpleProgramPointTag
AutoreleaseTag("RetainCountChecker : Autorelease");
static CheckerProgramPointTag AutoreleaseTag(this, "Autorelease");
state = handleAutoreleaseCounts(state, Pred, &AutoreleaseTag, C, Sym, X);
// Did we cache out?
@ -3320,8 +3319,7 @@ void RetainCountChecker::checkReturnWithRetEffect(const ReturnStmt *S,
// Generate an error node.
state = setRefBinding(state, Sym, X);
static SimpleProgramPointTag
ReturnOwnLeakTag("RetainCountChecker : ReturnsOwnLeak");
static CheckerProgramPointTag ReturnOwnLeakTag(this, "ReturnsOwnLeak");
ExplodedNode *N = C.addTransition(state, Pred, &ReturnOwnLeakTag);
if (N) {
const LangOptions &LOpts = C.getASTContext().getLangOpts();
@ -3341,8 +3339,8 @@ void RetainCountChecker::checkReturnWithRetEffect(const ReturnStmt *S,
// owned object.
state = setRefBinding(state, Sym, X ^ RefVal::ErrorReturnedNotOwned);
static SimpleProgramPointTag
ReturnNotOwnedTag("RetainCountChecker : ReturnNotOwnedForOwned");
static CheckerProgramPointTag ReturnNotOwnedTag(this,
"ReturnNotOwnedForOwned");
ExplodedNode *N = C.addTransition(state, Pred, &ReturnNotOwnedTag);
if (N) {
if (!returnNotOwnedForOwned)
@ -3628,13 +3626,13 @@ void RetainCountChecker::checkEndFunction(CheckerContext &Ctx) const {
const ProgramPointTag *
RetainCountChecker::getDeadSymbolTag(SymbolRef sym) const {
const SimpleProgramPointTag *&tag = DeadSymbolTags[sym];
const CheckerProgramPointTag *&tag = DeadSymbolTags[sym];
if (!tag) {
SmallString<64> buf;
llvm::raw_svector_ostream out(buf);
out << "RetainCountChecker : Dead Symbol : ";
out << "Dead Symbol : ";
sym->dumpToStream(out);
tag = new SimpleProgramPointTag(out.str());
tag = new CheckerProgramPointTag(this, out.str());
}
return tag;
}

View File

@ -18,12 +18,25 @@ using namespace clang;
using namespace ento;
StringRef CheckerBase::getTagDescription() const {
// FIXME: We want to return the package + name of the checker here.
return "A Checker";
return getCheckName().getName();
}
CheckName CheckerBase::getCheckName() const { return Name; }
CheckerProgramPointTag::CheckerProgramPointTag(StringRef CheckerName,
StringRef Msg)
: SimpleProgramPointTag(CheckerName, Msg) {}
CheckerProgramPointTag::CheckerProgramPointTag(const CheckerBase *Checker,
StringRef Msg)
: SimpleProgramPointTag(Checker->getCheckName().getName(), Msg) {}
raw_ostream& clang::ento::operator<<(raw_ostream &Out,
const CheckerBase &Checker) {
Out << Checker.getCheckName().getName();
return Out;
}
void Checker<check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,

View File

@ -55,6 +55,8 @@ STATISTIC(NumTimesRetriedWithoutInlining,
// Engine construction and deletion.
//===----------------------------------------------------------------------===//
static const char* TagProviderName = "ExprEngine";
ExprEngine::ExprEngine(AnalysisManager &mgr, bool gcEnabled,
SetOfConstDecls *VisitedCalleesIn,
FunctionSummariesTy *FS,
@ -366,7 +368,7 @@ void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out,
// Process any special transfer function for dead symbols.
// A tag to track convenience transitions, which can be removed at cleanup.
static SimpleProgramPointTag cleanupTag("ExprEngine : Clean Node");
static SimpleProgramPointTag cleanupTag(TagProviderName, "Clean Node");
if (!SymReaper.hasDeadSymbols()) {
// Generate a CleanedNode that has the environment and store cleaned
// up. Since no symbols are dead, we can optimize and not clean out
@ -1273,7 +1275,7 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
// FIXME: Refactor this into a checker.
if (nodeBuilder.getContext().blockCount() >= AMgr.options.maxBlockVisitOnPath) {
static SimpleProgramPointTag tag("ExprEngine : Block count exceeded");
static SimpleProgramPointTag tag(TagProviderName, "Block count exceeded");
const ExplodedNode *Sink =
nodeBuilder.generateSink(Pred->getState(), Pred, &tag);
@ -2067,7 +2069,7 @@ void ExprEngine::evalLoad(ExplodedNodeSet &Dst,
QualType ValTy = TR->getValueType();
if (const ReferenceType *RT = ValTy->getAs<ReferenceType>()) {
static SimpleProgramPointTag
loadReferenceTag("ExprEngine : Load Reference");
loadReferenceTag(TagProviderName, "Load Reference");
ExplodedNodeSet Tmp;
evalLoadCommon(Tmp, NodeEx, BoundEx, Pred, state,
location, &loadReferenceTag,
@ -2150,7 +2152,7 @@ void ExprEngine::evalLocation(ExplodedNodeSet &Dst,
// instead "int *p" is noted as
// "Variable 'p' initialized to a null pointer value"
static SimpleProgramPointTag tag("ExprEngine: Location");
static SimpleProgramPointTag tag(TagProviderName, "Location");
Bldr.generateNode(NodeEx, Pred, state, &tag);
}
ExplodedNodeSet Tmp;
@ -2162,8 +2164,10 @@ void ExprEngine::evalLocation(ExplodedNodeSet &Dst,
std::pair<const ProgramPointTag *, const ProgramPointTag*>
ExprEngine::geteagerlyAssumeBinOpBifurcationTags() {
static SimpleProgramPointTag
eagerlyAssumeBinOpBifurcationTrue("ExprEngine : Eagerly Assume True"),
eagerlyAssumeBinOpBifurcationFalse("ExprEngine : Eagerly Assume False");
eagerlyAssumeBinOpBifurcationTrue(TagProviderName,
"Eagerly Assume True"),
eagerlyAssumeBinOpBifurcationFalse(TagProviderName,
"Eagerly Assume False");
return std::make_pair(&eagerlyAssumeBinOpBifurcationTrue,
&eagerlyAssumeBinOpBifurcationFalse);
}

View File

@ -282,7 +282,7 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
// they occurred.
ExplodedNodeSet CleanedNodes;
if (LastSt && Blk && AMgr.options.AnalysisPurgeOpt != PurgeNone) {
static SimpleProgramPointTag retValBind("ExprEngine : Bind Return Value");
static SimpleProgramPointTag retValBind("ExprEngine", "Bind Return Value");
PostStmt Loc(LastSt, calleeCtx, &retValBind);
bool isNew;
ExplodedNode *BindedRetNode = G.getNode(Loc, state, false, &isNew);