diff options
author | Anna Zaks <ganna@apple.com> | 2011-08-19 22:33:38 +0000 |
---|---|---|
committer | Anna Zaks <ganna@apple.com> | 2011-08-19 22:33:38 +0000 |
commit | 50bbc165b063155cc23c360deb7b865502e068e2 (patch) | |
tree | 26bd4515516fcefcc82b4593b9754c6b1ede5700 /lib | |
parent | e6452785f095db92887ad403299bfa616ce198e2 (diff) |
Static Analyzer Diagnostics: Kill the addVisitorCreator(callbackTy, void*) API in favor of addVisitor(BugReporterVisitor*).
1) Create a header file to expose the predefined visitors. And move the parent(BugReporterVisitor) there as well.
2) Remove the registerXXXVisitor functions - the Visitor constructors/getters can be used now to create the object. One exception is registerVarDeclsLastStore(), which registers more then one visitor, so make it static member of FindLastStoreBRVisitor.
3) Modify all the checkers to use the new API.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@138126 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
18 files changed, 255 insertions, 360 deletions
diff --git a/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp b/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp index 285b3920fa..8296eb93c5 100644 --- a/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp @@ -101,15 +101,14 @@ void AttrNonNullChecker::checkPreStmt(const CallExpr *CE, "API")); BugReport *R = - new BugReport(*BT, - "Null pointer passed as an argument to a " - "'nonnull' parameter", errorNode); + new BugReport(*BT, "Null pointer passed as an argument to a " + "'nonnull' parameter", errorNode); // Highlight the range of the argument that was null. const Expr *arg = *I; R->addRange(arg->getSourceRange()); - R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, arg); - + R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(errorNode, + arg)); // Emit the bug report. C.EmitReport(R); } diff --git a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp index da592050eb..1631df8af9 100644 --- a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp +++ b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp @@ -414,7 +414,7 @@ void CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE, BugReport *report = new BugReport(*BT, description, N); report->addRange(Arg->getSourceRange()); - report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Arg); + report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Arg)); C.EmitReport(report); return; } diff --git a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index c5d4379fcb..d043e2d8ae 100644 --- a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -231,7 +231,7 @@ const ProgramState *CStringChecker::checkNonNull(CheckerContext &C, BugReport *report = new BugReport(*BT, os.str(), N); report->addRange(S->getSourceRange()); - report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, S); + report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, S)); C.EmitReport(report); return NULL; } diff --git a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp index 191d4bba02..ba1dae8738 100644 --- a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp @@ -65,8 +65,8 @@ void CallAndMessageChecker::EmitBadCall(BugType *BT, CheckerContext &C, return; BugReport *R = new BugReport(*BT, BT->getName(), N); - R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, - bugreporter::GetCalleeExpr(N)); + R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, + bugreporter::GetCalleeExpr(N))); C.EmitReport(R); } @@ -95,7 +95,7 @@ bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C, BugReport *R = new BugReport(*BT, BT->getName(), N); R->addRange(argRange); if (argEx) - R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, argEx); + R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, argEx)); C.EmitReport(R); } return true; @@ -230,8 +230,8 @@ void CallAndMessageChecker::checkPreObjCMessage(ObjCMessage msg, BugReport *R = new BugReport(*BT_msg_undef, BT_msg_undef->getName(), N); R->addRange(receiver->getSourceRange()); - R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, - receiver); + R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, + receiver)); C.EmitReport(R); } return; @@ -275,8 +275,8 @@ void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C, BugReport *report = new BugReport(*BT_msg_ret, os.str(), N); if (const Expr *receiver = msg.getInstanceReceiver()) { report->addRange(receiver->getSourceRange()); - report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, - receiver); + report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, + receiver)); } C.EmitReport(report); } diff --git a/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp b/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp index 22af688547..c416dd8e8e 100644 --- a/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp @@ -75,8 +75,8 @@ void DereferenceChecker::checkLocation(SVal l, bool isLoad, BugReport *report = new BugReport(*BT_undef, BT_undef->getDescription(), N); - report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, - bugreporter::GetDerefExpr(N)); + report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, + bugreporter::GetDerefExpr(N))); C.EmitReport(report); } return; @@ -162,8 +162,8 @@ void DereferenceChecker::checkLocation(SVal l, bool isLoad, buf.empty() ? BT_null->getDescription():buf.str(), N); - report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, - bugreporter::GetDerefExpr(N)); + report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, + bugreporter::GetDerefExpr(N))); for (SmallVectorImpl<SourceRange>::iterator I = Ranges.begin(), E = Ranges.end(); I!=E; ++I) diff --git a/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp b/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp index d87c773d6e..75b7cc47aa 100644 --- a/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp @@ -63,8 +63,8 @@ void DivZeroChecker::checkPreStmt(const BinaryOperator *B, BugReport *R = new BugReport(*BT, BT->getDescription(), N); - R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, - bugreporter::GetDenomExpr(N)); + R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, + bugreporter::GetDenomExpr(N))); C.EmitReport(R); } diff --git a/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp b/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp index af819ecf30..46f06a0a84 100644 --- a/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp @@ -413,12 +413,12 @@ void IdempotentOperationChecker::checkEndAnalysis(ExplodedGraph &G, if (LHSRelevant) { const Expr *LHS = i->first->getLHS(); report->addRange(LHS->getSourceRange()); - report->addVisitorCreator(bugreporter::registerVarDeclsLastStore, LHS); + FindLastStoreBRVisitor::registerStatementVarDecls(*report, LHS); } if (RHSRelevant) { const Expr *RHS = i->first->getRHS(); report->addRange(i->first->getRHS()->getSourceRange()); - report->addVisitorCreator(bugreporter::registerVarDeclsLastStore, RHS); + FindLastStoreBRVisitor::registerStatementVarDecls(*report, RHS); } BR.EmitReport(report); diff --git a/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp index 7b964a44ba..3e4e07b650 100644 --- a/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp @@ -49,7 +49,7 @@ void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S, "for @synchronized")); BugReport *report = new BugReport(*BT_undef, BT_undef->getDescription(), N); - report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex); + report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Ex)); C.EmitReport(report); } return; @@ -72,8 +72,7 @@ void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S, "(no synchronization will occur)")); BugReport *report = new BugReport(*BT_null, BT_null->getDescription(), N); - report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, - Ex); + report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Ex)); C.EmitReport(report); return; diff --git a/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp b/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp index 979c107792..e8c8d902a5 100644 --- a/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp @@ -54,7 +54,7 @@ void ReturnUndefChecker::checkPreStmt(const ReturnStmt *RS, new BugReport(*BT, BT->getDescription(), N); report->addRange(RetE->getSourceRange()); - report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, RetE); + report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, RetE)); C.EmitReport(report); } diff --git a/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp index f29cac6028..de20e89dff 100644 --- a/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp @@ -99,8 +99,8 @@ void UndefBranchChecker::checkBranchCondition(const Stmt *Condition, Ex = FindIt.FindExpr(Ex); // Emit the bug report. - BugReport *R = new BugReport(*BT, BT->getDescription(),N); - R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex); + BugReport *R = new BugReport(*BT, BT->getDescription(), N); + R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Ex)); R->addRange(Ex->getSourceRange()); Eng.getBugReporter().EmitReport(R); diff --git a/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp index 486ddbb135..2aebed9346 100644 --- a/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp @@ -74,8 +74,9 @@ UndefCapturedBlockVarChecker::checkPostStmt(const BlockExpr *BE, // Get the VarRegion associated with VD in the local stack frame. const LocationContext *LC = C.getPredecessor()->getLocationContext(); VR = C.getSValBuilder().getRegionManager().getVarRegion(VD, LC); + SVal VRVal = state->getSVal(VR); - if (state->getSVal(VR).isUndef()) + if (VRVal.isUndef()) if (ExplodedNode *N = C.generateSink()) { if (!BT) BT.reset(new BuiltinBug("uninitialized variable captured by block")); @@ -90,7 +91,7 @@ UndefCapturedBlockVarChecker::checkPostStmt(const BlockExpr *BE, BugReport *R = new BugReport(*BT, os.str(), N); if (const Expr *Ex = FindBlockDeclRefExpr(BE->getBody(), VD)) R->addRange(Ex->getSourceRange()); - R->addVisitorCreator(bugreporter::registerFindLastStore, VR); + R->addVisitor(new FindLastStoreBRVisitor(VRVal, VR)); // need location of block C.EmitReport(R); } diff --git a/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp index 1074688562..7ae966865c 100644 --- a/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp @@ -74,10 +74,10 @@ void UndefResultChecker::checkPostStmt(const BinaryOperator *B, BugReport *report = new BugReport(*BT, OS.str(), N); if (Ex) { report->addRange(Ex->getSourceRange()); - report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex); + report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Ex)); } else - report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, B); + report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, B)); C.EmitReport(report); } } diff --git a/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp index 92e656109f..bb6831b783 100644 --- a/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp @@ -42,8 +42,8 @@ UndefinedArraySubscriptChecker::checkPreStmt(const ArraySubscriptExpr *A, // Generate a report for this bug. BugReport *R = new BugReport(*BT, BT->getName(), N); R->addRange(A->getIdx()->getSourceRange()); - R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, - A->getIdx()); + R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, + A->getIdx())); C.EmitReport(R); } } diff --git a/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp index 6f937c6816..b0c4bee424 100644 --- a/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp @@ -77,7 +77,7 @@ void UndefinedAssignmentChecker::checkBind(SVal location, SVal val, BugReport *R = new BugReport(*BT, str, N); if (ex) { R->addRange(ex->getSourceRange()); - R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, ex); + R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, ex)); } C.EmitReport(R); } diff --git a/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp index f6931fc09f..336df59bd8 100644 --- a/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp @@ -206,8 +206,8 @@ void UnixAPIChecker::CheckMallocZero(CheckerContext &C, new BugReport(*BT_mallocZero, "Call to 'malloc' has an allocation" " size of 0 bytes", N); report->addRange(CE->getArg(0)->getSourceRange()); - report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, - CE->getArg(0)); + report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, + CE->getArg(0))); C.EmitReport(report); return; } diff --git a/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp b/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp index 61590b296a..b34b97c5b3 100644 --- a/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp @@ -65,7 +65,7 @@ void VLASizeChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const { BugReport *report = new BugReport(*BT_undef, BT_undef->getName(), N); report->addRange(SE->getSourceRange()); - report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE); + report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, SE)); C.EmitReport(report); return; } @@ -90,7 +90,7 @@ void VLASizeChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const { BugReport *report = new BugReport(*BT_zero, BT_zero->getName(), N); report->addRange(SE->getSourceRange()); - report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE); + report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, SE)); C.EmitReport(report); return; } diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index 6821806c84..fb0331c274 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -1672,8 +1672,8 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD, return; // Register additional node visitors. - bugreporter::registerNilReceiverVisitor(*R); - bugreporter::registerConditionVisitor(*R); + R->addVisitor(new NilReceiverBRVisitor()); + R->addVisitor(new ConditionBRVisitor()); switch (PDB.getGenerationScheme()) { case PathDiagnosticClient::Extensive: diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index b6e726fd0b..9fbccf8f81 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -11,6 +11,7 @@ // enhance the diagnostics reported for a bug. // //===----------------------------------------------------------------------===// +#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprObjC.h" @@ -71,249 +72,213 @@ const Stmt *bugreporter::GetRetValExpr(const ExplodedNode *N) { //===----------------------------------------------------------------------===// // Definitions for bug reporter visitors. //===----------------------------------------------------------------------===// +void FindLastStoreBRVisitor ::Profile(llvm::FoldingSetNodeID &ID) const { + static int tag = 0; + ID.AddPointer(&tag); + ID.AddPointer(R); + ID.Add(V); +} -namespace { -class FindLastStoreBRVisitor : public BugReporterVisitor { - const MemRegion *R; - SVal V; - bool satisfied; - const ExplodedNode *StoreSite; -public: - FindLastStoreBRVisitor(SVal v, const MemRegion *r) - : R(r), V(v), satisfied(false), StoreSite(0) {} - - virtual void Profile(llvm::FoldingSetNodeID &ID) const { - static int tag = 0; - ID.AddPointer(&tag); - ID.AddPointer(R); - ID.Add(V); - } - - PathDiagnosticPiece *VisitNode(const ExplodedNode *N, - const ExplodedNode *PrevN, - BugReporterContext &BRC, - BugReport &BR) { - - if (satisfied) - return NULL; - - if (!StoreSite) { - const ExplodedNode *Node = N, *Last = NULL; +PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *N, + const ExplodedNode *PrevN, + BugReporterContext &BRC, + BugReport &BR) { - for ( ; Node ; Last = Node, Node = Node->getFirstPred()) { + if (satisfied) + return NULL; - if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { - if (const PostStmt *P = Node->getLocationAs<PostStmt>()) - if (const DeclStmt *DS = P->getStmtAs<DeclStmt>()) - if (DS->getSingleDecl() == VR->getDecl()) { - Last = Node; - break; - } - } + if (!StoreSite) { + const ExplodedNode *Node = N, *Last = NULL; - if (Node->getState()->getSVal(R) != V) - break; - } + for ( ; Node ; Last = Node, Node = Node->getFirstPred()) { - if (!Node || !Last) { - satisfied = true; - return NULL; + if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { + if (const PostStmt *P = Node->getLocationAs<PostStmt>()) + if (const DeclStmt *DS = P->getStmtAs<DeclStmt>()) + if (DS->getSingleDecl() == VR->getDecl()) { + Last = Node; + break; + } } - StoreSite = Last; + if (Node->getState()->getSVal(R) != V) + break; } - if (StoreSite != N) + if (!Node || !Last) { + satisfied = true; return NULL; + } - satisfied = true; - llvm::SmallString<256> sbuf; - llvm::raw_svector_ostream os(sbuf); + StoreSite = Last; + } - if (const PostStmt *PS = N->getLocationAs<PostStmt>()) { - if (const DeclStmt *DS = PS->getStmtAs<DeclStmt>()) { + if (StoreSite != N) + return NULL; - if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { - os << "Variable '" << VR->getDecl() << "' "; - } - else - return NULL; - - if (isa<loc::ConcreteInt>(V)) { - bool b = false; - if (R->isBoundable()) { - if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { - if (TR->getValueType()->isObjCObjectPointerType()) { - os << "initialized to nil"; - b = true; - } - } - } + satisfied = true; + llvm::SmallString<256> sbuf; + llvm::raw_svector_ostream os(sbuf); - if (!b) - os << "initialized to a null pointer value"; - } - else if (isa<nonloc::ConcreteInt>(V)) { - os << "initialized to " << cast<nonloc::ConcreteInt>(V).getValue(); - } - else if (V.isUndef()) { - if (isa<VarRegion>(R)) { - const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl()); - if (VD->getInit()) - os << "initialized to a garbage value"; - else - os << "declared without an initial value"; - } - } + if (const PostStmt *PS = N->getLocationAs<PostStmt>()) { + if (const DeclStmt *DS = PS->getStmtAs<DeclStmt>()) { + + if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { + os << "Variable '" << VR->getDecl() << "' "; } - } + else + return NULL; - if (os.str().empty()) { if (isa<loc::ConcreteInt>(V)) { bool b = false; if (R->isBoundable()) { if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { if (TR->getValueType()->isObjCObjectPointerType()) { - os << "nil object reference stored to "; + os << "initialized to nil"; b = true; } } } if (!b) - os << "Null pointer value stored to "; - } - else if (V.isUndef()) { - os << "Uninitialized value stored to "; + os << "initialized to a null pointer value"; } else if (isa<nonloc::ConcreteInt>(V)) { - os << "The value " << cast<nonloc::ConcreteInt>(V).getValue() - << " is assigned to "; + os << "initialized to " << cast<nonloc::ConcreteInt>(V).getValue(); } - else - return NULL; - - if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { - os << '\'' << VR->getDecl() << '\''; + else if (V.isUndef()) { + if (isa<VarRegion>(R)) { + const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl()); + if (VD->getInit()) + os << "initialized to a garbage value"; + else + os << "declared without an initial value"; + } } - else - return NULL; } + } - // FIXME: Refactor this into BugReporterContext. - const Stmt *S = 0; - ProgramPoint P = N->getLocation(); + if (os.str().empty()) { + if (isa<loc::ConcreteInt>(V)) { + bool b = false; + if (R->isBoundable()) { + if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { + if (TR->getValueType()->isObjCObjectPointerType()) { + os << "nil object reference stored to "; + b = true; + } + } + } - if (BlockEdge *BE = dyn_cast<BlockEdge>(&P)) { - const CFGBlock *BSrc = BE->getSrc(); - S = BSrc->getTerminatorCondition(); + if (!b) + os << "Null pointer value stored to "; } - else if (PostStmt *PS = dyn_cast<PostStmt>(&P)) { - S = PS->getStmt(); + else if (V.isUndef()) { + os << "Uninitialized value stored to "; } - - if (!S) + else if (isa<nonloc::ConcreteInt>(V)) { + os << "The value " << cast<nonloc::ConcreteInt>(V).getValue() + << " is assigned to "; + } + else return NULL; - // Construct a new PathDiagnosticPiece. - PathDiagnosticLocation L(S, BRC.getSourceManager()); - return new PathDiagnosticEventPiece(L, os.str()); + if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { + os << '\'' << VR->getDecl() << '\''; + } + else + return NULL; } -}; + // FIXME: Refactor this into BugReporterContext. + const Stmt *S = 0; + ProgramPoint P = N->getLocation(); -static void registerFindLastStore(BugReport &BR, const MemRegion *R, - SVal V) { - BR.addVisitor(new FindLastStoreBRVisitor(V, R)); -} - -class TrackConstraintBRVisitor : public BugReporterVisitor { - DefinedSVal Constraint; - const bool Assumption; - bool isSatisfied; -public: - TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption) - : Constraint(constraint), Assumption(assumption), isSatisfied(false) {} - - void Profile(llvm::FoldingSetNodeID &ID) const { - static int tag = 0; - ID.AddPointer(&tag); - ID.AddBoolean(Assumption); - ID.Add(Constraint); + if (BlockEdge *BE = dyn_cast<BlockEdge>(&P)) { + const CFGBlock *BSrc = BE->getSrc(); + S = BSrc->getTerminatorCondition(); + } + else if (PostStmt *PS = dyn_cast<PostStmt>(&P)) { + S = PS->getStmt(); } - PathDiagnosticPiece *VisitNode(const ExplodedNode *N, - const ExplodedNode *PrevN, - BugReporterContext &BRC, - BugReport &BR) { - if (isSatisfied) - return NULL; + if (!S) + return NULL; - // Check if in the previous state it was feasible for this constraint - // to *not* be true. - if (PrevN->getState()->assume(Constraint, !Assumption)) { + // Construct a new PathDiagnosticPiece. + PathDiagnosticLocation L(S, BRC.getSourceManager()); + return new PathDiagnosticEventPiece(L, os.str()); +} - isSatisfied = true; +void TrackConstraintBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const { + static int tag = 0; + ID.AddPointer(&tag); + ID.AddBoolean(Assumption); + ID.Add(Constraint); +} - // As a sanity check, make sure that the negation of the constraint - // was infeasible in the current state. If it is feasible, we somehow - // missed the transition point. - if (N->getState()->assume(Constraint, !Assumption)) - return NULL; +PathDiagnosticPiece * +TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N, + const ExplodedNode *PrevN, + BugReporterContext &BRC, + BugReport &BR) { + if (isSatisfied) + return NULL; - // We found the transition point for the constraint. We now need to - // pretty-print the constraint. (work-in-progress) - std::string sbuf; - llvm::raw_string_ostream os(sbuf); + // Check if in the previous state it was feasible for this constraint + // to *not* be true. + if (PrevN->getState()->assume(Constraint, !Assumption)) { - if (isa<Loc>(Constraint)) { - os << "Assuming pointer value is "; - os << (Assumption ? "non-null" : "null"); - } + isSatisfied = true; - if (os.str().empty()) - return NULL; + // As a sanity check, make sure that the negation of the constraint + // was infeasible in the current state. If it is feasible, we somehow + // missed the transition point. + if (N->getState()->assume(Constraint, !Assumption)) + return NULL; - // FIXME: Refactor this into BugReporterContext. - const Stmt *S = 0; - ProgramPoint P = N->getLocation(); + // We found the transition point for the constraint. We now need to + // pretty-print the constraint. (work-in-progress) + std::string sbuf; + llvm::raw_string_ostream os(sbuf); - if (BlockEdge *BE = dyn_cast<BlockEdge>(&P)) { - const CFGBlock *BSrc = BE->getSrc(); - S = BSrc->getTerminatorCondition(); - } - else if (PostStmt *PS = dyn_cast<PostStmt>(&P)) { - S = PS->getStmt(); - } + if (isa<Loc>(Constraint)) { + os << "Assuming pointer value is "; + os << (Assumption ? "non-null" : "null"); + } - if (!S) - return NULL; + if (os.str().empty()) + return NULL; + + // FIXME: Refactor this into BugReporterContext. + const Stmt *S = 0; + ProgramPoint P = N->getLocation(); - // Construct a new PathDiagnosticPiece. - PathDiagnosticLocation L(S, BRC.getSourceManager()); - return new PathDiagnosticEventPiece(L, os.str()); + if (BlockEdge *BE = dyn_cast<BlockEdge>(&P)) { + const CFGBlock *BSrc = BE->getSrc(); + |