aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/BugReporter.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2009-05-01 16:08:09 +0000
committerTed Kremenek <kremenek@apple.com>2009-05-01 16:08:09 +0000
commit8f9b1b3865cd5814a8c4c768a34d56df6d6c93be (patch)
treed8b090a72e4477569615c4752a5fc04d01f1995f /lib/Analysis/BugReporter.cpp
parent180bb63b482381c5ffcdb2c4eca5c28c0b1f22af (diff)
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
Diffstat (limited to 'lib/Analysis/BugReporter.cpp')
-rw-r--r--lib/Analysis/BugReporter.cpp51
1 files changed, 41 insertions, 10 deletions
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<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());
}