From: Ted Kremenek Date: Thu, 17 Apr 2008 23:44:37 +0000 (+0000) Subject: Modified BugReport::getEndPath() to handle the case where end path is at X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bd7efa8ca27ed9676acf00abf31d5e1cd54651cc;p=clang Modified BugReport::getEndPath() to handle the case where end path is at the exit block of the CFG. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49880 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Analysis/PathSensitive/BugReporter.h b/include/clang/Analysis/PathSensitive/BugReporter.h index 792b2e2d9e..2312583589 100644 --- a/include/clang/Analysis/PathSensitive/BugReporter.h +++ b/include/clang/Analysis/PathSensitive/BugReporter.h @@ -63,7 +63,8 @@ public: return getBugType().getDescription(); } - virtual PathDiagnosticPiece* getEndPath(ASTContext& Ctx) const; + virtual PathDiagnosticPiece* getEndPath(BugReporter& BR, + ExplodedNode* N) const; virtual FullSourceLoc getLocation(SourceManager& Mgr); @@ -124,6 +125,8 @@ public: GRExprEngine& getEngine() { return Eng; } + CFG& getCFG() { return getGraph().getCFG(); } + void EmitPathWarning(BugReport& R); void EmitWarning(BugReport& R); diff --git a/lib/Analysis/BugReporter.cpp b/lib/Analysis/BugReporter.cpp index 7572a55679..d1689e2e51 100644 --- a/lib/Analysis/BugReporter.cpp +++ b/lib/Analysis/BugReporter.cpp @@ -55,15 +55,44 @@ static inline Stmt* GetStmt(const CFGBlock* B) { Stmt* BugReport::getStmt() const { return N ? GetStmt(N->getLocation()) : NULL; } + +static inline ExplodedNode* +GetNextNode(ExplodedNode* N) { + return N->pred_empty() ? NULL : *(N->pred_begin()); +} -PathDiagnosticPiece* BugReport::getEndPath(ASTContext& Ctx) const { - Stmt* S = getStmt(); +static Stmt* GetLastStmt(ExplodedNode* N) { + assert (isa(N->getLocation())); + + for (N = GetNextNode(N); N; N = GetNextNode(N)) { + + ProgramPoint P = N->getLocation(); + + if (PostStmt* PS = dyn_cast(&P)) + return PS->getStmt(); + } + + return NULL; +} + +PathDiagnosticPiece* +BugReport::getEndPath(BugReporter& BR, + ExplodedNode* EndPathNode) const { + + ProgramPoint ProgP = EndPathNode->getLocation(); + Stmt *S = NULL; + + if (BlockEntrance* BE = dyn_cast(&ProgP)) + if (BE->getBlock() == &BR.getCFG().getExit()) + S = GetLastStmt(EndPathNode); + if (!S) + S = GetStmt(ProgP); if (!S) return NULL; - FullSourceLoc L(S->getLocStart(), Ctx.getSourceManager()); + FullSourceLoc L(S->getLocStart(), BR.getContext().getSourceManager()); PathDiagnosticPiece* P = new PathDiagnosticPiece(L, getDescription()); @@ -113,26 +142,18 @@ PathDiagnosticPiece* BugReport::VisitNode(ExplodedNode* N, void BugReporter::GeneratePathDiagnostic(PathDiagnostic& PD, BugReport& R) { - ExplodedNode* N = R.getEndNode(); - + ExplodedNode* N = R.getEndNode(); assert (N && "Path diagnostic requires a ExplodedNode."); - if (PathDiagnosticPiece* Piece = R.getEndPath(Ctx)) - PD.push_back(Piece); - else - return; - - SourceManager& SMgr = Ctx.getSourceManager(); - llvm::OwningPtr > GTrim(getGraph().Trim(&N, &N+1)); - + // Find the sink in the trimmed graph. // FIXME: Should we eventually have a sink iterator? ExplodedNode* NewN = 0; for (ExplodedGraph::node_iterator - I = GTrim->nodes_begin(), E = GTrim->nodes_end(); I != E; ++I) { + I = GTrim->nodes_begin(), E = GTrim->nodes_end(); I != E; ++I) { if (I->isSink()) { NewN = &*I; @@ -144,15 +165,22 @@ void BugReporter::GeneratePathDiagnostic(PathDiagnostic& PD, assert (NewN->getLocation() == N->getLocation()); N = NewN; + + if (PathDiagnosticPiece* Piece = R.getEndPath(*this, N)) + PD.push_back(Piece); + else + return; ExplodedNode* NextNode = N->pred_empty() ? NULL : *(N->pred_begin()); + SourceManager& SMgr = Ctx.getSourceManager(); + while (NextNode) { ExplodedNode* LastNode = N; N = NextNode; - NextNode = N->pred_empty() ? NULL : *(N->pred_begin()); + NextNode = GetNextNode(N); ProgramPoint P = N->getLocation();