[llvm] [LLVM][Coverage][Unittest] Fix dangling reference in unittest (PR #147118)

Tomohiro Kashiwada via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 4 15:34:34 PDT 2025


https://github.com/kikairoya created https://github.com/llvm/llvm-project/pull/147118

In loop of `writeAndReadCoverageRegions`, `OutputFunctions[I].Filenames` references to contents of `Filenames` after returning from `readCoverageRegions` but `Filenames` will be cleared in next call of `readCoverageRegions`, causes dangling reference.
The lifetime of the contents of `Filenames` must be equal or longer than `OutputFunctions[I]`, thus it has been moved into `OutputFunctions[I]` (typed `OutputFunctionCoverageData`).

>From 7ecd8e7100bc713dfa782d94440b16790a2b9b5d Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Sun, 29 Jun 2025 10:50:49 +0900
Subject: [PATCH] [LLVM][Coverage][Unittest] Fix dangling reference in unittest

In loop of `writeAndReadCoverageRegions`, `OutputFunctions[I].Filenames` references to
contents of `Filenames` after returning from `readCoverageRegions` but `Filenames` will be
cleared in next call of `readCoverageRegions`, causes dangling reference.
The lifetime of the contents of `Filenames` must be equal or longer than `OutputFunctions[I]`,
thus it has been moved into `OutputFunctions[I]` (typed `OutputFunctionCoverageData`).
---
 .../ProfileData/CoverageMappingTest.cpp         | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/llvm/unittests/ProfileData/CoverageMappingTest.cpp b/llvm/unittests/ProfileData/CoverageMappingTest.cpp
index ec81e5f274efa..59c381a1b4e82 100644
--- a/llvm/unittests/ProfileData/CoverageMappingTest.cpp
+++ b/llvm/unittests/ProfileData/CoverageMappingTest.cpp
@@ -64,6 +64,7 @@ namespace {
 struct OutputFunctionCoverageData {
   StringRef Name;
   uint64_t Hash;
+  std::vector<std::string> FilenamesStorage;
   std::vector<StringRef> Filenames;
   std::vector<CounterMappingRegion> Regions;
   std::vector<CounterExpression> Expressions;
@@ -71,8 +72,10 @@ struct OutputFunctionCoverageData {
   OutputFunctionCoverageData() : Hash(0) {}
 
   OutputFunctionCoverageData(OutputFunctionCoverageData &&OFCD)
-      : Name(OFCD.Name), Hash(OFCD.Hash), Filenames(std::move(OFCD.Filenames)),
-        Regions(std::move(OFCD.Regions)) {}
+      : Name(OFCD.Name), Hash(OFCD.Hash),
+        FilenamesStorage(std::move(OFCD.FilenamesStorage)),
+        Filenames(std::move(OFCD.Filenames)), Regions(std::move(OFCD.Regions)) {
+  }
 
   OutputFunctionCoverageData(const OutputFunctionCoverageData &) = delete;
   OutputFunctionCoverageData &
@@ -135,7 +138,6 @@ struct InputFunctionCoverageData {
 struct CoverageMappingTest : ::testing::TestWithParam<std::tuple<bool, bool>> {
   bool UseMultipleReaders;
   StringMap<unsigned> Files;
-  std::vector<std::string> Filenames;
   std::vector<InputFunctionCoverageData> InputFunctions;
   std::vector<OutputFunctionCoverageData> OutputFunctions;
 
@@ -233,13 +235,10 @@ struct CoverageMappingTest : ::testing::TestWithParam<std::tuple<bool, bool>> {
 
   void readCoverageRegions(const std::string &Coverage,
                            OutputFunctionCoverageData &Data) {
-    // We will re-use the StringRef in duplicate tests, clear it to avoid
-    // clobber previous ones.
-    Filenames.clear();
-    Filenames.resize(Files.size() + 1);
+    Data.FilenamesStorage.resize(Files.size() + 1);
     for (const auto &E : Files)
-      Filenames[E.getValue()] = E.getKey().str();
-    ArrayRef<std::string> FilenameRefs = llvm::ArrayRef(Filenames);
+      Data.FilenamesStorage[E.getValue()] = E.getKey().str();
+    ArrayRef<std::string> FilenameRefs = llvm::ArrayRef(Data.FilenamesStorage);
     RawCoverageMappingReader Reader(Coverage, FilenameRefs, Data.Filenames,
                                     Data.Expressions, Data.Regions);
     EXPECT_THAT_ERROR(Reader.read(), Succeeded());



More information about the llvm-commits mailing list