diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 15 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/BugReporter.cpp | 39 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/PathDiagnostic.cpp | 2 |
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()); } |