Index: llvm/tools/llvm-cov/CodeCoverage.cpp =================================================================== --- llvm/tools/llvm-cov/CodeCoverage.cpp +++ llvm/tools/llvm-cov/CodeCoverage.cpp @@ -157,7 +157,7 @@ /// The coverage data path to be remapped from, and the source path to be /// remapped to, when using -path-equivalence. - Optional> PathRemapping; + Optional>> PathRemappings; /// File status cache used when finding the same file. StringMap> FileStatusCache; @@ -219,7 +219,7 @@ llvm::sys::fs::file_status Status; llvm::sys::fs::status(Path, Status); if (!llvm::sys::fs::exists(Status)) { - if (PathRemapping) + if (PathRemappings) addCollectedPath(Path); else warning("Source file doesn't exist, proceeded by ignoring it.", Path); @@ -466,7 +466,7 @@ } void CodeCoverageTool::remapPathNames(const CoverageMapping &Coverage) { - if (!PathRemapping) + if (!PathRemappings) return; // Convert remapping paths to native paths with trailing seperators. @@ -480,32 +480,38 @@ NativePath += sys::path::get_separator(); return NativePath.c_str(); }; - std::string RemapFrom = nativeWithTrailing(PathRemapping->first); - std::string RemapTo = nativeWithTrailing(PathRemapping->second); - - // Create a mapping from coverage data file paths to local paths. - for (StringRef Filename : Coverage.getUniqueSourceFiles()) { - SmallString<128> NativeFilename; - sys::path::native(Filename, NativeFilename); - sys::path::remove_dots(NativeFilename, true); - if (NativeFilename.startswith(RemapFrom)) { - RemappedFilenames[Filename] = - RemapTo + NativeFilename.substr(RemapFrom.size()).str(); + + for (std::pair &PathRemapping : *PathRemappings) { + std::string RemapFrom = nativeWithTrailing(PathRemapping.first); + std::string RemapTo = nativeWithTrailing(PathRemapping.second); + + // Create a mapping from coverage data file paths to local paths. + for (StringRef Filename : Coverage.getUniqueSourceFiles()) { + if (!RemappedFilenames[Filename].empty()) + continue; + + SmallString<128> NativeFilename; + sys::path::native(Filename, NativeFilename); + sys::path::remove_dots(NativeFilename, true); + if (NativeFilename.startswith(RemapFrom)) { + RemappedFilenames[Filename] = + RemapTo + NativeFilename.substr(RemapFrom.size()).str(); + } } - } - // Convert input files from local paths to coverage data file paths. - StringMap InvRemappedFilenames; - for (const auto &RemappedFilename : RemappedFilenames) - InvRemappedFilenames[RemappedFilename.getValue()] = - std::string(RemappedFilename.getKey()); - - for (std::string &Filename : SourceFiles) { - SmallString<128> NativeFilename; - sys::path::native(Filename, NativeFilename); - auto CovFileName = InvRemappedFilenames.find(NativeFilename); - if (CovFileName != InvRemappedFilenames.end()) - Filename = CovFileName->second; + // Convert input files from local paths to coverage data file paths. + StringMap InvRemappedFilenames; + for (const auto &RemappedFilename : RemappedFilenames) + InvRemappedFilenames[RemappedFilename.getValue()] = + std::string(RemappedFilename.getKey()); + + for (std::string &Filename : SourceFiles) { + SmallString<128> NativeFilename; + sys::path::native(Filename, NativeFilename); + auto CovFileName = InvRemappedFilenames.find(NativeFilename); + if (CovFileName != InvRemappedFilenames.end()) + Filename = CovFileName->second; + } } } @@ -657,8 +663,8 @@ cl::opt PathRemap( "path-equivalence", cl::Optional, - cl::desc(", Map coverage data paths to local source file " - "paths")); + cl::desc(",,... Map coverage data paths to local source file " + "paths.")); cl::OptionCategory FilteringCategory("Function filtering options"); @@ -782,12 +788,19 @@ break; } + SmallVector EquivPairs; + // If path-equivalence was given and is a comma seperated pair then set // PathRemapping. - auto EquivPair = StringRef(PathRemap).split(','); - if (!(EquivPair.first.empty() && EquivPair.second.empty())) - PathRemapping = {std::string(EquivPair.first), - std::string(EquivPair.second)}; + StringRef(PathRemap).split(EquivPairs, ','); + std::vector> Remappings; + for (size_t i = 1; i < EquivPairs.size(); i += 2) { + Remappings.push_back( + {std::string(EquivPairs[i - 1]), std::string(EquivPairs[i])}); + } + if (!Remappings.empty()) { + PathRemappings = Remappings; + } // If a demangler is supplied, check if it exists and register it. if (!DemanglerOpts.empty()) {