diff --git a/llvm/tools/llvm-cov/CodeCoverage.cpp b/llvm/tools/llvm-cov/CodeCoverage.cpp --- a/llvm/tools/llvm-cov/CodeCoverage.cpp +++ b/llvm/tools/llvm-cov/CodeCoverage.cpp @@ -80,6 +80,12 @@ /// directory, recursively collect all of the paths within the directory. void collectPaths(const std::string &Path); + /// Check if the two given files are the same file. + bool isEquivalentFile(StringRef FilePath1, StringRef FilePath2); + + /// Retrieve a file status with a cache. + Optional getFileStatus(StringRef FilePath); + /// Return a memory buffer for the given source file. ErrorOr getSourceFile(StringRef SourceFile); @@ -153,6 +159,9 @@ /// remapped to, when using -path-equivalence. Optional> PathRemapping; + /// File status cache used when finding the same file. + StringMap> FileStatusCache; + /// The architecture the coverage mapping data targets. std::vector CoverageArches; @@ -239,6 +248,27 @@ } } +Optional +CodeCoverageTool::getFileStatus(StringRef FilePath) { + auto It = FileStatusCache.try_emplace(FilePath); + auto &CachedStatus = It.first->getValue(); + if (!It.second) + return CachedStatus; + + sys::fs::file_status Status; + if (!sys::fs::status(FilePath, Status)) + CachedStatus = Status; + return CachedStatus; +} + +bool CodeCoverageTool::isEquivalentFile(StringRef FilePath1, + StringRef FilePath2) { + auto Status1 = getFileStatus(FilePath1); + auto Status2 = getFileStatus(FilePath2); + return Status1.hasValue() && Status2.hasValue() && + sys::fs::equivalent(Status1.getValue(), Status2.getValue()); +} + ErrorOr CodeCoverageTool::getSourceFile(StringRef SourceFile) { // If we've remapped filenames, look up the real location for this file. @@ -249,7 +279,7 @@ SourceFile = Loc->second; } for (const auto &Files : LoadedSourceFiles) - if (sys::fs::equivalent(SourceFile, Files.first)) + if (isEquivalentFile(SourceFile, Files.first)) return *Files.second; auto Buffer = MemoryBuffer::getFile(SourceFile); if (auto EC = Buffer.getError()) {