[llvm] Fix llvm::StripTemplateParameters to not return an empty name. (PR #157553)
Greg Clayton via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 12 10:24:58 PDT 2025
https://github.com/clayborg updated https://github.com/llvm/llvm-project/pull/157553
>From b31cccc9b1fb494b39c6ba2bc2430964257f6a29 Mon Sep 17 00:00:00 2001
From: Greg Clayton <clayborg at gmail.com>
Date: Mon, 8 Sep 2025 13:57:49 -0700
Subject: [PATCH 1/4] Fix llvm::StripTemplateParameters to not return an empty
name.
llvm::StripTemplateParameters was used to add accelerator table entries to the DWARF accelerator tables by adding and entry for the template name without the template. There is a bug where if a string starts with a '<' character, this function would return an std::optional<StringRef> that was empty. This causes invalid entries to be added to __apple_XXXX accelerator tables where entries with empty strings would be added and were causing issues with the AppleAcceleratorTable::Iterator before the fix that was submitted (https://github.com/llvm/llvm-project/pull/157538).
---
llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp | 14 ++++++++------
.../DebugInfo/DWARF/DWARFAcceleratorTableTest.cpp | 14 ++++++++++++++
2 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
index ea336378bebb3..5e862e0c233e9 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
@@ -248,8 +248,8 @@ LLVM_DUMP_METHOD void AppleAcceleratorTable::dump(raw_ostream &OS) const {
}
for (unsigned HashIdx = Index; HashIdx < Hdr.HashCount; ++HashIdx) {
- uint64_t HashOffset = HashesBase + HashIdx*4;
- uint64_t OffsetsOffset = OffsetsBase + HashIdx*4;
+ uint64_t HashOffset = HashesBase + HashIdx * 4;
+ uint64_t OffsetsOffset = OffsetsBase + HashIdx * 4;
uint32_t Hash = AccelSection.getU32(&HashOffset);
if (Hash % Hdr.BucketCount != Bucket)
@@ -443,7 +443,7 @@ void DWARFDebugNames::Header::dump(ScopedPrinter &W) const {
}
Error DWARFDebugNames::Header::extract(const DWARFDataExtractor &AS,
- uint64_t *Offset) {
+ uint64_t *Offset) {
auto HeaderError = [Offset = *Offset](Error E) {
return createStringError(errc::illegal_byte_sequence,
"parsing .debug_names header at 0x%" PRIx64 ": %s",
@@ -830,8 +830,9 @@ bool DWARFDebugNames::NameIndex::dumpEntry(ScopedPrinter &W,
uint64_t EntryId = *Offset;
auto EntryOr = getEntry(Offset);
if (!EntryOr) {
- handleAllErrors(EntryOr.takeError(), [](const SentinelError &) {},
- [&W](const ErrorInfoBase &EI) { EI.log(W.startLine()); });
+ handleAllErrors(
+ EntryOr.takeError(), [](const SentinelError &) {},
+ [&W](const ErrorInfoBase &EI) { EI.log(W.startLine()); });
return false;
}
@@ -1117,7 +1118,8 @@ std::optional<StringRef> llvm::StripTemplateParameters(StringRef Name) {
//
// We look for > at the end but if it does not contain any < then we
// have something like operator>>. We check for the operator<=> case.
- if (!Name.ends_with(">") || Name.count("<") == 0 || Name.ends_with("<=>"))
+ if (Name.starts_with("<") || !Name.ends_with(">") || Name.count("<") == 0 ||
+ Name.ends_with("<=>"))
return {};
// How many < until we have the start of the template parameters.
diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFAcceleratorTableTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFAcceleratorTableTest.cpp
index dedcf816cf63f..2265ff9dd42be 100644
--- a/llvm/unittests/DebugInfo/DWARF/DWARFAcceleratorTableTest.cpp
+++ b/llvm/unittests/DebugInfo/DWARF/DWARFAcceleratorTableTest.cpp
@@ -299,4 +299,18 @@ TEST(DWARFDebugNames, UnsupportedForm) {
Sections,
FailedWithMessage("unsupported Form for YAML debug_names emitter"));
}
+
+TEST(DWARFDebugNames, TestStripTemplateParameters) {
+
+ std::optional<StringRef> stripped_name;
+ // Make sure we can extract the name "foo" from the template parameters.
+ stripped_name = StripTemplateParameters("foo<int>");
+ ASSERT_TRUE(stripped_name.has_value());
+ ASSERT_EQ(*stripped_name, StringRef("foo"));
+ // Make sure that we don't get an empty name back when the string starts with
+ // '<'.
+ stripped_name = StripTemplateParameters("<int>");
+ ASSERT_FALSE(stripped_name.has_value());
+}
+
} // end anonymous namespace
>From 6d612bd741985ae73f51277ec0ca567e9ad92c4d Mon Sep 17 00:00:00 2001
From: Greg Clayton <clayborg at gmail.com>
Date: Tue, 9 Sep 2025 11:08:03 -0700
Subject: [PATCH 2/4] Remove extra clang format changes and fix comment.
---
llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp | 11 +++++------
.../DebugInfo/DWARF/DWARFAcceleratorTableTest.cpp | 2 +-
2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
index 5e862e0c233e9..5a9fa7c4c9cb1 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
@@ -248,8 +248,8 @@ LLVM_DUMP_METHOD void AppleAcceleratorTable::dump(raw_ostream &OS) const {
}
for (unsigned HashIdx = Index; HashIdx < Hdr.HashCount; ++HashIdx) {
- uint64_t HashOffset = HashesBase + HashIdx * 4;
- uint64_t OffsetsOffset = OffsetsBase + HashIdx * 4;
+ uint64_t HashOffset = HashesBase + HashIdx*4;
+ uint64_t OffsetsOffset = OffsetsBase + HashIdx*4;
uint32_t Hash = AccelSection.getU32(&HashOffset);
if (Hash % Hdr.BucketCount != Bucket)
@@ -443,7 +443,7 @@ void DWARFDebugNames::Header::dump(ScopedPrinter &W) const {
}
Error DWARFDebugNames::Header::extract(const DWARFDataExtractor &AS,
- uint64_t *Offset) {
+ uint64_t *Offset) {
auto HeaderError = [Offset = *Offset](Error E) {
return createStringError(errc::illegal_byte_sequence,
"parsing .debug_names header at 0x%" PRIx64 ": %s",
@@ -830,9 +830,8 @@ bool DWARFDebugNames::NameIndex::dumpEntry(ScopedPrinter &W,
uint64_t EntryId = *Offset;
auto EntryOr = getEntry(Offset);
if (!EntryOr) {
- handleAllErrors(
- EntryOr.takeError(), [](const SentinelError &) {},
- [&W](const ErrorInfoBase &EI) { EI.log(W.startLine()); });
+ handleAllErrors(EntryOr.takeError(), [](const SentinelError &) {},
+ [&W](const ErrorInfoBase &EI) { EI.log(W.startLine()); });
return false;
}
diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFAcceleratorTableTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFAcceleratorTableTest.cpp
index 2265ff9dd42be..82cc02c921d15 100644
--- a/llvm/unittests/DebugInfo/DWARF/DWARFAcceleratorTableTest.cpp
+++ b/llvm/unittests/DebugInfo/DWARF/DWARFAcceleratorTableTest.cpp
@@ -307,7 +307,7 @@ TEST(DWARFDebugNames, TestStripTemplateParameters) {
stripped_name = StripTemplateParameters("foo<int>");
ASSERT_TRUE(stripped_name.has_value());
ASSERT_EQ(*stripped_name, StringRef("foo"));
- // Make sure that we don't get an empty name back when the string starts with
+ // Make sure that we don't get a valid name back when the string starts with
// '<'.
stripped_name = StripTemplateParameters("<int>");
ASSERT_FALSE(stripped_name.has_value());
>From be5014815ebd3698cdbf7eca73a90fce6fa66ec8 Mon Sep 17 00:00:00 2001
From: Greg Clayton <clayborg at gmail.com>
Date: Thu, 11 Sep 2025 10:59:15 -0700
Subject: [PATCH 3/4] Make sure that if the string is empty that we return
std::nullopt
---
llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
index 5a9fa7c4c9cb1..bcd3181a81a73 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
@@ -1139,5 +1139,8 @@ std::optional<StringRef> llvm::StripTemplateParameters(StringRef Name) {
while (NumLeftAnglesToSkip--)
StartOfTemplate = Name.find('<', StartOfTemplate) + 1;
- return Name.substr(0, StartOfTemplate - 1);
+ StringRef Result = Name.substr(0, StartOfTemplate - 1);
+ if (Result.empty())
+ return std::nullopt;
+ return Result;
}
>From 8442dfb4d360266302bacc4442820687bab46036 Mon Sep 17 00:00:00 2001
From: Greg Clayton <clayborg at gmail.com>
Date: Fri, 12 Sep 2025 10:24:28 -0700
Subject: [PATCH 4/4] Remove check for name starting with '<'.
---
llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
index bcd3181a81a73..4b80a44746127 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
@@ -1117,8 +1117,7 @@ std::optional<StringRef> llvm::StripTemplateParameters(StringRef Name) {
//
// We look for > at the end but if it does not contain any < then we
// have something like operator>>. We check for the operator<=> case.
- if (Name.starts_with("<") || !Name.ends_with(">") || Name.count("<") == 0 ||
- Name.ends_with("<=>"))
+ if (!Name.ends_with(">") || Name.count("<") == 0 || Name.ends_with("<=>"))
return {};
// How many < until we have the start of the template parameters.
More information about the llvm-commits
mailing list