From: Ted Kremenek Date: Fri, 1 May 2009 16:08:09 +0000 (+0000) Subject: BugReporter (extensive diagnostics): introduce the notion of a "dead" X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8f9b1b3865cd5814a8c4c768a34d56df6d6c93be;p=clang 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70545 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/BugReporter.cpp b/lib/Analysis/BugReporter.cpp index 18bbe45c0e..dcc88febec 100644 --- a/lib/Analysis/BugReporter.cpp +++ b/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 CLocs; - typedef std::vector::iterator iterator; + std::vector CLocs; + typedef std::vector::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(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(&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()); }