[llvm] [llvm-cov] - Output better error message when the error kind is `coveragemap_error::malforme`. (PR #65264)

via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 6 06:57:50 PDT 2023


https://github.com/MaggieYingYi updated https://github.com/llvm/llvm-project/pull/65264:

>From ba513007051fdf6c1acdecff950877de15829da0 Mon Sep 17 00:00:00 2001
From: Ying Yi <ying.yi at sony.com>
Date: Fri, 1 Sep 2023 14:18:46 +0100
Subject: [PATCH] [llvm-cov] - Output better error message when the error kind
 is `coveragemap_error::malforme`.

The current llvm-cov error message for kind `coveragemap_error::malforme`, just gives the issue kind without any reason for what caused the issue. This patch is aimed at improving the llvm-cov error message to help identify what caused the issue.

Reviewed By: MaskRay

Close: https://github.com/llvm/llvm-project/pull/65264
---
 .../ProfileData/Coverage/CoverageMapping.h    |   8 +-
 .../ProfileData/Coverage/CoverageMapping.cpp  |  46 +++++---
 .../Coverage/CoverageMappingReader.cpp        | 107 +++++++++++++-----
 llvm/test/tools/llvm-cov/double_dots.c        |   2 +-
 .../test/tools/llvm-cov/missing-binaries.test |   2 +-
 .../tools/llvm-cov/misssing-profdata.test     |   2 +-
 llvm/test/tools/llvm-cov/report.cpp           |   2 +-
 llvm/test/tools/llvm-cov/universal-binary.c   |   6 +-
 llvm/test/tools/llvm-cov/warnings.h           |   2 +-
 llvm/tools/llvm-cov/CodeCoverage.cpp          |  34 +++---
 .../ProfileData/CoverageMappingTest.cpp       |  10 +-
 11 files changed, 147 insertions(+), 74 deletions(-)

diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 58f4fbd4953ba8b..b407fe277c543b8 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<CoverageMapError> {
 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 @@ class CoverageMapError : public ErrorInfo<CoverageMapError> {
   }
 
   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<uint32_t, Endian>(NameSize);
     FuncName = ProfileNames.getFuncName(NameRef, NameS);
     if (NameS && FuncName.empty())
-      return make_error<CoverageMapError>(coveragemap_error::malformed);
+      return make_error<CoverageMapError>(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 849ee80bfaa3326..ff4171d087cda98 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<CoverageMapError>(coveragemap_error::malformed);
+    return make_error<CoverageMapError>(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>(Error::success());
-        return make_error<CoverageMapError>(CME.get());
+        return make_error<CoverageMapError>(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 bee9c8d3fce7451..e468fbf7184f8f9 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<CoverageMapError>(coveragemap_error::malformed);
+    return make_error<CoverageMapError>(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<CoverageMapError>(coveragemap_error::malformed);
+    return make_error<CoverageMapError>(
+        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<CoverageMapError>(coveragemap_error::malformed);
+    return make_error<CoverageMapError>(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<CoverageMapError>(coveragemap_error::malformed);
+    return make_error<CoverageMapError>(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<CoverageMapError>(coveragemap_error::malformed);
+      return make_error<CoverageMapError>(coveragemap_error::malformed,
+                                          "counter expression is invalid");
     Expressions[ID].Kind = CounterExpression::ExprKind(Tag);
     C = Counter::getExpression(ID);
     break;
   }
   default:
-    return make_error<CoverageMapError>(coveragemap_error::malformed);
+    return make_error<CoverageMapError>(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<CoverageMapError>(coveragemap_error::malformed);
+          return make_error<CoverageMapError>(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<CoverageMapError>(coveragemap_error::malformed);
+          return make_error<CoverageMapError>(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<unsigned>::max())
-      return make_error<CoverageMapError>(coveragemap_error::malformed);
+      return make_error<CoverageMapError>(coveragemap_error::malformed,
+                                          "start column is too big");
     if (auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max()))
       return Err;
     if (auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max()))
@@ -341,7 +351,9 @@ Error RawCoverageMappingReader::readMappingRegionsSubArray(
                                     LineStart, ColumnStart,
                                     LineStart + NumLines, ColumnEnd, Kind);
     if (CMR.startLoc() > CMR.endLoc())
-      return make_error<CoverageMapError>(coveragemap_error::malformed);
+      return make_error<CoverageMapError>(
+          coveragemap_error::malformed,
+          "counter mapping region locations are incorrect");
     MappingRegions.push_back(CMR);
   }
   return Error::success();
@@ -613,7 +625,9 @@ class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
     using namespace support;
 
     if (CovBuf + sizeof(CovMapHeader) > CovBufEnd)
-      return make_error<CoverageMapError>(coveragemap_error::malformed);
+      return make_error<CoverageMapError>(
+          coveragemap_error::malformed,
+          "coverage mapping header section is larger than buffer size");
     auto CovHeader = reinterpret_cast<const CovMapHeader *>(CovBuf);
     uint32_t NRecords = CovHeader->getNRecords<Endian>();
     uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>();
@@ -634,7 +648,9 @@ class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
 
     // Get the filenames.
     if (CovBuf + FilenamesSize > CovBufEnd)
-      return make_error<CoverageMapError>(coveragemap_error::malformed);
+      return make_error<CoverageMapError>(
+          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 @@ class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
     // coverage header).
     const char *MappingBuf = CovBuf;
     if (Version >= CovMapVersion::Version4 && CoverageSize != 0)
-      return make_error<CoverageMapError>(coveragemap_error::malformed);
+      return make_error<CoverageMapError>(coveragemap_error::malformed,
+                                          "coverage mapping size is not zero");
     CovBuf += CoverageSize;
     const char *MappingEnd = CovBuf;
 
     if (CovBuf > CovBufEnd)
-      return make_error<CoverageMapError>(coveragemap_error::malformed);
+      return make_error<CoverageMapError>(
+          coveragemap_error::malformed,
+          "function records section is larger than buffer size");
 
     if (Version < CovMapVersion::Version4) {
       // Read each function record.
@@ -707,7 +726,9 @@ class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
           CFR->template advanceByOne<Endian>(OutOfLineMappingBuf);
       if (Version < CovMapVersion::Version4)
         if (NextMappingBuf > OutOfLineMappingBufEnd)
-          return make_error<CoverageMapError>(coveragemap_error::malformed);
+          return make_error<CoverageMapError>(
+              coveragemap_error::malformed,
+              "next mapping buffer is larger than buffer size");
 
       // Look up the set of filenames associated with this function record.
       std::optional<FilenameRange> FileRange;
@@ -717,7 +738,10 @@ class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
         uint64_t FilenamesRef = CFR->template getFilenamesRef<Endian>();
         auto It = FileRangeMap.find(FilenamesRef);
         if (It == FileRangeMap.end())
-          return make_error<CoverageMapError>(coveragemap_error::malformed);
+          return make_error<CoverageMapError>(
+              coveragemap_error::malformed,
+              "no filename found for function with hash=0x" +
+                  Twine::utohexstr(FilenamesRef));
         else
           FileRange = It->getSecond();
       }
@@ -728,7 +752,9 @@ class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
             CFR->template getCoverageMapping<Endian>(OutOfLineMappingBuf);
         if (Version >= CovMapVersion::Version4 &&
             Mapping.data() + Mapping.size() > FuncRecBufEnd)
-          return make_error<CoverageMapError>(coveragemap_error::malformed);
+          return make_error<CoverageMapError>(
+              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<CoverageMapError>(coveragemap_error::malformed);
+    return make_error<CoverageMapError>(
+        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<CoverageMapError>(coveragemap_error::malformed);
+    return make_error<CoverageMapError>(coveragemap_error::malformed,
+                                        "the size of data is too small");
   auto TestingVersion =
       support::endian::byte_swap<uint64_t, support::endianness::little>(
           *reinterpret_cast<const uint64_t *>(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<CoverageMapError>(coveragemap_error::malformed);
+    return make_error<CoverageMapError>(
+        coveragemap_error::malformed,
+        "the size of TestingFormatMagic is too big");
   Data = Data.substr(N);
   if (Data.empty())
     return make_error<CoverageMapError>(coveragemap_error::truncated);
   N = 0;
   uint64_t Address = decodeULEB128(Data.bytes_begin(), &N);
   if (N > Data.size())
-    return make_error<CoverageMapError>(coveragemap_error::malformed);
+    return make_error<CoverageMapError>(coveragemap_error::malformed,
+                                        "the size of ULEB128 is too big");
   Data = Data.substr(N);
   if (Data.size() < ProfileNamesSize)
-    return make_error<CoverageMapError>(coveragemap_error::malformed);
+    return make_error<CoverageMapError>(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<CoverageMapError>(coveragemap_error::malformed);
+      return make_error<CoverageMapError>(coveragemap_error::malformed,
+                                          "the size of ULEB128 is too big");
     Data = Data.substr(N);
     if (CoverageMappingSize < sizeof(CovMapHeader))
-      return make_error<CoverageMapError>(coveragemap_error::malformed);
+      return make_error<CoverageMapError>(
+          coveragemap_error::malformed,
+          "the size of CoverageMapping is teoo small");
   } else if (TestingVersion != uint64_t(TestingFormatVersion::Version1)) {
     return make_error<CoverageMapError>(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<CoverageMapError>(coveragemap_error::malformed);
+    return make_error<CoverageMapError>(coveragemap_error::malformed,
+                                        "insufficient padding");
   Data = Data.substr(Pad);
   if (Data.size() < sizeof(CovMapHeader))
-    return make_error<CoverageMapError>(coveragemap_error::malformed);
+    return make_error<CoverageMapError>(
+        coveragemap_error::malformed,
+        "coverage mapping header section is larger than data size");
   auto const *CovHeader = reinterpret_cast<const CovMapHeader *>(
       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<CoverageMapError>(coveragemap_error::malformed);
+      return make_error<CoverageMapError>(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<CoverageMapError>(coveragemap_error::malformed);
+      return make_error<CoverageMapError>(coveragemap_error::malformed,
+                                          "insufficient padding");
     Data = Data.substr(Pad);
   }
   BinaryCoverageReader::FuncRecordsStorage CoverageRecords =
@@ -1000,7 +1041,8 @@ loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch,
       return errorCodeToError(object_error::arch_not_found);
   } else
     // We can only handle object files.
-    return make_error<CoverageMapError>(coveragemap_error::malformed);
+    return make_error<CoverageMapError>(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<Binary> Bin, StringRef Arch,
     return std::move(E);
   std::vector<SectionRef> CoverageSectionRefs = *CoverageSection;
   if (CoverageSectionRefs.size() != 1)
-    return make_error<CoverageMapError>(coveragemap_error::malformed);
+    return make_error<CoverageMapError>(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<Binary> Bin, StringRef Arch,
   InstrProfSymtab ProfileNames;
   std::vector<SectionRef> NamesSectionRefs = *NamesSection;
   if (NamesSectionRefs.size() != 1)
-    return make_error<CoverageMapError>(coveragemap_error::malformed);
+    return make_error<CoverageMapError>(
+        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 9f4b7c125f65638..c3eec3ce379c8f9 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 e0ba107ac9f4ebe..0ba1d27ec6ec3f6 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 0ea8fd74e5bb7c8..ab0a04f7a5b951e 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 6676ed812b06af7..61f22ba89171f20 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 985bad345cd1782..3eb8c25e95d5230 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 b7b124565f59d4a..8c50dc35c5b731b 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 f26db153d4e3698..b5d763d8643cd7d 100644
--- a/llvm/tools/llvm-cov/CodeCoverage.cpp
+++ b/llvm/tools/llvm-cov/CodeCoverage.cpp
@@ -447,7 +447,7 @@ std::unique_ptr<CoverageMapping> 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 884a76c83061198..873bc05b2ecc3f3 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) {



More information about the llvm-commits mailing list