diff options
author | Ted Kremenek <kremenek@apple.com> | 2009-05-01 16:08:09 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2009-05-01 16:08:09 +0000 |
commit | afbff15e640e94099ba2a13f92a14498c829d16d (patch) | |
tree | 14b40141c66e48540aff36b19365999a8efe9c8d /clang/lib/Analysis/BugReporter.cpp | |
parent | f16a8a7443c99e205e092f8c6a776fb16a9919b6 (diff) | |
download | bcm5719-llvm-afbff15e640e94099ba2a13f92a14498c829d16d.tar.gz bcm5719-llvm-afbff15e640e94099ba2a13f92a14498c829d16d.zip |
BugReporter (extensive diagnostics): introduce the notion of a "dead"
location context. This allows us to postpone the decision of whether
or not a context should add a control-flow piece to the diagnostics
when inspecting its subexpressions.
llvm-svn: 70545
Diffstat (limited to 'clang/lib/Analysis/BugReporter.cpp')
-rw-r--r-- | clang/lib/Analysis/BugReporter.cpp | 51 |
1 files changed, 41 insertions, 10 deletions
diff --git a/clang/lib/Analysis/BugReporter.cpp b/clang/lib/Analysis/BugReporter.cpp index 18bbe45c0ea..dcc88febec9 100644 --- a/clang/lib/Analysis/BugReporter.cpp +++ b/clang/lib/Analysis/BugReporter.cpp @@ -757,21 +757,33 @@ static bool IsControlFlowExpr(const Stmt *S) { } namespace { +class VISIBILITY_HIDDEN ContextLocation : public PathDiagnosticLocation { + bool IsDead; +public: + ContextLocation(const PathDiagnosticLocation &L, bool isdead = false) + : PathDiagnosticLocation(L), IsDead(isdead) {} + + void markDead() { IsDead = true; } + bool isDead() const { return IsDead; } +}; + class VISIBILITY_HIDDEN EdgeBuilder { - std::vector<PathDiagnosticLocation> CLocs; - typedef std::vector<PathDiagnosticLocation>::iterator iterator; + std::vector<ContextLocation> CLocs; + typedef std::vector<ContextLocation>::iterator iterator; PathDiagnostic &PD; PathDiagnosticBuilder &PDB; PathDiagnosticLocation PrevLoc; - + + bool IsConsumedExpr(const PathDiagnosticLocation &L); + bool containsLocation(const PathDiagnosticLocation &Container, const PathDiagnosticLocation &Containee); PathDiagnosticLocation getContextLocation(const PathDiagnosticLocation &L); void popLocation() { - PathDiagnosticLocation L = CLocs.back(); - if (L.asLocation().isFileID()) { + if (!CLocs.back().isDead() && CLocs.back().asLocation().isFileID()) { + PathDiagnosticLocation L = CLocs.back(); if (const Stmt *S = L.asStmt()) { while (1) { @@ -938,20 +950,30 @@ void EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd) { const PathDiagnosticLocation &CLoc = getContextLocation(NewLoc); while (!CLocs.empty()) { - const PathDiagnosticLocation &TopContextLoc = CLocs.back(); + ContextLocation &TopContextLoc = CLocs.back(); // Is the top location context the same as the one for the new location? if (TopContextLoc == CLoc) { - if (alwaysAdd) + if (alwaysAdd) { + if (IsConsumedExpr(TopContextLoc)) + TopContextLoc.markDead(); + rawAddEdge(NewLoc); + } return; } if (containsLocation(TopContextLoc, CLoc)) { - if (alwaysAdd) + if (alwaysAdd) { rawAddEdge(NewLoc); - + + if (IsConsumedExpr(CLoc)) { + CLocs.push_back(ContextLocation(CLoc, true)); + return; + } + } + CLocs.push_back(CLoc); return; } @@ -964,6 +986,13 @@ void EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd) { rawAddEdge(NewLoc); } +bool EdgeBuilder::IsConsumedExpr(const PathDiagnosticLocation &L) { + if (const Expr *X = dyn_cast_or_null<Expr>(L.asStmt())) + return PDB.getParentMap().isConsumedExpr(X) && !IsControlFlowExpr(X); + + return false; +} + void EdgeBuilder::addContext(const Stmt *S) { if (!S) return; @@ -1040,8 +1069,10 @@ static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD, if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) { if (const Stmt* S = BE->getFirstStmt()) { - if (IsControlFlowExpr(S)) + if (IsControlFlowExpr(S)) { + // Add the proper context for '&&', '||', and '?'. EB.addContext(S); + } else EB.addContext(PDB.getEnclosingStmtLocation(S).asStmt()); } |