aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2013-01-18 18:27:14 +0000
committerJordan Rose <jordan_rose@apple.com>2013-01-18 18:27:14 +0000
commitdc47c9a71c99ce2e5b9d84f1cd3487b6852b3543 (patch)
tree410746fd6f334ae6facba9c7ee59f67c81410f60 /lib/StaticAnalyzer/Core/PathDiagnostic.cpp
parentba287dc2fa46af68a84d69004ffc086e3e7311f1 (diff)
[analyzer] Do a better job describing C++ member functions in the call stack.
Examples: Calling constructor for 'Foo' Entered call from 'Foo::create' git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172832 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core/PathDiagnostic.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/PathDiagnostic.cpp72
1 files changed, 51 insertions, 21 deletions
diff --git a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
index 166e04327d..30b7d64290 100644
--- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
@@ -788,51 +788,81 @@ void PathDiagnosticCallPiece::setCallee(const CallEnter &CE,
callEnter = getLocationForCaller(CalleeCtx, CE.getLocationContext(), SM);
}
+static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
+ bool ShouldDescribeBlock,
+ StringRef Prefix = StringRef()) {
+ if (!D)
+ return false;
+
+ if (isa<BlockDecl>(D)) {
+ if (ShouldDescribeBlock)
+ Out << Prefix << "anonymous block";
+ return ShouldDescribeBlock;
+ }
+
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+ if (isa<CXXConstructorDecl>(MD))
+ Out << Prefix << "constructor for '" << *MD << "'";
+ else if (isa<CXXDestructorDecl>(MD))
+ Out << Prefix << "'" << *MD << "'";
+ else if (MD->getParent()->getIdentifier())
+ Out << Prefix << "'" << *MD->getParent() << "::" << *MD << "'";
+ else
+ Out << Prefix << "'" << *MD << "'";
+
+ return true;
+ }
+
+ Out << Prefix << '\'' << cast<NamedDecl>(*D) << '\'';
+ return true;
+}
+
IntrusiveRefCntPtr<PathDiagnosticEventPiece>
PathDiagnosticCallPiece::getCallEnterEvent() const {
if (!Callee)
return 0;
+
SmallString<256> buf;
llvm::raw_svector_ostream Out(buf);
- if (isa<BlockDecl>(Callee))
- Out << "Calling anonymous block";
- else if (const NamedDecl *ND = dyn_cast<NamedDecl>(Callee))
- Out << "Calling '" << *ND << "'";
- StringRef msg = Out.str();
- if (msg.empty())
- return 0;
+
+ Out << "Calling ";
+ describeCodeDecl(Out, Callee, /*DescribeBlocks=*/true);
+
assert(callEnter.asLocation().isValid());
- return new PathDiagnosticEventPiece(callEnter, msg);
+ return new PathDiagnosticEventPiece(callEnter, Out.str());
}
IntrusiveRefCntPtr<PathDiagnosticEventPiece>
PathDiagnosticCallPiece::getCallEnterWithinCallerEvent() const {
if (!callEnterWithin.asLocation().isValid())
return 0;
+
SmallString<256> buf;
llvm::raw_svector_ostream Out(buf);
- if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Caller))
- Out << "Entered call from '" << *ND << "'";
- else
- Out << "Entered call";
- StringRef msg = Out.str();
- if (msg.empty())
- return 0;
- return new PathDiagnosticEventPiece(callEnterWithin, msg);
+
+ Out << "Entered call";
+ describeCodeDecl(Out, Caller, /*DescribeBlocks=*/false, " from ");
+
+ return new PathDiagnosticEventPiece(callEnterWithin, Out.str());
}
IntrusiveRefCntPtr<PathDiagnosticEventPiece>
PathDiagnosticCallPiece::getCallExitEvent() const {
if (NoExit)
return 0;
+
SmallString<256> buf;
llvm::raw_svector_ostream Out(buf);
- if (!CallStackMessage.empty())
+
+ if (!CallStackMessage.empty()) {
Out << CallStackMessage;
- else if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Callee))
- Out << "Returning from '" << *ND << "'";
- else
- Out << "Returning to caller";
+ } else {
+ bool DidDescribe = describeCodeDecl(Out, Callee, /*DescribeBlocks=*/false,
+ "Returning from ");
+ if (!DidDescribe)
+ Out << "Returning to caller";
+ }
+
assert(callReturn.asLocation().isValid());
return new PathDiagnosticEventPiece(callReturn, Out.str());
}