summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2012-02-24 00:38:56 +0000
committerTed Kremenek <kremenek@apple.com>2012-02-24 00:38:56 +0000
commitf2131e7d953ce9cd751a05073c0d46ab1db87419 (patch)
tree82d5929eadf537451962e03d9b795f7c56e40fa1 /clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
parenteee9bca03de4602cd8e899c708f0c8dc677e8bba (diff)
downloadbcm5719-llvm-f2131e7d953ce9cd751a05073c0d46ab1db87419.tar.gz
bcm5719-llvm-f2131e7d953ce9cd751a05073c0d46ab1db87419.zip
Rework PathDiagnostic creation so that call stacks are captured by a nested PathDiagnosticCallPiece.
llvm-svn: 151317
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp80
1 files changed, 76 insertions, 4 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
index bc03a2bc30e..9a128ff8e2a 100644
--- a/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ b/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
@@ -51,11 +51,10 @@ PathDiagnosticPiece::PathDiagnosticPiece(Kind k, DisplayHint hint)
PathDiagnosticPiece::~PathDiagnosticPiece() {}
PathDiagnosticEventPiece::~PathDiagnosticEventPiece() {}
-PathDiagnosticCallEnterPiece::~PathDiagnosticCallEnterPiece() {}
-PathDiagnosticCallExitPiece::~PathDiagnosticCallExitPiece() {}
+PathDiagnosticCallPiece::~PathDiagnosticCallPiece() {}
PathDiagnosticControlFlowPiece::~PathDiagnosticControlFlowPiece() {}
PathDiagnosticMacroPiece::~PathDiagnosticMacroPiece() {}
-PathDiagnostic::PathDiagnostic() {}
+PathDiagnostic::PathDiagnostic() : path(pathImpl) {}
PathPieces::~PathPieces() {}
PathDiagnostic::~PathDiagnostic() {}
@@ -63,7 +62,8 @@ PathDiagnostic::PathDiagnostic(StringRef bugtype, StringRef desc,
StringRef category)
: BugType(StripTrailingDots(bugtype)),
Desc(StripTrailingDots(desc)),
- Category(StripTrailingDots(category)) {}
+ Category(StripTrailingDots(category)),
+ path(pathImpl) {}
void PathDiagnosticConsumer::anchor() { }
@@ -421,6 +421,78 @@ void PathDiagnosticLocation::flatten() {
}
}
+
+//===----------------------------------------------------------------------===//
+// Manipulation of PathDiagnosticCallPieces.
+//===----------------------------------------------------------------------===//
+
+static PathDiagnosticLocation getLastStmtLoc(const ExplodedNode *N,
+ const SourceManager &SM) {
+ while (N) {
+ ProgramPoint PP = N->getLocation();
+ if (const StmtPoint *SP = dyn_cast<StmtPoint>(&PP))
+ return PathDiagnosticLocation(SP->getStmt(), SM, PP.getLocationContext());
+ if (N->pred_empty())
+ break;
+ N = *N->pred_begin();
+ }
+ return PathDiagnosticLocation();
+}
+
+PathDiagnosticCallPiece *
+PathDiagnosticCallPiece::construct(const ExplodedNode *N,
+ const CallExit &CE,
+ const SourceManager &SM) {
+ const Decl *caller = CE.getLocationContext()->getParent()->getDecl();
+ PathDiagnosticLocation pos = getLastStmtLoc(N, SM);
+ return new PathDiagnosticCallPiece(caller, pos);
+}
+
+PathDiagnosticCallPiece *
+PathDiagnosticCallPiece::construct(PathPieces &path) {
+ PathDiagnosticCallPiece *C = new PathDiagnosticCallPiece(path);
+ path.clear();
+ path.push_front(C);
+ return C;
+}
+
+void PathDiagnosticCallPiece::setCallee(const CallEnter &CE,
+ const SourceManager &SM) {
+ const Decl *D = CE.getCalleeContext()->getDecl();
+ Caller = D;
+ callEnter = PathDiagnosticLocation(CE.getCallExpr(), SM,
+ CE.getLocationContext());
+}
+
+IntrusiveRefCntPtr<PathDiagnosticEventPiece>
+PathDiagnosticCallPiece::getCallEnterEvent() const {
+ if (!Callee)
+ return 0;
+ SmallString<256> buf;
+ llvm::raw_svector_ostream Out(buf);
+ if (isa<BlockDecl>(Callee))
+ Out << "Entering call to block";
+ else if (const NamedDecl *ND = dyn_cast<NamedDecl>(Callee))
+ Out << "Entering call to '" << *ND << "'";
+ StringRef msg = Out.str();
+ if (msg.empty())
+ return 0;
+ return new PathDiagnosticEventPiece(callEnter, msg);
+}
+
+IntrusiveRefCntPtr<PathDiagnosticEventPiece>
+PathDiagnosticCallPiece::getCallExitEvent() const {
+ if (!Caller)
+ return 0;
+ SmallString<256> buf;
+ llvm::raw_svector_ostream Out(buf);
+ if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Caller))
+ Out << "Returning to '" << *ND << "'";
+ else
+ Out << "Returning to caller";
+ return new PathDiagnosticEventPiece(callReturn, Out.str());
+}
+
//===----------------------------------------------------------------------===//
// FoldingSet profiling methods.
//===----------------------------------------------------------------------===//
OpenPOWER on IntegriCloud