diff options
| author | Artem Dergachev <artem.dergachev@gmail.com> | 2019-09-11 20:54:24 +0000 |
|---|---|---|
| committer | Artem Dergachev <artem.dergachev@gmail.com> | 2019-09-11 20:54:24 +0000 |
| commit | 2bce23a4f8af8c208d97d6a3503e8659b1a4f71f (patch) | |
| tree | d8ea6c8028a74d86e79e4c0e3d48d59c556b126a /clang/lib/StaticAnalyzer/Core/BugReporter.cpp | |
| parent | 6b85f8e99b38aed5bb4eeb4ca8d7ccdd5a1bf48c (diff) | |
| download | bcm5719-llvm-2bce23a4f8af8c208d97d6a3503e8659b1a4f71f.tar.gz bcm5719-llvm-2bce23a4f8af8c208d97d6a3503e8659b1a4f71f.zip | |
[analyzer] NFC: Move resetDiagnosticLocationToMainFile() to BugReporter.
This method of PathDiagnostic is a part of Static Analyzer's particular
path diagnostic construction scheme. As such, it doesn't belong to
the PathDiagnostic class, but to the Analyzer.
Differential Revision: https://reviews.llvm.org/D67418
llvm-svn: 371660
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/BugReporter.cpp')
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/BugReporter.cpp | 67 |
1 files changed, 66 insertions, 1 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp index 57f639afbab..657569dab6f 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -3125,6 +3125,71 @@ BugReporter::generateDiagnosticForConsumerMap( return Out; } +static PathDiagnosticCallPiece * +getFirstStackedCallToHeaderFile(PathDiagnosticCallPiece *CP, + const SourceManager &SMgr) { + SourceLocation CallLoc = CP->callEnter.asLocation(); + + // If the call is within a macro, don't do anything (for now). + if (CallLoc.isMacroID()) + return nullptr; + + assert(AnalysisManager::isInCodeFile(CallLoc, SMgr) && + "The call piece should not be in a header file."); + + // Check if CP represents a path through a function outside of the main file. + if (!AnalysisManager::isInCodeFile(CP->callEnterWithin.asLocation(), SMgr)) + return CP; + + const PathPieces &Path = CP->path; + if (Path.empty()) + return nullptr; + + // Check if the last piece in the callee path is a call to a function outside + // of the main file. + if (auto *CPInner = dyn_cast<PathDiagnosticCallPiece>(Path.back().get())) + return getFirstStackedCallToHeaderFile(CPInner, SMgr); + + // Otherwise, the last piece is in the main file. + return nullptr; +} + +static void resetDiagnosticLocationToMainFile(PathDiagnostic &PD) { + if (PD.path.empty()) + return; + + PathDiagnosticPiece *LastP = PD.path.back().get(); + assert(LastP); + const SourceManager &SMgr = LastP->getLocation().getManager(); + + // We only need to check if the report ends inside headers, if the last piece + // is a call piece. + if (auto *CP = dyn_cast<PathDiagnosticCallPiece>(LastP)) { + CP = getFirstStackedCallToHeaderFile(CP, SMgr); + if (CP) { + // Mark the piece. + CP->setAsLastInMainSourceFile(); + + // Update the path diagnostic message. + const auto *ND = dyn_cast<NamedDecl>(CP->getCallee()); + if (ND) { + SmallString<200> buf; + llvm::raw_svector_ostream os(buf); + os << " (within a call to '" << ND->getDeclName() << "')"; + PD.appendToDesc(os.str()); + } + + // Reset the report containing declaration and location. + PD.setDeclWithIssue(CP->getCaller()); + PD.setLocation(CP->getLocation()); + + return; + } + } +} + + + std::unique_ptr<DiagnosticForConsumerMapTy> PathSensitiveBugReporter::generateDiagnosticForConsumerMap( BugReport *exampleReport, ArrayRef<PathDiagnosticConsumer *> consumers, @@ -3159,7 +3224,7 @@ PathSensitiveBugReporter::generateDiagnosticForConsumerMap( const AnalyzerOptions &Opts = getAnalyzerOptions(); for (auto const &P : *Out) if (Opts.ShouldReportIssuesInMainSourceFile && !Opts.AnalyzeAll) - P.second->resetDiagnosticLocationToMainFile(); + resetDiagnosticLocationToMainFile(*P.second); return Out; } |

