From fc36b586fb07904dc9f0e311c9630a0d1c768e45 Mon Sep 17 00:00:00 2001 From: Artem Dergachev Date: Fri, 7 Oct 2016 10:44:09 +0000 Subject: [analyzer] Try to re-apply r283092 "Extend bug reports with extra notes" Replace SmallVector with a vector of plain pointers. Would insignificantly increase memory usage. llvm-svn: 283536 --- clang/lib/StaticAnalyzer/Core/BugReporter.cpp | 79 +++++++++++++++++++++------ 1 file changed, 61 insertions(+), 18 deletions(-) (limited to 'clang/lib/StaticAnalyzer/Core/BugReporter.cpp') diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp index 1800eff76bd..9bc7470c61d 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -114,15 +114,15 @@ static void removeRedundantMsgs(PathPieces &path) { path.pop_front(); switch (piece->getKind()) { - case clang::ento::PathDiagnosticPiece::Call: + case PathDiagnosticPiece::Call: removeRedundantMsgs(cast(piece)->path); break; - case clang::ento::PathDiagnosticPiece::Macro: + case PathDiagnosticPiece::Macro: removeRedundantMsgs(cast(piece)->subPieces); break; - case clang::ento::PathDiagnosticPiece::ControlFlow: + case PathDiagnosticPiece::ControlFlow: break; - case clang::ento::PathDiagnosticPiece::Event: { + case PathDiagnosticPiece::Event: { if (i == N-1) break; @@ -142,6 +142,8 @@ static void removeRedundantMsgs(PathPieces &path) { } break; } + case PathDiagnosticPiece::Note: + break; } path.push_back(piece); } @@ -199,6 +201,9 @@ static bool removeUnneededCalls(PathPieces &pieces, BugReport *R, } case PathDiagnosticPiece::ControlFlow: break; + + case PathDiagnosticPiece::Note: + break; } pieces.push_back(piece); @@ -2554,6 +2559,12 @@ BugReport::~BugReport() { while (!interestingSymbols.empty()) { popInterestingSymbolsAndRegions(); } + + // FIXME: Replace Notes with a list of shared pointers. + for (const auto *P: Notes) { + delete P; + } + Notes.clear(); } const Decl *BugReport::getDeclWithIssue() const { @@ -3405,25 +3416,28 @@ void BugReporter::FlushReport(BugReport *exampleReport, exampleReport->getUniqueingLocation(), exampleReport->getUniqueingDecl())); - MaxBugClassSize = std::max(bugReports.size(), - static_cast(MaxBugClassSize)); + if (exampleReport->isPathSensitive()) { + // Generate the full path diagnostic, using the generation scheme + // specified by the PathDiagnosticConsumer. Note that we have to generate + // path diagnostics even for consumers which do not support paths, because + // the BugReporterVisitors may mark this bug as a false positive. + assert(!bugReports.empty()); + + MaxBugClassSize = + std::max(bugReports.size(), static_cast(MaxBugClassSize)); - // Generate the full path diagnostic, using the generation scheme - // specified by the PathDiagnosticConsumer. Note that we have to generate - // path diagnostics even for consumers which do not support paths, because - // the BugReporterVisitors may mark this bug as a false positive. - if (!bugReports.empty()) if (!generatePathDiagnostic(*D.get(), PD, bugReports)) return; - MaxValidBugClassSize = std::max(bugReports.size(), - static_cast(MaxValidBugClassSize)); + MaxValidBugClassSize = + std::max(bugReports.size(), static_cast(MaxValidBugClassSize)); - // Examine the report and see if the last piece is in a header. Reset the - // report location to the last piece in the main source file. - AnalyzerOptions& Opts = getAnalyzerOptions(); - if (Opts.shouldReportIssuesInMainSourceFile() && !Opts.AnalyzeAll) - D->resetDiagnosticLocationToMainFile(); + // Examine the report and see if the last piece is in a header. Reset the + // report location to the last piece in the main source file. + AnalyzerOptions &Opts = getAnalyzerOptions(); + if (Opts.shouldReportIssuesInMainSourceFile() && !Opts.AnalyzeAll) + D->resetDiagnosticLocationToMainFile(); + } // If the path is empty, generate a single step path with the location // of the issue. @@ -3436,6 +3450,28 @@ void BugReporter::FlushReport(BugReport *exampleReport, D->setEndOfPath(std::move(piece)); } + PathPieces &Pieces = D->getMutablePieces(); + bool ShouldConvert = getAnalyzerOptions().shouldDisplayNotesAsEvents(); + // For path diagnostic consumers that don't support extra notes, + // we may optionally convert those to path notes. + for (auto I = exampleReport->getNotes().rbegin(), + E = exampleReport->getNotes().rend(); I != E; ++I) { + const PathDiagnosticNotePiece *Piece = *I; + // FIXME: getNotes() was supposed to return a list of shared pointers, + // and then we wouldn't normally create a new piece here, + // unless ShouldConvert is set. + PathDiagnosticPiece *ConvertedPiece = + ShouldConvert + ? static_cast(new PathDiagnosticEventPiece( + Piece->getLocation(), Piece->getString())) + : static_cast(new PathDiagnosticNotePiece( + Piece->getLocation(), Piece->getString())); + for (const auto &R : Piece->getRanges()) + ConvertedPiece->addRange(R); + + Pieces.push_front(ConvertedPiece); + } + // Get the meta data. const BugReport::ExtraTextList &Meta = exampleReport->getExtraText(); for (BugReport::ExtraTextList::const_iterator i = Meta.begin(), @@ -3520,6 +3556,13 @@ LLVM_DUMP_METHOD void PathDiagnosticMacroPiece::dump() const { // FIXME: Print which macro is being invoked. } +LLVM_DUMP_METHOD void PathDiagnosticNotePiece::dump() const { + llvm::errs() << "NOTE\n--------------\n"; + llvm::errs() << getString() << "\n"; + llvm::errs() << " ---- at ----\n"; + getLocation().dump(); +} + LLVM_DUMP_METHOD void PathDiagnosticLocation::dump() const { if (!isValid()) { llvm::errs() << "\n"; -- cgit v1.2.3