diff options
author | Jordan Rose <jordan_rose@apple.com> | 2013-01-18 18:27:14 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2013-01-18 18:27:14 +0000 |
commit | dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543 (patch) | |
tree | 410746fd6f334ae6facba9c7ee59f67c81410f60 /lib/StaticAnalyzer/Core/PathDiagnostic.cpp | |
parent | ba287dc2fa46af68a84d69004ffc086e3e7311f1 (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.cpp | 72 |
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()); } |