diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h index 58f4fbd4953b..b407fe277c54 100644 --- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h +++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h @@ -75,7 +75,8 @@ inline std::error_code make_error_code(coveragemap_error E) { class CoverageMapError : public ErrorInfo { public: - CoverageMapError(coveragemap_error Err) : Err(Err) { + CoverageMapError(coveragemap_error Err, const Twine &ErrStr = Twine()) + : Err(Err), Msg(ErrStr.str()) { assert(Err != coveragemap_error::success && "Not an error"); } @@ -88,11 +89,13 @@ public: } coveragemap_error get() const { return Err; } + const std::string &getMessage() const { return Msg; } static char ID; private: coveragemap_error Err; + std::string Msg; }; /// A Counter is an abstract value that describes how to compute the @@ -864,7 +867,8 @@ struct CovMapFunctionRecordV1 { uint32_t NameS = support::endian::byte_swap(NameSize); FuncName = ProfileNames.getFuncName(NameRef, NameS); if (NameS && FuncName.empty()) - return make_error(coveragemap_error::malformed); + return make_error(coveragemap_error::malformed, + "function name is empty"); return Error::success(); } diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp index 849ee80bfaa3..ff4171d087cd 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp @@ -237,7 +237,8 @@ Error CoverageMapping::loadFunctionRecord( IndexedInstrProfReader &ProfileReader) { StringRef OrigFuncName = Record.FunctionName; if (OrigFuncName.empty()) - return make_error(coveragemap_error::malformed); + return make_error(coveragemap_error::malformed, + "record function name is empty"); if (Record.Filenames.empty()) OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName); @@ -342,7 +343,7 @@ static Error handleMaybeNoDataFoundError(Error E) { std::move(E), [](const CoverageMapError &CME) { if (CME.get() == coveragemap_error::no_data_found) return static_cast(Error::success()); - return make_error(CME.get()); + return make_error(CME.get(), CME.getMessage()); }); } @@ -925,26 +926,45 @@ LineCoverageIterator &LineCoverageIterator::operator++() { return *this; } -static std::string getCoverageMapErrString(coveragemap_error Err) { +static std::string getCoverageMapErrString(coveragemap_error Err, + const std::string &ErrMsg = "") { + std::string Msg; + raw_string_ostream OS(Msg); + switch (Err) { case coveragemap_error::success: - return "Success"; + OS << "success"; + break; case coveragemap_error::eof: - return "End of File"; + OS << "end of File"; + break; case coveragemap_error::no_data_found: - return "No coverage data found"; + OS << "no coverage data found"; + break; case coveragemap_error::unsupported_version: - return "Unsupported coverage format version"; + OS << "unsupported coverage format version"; + break; case coveragemap_error::truncated: - return "Truncated coverage data"; + OS << "truncated coverage data"; + break; case coveragemap_error::malformed: - return "Malformed coverage data"; + OS << "malformed coverage data"; + break; case coveragemap_error::decompression_failed: - return "Failed to decompress coverage data (zlib)"; + OS << "failed to decompress coverage data (zlib)"; + break; case coveragemap_error::invalid_or_missing_arch_specifier: - return "`-arch` specifier is invalid or missing for universal binary"; + OS << "`-arch` specifier is invalid or missing for universal binary"; + break; + default: + llvm_unreachable("invalid coverage mapping error."); } - llvm_unreachable("A value of coveragemap_error has no message."); + + // If optional error message is not empty, append it to the message. + if (!ErrMsg.empty()) + OS << ": " << ErrMsg; + + return Msg; } namespace { @@ -962,7 +982,7 @@ class CoverageMappingErrorCategoryType : public std::error_category { } // end anonymous namespace std::string CoverageMapError::message() const { - return getCoverageMapErrString(Err); + return getCoverageMapErrString(Err, Msg); } const std::error_category &llvm::coverage::coveragemap_category() { diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp index bee9c8d3fce7..e468fbf7184f 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp @@ -68,7 +68,8 @@ Error RawCoverageReader::readULEB128(uint64_t &Result) { unsigned N = 0; Result = decodeULEB128(Data.bytes_begin(), &N); if (N > Data.size()) - return make_error(coveragemap_error::malformed); + return make_error(coveragemap_error::malformed, + "the size of ULEB128 is too big"); Data = Data.substr(N); return Error::success(); } @@ -77,7 +78,9 @@ Error RawCoverageReader::readIntMax(uint64_t &Result, uint64_t MaxPlus1) { if (auto Err = readULEB128(Result)) return Err; if (Result >= MaxPlus1) - return make_error(coveragemap_error::malformed); + return make_error( + coveragemap_error::malformed, + "the value of ULEB128 is greater than or equal to MaxPlus1"); return Error::success(); } @@ -85,7 +88,8 @@ Error RawCoverageReader::readSize(uint64_t &Result) { if (auto Err = readULEB128(Result)) return Err; if (Result > Data.size()) - return make_error(coveragemap_error::malformed); + return make_error(coveragemap_error::malformed, + "the value of ULEB128 is too big"); return Error::success(); } @@ -103,7 +107,8 @@ Error RawCoverageFilenamesReader::read(CovMapVersion Version) { if (auto Err = readSize(NumFilenames)) return Err; if (!NumFilenames) - return make_error(coveragemap_error::malformed); + return make_error(coveragemap_error::malformed, + "number of filenames is zero"); if (Version < CovMapVersion::Version4) return readUncompressed(Version, NumFilenames); @@ -201,13 +206,15 @@ Error RawCoverageMappingReader::decodeCounter(unsigned Value, Counter &C) { case CounterExpression::Add: { auto ID = Value >> Counter::EncodingTagBits; if (ID >= Expressions.size()) - return make_error(coveragemap_error::malformed); + return make_error(coveragemap_error::malformed, + "counter expression is invalid"); Expressions[ID].Kind = CounterExpression::ExprKind(Tag); C = Counter::getExpression(ID); break; } default: - return make_error(coveragemap_error::malformed); + return make_error(coveragemap_error::malformed, + "counter expression kind is invalid"); } return Error::success(); } @@ -268,7 +275,8 @@ Error RawCoverageMappingReader::readMappingRegionsSubArray( ExpandedFileID = EncodedCounterAndRegion >> Counter::EncodingCounterTagAndExpansionRegionTagBits; if (ExpandedFileID >= NumFileIDs) - return make_error(coveragemap_error::malformed); + return make_error(coveragemap_error::malformed, + "ExpandedFileID is invalid"); } else { switch (EncodedCounterAndRegion >> Counter::EncodingCounterTagAndExpansionRegionTagBits) { @@ -287,7 +295,8 @@ Error RawCoverageMappingReader::readMappingRegionsSubArray( return Err; break; default: - return make_error(coveragemap_error::malformed); + return make_error(coveragemap_error::malformed, + "region kind is incorrect"); } } } @@ -300,7 +309,8 @@ Error RawCoverageMappingReader::readMappingRegionsSubArray( if (auto Err = readULEB128(ColumnStart)) return Err; if (ColumnStart > std::numeric_limits::max()) - return make_error(coveragemap_error::malformed); + return make_error(coveragemap_error::malformed, + "start column is too big"); if (auto Err = readIntMax(NumLines, std::numeric_limits::max())) return Err; if (auto Err = readIntMax(ColumnEnd, std::numeric_limits::max())) @@ -341,7 +351,9 @@ Error RawCoverageMappingReader::readMappingRegionsSubArray( LineStart, ColumnStart, LineStart + NumLines, ColumnEnd, Kind); if (CMR.startLoc() > CMR.endLoc()) - return make_error(coveragemap_error::malformed); + return make_error( + coveragemap_error::malformed, + "counter mapping region locations are incorrect"); MappingRegions.push_back(CMR); } return Error::success(); @@ -613,7 +625,9 @@ public: using namespace support; if (CovBuf + sizeof(CovMapHeader) > CovBufEnd) - return make_error(coveragemap_error::malformed); + return make_error( + coveragemap_error::malformed, + "coverage mapping header section is larger than buffer size"); auto CovHeader = reinterpret_cast(CovBuf); uint32_t NRecords = CovHeader->getNRecords(); uint32_t FilenamesSize = CovHeader->getFilenamesSize(); @@ -634,7 +648,9 @@ public: // Get the filenames. if (CovBuf + FilenamesSize > CovBufEnd) - return make_error(coveragemap_error::malformed); + return make_error( + coveragemap_error::malformed, + "filenames section is larger than buffer size"); size_t FilenamesBegin = Filenames.size(); StringRef FilenameRegion(CovBuf, FilenamesSize); RawCoverageFilenamesReader Reader(FilenameRegion, Filenames, @@ -673,12 +689,15 @@ public: // coverage header). const char *MappingBuf = CovBuf; if (Version >= CovMapVersion::Version4 && CoverageSize != 0) - return make_error(coveragemap_error::malformed); + return make_error(coveragemap_error::malformed, + "coverage mapping size is not zero"); CovBuf += CoverageSize; const char *MappingEnd = CovBuf; if (CovBuf > CovBufEnd) - return make_error(coveragemap_error::malformed); + return make_error( + coveragemap_error::malformed, + "function records section is larger than buffer size"); if (Version < CovMapVersion::Version4) { // Read each function record. @@ -707,7 +726,9 @@ public: CFR->template advanceByOne(OutOfLineMappingBuf); if (Version < CovMapVersion::Version4) if (NextMappingBuf > OutOfLineMappingBufEnd) - return make_error(coveragemap_error::malformed); + return make_error( + coveragemap_error::malformed, + "next mapping buffer is larger than buffer size"); // Look up the set of filenames associated with this function record. std::optional FileRange; @@ -717,7 +738,10 @@ public: uint64_t FilenamesRef = CFR->template getFilenamesRef(); auto It = FileRangeMap.find(FilenamesRef); if (It == FileRangeMap.end()) - return make_error(coveragemap_error::malformed); + return make_error( + coveragemap_error::malformed, + "no filename found for function with hash=0x" + + Twine::utohexstr(FilenamesRef)); else FileRange = It->getSecond(); } @@ -728,7 +752,9 @@ public: CFR->template getCoverageMapping(OutOfLineMappingBuf); if (Version >= CovMapVersion::Version4 && Mapping.data() + Mapping.size() > FuncRecBufEnd) - return make_error(coveragemap_error::malformed); + return make_error( + coveragemap_error::malformed, + "coverage mapping data is larger than buffer size"); if (Error Err = insertFunctionRecordIfNeeded(CFR, Mapping, *FileRange)) return Err; } @@ -854,7 +880,9 @@ BinaryCoverageReader::createCoverageReaderFromBuffer( Reader->MappingRecords, CompilationDir, Reader->Filenames)) return std::move(E); } else - return make_error(coveragemap_error::malformed); + return make_error( + coveragemap_error::malformed, + "not supported endianness or bytes in address"); return std::move(Reader); } @@ -866,7 +894,8 @@ loadTestingFormat(StringRef Data, StringRef CompilationDir) { // Read the magic and version. Data = Data.substr(sizeof(TestingFormatMagic)); if (Data.size() < sizeof(uint64_t)) - return make_error(coveragemap_error::malformed); + return make_error(coveragemap_error::malformed, + "the size of data is too small"); auto TestingVersion = support::endian::byte_swap( *reinterpret_cast(Data.data())); @@ -878,17 +907,21 @@ loadTestingFormat(StringRef Data, StringRef CompilationDir) { unsigned N = 0; uint64_t ProfileNamesSize = decodeULEB128(Data.bytes_begin(), &N); if (N > Data.size()) - return make_error(coveragemap_error::malformed); + return make_error( + coveragemap_error::malformed, + "the size of TestingFormatMagic is too big"); Data = Data.substr(N); if (Data.empty()) return make_error(coveragemap_error::truncated); N = 0; uint64_t Address = decodeULEB128(Data.bytes_begin(), &N); if (N > Data.size()) - return make_error(coveragemap_error::malformed); + return make_error(coveragemap_error::malformed, + "the size of ULEB128 is too big"); Data = Data.substr(N); if (Data.size() < ProfileNamesSize) - return make_error(coveragemap_error::malformed); + return make_error(coveragemap_error::malformed, + "the size of ProfileNames is too big"); InstrProfSymtab ProfileNames; if (Error E = ProfileNames.create(Data.substr(0, ProfileNamesSize), Address)) return std::move(E); @@ -900,10 +933,13 @@ loadTestingFormat(StringRef Data, StringRef CompilationDir) { N = 0; CoverageMappingSize = decodeULEB128(Data.bytes_begin(), &N); if (N > Data.size()) - return make_error(coveragemap_error::malformed); + return make_error(coveragemap_error::malformed, + "the size of ULEB128 is too big"); Data = Data.substr(N); if (CoverageMappingSize < sizeof(CovMapHeader)) - return make_error(coveragemap_error::malformed); + return make_error( + coveragemap_error::malformed, + "the size of CoverageMapping is teoo small"); } else if (TestingVersion != uint64_t(TestingFormatVersion::Version1)) { return make_error(coveragemap_error::unsupported_version); } @@ -911,10 +947,13 @@ loadTestingFormat(StringRef Data, StringRef CompilationDir) { // Skip the padding bytes because coverage map data has an alignment of 8. auto Pad = offsetToAlignedAddr(Data.data(), Align(8)); if (Data.size() < Pad) - return make_error(coveragemap_error::malformed); + return make_error(coveragemap_error::malformed, + "insufficient padding"); Data = Data.substr(Pad); if (Data.size() < sizeof(CovMapHeader)) - return make_error(coveragemap_error::malformed); + return make_error( + coveragemap_error::malformed, + "coverage mapping header section is larger than data size"); auto const *CovHeader = reinterpret_cast( Data.substr(0, sizeof(CovMapHeader)).data()); auto Version = @@ -937,13 +976,15 @@ loadTestingFormat(StringRef Data, StringRef CompilationDir) { // Read the CoverageRecords data. if (Version < CovMapVersion::Version4) { if (!Data.empty()) - return make_error(coveragemap_error::malformed); + return make_error(coveragemap_error::malformed, + "data is not empty"); } else { // Skip the padding bytes because coverage records data has an alignment // of 8. Pad = offsetToAlignedAddr(Data.data(), Align(8)); if (Data.size() < Pad) - return make_error(coveragemap_error::malformed); + return make_error(coveragemap_error::malformed, + "insufficient padding"); Data = Data.substr(Pad); } BinaryCoverageReader::FuncRecordsStorage CoverageRecords = @@ -1000,7 +1041,8 @@ loadBinaryFormat(std::unique_ptr Bin, StringRef Arch, return errorCodeToError(object_error::arch_not_found); } else // We can only handle object files. - return make_error(coveragemap_error::malformed); + return make_error(coveragemap_error::malformed, + "binary is not an object file"); // The coverage uses native pointer sizes for the object it's written in. uint8_t BytesInAddress = OF->getBytesInAddress(); @@ -1022,7 +1064,8 @@ loadBinaryFormat(std::unique_ptr Bin, StringRef Arch, return std::move(E); std::vector CoverageSectionRefs = *CoverageSection; if (CoverageSectionRefs.size() != 1) - return make_error(coveragemap_error::malformed); + return make_error(coveragemap_error::malformed, + "the size of name section is not one"); auto CoverageMappingOrErr = CoverageSectionRefs.back().getContents(); if (!CoverageMappingOrErr) return CoverageMappingOrErr.takeError(); @@ -1031,7 +1074,9 @@ loadBinaryFormat(std::unique_ptr Bin, StringRef Arch, InstrProfSymtab ProfileNames; std::vector NamesSectionRefs = *NamesSection; if (NamesSectionRefs.size() != 1) - return make_error(coveragemap_error::malformed); + return make_error( + coveragemap_error::malformed, + "the size of coverage mapping section is not one"); if (Error E = ProfileNames.create(NamesSectionRefs.back())) return std::move(E); diff --git a/llvm/test/tools/llvm-cov/double_dots.c b/llvm/test/tools/llvm-cov/double_dots.c index 9f4b7c125f65..c3eec3ce379c 100644 --- a/llvm/test/tools/llvm-cov/double_dots.c +++ b/llvm/test/tools/llvm-cov/double_dots.c @@ -21,4 +21,4 @@ int main() {} // Check that we get the right error when writing to an invalid path: // RUN: not llvm-cov show %S/Inputs/double_dots.covmapping -instr-profile=%t.profdata -o /dev/null 2>&1 | FileCheck %s -check-prefix=ERROR-MESSAGE -// ERROR-MESSAGE: error: {{.*}}: Could not create index file! +// ERROR-MESSAGE: error: {{.*}}: could not create index file! diff --git a/llvm/test/tools/llvm-cov/missing-binaries.test b/llvm/test/tools/llvm-cov/missing-binaries.test index e0ba107ac9f4..0ba1d27ec6ec 100644 --- a/llvm/test/tools/llvm-cov/missing-binaries.test +++ b/llvm/test/tools/llvm-cov/missing-binaries.test @@ -1,4 +1,4 @@ RUN: llvm-profdata merge %S/Inputs/binary-formats.proftext -o %t.profdata RUN: not llvm-cov show -instr-profile=%t.profdata --object=%t.nonexistent.binary.1 --object=%t.nonexistent.binary.2 2>&1 | FileCheck %s -CHECK: Failed to load coverage: '{{.*}}nonexistent.binary.1': +CHECK: failed to load coverage: '{{.*}}nonexistent.binary.1': diff --git a/llvm/test/tools/llvm-cov/misssing-profdata.test b/llvm/test/tools/llvm-cov/misssing-profdata.test index 0ea8fd74e5bb..ab0a04f7a5b9 100644 --- a/llvm/test/tools/llvm-cov/misssing-profdata.test +++ b/llvm/test/tools/llvm-cov/misssing-profdata.test @@ -2,4 +2,4 @@ RUN: not llvm-cov show -instr-profile=%t.nonexistent.profdata %t.nonexistent 2>& RUN: not llvm-cov export -instr-profile=%t.nonexistent.profdata %t.nonexistent 2>&1 | FileCheck %s RUN: not llvm-cov report -instr-profile=%t.nonexistent.profdata %t.nonexistent 2>&1 | FileCheck %s -CHECK: nonexistent.profdata: Could not read profile data! +CHECK: nonexistent.profdata: could not read profile data! diff --git a/llvm/test/tools/llvm-cov/report.cpp b/llvm/test/tools/llvm-cov/report.cpp index 6676ed812b06..61f22ba89171 100644 --- a/llvm/test/tools/llvm-cov/report.cpp +++ b/llvm/test/tools/llvm-cov/report.cpp @@ -3,7 +3,7 @@ // RUN: llvm-cov report -show-functions %S/Inputs/report.covmapping -instr-profile %S/Inputs/report.profdata -path-equivalence=/tmp,%S %s does-not-exist.cpp 2>&1 | FileCheck -check-prefix=FILT %s // RUN: not llvm-cov report -show-functions %S/Inputs/report.covmapping -instr-profile %S/Inputs/report.profdata -path-equivalence=/tmp,%S 2>&1 | FileCheck -check-prefix=NO_FILES %s -// NO_FILES: Source files must be specified when -show-functions=true is specified +// NO_FILES: source files must be specified when -show-functions=true is specified // CHECK: Regions Missed Regions Cover Functions Missed Functions Executed Instantiations Missed Insts. Executed Lines Missed Lines Cover // CHECK-NEXT: --- diff --git a/llvm/test/tools/llvm-cov/universal-binary.c b/llvm/test/tools/llvm-cov/universal-binary.c index 985bad345cd1..3eb8c25e95d5 100644 --- a/llvm/test/tools/llvm-cov/universal-binary.c +++ b/llvm/test/tools/llvm-cov/universal-binary.c @@ -14,13 +14,13 @@ int main(int argc, const char *argv[]) {} // RUN: not llvm-cov show %S/Inputs/universal-binary -instr-profile %t.profdata -path-equivalence=/tmp,%S %s 2>&1 | FileCheck --check-prefix=WRONG-ARCH %s // RUN: not llvm-cov show %S/Inputs/universal-binary -instr-profile %t.profdata -path-equivalence=/tmp,%S %s -arch i386 2>&1 | FileCheck --check-prefix=WRONG-ARCH %s -// WRONG-ARCH: Failed to load coverage: '{{.*}}universal-binary': `-arch` specifier is invalid or missing for universal binary +// WRONG-ARCH: failed to load coverage: '{{.*}}universal-binary': `-arch` specifier is invalid or missing for universal binary // RUN: not llvm-cov show %S/Inputs/universal-binary -instr-profile %t.profdata -path-equivalence=/tmp,%S %s -arch definitly_a_made_up_architecture 2>&1 | FileCheck --check-prefix=MADE-UP-ARCH %s -// MADE-UP-ARCH: Unknown architecture: definitly_a_made_up_architecture +// MADE-UP-ARCH: unknown architecture: definitly_a_made_up_architecture // RUN: not llvm-cov show %S/Inputs/universal-binary -instr-profile %t.profdata -path-equivalence=/tmp,%S %s -arch=x86_64 -arch=x86_64 2>&1 | FileCheck --check-prefix=TOO-MANY-ARCH %s -// TOO-MANY-ARCH: Number of architectures doesn't match the number of objects +// TOO-MANY-ARCH: number of architectures doesn't match the number of objects // // RUN: not llvm-cov report -instr-profile %t.profdata 2>&1 | FileCheck --check-prefix=MISSING-BINARY %s // MISSING-BINARY: No filenames specified! diff --git a/llvm/test/tools/llvm-cov/warnings.h b/llvm/test/tools/llvm-cov/warnings.h index b7b124565f59..8c50dc35c5b7 100644 --- a/llvm/test/tools/llvm-cov/warnings.h +++ b/llvm/test/tools/llvm-cov/warnings.h @@ -13,4 +13,4 @@ // FAKE-FUNC-STDERR: Could not read coverage for '{{.*}}'. // RUN: not llvm-cov report %S/Inputs/malformedRegions.covmapping -instr-profile %S/Inputs/elf_binary_comdat.profdata 2>&1 | FileCheck %s -check-prefix=MALFORMED-REGION -// MALFORMED-REGION: Failed to load coverage: '{{.*}}malformedRegions.covmapping': Malformed coverage data +// MALFORMED-REGION: failed to load coverage: '{{.*}}malformedRegions.covmapping': malformed coverage data diff --git a/llvm/tools/llvm-cov/CodeCoverage.cpp b/llvm/tools/llvm-cov/CodeCoverage.cpp index f26db153d4e3..b5d763d8643c 100644 --- a/llvm/tools/llvm-cov/CodeCoverage.cpp +++ b/llvm/tools/llvm-cov/CodeCoverage.cpp @@ -447,7 +447,7 @@ std::unique_ptr CodeCoverageTool::load() { ObjectFilenames, PGOFilename, *FS, CoverageArches, ViewOpts.CompilationDirectory, BIDFetcher.get(), CheckBinaryIDs); if (Error E = CoverageOrErr.takeError()) { - error("Failed to load coverage: " + toString(std::move(E))); + error("failed to load coverage: " + toString(std::move(E))); return nullptr; } auto Coverage = std::move(CoverageOrErr.get()); @@ -599,7 +599,7 @@ void CodeCoverageTool::demangleSymbols(const CoverageMapping &Coverage) { DemanglerData.split(Symbols, '\n', /*MaxSplit=*/NumSymbols, /*KeepEmpty=*/false); if (Symbols.size() != NumSymbols) { - error("Demangler did not provide expected number of symbols"); + error("demangler did not provide expected number of symbols"); return; } @@ -623,7 +623,7 @@ void CodeCoverageTool::writeSourceFileView(StringRef SourceFile, auto OSOrErr = Printer->createViewFile(SourceFile, /*InToplevel=*/false); if (Error E = OSOrErr.takeError()) { - error("Could not create view file!", toString(std::move(E))); + error("could not create view file!", toString(std::move(E))); return; } auto OS = std::move(OSOrErr.get()); @@ -842,7 +842,7 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) { if (!DemanglerOpts.empty()) { auto DemanglerPathOrErr = sys::findProgramByName(DemanglerOpts[0]); if (!DemanglerPathOrErr) { - error("Could not find the demangler!", + error("could not find the demangler!", DemanglerPathOrErr.getError().message()); return 1; } @@ -901,14 +901,14 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) { if (!Arches.empty()) { for (const std::string &Arch : Arches) { if (Triple(Arch).getArch() == llvm::Triple::ArchType::UnknownArch) { - error("Unknown architecture: " + Arch); + error("unknown architecture: " + Arch); return 1; } CoverageArches.emplace_back(Arch); } if (CoverageArches.size() != 1 && CoverageArches.size() != ObjectFilenames.size()) { - error("Number of architectures doesn't match the number of objects"); + error("number of architectures doesn't match the number of objects"); return 1; } } @@ -1011,7 +1011,7 @@ int CodeCoverageTool::doShow(int argc, const char **argv, return Err; if (ViewOpts.Format == CoverageViewOptions::OutputFormat::Lcov) { - error("Lcov format should be used with 'llvm-cov export'."); + error("lcov format should be used with 'llvm-cov export'."); return 1; } @@ -1073,14 +1073,14 @@ int CodeCoverageTool::doShow(int argc, const char **argv, if (ViewOpts.hasOutputDirectory()) { if (auto E = sys::fs::create_directories(ViewOpts.ShowOutputDirectory)) { - error("Could not create output directory!", E.message()); + error("could not create output directory!", E.message()); return 1; } } sys::fs::file_status Status; if (std::error_code EC = sys::fs::status(PGOFilename, Status)) { - error("Could not read profile data!" + EC.message(), PGOFilename); + error("could not read profile data!" + EC.message(), PGOFilename); return 1; } @@ -1107,7 +1107,7 @@ int CodeCoverageTool::doShow(int argc, const char **argv, // Create an index out of the source files. if (ViewOpts.hasOutputDirectory()) { if (Error E = Printer->createIndexFile(SourceFiles, *Coverage, Filters)) { - error("Could not create index file!", toString(std::move(E))); + error("could not create index file!", toString(std::move(E))); return 1; } } @@ -1128,7 +1128,7 @@ int CodeCoverageTool::doShow(int argc, const char **argv, auto OSOrErr = Printer->createViewFile(File, /*InToplevel=*/false); if (Error E = OSOrErr.takeError()) { - error("Could not create view file!", toString(std::move(E))); + error("could not create view file!", toString(std::move(E))); return 1; } auto OS = std::move(OSOrErr.get()); @@ -1193,13 +1193,13 @@ int CodeCoverageTool::doReport(int argc, const char **argv, error("HTML output for summary reports is not yet supported."); return 1; } else if (ViewOpts.Format == CoverageViewOptions::OutputFormat::Lcov) { - error("Lcov format should be used with 'llvm-cov export'."); + error("lcov format should be used with 'llvm-cov export'."); return 1; } sys::fs::file_status Status; if (std::error_code EC = sys::fs::status(PGOFilename, Status)) { - error("Could not read profile data!" + EC.message(), PGOFilename); + error("could not read profile data!" + EC.message(), PGOFilename); return 1; } @@ -1215,7 +1215,7 @@ int CodeCoverageTool::doReport(int argc, const char **argv, Report.renderFileReports(llvm::outs(), SourceFiles); } else { if (SourceFiles.empty()) { - error("Source files must be specified when -show-functions=true is " + error("source files must be specified when -show-functions=true is " "specified"); return 1; } @@ -1252,20 +1252,20 @@ int CodeCoverageTool::doExport(int argc, const char **argv, if (ViewOpts.Format != CoverageViewOptions::OutputFormat::Text && ViewOpts.Format != CoverageViewOptions::OutputFormat::Lcov) { - error("Coverage data can only be exported as textual JSON or an " + error("coverage data can only be exported as textual JSON or an " "lcov tracefile."); return 1; } sys::fs::file_status Status; if (std::error_code EC = sys::fs::status(PGOFilename, Status)) { - error("Could not read profile data!" + EC.message(), PGOFilename); + error("could not read profile data!" + EC.message(), PGOFilename); return 1; } auto Coverage = load(); if (!Coverage) { - error("Could not load coverage information"); + error("could not load coverage information"); return 1; } diff --git a/llvm/unittests/ProfileData/CoverageMappingTest.cpp b/llvm/unittests/ProfileData/CoverageMappingTest.cpp index 884a76c83061..873bc05b2ecc 100644 --- a/llvm/unittests/ProfileData/CoverageMappingTest.cpp +++ b/llvm/unittests/ProfileData/CoverageMappingTest.cpp @@ -23,14 +23,17 @@ using namespace llvm; using namespace coverage; [[nodiscard]] static ::testing::AssertionResult -ErrorEquals(coveragemap_error Expected, Error E) { +ErrorEquals(Error E, coveragemap_error Expected_Err, + const std::string &Expected_Msg = std::string()) { coveragemap_error Found; + std::string Msg; std::string FoundMsg; handleAllErrors(std::move(E), [&](const CoverageMapError &CME) { Found = CME.get(); + Msg = CME.getMessage(); FoundMsg = CME.message(); }); - if (Expected == Found) + if (Expected_Err == Found && Msg == Expected_Msg) return ::testing::AssertionSuccess(); return ::testing::AssertionFailure() << "error: " << FoundMsg << "\n"; } @@ -342,7 +345,8 @@ TEST_P(CoverageMappingTest, load_coverage_with_bogus_function_name) { ProfileWriter.addRecord({"", 0x1234, {10}}, Err); startFunction("", 0x1234); addCMR(Counter::getCounter(0), "foo", 1, 1, 5, 5); - EXPECT_TRUE(ErrorEquals(coveragemap_error::malformed, loadCoverageMapping())); + EXPECT_TRUE(ErrorEquals(loadCoverageMapping(), coveragemap_error::malformed, + "record function name is empty")); } TEST_P(CoverageMappingTest, load_coverage_for_several_functions) {