[llvm] 8280ece - [Coverage] Support overriding compilation directory

Petr Hosek via llvm-commits llvm-commits at lists.llvm.org
Tue May 11 15:26:53 PDT 2021


Author: Petr Hosek
Date: 2021-05-11T15:26:45-07:00
New Revision: 8280ece0c972db24e51aae5074ca5433002f1071

URL: https://github.com/llvm/llvm-project/commit/8280ece0c972db24e51aae5074ca5433002f1071
DIFF: https://github.com/llvm/llvm-project/commit/8280ece0c972db24e51aae5074ca5433002f1071.diff

LOG: [Coverage] Support overriding compilation directory

When making compilation relocatable, for example in distributed
compilation scenarios, we want to set compilation dir to a relative
value like `.` but this presents a problem when generating reports
because if the file path is relative as well, for example `..`, you
may end up writing files outside of the output directory.

This change introduces a flag that allows overriding the compilation
directory that's stored inside the profile with a different value that
is absolute.

Differential Revision: https://reviews.llvm.org/D100232

Added: 
    llvm/test/tools/llvm-cov/Inputs/compilation_dir.covmapping
    llvm/test/tools/llvm-cov/Inputs/compilation_dir.proftext
    llvm/test/tools/llvm-cov/compilation_dir.c

Modified: 
    llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
    llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
    llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
    llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
    llvm/tools/llvm-cov/CodeCoverage.cpp
    llvm/tools/llvm-cov/CoverageViewOptions.h
    llvm/unittests/ProfileData/CoverageMappingTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 3e06de356af6a..587eb916f4704 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -603,7 +603,7 @@ class CoverageMapping {
   /// Ignores non-instrumented object files unless all are not instrumented.
   static Expected<std::unique_ptr<CoverageMapping>>
   load(ArrayRef<StringRef> ObjectFilenames, StringRef ProfileFilename,
-       ArrayRef<StringRef> Arches = None);
+       ArrayRef<StringRef> Arches = None, StringRef CompilationDir = "");
 
   /// The number of functions that couldn't have their profiles mapped.
   ///

diff  --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
index e823d21add136..eb71bf6c8975c 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
@@ -202,13 +202,15 @@ class BinaryCoverageReader : public CoverageMappingReader {
 
   static Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>>
   create(MemoryBufferRef ObjectBuffer, StringRef Arch,
-         SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers);
+         SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers,
+         StringRef CompilationDir = "");
 
   static Expected<std::unique_ptr<BinaryCoverageReader>>
   createCoverageReaderFromBuffer(StringRef Coverage, std::string &&FuncRecords,
                                  InstrProfSymtab &&ProfileNames,
                                  uint8_t BytesInAddress,
-                                 support::endianness Endian);
+                                 support::endianness Endian,
+                                 StringRef CompilationDir = "");
 
   Error readNextRecord(CoverageMappingRecord &Record) override;
 };
@@ -216,14 +218,17 @@ class BinaryCoverageReader : public CoverageMappingReader {
 /// Reader for the raw coverage filenames.
 class RawCoverageFilenamesReader : public RawCoverageReader {
   std::vector<std::string> &Filenames;
+  StringRef CompilationDir;
 
   // Read an uncompressed sequence of filenames.
   Error readUncompressed(CovMapVersion Version, uint64_t NumFilenames);
 
 public:
   RawCoverageFilenamesReader(StringRef Data,
-                             std::vector<std::string> &Filenames)
-      : RawCoverageReader(Data), Filenames(Filenames) {}
+                             std::vector<std::string> &Filenames,
+                             StringRef CompilationDir = "")
+      : RawCoverageReader(Data), Filenames(Filenames),
+        CompilationDir(CompilationDir) {}
   RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) = delete;
   RawCoverageFilenamesReader &
   operator=(const RawCoverageFilenamesReader &) = delete;

diff  --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index f81394612190f..2fd70a0a1b9fd 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -319,7 +319,8 @@ static Error handleMaybeNoDataFoundError(Error E) {
 
 Expected<std::unique_ptr<CoverageMapping>>
 CoverageMapping::load(ArrayRef<StringRef> ObjectFilenames,
-                      StringRef ProfileFilename, ArrayRef<StringRef> Arches) {
+                      StringRef ProfileFilename, ArrayRef<StringRef> Arches,
+                      StringRef CompilationDir) {
   auto ProfileReaderOrErr = IndexedInstrProfReader::create(ProfileFilename);
   if (Error E = ProfileReaderOrErr.takeError())
     return std::move(E);
@@ -336,8 +337,8 @@ CoverageMapping::load(ArrayRef<StringRef> ObjectFilenames,
     MemoryBufferRef CovMappingBufRef =
         CovMappingBufOrErr.get()->getMemBufferRef();
     SmallVector<std::unique_ptr<MemoryBuffer>, 4> Buffers;
-    auto CoverageReadersOrErr =
-        BinaryCoverageReader::create(CovMappingBufRef, Arch, Buffers);
+    auto CoverageReadersOrErr = BinaryCoverageReader::create(
+        CovMappingBufRef, Arch, Buffers, CompilationDir);
     if (Error E = CoverageReadersOrErr.takeError()) {
       E = handleMaybeNoDataFoundError(std::move(E));
       if (E)

diff  --git a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
index d7352f2c2b3a9..4fbcefd236cbe 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
@@ -138,7 +138,8 @@ Error RawCoverageFilenamesReader::read(CovMapVersion Version) {
     }
 
     StringRef UncompressedFilenames(StorageBuf.data(), StorageBuf.size());
-    RawCoverageFilenamesReader Delegate(UncompressedFilenames, Filenames);
+    RawCoverageFilenamesReader Delegate(UncompressedFilenames, Filenames,
+                                        CompilationDir);
     return Delegate.readUncompressed(Version, NumFilenames);
   }
 
@@ -168,7 +169,11 @@ Error RawCoverageFilenamesReader::readUncompressed(CovMapVersion Version,
       if (sys::path::is_absolute(Filename)) {
         Filenames.push_back(Filename.str());
       } else {
-        SmallString<256> P(CWD);
+        SmallString<256> P;
+        if (!CompilationDir.empty())
+          P.assign(CompilationDir);
+        else
+          P.assign(CWD);
         llvm::sys::path::append(P, Filename);
         Filenames.push_back(static_cast<std::string>(P));
       }
@@ -520,7 +525,7 @@ struct CovMapFuncRecordReader {
   template <class IntPtrT, support::endianness Endian>
   static Expected<std::unique_ptr<CovMapFuncRecordReader>>
   get(CovMapVersion Version, InstrProfSymtab &P,
-      std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
+      std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
       std::vector<std::string> &F);
 };
 
@@ -535,6 +540,7 @@ class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
   // in \c Records.
   DenseMap<NameRefType, size_t> FunctionRecords;
   InstrProfSymtab &ProfileNames;
+  StringRef CompilationDir;
   std::vector<std::string> &Filenames;
   std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records;
 
@@ -594,9 +600,9 @@ class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
 public:
   VersionedCovMapFuncRecordReader(
       InstrProfSymtab &P,
-      std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
+      std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
       std::vector<std::string> &F)
-      : ProfileNames(P), Filenames(F), Records(R) {}
+      : ProfileNames(P), CompilationDir(D), Filenames(F), Records(R) {}
 
   ~VersionedCovMapFuncRecordReader() override = default;
 
@@ -629,7 +635,8 @@ class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
       return make_error<CoverageMapError>(coveragemap_error::malformed);
     size_t FilenamesBegin = Filenames.size();
     StringRef FilenameRegion(CovBuf, FilenamesSize);
-    RawCoverageFilenamesReader Reader(FilenameRegion, Filenames);
+    RawCoverageFilenamesReader Reader(FilenameRegion, Filenames,
+                                      CompilationDir);
     if (auto Err = Reader.read(Version))
       return std::move(Err);
     CovBuf += FilenamesSize;
@@ -735,14 +742,14 @@ class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
 template <class IntPtrT, support::endianness Endian>
 Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(
     CovMapVersion Version, InstrProfSymtab &P,
-    std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
+    std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
     std::vector<std::string> &F) {
   using namespace coverage;
 
   switch (Version) {
   case CovMapVersion::Version1:
     return std::make_unique<VersionedCovMapFuncRecordReader<
-        CovMapVersion::Version1, IntPtrT, Endian>>(P, R, F);
+        CovMapVersion::Version1, IntPtrT, Endian>>(P, R, D, F);
   case CovMapVersion::Version2:
   case CovMapVersion::Version3:
   case CovMapVersion::Version4:
@@ -753,19 +760,19 @@ Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(
       return std::move(E);
     if (Version == CovMapVersion::Version2)
       return std::make_unique<VersionedCovMapFuncRecordReader<
-          CovMapVersion::Version2, IntPtrT, Endian>>(P, R, F);
+          CovMapVersion::Version2, IntPtrT, Endian>>(P, R, D, F);
     else if (Version == CovMapVersion::Version3)
       return std::make_unique<VersionedCovMapFuncRecordReader<
-          CovMapVersion::Version3, IntPtrT, Endian>>(P, R, F);
+          CovMapVersion::Version3, IntPtrT, Endian>>(P, R, D, F);
     else if (Version == CovMapVersion::Version4)
       return std::make_unique<VersionedCovMapFuncRecordReader<
-          CovMapVersion::Version4, IntPtrT, Endian>>(P, R, F);
+          CovMapVersion::Version4, IntPtrT, Endian>>(P, R, D, F);
     else if (Version == CovMapVersion::Version5)
       return std::make_unique<VersionedCovMapFuncRecordReader<
-          CovMapVersion::Version5, IntPtrT, Endian>>(P, R, F);
+          CovMapVersion::Version5, IntPtrT, Endian>>(P, R, D, F);
     else if (Version == CovMapVersion::Version6)
       return std::make_unique<VersionedCovMapFuncRecordReader<
-          CovMapVersion::Version6, IntPtrT, Endian>>(P, R, F);
+          CovMapVersion::Version6, IntPtrT, Endian>>(P, R, D, F);
   }
   llvm_unreachable("Unsupported version");
 }
@@ -774,7 +781,7 @@ template <typename T, support::endianness Endian>
 static Error readCoverageMappingData(
     InstrProfSymtab &ProfileNames, StringRef CovMap, StringRef FuncRecords,
     std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
-    std::vector<std::string> &Filenames) {
+    StringRef CompilationDir, std::vector<std::string> &Filenames) {
   using namespace coverage;
 
   // Read the records in the coverage data section.
@@ -785,7 +792,7 @@ static Error readCoverageMappingData(
     return make_error<CoverageMapError>(coveragemap_error::unsupported_version);
   Expected<std::unique_ptr<CovMapFuncRecordReader>> ReaderExpected =
       CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records,
-                                             Filenames);
+                                             CompilationDir, Filenames);
   if (Error E = ReaderExpected.takeError())
     return E;
   auto Reader = std::move(ReaderExpected.get());
@@ -817,8 +824,9 @@ static const char *TestingFormatMagic = "llvmcovmtestdata";
 
 Expected<std::unique_ptr<BinaryCoverageReader>>
 BinaryCoverageReader::createCoverageReaderFromBuffer(
-    StringRef Coverage, std::string &&FuncRecords, InstrProfSymtab &&ProfileNames,
-    uint8_t BytesInAddress, support::endianness Endian) {
+    StringRef Coverage, std::string &&FuncRecords,
+    InstrProfSymtab &&ProfileNames, uint8_t BytesInAddress,
+    support::endianness Endian, StringRef CompilationDir) {
   std::unique_ptr<BinaryCoverageReader> Reader(
       new BinaryCoverageReader(std::move(FuncRecords)));
   Reader->ProfileNames = std::move(ProfileNames);
@@ -827,23 +835,23 @@ BinaryCoverageReader::createCoverageReaderFromBuffer(
     if (Error E =
             readCoverageMappingData<uint32_t, support::endianness::little>(
                 Reader->ProfileNames, Coverage, FuncRecordsRef,
-                Reader->MappingRecords, Reader->Filenames))
+                Reader->MappingRecords, CompilationDir, Reader->Filenames))
       return std::move(E);
   } else if (BytesInAddress == 4 && Endian == support::endianness::big) {
     if (Error E = readCoverageMappingData<uint32_t, support::endianness::big>(
             Reader->ProfileNames, Coverage, FuncRecordsRef,
-            Reader->MappingRecords, Reader->Filenames))
+            Reader->MappingRecords, CompilationDir, Reader->Filenames))
       return std::move(E);
   } else if (BytesInAddress == 8 && Endian == support::endianness::little) {
     if (Error E =
             readCoverageMappingData<uint64_t, support::endianness::little>(
                 Reader->ProfileNames, Coverage, FuncRecordsRef,
-                Reader->MappingRecords, Reader->Filenames))
+                Reader->MappingRecords, CompilationDir, Reader->Filenames))
       return std::move(E);
   } else if (BytesInAddress == 8 && Endian == support::endianness::big) {
     if (Error E = readCoverageMappingData<uint64_t, support::endianness::big>(
             Reader->ProfileNames, Coverage, FuncRecordsRef,
-            Reader->MappingRecords, Reader->Filenames))
+            Reader->MappingRecords, CompilationDir, Reader->Filenames))
       return std::move(E);
   } else
     return make_error<CoverageMapError>(coveragemap_error::malformed);
@@ -851,7 +859,7 @@ BinaryCoverageReader::createCoverageReaderFromBuffer(
 }
 
 static Expected<std::unique_ptr<BinaryCoverageReader>>
-loadTestingFormat(StringRef Data) {
+loadTestingFormat(StringRef Data, StringRef CompilationDir) {
   uint8_t BytesInAddress = 8;
   support::endianness Endian = support::endianness::little;
 
@@ -911,7 +919,7 @@ loadTestingFormat(StringRef Data) {
   }
   return BinaryCoverageReader::createCoverageReaderFromBuffer(
       CoverageMapping, CoverageRecords.str(), std::move(ProfileNames),
-      BytesInAddress, Endian);
+      BytesInAddress, Endian, CompilationDir);
 }
 
 /// Find all sections that match \p Name. There may be more than one if comdats
@@ -941,7 +949,8 @@ static Expected<std::vector<SectionRef>> lookupSections(ObjectFile &OF,
 }
 
 static Expected<std::unique_ptr<BinaryCoverageReader>>
-loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch) {
+loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch,
+                 StringRef CompilationDir = "") {
   std::unique_ptr<ObjectFile> OF;
   if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
     // If we have a universal binary, try to look up the object for the
@@ -1013,7 +1022,7 @@ loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch) {
 
   return BinaryCoverageReader::createCoverageReaderFromBuffer(
       CoverageMapping, std::move(FuncRecords), std::move(ProfileNames),
-      BytesInAddress, Endian);
+      BytesInAddress, Endian, CompilationDir);
 }
 
 /// Determine whether \p Arch is invalid or empty, given \p Bin.
@@ -1032,12 +1041,14 @@ static bool isArchSpecifierInvalidOrMissing(Binary *Bin, StringRef Arch) {
 Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>>
 BinaryCoverageReader::create(
     MemoryBufferRef ObjectBuffer, StringRef Arch,
-    SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers) {
+    SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers,
+    StringRef CompilationDir) {
   std::vector<std::unique_ptr<BinaryCoverageReader>> Readers;
 
   if (ObjectBuffer.getBuffer().startswith(TestingFormatMagic)) {
     // This is a special format used for testing.
-    auto ReaderOrErr = loadTestingFormat(ObjectBuffer.getBuffer());
+    auto ReaderOrErr =
+        loadTestingFormat(ObjectBuffer.getBuffer(), CompilationDir);
     if (!ReaderOrErr)
       return ReaderOrErr.takeError();
     Readers.push_back(std::move(ReaderOrErr.get()));
@@ -1070,7 +1081,8 @@ BinaryCoverageReader::create(
       }
 
       return BinaryCoverageReader::create(
-          ArchiveOrErr.get()->getMemoryBufferRef(), Arch, ObjectFileBuffers);
+          ArchiveOrErr.get()->getMemoryBufferRef(), Arch, ObjectFileBuffers,
+          CompilationDir);
     }
   }
 
@@ -1083,7 +1095,7 @@ BinaryCoverageReader::create(
         return ChildBufOrErr.takeError();
 
       auto ChildReadersOrErr = BinaryCoverageReader::create(
-          ChildBufOrErr.get(), Arch, ObjectFileBuffers);
+          ChildBufOrErr.get(), Arch, ObjectFileBuffers, CompilationDir);
       if (!ChildReadersOrErr)
         return ChildReadersOrErr.takeError();
       for (auto &Reader : ChildReadersOrErr.get())
@@ -1102,7 +1114,7 @@ BinaryCoverageReader::create(
     return std::move(Readers);
   }
 
-  auto ReaderOrErr = loadBinaryFormat(std::move(Bin), Arch);
+  auto ReaderOrErr = loadBinaryFormat(std::move(Bin), Arch, CompilationDir);
   if (!ReaderOrErr)
     return ReaderOrErr.takeError();
   Readers.push_back(std::move(ReaderOrErr.get()));

diff  --git a/llvm/test/tools/llvm-cov/Inputs/compilation_dir.covmapping b/llvm/test/tools/llvm-cov/Inputs/compilation_dir.covmapping
new file mode 100644
index 0000000000000..01879d7bd9529
Binary files /dev/null and b/llvm/test/tools/llvm-cov/Inputs/compilation_dir.covmapping 
diff er

diff  --git a/llvm/test/tools/llvm-cov/Inputs/compilation_dir.proftext b/llvm/test/tools/llvm-cov/Inputs/compilation_dir.proftext
new file mode 100644
index 0000000000000..5419d233fc08f
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/compilation_dir.proftext
@@ -0,0 +1,8 @@
+main
+# Func Hash:
+0
+# Num Counters:
+1
+# Counter Values:
+1
+

diff  --git a/llvm/test/tools/llvm-cov/compilation_dir.c b/llvm/test/tools/llvm-cov/compilation_dir.c
new file mode 100644
index 0000000000000..8f1864a8140cb
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/compilation_dir.c
@@ -0,0 +1,3 @@
+// RUN: llvm-profdata merge %S/Inputs/compilation_dir.proftext -o %t.profdata
+// RUN: llvm-cov show %S/Inputs/compilation_dir.covmapping -instr-profile=%t.profdata -compilation-dir=%S | FileCheck %s
+int main() {} // CHECK: [[@LINE]]|      1|int main() {}

diff  --git a/llvm/tools/llvm-cov/CodeCoverage.cpp b/llvm/tools/llvm-cov/CodeCoverage.cpp
index 144f338b10ed9..02c0106cbc29e 100644
--- a/llvm/tools/llvm-cov/CodeCoverage.cpp
+++ b/llvm/tools/llvm-cov/CodeCoverage.cpp
@@ -434,7 +434,8 @@ std::unique_ptr<CoverageMapping> CodeCoverageTool::load() {
       warning("profile data may be out of date - object is newer",
               ObjectFilename);
   auto CoverageOrErr =
-      CoverageMapping::load(ObjectFilenames, PGOFilename, CoverageArches);
+      CoverageMapping::load(ObjectFilenames, PGOFilename, CoverageArches,
+                            ViewOpts.CompilationDirectory);
   if (Error E = CoverageOrErr.takeError()) {
     error("Failed to load coverage: " + toString(std::move(E)),
           join(ObjectFilenames.begin(), ObjectFilenames.end(), ", "));
@@ -739,6 +740,10 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
   cl::alias NumThreadsA("j", cl::desc("Alias for --num-threads"),
                         cl::aliasopt(NumThreads));
 
+  cl::opt<std::string> CompilationDirectory(
+      "compilation-dir", cl::init(""),
+      cl::desc("Directory used as a base for relative coverage mapping paths"));
+
   auto commandLineParser = [&, this](int argc, const char **argv) -> int {
     cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");
     ViewOpts.Debug = DebugDump;
@@ -873,6 +878,7 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
     ViewOpts.ShowInstantiationSummary = InstantiationSummary;
     ViewOpts.ExportSummaryOnly = SummaryOnly;
     ViewOpts.NumThreads = NumThreads;
+    ViewOpts.CompilationDirectory = CompilationDirectory;
 
     return 0;
   };

diff  --git a/llvm/tools/llvm-cov/CoverageViewOptions.h b/llvm/tools/llvm-cov/CoverageViewOptions.h
index eee4ba74e165a..045fb1787bcea 100644
--- a/llvm/tools/llvm-cov/CoverageViewOptions.h
+++ b/llvm/tools/llvm-cov/CoverageViewOptions.h
@@ -49,6 +49,7 @@ struct CoverageViewOptions {
   std::string ProjectTitle;
   std::string CreatedTimeStr;
   unsigned NumThreads;
+  std::string CompilationDirectory;
 
   /// Change the output's stream color if the colors are enabled.
   ColoredRawOstream colored_ostream(raw_ostream &OS,

diff  --git a/llvm/unittests/ProfileData/CoverageMappingTest.cpp b/llvm/unittests/ProfileData/CoverageMappingTest.cpp
index b10400b14c775..6434474b06850 100644
--- a/llvm/unittests/ProfileData/CoverageMappingTest.cpp
+++ b/llvm/unittests/ProfileData/CoverageMappingTest.cpp
@@ -900,7 +900,7 @@ INSTANTIATE_TEST_CASE_P(ParameterizedCovMapTest, CoverageMappingTest,
                                           std::pair<bool, bool>({true, true})),);
 
 TEST(CoverageMappingTest, filename_roundtrip) {
-  std::vector<std::string> Paths({"", "a", "b", "c", "d", "e"});
+  std::vector<std::string> Paths({"dir", "a", "b", "c", "d", "e"});
 
   for (bool Compress : {false, true}) {
     std::string EncodedFilenames;
@@ -915,8 +915,37 @@ TEST(CoverageMappingTest, filename_roundtrip) {
     EXPECT_THAT_ERROR(Reader.read(CovMapVersion::CurrentVersion), Succeeded());
 
     ASSERT_EQ(ReadFilenames.size(), Paths.size());
-    for (unsigned I = 1; I < Paths.size(); ++I)
-      ASSERT_TRUE(ReadFilenames[I] == Paths[I]);
+    for (unsigned I = 1; I < Paths.size(); ++I) {
+      SmallString<256> P(Paths[0]);
+      llvm::sys::path::append(P, Paths[I]);
+      ASSERT_TRUE(ReadFilenames[I] == P);
+    }
+  }
+}
+
+TEST(CoverageMappingTest, filename_compilation_dir) {
+  std::vector<std::string> Paths({"dir", "a", "b", "c", "d", "e"});
+
+  for (bool Compress : {false, true}) {
+    std::string EncodedFilenames;
+    {
+      raw_string_ostream OS(EncodedFilenames);
+      CoverageFilenamesSectionWriter Writer(Paths);
+      Writer.write(OS, Compress);
+    }
+
+    StringRef CompilationDir = "out";
+    std::vector<std::string> ReadFilenames;
+    RawCoverageFilenamesReader Reader(EncodedFilenames, ReadFilenames,
+                                      CompilationDir);
+    EXPECT_THAT_ERROR(Reader.read(CovMapVersion::CurrentVersion), Succeeded());
+
+    ASSERT_EQ(ReadFilenames.size(), Paths.size());
+    for (unsigned I = 1; I < Paths.size(); ++I) {
+      SmallString<256> P(CompilationDir);
+      llvm::sys::path::append(P, Paths[I]);
+      ASSERT_TRUE(ReadFilenames[I] == P);
+    }
   }
 }
 


        


More information about the llvm-commits mailing list