aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/StaticAnalyzer/Core/PathDiagnostic.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/PathDiagnostic.cpp70
1 files changed, 56 insertions, 14 deletions
diff --git a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
index 30b7d64290..a584a84eea 100644
--- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
@@ -788,27 +788,68 @@ void PathDiagnosticCallPiece::setCallee(const CallEnter &CE,
callEnter = getLocationForCaller(CalleeCtx, CE.getLocationContext(), SM);
}
+static inline void describeClass(raw_ostream &Out, const CXXRecordDecl *D,
+ StringRef Prefix = StringRef()) {
+ if (!D->getIdentifier())
+ return;
+ Out << Prefix << '\'' << *D << '\'';
+}
+
static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
- bool ShouldDescribeBlock,
+ bool ExtendedDescription,
StringRef Prefix = StringRef()) {
if (!D)
return false;
if (isa<BlockDecl>(D)) {
- if (ShouldDescribeBlock)
+ if (ExtendedDescription)
Out << Prefix << "anonymous block";
- return ShouldDescribeBlock;
+ return ExtendedDescription;
}
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 << "'";
+ Out << Prefix;
+ if (ExtendedDescription && !MD->isUserProvided()) {
+ if (MD->isExplicitlyDefaulted())
+ Out << "defaulted ";
+ else
+ Out << "implicit ";
+ }
+
+ if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(MD)) {
+ if (CD->isDefaultConstructor())
+ Out << "default ";
+ else if (CD->isCopyConstructor())
+ Out << "copy ";
+ else if (CD->isMoveConstructor())
+ Out << "move ";
+
+ Out << "constructor";
+ describeClass(Out, MD->getParent(), " for ");
+
+ } else if (isa<CXXDestructorDecl>(MD)) {
+ if (!MD->isUserProvided()) {
+ Out << "destructor";
+ describeClass(Out, MD->getParent(), " for ");
+ } else {
+ // Use ~Foo for explicitly-written destructors.
+ Out << "'" << *MD << "'";
+ }
+
+ } else if (MD->isCopyAssignmentOperator()) {
+ Out << "copy assignment operator";
+ describeClass(Out, MD->getParent(), " for ");
+
+ } else if (MD->isMoveAssignmentOperator()) {
+ Out << "move assignment operator";
+ describeClass(Out, MD->getParent(), " for ");
+
+ } else {
+ if (MD->getParent()->getIdentifier())
+ Out << "'" << *MD->getParent() << "::" << *MD << "'";
+ else
+ Out << "'" << *MD << "'";
+ }
return true;
}
@@ -826,7 +867,7 @@ PathDiagnosticCallPiece::getCallEnterEvent() const {
llvm::raw_svector_ostream Out(buf);
Out << "Calling ";
- describeCodeDecl(Out, Callee, /*DescribeBlocks=*/true);
+ describeCodeDecl(Out, Callee, /*ExtendedDescription=*/true);
assert(callEnter.asLocation().isValid());
return new PathDiagnosticEventPiece(callEnter, Out.str());
@@ -841,7 +882,7 @@ PathDiagnosticCallPiece::getCallEnterWithinCallerEvent() const {
llvm::raw_svector_ostream Out(buf);
Out << "Entered call";
- describeCodeDecl(Out, Caller, /*DescribeBlocks=*/false, " from ");
+ describeCodeDecl(Out, Caller, /*ExtendedDescription=*/false, " from ");
return new PathDiagnosticEventPiece(callEnterWithin, Out.str());
}
@@ -857,7 +898,8 @@ PathDiagnosticCallPiece::getCallExitEvent() const {
if (!CallStackMessage.empty()) {
Out << CallStackMessage;
} else {
- bool DidDescribe = describeCodeDecl(Out, Callee, /*DescribeBlocks=*/false,
+ bool DidDescribe = describeCodeDecl(Out, Callee,
+ /*ExtendedDescription=*/false,
"Returning from ");
if (!DidDescribe)
Out << "Returning to caller";