aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/StaticAnalyzer/Checkers/MallocChecker.cpp15
-rw-r--r--lib/StaticAnalyzer/Core/BugReporter.cpp39
-rw-r--r--lib/StaticAnalyzer/Core/PathDiagnostic.cpp2
3 files changed, 51 insertions, 5 deletions
diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index 3f0d3d456e..e071626eb6 100644
--- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -1249,6 +1249,7 @@ MallocChecker::MallocBugVisitor::VisitNode(const ExplodedNode *N,
const Stmt *S = 0;
const char *Msg = 0;
+ const char *StackMsg = 0;
// Retrieve the associated statement.
ProgramPoint ProgLoc = N->getLocation();
@@ -1264,14 +1265,18 @@ MallocChecker::MallocBugVisitor::VisitNode(const ExplodedNode *N,
return 0;
// Find out if this is an interesting point and what is the kind.
+ // TODO: Replace 'callee' by the function name.
if (Mode == Normal) {
- if (isAllocated(RS, RSPrev, S))
+ if (isAllocated(RS, RSPrev, S)) {
Msg = "Memory is allocated";
- else if (isReleased(RS, RSPrev, S))
+ StackMsg = ", which allocated memory";
+ } else if (isReleased(RS, RSPrev, S)) {
Msg = "Memory is released";
- else if (isReallocFailedCheck(RS, RSPrev, S)) {
+ StackMsg = ", which released memory";
+ } else if (isReallocFailedCheck(RS, RSPrev, S)) {
Mode = ReallocationFailed;
Msg = "Reallocation failed";
+ StackMsg = ", where reallocation failed";
}
// We are in a special mode if a reallocation failed later in the path.
@@ -1291,16 +1296,18 @@ MallocChecker::MallocBugVisitor::VisitNode(const ExplodedNode *N,
if (!(FunName.equals("realloc") || FunName.equals("reallocf")))
return 0;
Msg = "Attempt to reallocate memory";
+ StackMsg = ", which attempted to reallocate memory";
Mode = Normal;
}
if (!Msg)
return 0;
+ assert(StackMsg);
// Generate the extra diagnostic.
PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
N->getLocationContext());
- return new PathDiagnosticEventPiece(Pos, Msg);
+ return new PathDiagnosticEventPiece(Pos, Msg, true, StackMsg);
}
diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp
index 995ef264eb..0a0c1fdb51 100644
--- a/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -380,6 +380,24 @@ PathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) {
//===----------------------------------------------------------------------===//
// "Minimal" path diagnostic generation algorithm.
//===----------------------------------------------------------------------===//
+static void updateStackPiecesWithMessage(PathDiagnosticPiece *P,
+ llvm::SmallVector<PathDiagnosticCallPiece*, 6> &CallStack) {
+ // If the piece contains a special message, add it to all the call
+ // pieces on the active stack.
+ if (PathDiagnosticEventPiece *ep =
+ dyn_cast<PathDiagnosticEventPiece>(P)) {
+ StringRef stackMsg = ep->getCallStackMessage();
+
+ if (!stackMsg.empty())
+ for (llvm::SmallVector<PathDiagnosticCallPiece*, 6>::iterator
+ I = CallStack.begin(), E = CallStack.end(); I != E; ++I)
+ // The last message on the path to final bug is the most important
+ // one. Since we traverse the path backwards, do not add the message
+ // if one has been previously added.
+ if (!(*I)->hasCallStackMessage())
+ (*I)->setCallStackMessage(stackMsg);
+ }
+}
static void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM);
@@ -391,6 +409,9 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
const LocationContext *LC = PDB.LC;
const ExplodedNode *NextNode = N->pred_empty()
? NULL : *(N->pred_begin());
+
+ llvm::SmallVector<PathDiagnosticCallPiece*, 6> CallStack;
+
while (NextNode) {
N = NextNode;
PDB.LC = N->getLocationContext();
@@ -403,6 +424,7 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
PathDiagnosticCallPiece::construct(N, *CE, SMgr);
PD.getActivePath().push_front(C);
PD.pushActivePath(&C->path);
+ CallStack.push_back(C);
continue;
}
@@ -423,6 +445,10 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller);
}
C->setCallee(*CE, SMgr);
+ if (!CallStack.empty()) {
+ assert(CallStack.back() == C);
+ CallStack.pop_back();
+ }
continue;
}
@@ -681,8 +707,10 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
BugReport *R = PDB.getBugReport();
for (BugReport::visitor_iterator I = R->visitor_begin(),
E = R->visitor_end(); I!=E; ++I) {
- if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R))
+ if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) {
PD.getActivePath().push_front(p);
+ updateStackPiecesWithMessage(p, CallStack);
+ }
}
}
}
@@ -1019,6 +1047,7 @@ static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
const ExplodedNode *N) {
EdgeBuilder EB(PD, PDB);
const SourceManager& SM = PDB.getSourceManager();
+ llvm::SmallVector<PathDiagnosticCallPiece*, 6> CallStack;
const ExplodedNode *NextNode = N->pred_empty() ? NULL : *(N->pred_begin());
while (NextNode) {
@@ -1039,6 +1068,7 @@ static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
PathDiagnosticCallPiece::construct(N, *CE, SM);
PD.getActivePath().push_front(C);
PD.pushActivePath(&C->path);
+ CallStack.push_back(C);
break;
}
@@ -1072,6 +1102,11 @@ static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
}
C->setCallee(*CE, SM);
EB.addContext(CE->getCallExpr());
+
+ if (!CallStack.empty()) {
+ assert(CallStack.back() == C);
+ CallStack.pop_back();
+ }
break;
}
@@ -1147,6 +1182,8 @@ static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
const PathDiagnosticLocation &Loc = p->getLocation();
EB.addEdge(Loc, true);
PD.getActivePath().push_front(p);
+ updateStackPiecesWithMessage(p, CallStack);
+
if (const Stmt *S = Loc.asStmt())
EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt());
}
diff --git a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
index ef815be0db..cd08f9ceb7 100644
--- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
@@ -572,6 +572,8 @@ PathDiagnosticCallPiece::getCallExitEvent() const {
Out << "Returning from '" << *ND << "'";
else
Out << "Returning to caller";
+ if (!CallStackMessage.empty())
+ Out << CallStackMessage;
return new PathDiagnosticEventPiece(callReturn, Out.str());
}