/// The string to embed in debug information as the current working directory.
std::string DebugCompilationDir;
+ /// The string to embed in coverage mapping as the current working directory.
+ std::string ProfileCompilationDir;
+
/// The string to embed in the debug information for the compile unit, if
/// non-empty.
std::string DwarfDebugFlags;
def fdebug_compilation_dir : Separate<["-"], "fdebug-compilation-dir">,
Group<f_Group>, Flags<[CC1Option, CC1AsOption, CoreOption]>,
Alias<fdebug_compilation_dir_EQ>;
+def fprofile_compilation_dir_EQ : Joined<["-"], "fprofile-compilation-dir=">,
+ Group<f_Group>, Flags<[CC1Option, CC1AsOption, CoreOption]>,
+ HelpText<"The compilation directory to embed in the coverage mapping.">,
+ MarshallingInfoString<CodeGenOpts<"ProfileCompilationDir">>;
defm debug_info_for_profiling : BoolFOption<"debug-info-for-profiling",
CodeGenOpts<"DebugInfoForProfiling">, DefaultFalse,
PosFlag<SetTrue, [CC1Option], "Emit extra debug info to make sample profile more accurate">,
ProfilePrefixMap = CGM.getCodeGenOpts().ProfilePrefixMap;
}
+std::string CoverageMappingModuleGen::getCurrentDirname() {
+ if (!CGM.getCodeGenOpts().ProfileCompilationDir.empty())
+ return CGM.getCodeGenOpts().ProfileCompilationDir;
+
+ SmallString<256> CWD;
+ llvm::sys::fs::current_path(CWD);
+ return CWD.str().str();
+}
+
std::string CoverageMappingModuleGen::normalizeFilename(StringRef Filename) {
llvm::SmallString<256> Path(Filename);
- llvm::sys::fs::make_absolute(Path);
llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
for (const auto &Entry : ProfilePrefixMap) {
if (llvm::sys::path::replace_path_prefix(Path, Entry.first, Entry.second))
// also processed by the CoverageMappingWriter which performs
// additional minimization operations such as reducing the number of
// expressions.
+ llvm::SmallVector<std::string, 16> FilenameStrs;
std::vector<StringRef> Filenames;
std::vector<CounterExpression> Expressions;
std::vector<CounterMappingRegion> Regions;
- llvm::SmallVector<std::string, 16> FilenameStrs;
- llvm::SmallVector<StringRef, 16> FilenameRefs;
- FilenameStrs.resize(FileEntries.size());
- FilenameRefs.resize(FileEntries.size());
+ FilenameStrs.resize(FileEntries.size() + 1);
+ FilenameStrs[0] = normalizeFilename(getCurrentDirname());
for (const auto &Entry : FileEntries) {
auto I = Entry.second;
FilenameStrs[I] = normalizeFilename(Entry.first->getName());
- FilenameRefs[I] = FilenameStrs[I];
}
+ ArrayRef<std::string> FilenameRefs = llvm::makeArrayRef(FilenameStrs);
RawCoverageMappingReader Reader(CoverageMapping, FilenameRefs, Filenames,
Expressions, Regions);
if (Reader.read())
// Create the filenames and merge them with coverage mappings
llvm::SmallVector<std::string, 16> FilenameStrs;
- llvm::SmallVector<StringRef, 16> FilenameRefs;
- FilenameStrs.resize(FileEntries.size());
- FilenameRefs.resize(FileEntries.size());
+ FilenameStrs.resize(FileEntries.size() + 1);
+ // The first filename is the current working directory.
+ FilenameStrs[0] = getCurrentDirname();
for (const auto &Entry : FileEntries) {
auto I = Entry.second;
FilenameStrs[I] = normalizeFilename(Entry.first->getName());
- FilenameRefs[I] = FilenameStrs[I];
}
std::string Filenames;
{
llvm::raw_string_ostream OS(Filenames);
- CoverageFilenamesSectionWriter(FilenameRefs).write(OS);
+ CoverageFilenamesSectionWriter(FilenameStrs).write(OS);
}
auto *FilenamesVal =
llvm::ConstantDataArray::getString(Ctx, Filenames, false);
auto It = FileEntries.find(File);
if (It != FileEntries.end())
return It->second;
- unsigned FileID = FileEntries.size();
+ unsigned FileID = FileEntries.size() + 1;
FileEntries.insert(std::make_pair(File, FileID));
return FileID;
}
std::vector<FunctionInfo> FunctionRecords;
std::map<std::string, std::string> ProfilePrefixMap;
+ std::string getCurrentDirname();
std::string normalizeFilename(StringRef Filename);
/// Emit a function record.
CmdArgs.push_back("-fcoverage-mapping");
}
+ if (Arg *A = Args.getLastArg(options::OPT_fprofile_compilation_dir_EQ)) {
+ A->render(Args, CmdArgs);
+ } else if (llvm::ErrorOr<std::string> CWD =
+ D.getVFS().getCurrentWorkingDirectory()) {
+ Args.MakeArgString("-fprofile-compilation-dir=" + *CWD);
+ }
+
if (Args.hasArg(options::OPT_fprofile_exclude_files_EQ)) {
auto *Arg = Args.getLastArg(options::OPT_fprofile_exclude_files_EQ);
if (!Args.hasArg(options::OPT_coverage))
--- /dev/null
+// RUN: mkdir -p %t.dir && cd %t.dir
+// RUN: cp %s rel.c
+// RUN: %clang_cc1 -fprofile-instrument=clang -fprofile-compilation-dir=/nonsense -fcoverage-mapping -emit-llvm -mllvm -enable-name-compression=false rel.c -o - | FileCheck -check-prefix=CHECK-NONSENSE %s
+
+// CHECK-NONSENSE: nonsense
+
+void f() {}
// RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false -fprofile-instrument=clang -fcoverage-mapping -mllvm -enable-name-compression=false -emit-llvm -main-file-name abspath.cpp %S/Inputs/../abspath.cpp -o - | FileCheck -check-prefix=RMDOTS %s
-// RMDOTS: @__llvm_coverage_mapping = {{.*}}"\01
+// RMDOTS: @__llvm_coverage_mapping = {{.*}}"\02
// RMDOTS-NOT: Inputs
// RMDOTS: "
// RUN: mkdir -p %t/test && cd %t/test
// RUN: echo "void f1() {}" > f1.c
-// RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false -fprofile-instrument=clang -fcoverage-mapping -mllvm -enable-name-compression=false -emit-llvm -main-file-name abspath.cpp ../test/f1.c -o - | FileCheck -check-prefix=RELPATH %s
+// RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false -fprofile-instrument=clang -fcoverage-mapping -mllvm -enable-name-compression=false -emit-llvm -main-file-name abspath.cpp %t/test/f1.c -o - | FileCheck -check-prefix=ABSPATH %s
-// RELPATH: @__llvm_coverage_mapping = {{.*}}"\01
-// RELPATH: {{[/\\].*(/|\\\\)test(/|\\\\)f1}}.c
+// RELPATH: @__llvm_coverage_mapping = {{.*}}"\02
+// RELPATH: {{..(/|\\\\)test(/|\\\\)f1}}.c
// RELPATH: "
+// ABSPATH: @__llvm_coverage_mapping = {{.*}}"\02
+// ABSPATH: {{[/\\].*(/|\\\\)test(/|\\\\)f1}}.c
+// ABSPATH: "
+
void f1() {}
// RUN: echo "void f1() {}" > %t/root/nested/profile-prefix-map.c
// RUN: cd %t/root
-// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -emit-llvm -mllvm -enable-name-compression=false -main-file-name profile-prefix-map.c nested/profile-prefix-map.c -o - | FileCheck --check-prefix=ABSOLUTE %s
+// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -emit-llvm -mllvm -enable-name-compression=false -main-file-name profile-prefix-map.c %t/root/nested/profile-prefix-map.c -o - | FileCheck --check-prefix=ABSOLUTE %s
//
-// ABSOLUTE: @__llvm_coverage_mapping = {{.*"\\01.*root.*nested.*profile-prefix-map\.c}}
+// ABSOLUTE: @__llvm_coverage_mapping = {{.*"\\02.*root.*nested.*profile-prefix-map\.c}}
-// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -emit-llvm -mllvm -enable-name-compression=false -main-file-name profile-prefix-map.c nested/profile-prefix-map.c -fprofile-prefix-map=%/t/root=. -o - | FileCheck --check-prefix=PROFILE-PREFIX-MAP %s --implicit-check-not=root
+// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -emit-llvm -mllvm -enable-name-compression=false -main-file-name profile-prefix-map.c ../root/nested/profile-prefix-map.c -o - | FileCheck --check-prefix=RELATIVE %s
//
-// PROFILE-PREFIX-MAP: @__llvm_coverage_mapping = {{.*"\\01[^/]*}}.{{/|\\+}}nested{{.*profile-prefix-map\.c}}
+// RELATIVE: @__llvm_coverage_mapping = {{.*"\\02.*}}..{{/|\\+}}root{{/|\\+}}nested{{.*profile-prefix-map\.c}}
+
+// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -emit-llvm -mllvm -enable-name-compression=false -main-file-name profile-prefix-map.c %t/root/nested/profile-prefix-map.c -fprofile-prefix-map=%/t/root=. -o - | FileCheck --check-prefix=PROFILE-PREFIX-MAP %s
+// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -emit-llvm -mllvm -enable-name-compression=false -main-file-name profile-prefix-map.c ../root/nested/profile-prefix-map.c -fprofile-prefix-map=../root=. -o - | FileCheck --check-prefix=PROFILE-PREFIX-MAP %s
+// PROFILE-PREFIX-MAP: @__llvm_coverage_mapping = {{.*"\\02.*}}.{{/|\\+}}nested{{.*profile-prefix-map\.c}}
/* Indexed profile format version (start from 1). */
#define INSTR_PROF_INDEX_VERSION 7
/* Coverage mapping format version (start from 0). */
-#define INSTR_PROF_COVMAP_VERSION 4
+#define INSTR_PROF_COVMAP_VERSION 5
/* Profile version is always of type uint64_t. Reserve the upper 8 bits in the
* version for other variants of profile. We set the lowest bit of the upper 8
[32 x i8] c"..." ; Encoded data (dissected later)
}, section "__llvm_covmap", align 8
-The current version of the format is version 5. There is one difference from version 4:
+The current version of the format is version 6.
+
+There is one difference between versions 6 and 5:
+
+* The first entry in the filename list is the compilation directory. When the
+ filename is relative, the compilation directory is combined with the relative
+ path to get an absolute path. This can reduce size by omitting the duplicate
+ prefix in filenames.
+
+There is one difference between versions 5 and 4:
* The notion of branch region has been introduced along with a corresponding
region kind. Branch regions encode two counters, one to track how many
Version4 = 3,
// Branch regions referring to two counters are added
Version5 = 4,
- // The current version is Version5.
+ // Compilation directory is stored separately and combined with relative
+ // filenames to produce an absolute file path.
+ Version6 = 5,
+ // The current version is Version6.
CurrentVersion = INSTR_PROF_COVMAP_VERSION
};
/// Reader for the raw coverage mapping data.
class RawCoverageMappingReader : public RawCoverageReader {
- ArrayRef<StringRef> TranslationUnitFilenames;
+ ArrayRef<std::string> &TranslationUnitFilenames;
std::vector<StringRef> &Filenames;
std::vector<CounterExpression> &Expressions;
std::vector<CounterMappingRegion> &MappingRegions;
public:
RawCoverageMappingReader(StringRef MappingData,
- ArrayRef<StringRef> TranslationUnitFilenames,
+ ArrayRef<std::string> &TranslationUnitFilenames,
std::vector<StringRef> &Filenames,
std::vector<CounterExpression> &Expressions,
std::vector<CounterMappingRegion> &MappingRegions)
FilenamesBegin(FilenamesBegin), FilenamesSize(FilenamesSize) {}
};
- using DecompressedData = std::vector<std::unique_ptr<SmallVector<char, 0>>>;
-
private:
- std::vector<StringRef> Filenames;
+ std::vector<std::string> Filenames;
std::vector<ProfileMappingRecord> MappingRecords;
InstrProfSymtab ProfileNames;
size_t CurrentRecord = 0;
// D69471, which can split up function records into multiple sections on ELF.
std::string FuncRecords;
- // Used to tie the lifetimes of decompressed strings to the lifetime of this
- // BinaryCoverageReader instance.
- DecompressedData Decompressed;
-
BinaryCoverageReader(std::string &&FuncRecords)
: FuncRecords(std::move(FuncRecords)) {}
/// Reader for the raw coverage filenames.
class RawCoverageFilenamesReader : public RawCoverageReader {
- std::vector<StringRef> &Filenames;
+ std::vector<std::string> &Filenames;
// Read an uncompressed sequence of filenames.
- Error readUncompressed(uint64_t NumFilenames);
+ Error readUncompressed(CovMapVersion Version, uint64_t NumFilenames);
public:
- RawCoverageFilenamesReader(StringRef Data, std::vector<StringRef> &Filenames)
+ RawCoverageFilenamesReader(StringRef Data,
+ std::vector<std::string> &Filenames)
: RawCoverageReader(Data), Filenames(Filenames) {}
RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) = delete;
RawCoverageFilenamesReader &
operator=(const RawCoverageFilenamesReader &) = delete;
- Error read(CovMapVersion Version,
- BinaryCoverageReader::DecompressedData &Decompressed);
+ Error read(CovMapVersion Version);
};
} // end namespace coverage
/// Writer of the filenames section for the instrumentation
/// based code coverage.
class CoverageFilenamesSectionWriter {
- ArrayRef<StringRef> Filenames;
+ ArrayRef<std::string> Filenames;
public:
- CoverageFilenamesSectionWriter(ArrayRef<StringRef> Filenames);
+ CoverageFilenamesSectionWriter(ArrayRef<std::string> Filenames);
/// Write encoded filenames to the given output stream. If \p Compress is
/// true, attempt to compress the filenames.
/* Indexed profile format version (start from 1). */
#define INSTR_PROF_INDEX_VERSION 7
/* Coverage mapping format version (start from 0). */
-#define INSTR_PROF_COVMAP_VERSION 4
+#define INSTR_PROF_COVMAP_VERSION 5
/* Profile version is always of type uint64_t. Reserve the upper 8 bits in the
* version for other variants of profile. We set the lowest bit of the upper 8
return Error::success();
}
-Error RawCoverageFilenamesReader::read(
- CovMapVersion Version,
- BinaryCoverageReader::DecompressedData &Decompressed) {
+Error RawCoverageFilenamesReader::read(CovMapVersion Version) {
uint64_t NumFilenames;
if (auto Err = readSize(NumFilenames))
return Err;
return make_error<CoverageMapError>(coveragemap_error::malformed);
if (Version < CovMapVersion::Version4)
- return readUncompressed(NumFilenames);
+ return readUncompressed(Version, NumFilenames);
// The uncompressed length may exceed the size of the encoded filenames.
// Skip size validation.
return make_error<CoverageMapError>(
coveragemap_error::decompression_failed);
- // Allocate memory for the decompressed filenames. Transfer ownership of
- // the memory to BinaryCoverageReader.
- auto DecompressedStorage = std::make_unique<SmallVector<char, 0>>();
- SmallVectorImpl<char> &StorageBuf = *DecompressedStorage.get();
- Decompressed.push_back(std::move(DecompressedStorage));
+ // Allocate memory for the decompressed filenames.
+ SmallVector<char, 0> StorageBuf;
// Read compressed filenames.
StringRef CompressedFilenames = Data.substr(0, CompressedLen);
StringRef UncompressedFilenames(StorageBuf.data(), StorageBuf.size());
RawCoverageFilenamesReader Delegate(UncompressedFilenames, Filenames);
- return Delegate.readUncompressed(NumFilenames);
+ return Delegate.readUncompressed(Version, NumFilenames);
}
- return readUncompressed(NumFilenames);
+ return readUncompressed(Version, NumFilenames);
}
-Error RawCoverageFilenamesReader::readUncompressed(uint64_t NumFilenames) {
+Error RawCoverageFilenamesReader::readUncompressed(CovMapVersion Version,
+ uint64_t NumFilenames) {
// Read uncompressed filenames.
- for (size_t I = 0; I < NumFilenames; ++I) {
- StringRef Filename;
- if (auto Err = readString(Filename))
+ if (Version < CovMapVersion::Version6) {
+ for (size_t I = 0; I < NumFilenames; ++I) {
+ StringRef Filename;
+ if (auto Err = readString(Filename))
+ return Err;
+ Filenames.push_back(Filename.str());
+ }
+ } else {
+ StringRef CWD;
+ if (auto Err = readString(CWD))
return Err;
- Filenames.push_back(Filename);
+ Filenames.push_back(CWD.str());
+
+ for (size_t I = 1; I < NumFilenames; ++I) {
+ StringRef Filename;
+ if (auto Err = readString(Filename))
+ return Err;
+ if (sys::path::is_absolute(Filename)) {
+ Filenames.push_back(Filename.str());
+ } else {
+ SmallString<256> P(CWD);
+ llvm::sys::path::append(P, Filename);
+ Filenames.push_back(static_cast<std::string>(P));
+ }
+ }
}
return Error::success();
}
//
// Returns a pointer to the next \c CovHeader if it exists, or to an address
// greater than \p CovEnd if not.
- virtual Expected<const char *>
- readCoverageHeader(const char *CovBuf, const char *CovBufEnd,
- BinaryCoverageReader::DecompressedData &Decompressed) = 0;
+ virtual Expected<const char *> readCoverageHeader(const char *CovBuf,
+ const char *CovBufEnd) = 0;
// Read function records.
//
static Expected<std::unique_ptr<CovMapFuncRecordReader>>
get(CovMapVersion Version, InstrProfSymtab &P,
std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
- std::vector<StringRef> &F);
+ std::vector<std::string> &F);
};
// A class for reading coverage mapping function records for a module.
// in \c Records.
DenseMap<NameRefType, size_t> FunctionRecords;
InstrProfSymtab &ProfileNames;
- std::vector<StringRef> &Filenames;
+ std::vector<std::string> &Filenames;
std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records;
// Maps a hash of the filenames in a TU to a \c FileRange. The range
VersionedCovMapFuncRecordReader(
InstrProfSymtab &P,
std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
- std::vector<StringRef> &F)
+ std::vector<std::string> &F)
: ProfileNames(P), Filenames(F), Records(R) {}
~VersionedCovMapFuncRecordReader() override = default;
- Expected<const char *> readCoverageHeader(
- const char *CovBuf, const char *CovBufEnd,
- BinaryCoverageReader::DecompressedData &Decompressed) override {
+ Expected<const char *> readCoverageHeader(const char *CovBuf,
+ const char *CovBufEnd) override {
using namespace support;
if (CovBuf + sizeof(CovMapHeader) > CovBufEnd)
size_t FilenamesBegin = Filenames.size();
StringRef FilenameRegion(CovBuf, FilenamesSize);
RawCoverageFilenamesReader Reader(FilenameRegion, Filenames);
- if (auto Err = Reader.read(Version, Decompressed))
+ if (auto Err = Reader.read(Version))
return std::move(Err);
CovBuf += FilenamesSize;
FilenameRange FileRange(FilenamesBegin, Filenames.size() - FilenamesBegin);
Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(
CovMapVersion Version, InstrProfSymtab &P,
std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
- std::vector<StringRef> &F) {
+ std::vector<std::string> &F) {
using namespace coverage;
switch (Version) {
case CovMapVersion::Version3:
case CovMapVersion::Version4:
case CovMapVersion::Version5:
+ case CovMapVersion::Version6:
// Decompress the name data.
if (Error E = P.create(P.getNameData()))
return std::move(E);
else if (Version == CovMapVersion::Version5)
return std::make_unique<VersionedCovMapFuncRecordReader<
CovMapVersion::Version5, IntPtrT, Endian>>(P, R, F);
+ else if (Version == CovMapVersion::Version6)
+ return std::make_unique<VersionedCovMapFuncRecordReader<
+ CovMapVersion::Version6, IntPtrT, Endian>>(P, R, F);
}
llvm_unreachable("Unsupported version");
}
static Error readCoverageMappingData(
InstrProfSymtab &ProfileNames, StringRef CovMap, StringRef FuncRecords,
std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
- std::vector<StringRef> &Filenames,
- BinaryCoverageReader::DecompressedData &Decompressed) {
+ std::vector<std::string> &Filenames) {
using namespace coverage;
// Read the records in the coverage data section.
// header.
//
// Return a pointer to the next coverage header.
- auto NextOrErr =
- Reader->readCoverageHeader(CovBuf, CovBufEnd, Decompressed);
+ auto NextOrErr = Reader->readCoverageHeader(CovBuf, CovBufEnd);
if (auto E = NextOrErr.takeError())
return E;
CovBuf = NextOrErr.get();
if (Error E =
readCoverageMappingData<uint32_t, support::endianness::little>(
Reader->ProfileNames, Coverage, FuncRecordsRef,
- Reader->MappingRecords, Reader->Filenames,
- Reader->Decompressed))
+ Reader->MappingRecords, 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->Decompressed))
+ Reader->MappingRecords, 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->Decompressed))
+ Reader->MappingRecords, 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->Decompressed))
+ Reader->MappingRecords, Reader->Filenames))
return std::move(E);
} else
return make_error<CoverageMapError>(coveragemap_error::malformed);
Expressions.clear();
MappingRegions.clear();
auto &R = MappingRecords[CurrentRecord];
- RawCoverageMappingReader Reader(
- R.CoverageMapping,
- makeArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize),
- FunctionsFilenames, Expressions, MappingRegions);
+ auto F = makeArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize);
+ RawCoverageMappingReader Reader(R.CoverageMapping, F, FunctionsFilenames,
+ Expressions, MappingRegions);
if (auto Err = Reader.read())
return Err;
using namespace coverage;
CoverageFilenamesSectionWriter::CoverageFilenamesSectionWriter(
- ArrayRef<StringRef> Filenames)
+ ArrayRef<std::string> Filenames)
: Filenames(Filenames) {
#ifndef NDEBUG
StringSet<> NameSet;
// RUN: llvm-cov show %S/Inputs/binary-formats.macho64l -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck %s
// RUN: llvm-cov show %S/Inputs/binary-formats.macho32b -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck %s
// RUN: llvm-cov show %S/Inputs/binary-formats.v3.macho64l -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck %s
+// RUN: llvm-cov show %S/Inputs/binary-formats.v6.linux64l -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck %s
// RUN: llvm-cov export %S/Inputs/binary-formats.macho64l -instr-profile %t.profdata | FileCheck %S/Inputs/binary-formats.canonical.json
struct CoverageMappingTest : ::testing::TestWithParam<std::pair<bool, bool>> {
bool UseMultipleReaders;
StringMap<unsigned> Files;
+ std::vector<std::string> Filenames;
std::vector<InputFunctionCoverageData> InputFunctions;
std::vector<OutputFunctionCoverageData> OutputFunctions;
auto R = Files.find(Name);
if (R != Files.end())
return R->second;
- unsigned Index = Files.size();
+ unsigned Index = Files.size() + 1;
Files.try_emplace(Name, Index);
return Index;
}
void readCoverageRegions(const std::string &Coverage,
OutputFunctionCoverageData &Data) {
- SmallVector<StringRef, 8> Filenames(Files.size());
+ Filenames.resize(Files.size() + 1);
for (const auto &E : Files)
- Filenames[E.getValue()] = E.getKey();
+ Filenames[E.getValue()] = E.getKey().str();
std::vector<CounterExpression> Expressions;
- RawCoverageMappingReader Reader(Coverage, Filenames, Data.Filenames,
+ ArrayRef<std::string> FilenameRefs = llvm::makeArrayRef(Filenames);
+ RawCoverageMappingReader Reader(Coverage, FilenameRefs, Data.Filenames,
Expressions, Data.Regions);
EXPECT_THAT_ERROR(Reader.read(), Succeeded());
}
std::pair<bool, bool>({true, true})),);
TEST(CoverageMappingTest, filename_roundtrip) {
- std::vector<StringRef> Paths({"a", "b", "c", "d", "e"});
+ std::vector<std::string> Paths({"", "a", "b", "c", "d", "e"});
for (bool Compress : {false, true}) {
std::string EncodedFilenames;
Writer.write(OS, Compress);
}
- std::vector<StringRef> ReadFilenames;
+ std::vector<std::string> ReadFilenames;
RawCoverageFilenamesReader Reader(EncodedFilenames, ReadFilenames);
- BinaryCoverageReader::DecompressedData Decompressed;
- EXPECT_THAT_ERROR(Reader.read(CovMapVersion::CurrentVersion, Decompressed),
- Succeeded());
- if (!Compress)
- ASSERT_EQ(Decompressed.size(), 0U);
+ EXPECT_THAT_ERROR(Reader.read(CovMapVersion::CurrentVersion), Succeeded());
ASSERT_EQ(ReadFilenames.size(), Paths.size());
- for (unsigned I = 0; I < Paths.size(); ++I)
+ for (unsigned I = 1; I < Paths.size(); ++I)
ASSERT_TRUE(ReadFilenames[I] == Paths[I]);
}
}