[libcxxabi] [llvm] [libcxxabi] Fix PODSmallVector zero-capacity growth (PR #215386)
Zaara Syeda via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 11 14:55:18 PDT 2026
https://github.com/syzaara updated https://github.com/llvm/llvm-project/pull/215386
>From 7b69185d7914be6232140d174c932051af7830d4 Mon Sep 17 00:00:00 2001
From: Zaara Syeda <syzaara at ca.ibm.com>
Date: Mon, 10 Aug 2026 16:25:37 -0400
Subject: [PATCH 1/3] [libcxxabi] Fix PODSmallVector zero-capacity growth
Fix PODSmallVector growth for PODSmallVector<T, 0>. Since the initial capacity
is zero, the first growth attempts reserve(0), which does not increase the
capacity. Allocate space for at least one element on the initial growth.
---
libcxxabi/src/demangle/ItaniumDemangle.h | 3 ++-
libcxxabi/test/unittest_demangle.pass.cpp | 7 +++++++
llvm/include/llvm/Demangle/ItaniumDemangle.h | 3 ++-
3 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h
index 2ae943e1998f1..e24941987eecc 100644
--- a/libcxxabi/src/demangle/ItaniumDemangle.h
+++ b/libcxxabi/src/demangle/ItaniumDemangle.h
@@ -123,7 +123,7 @@ template <class T, size_t N> class PODSmallVector {
// NOLINTNEXTLINE(readability-identifier-naming)
void push_back(const T &Elem) {
if (Last == Cap)
- reserve(size() * 2);
+ reserve(std::max<size_t>(1, size() * 2));
*Last++ = Elem;
}
@@ -143,6 +143,7 @@ template <class T, size_t N> class PODSmallVector {
bool empty() const { return First == Last; }
size_t size() const { return static_cast<size_t>(Last - First); }
+ size_t capacity() const { return static_cast<size_t>(Cap - First); }
T &back() {
DEMANGLE_ASSERT(Last != First, "Calling back() on empty vector!");
return *(Last - 1);
diff --git a/libcxxabi/test/unittest_demangle.pass.cpp b/libcxxabi/test/unittest_demangle.pass.cpp
index 3f86e9c49a8a5..5df4f1d0cf62c 100644
--- a/libcxxabi/test/unittest_demangle.pass.cpp
+++ b/libcxxabi/test/unittest_demangle.pass.cpp
@@ -81,6 +81,13 @@ void testPODSmallVector() {
(void)x;
}
}
+
+ {
+ itanium_demangle::PODSmallVector<int, 0> PSV;
+ PSV.push_back(10);
+ assert(PSV.size() == 1);
+ assert(PSV.capacity() >= PSV.size());
+ }
}
int main(int, char**) {
diff --git a/llvm/include/llvm/Demangle/ItaniumDemangle.h b/llvm/include/llvm/Demangle/ItaniumDemangle.h
index 0f1deb3d710e2..6187926907176 100644
--- a/llvm/include/llvm/Demangle/ItaniumDemangle.h
+++ b/llvm/include/llvm/Demangle/ItaniumDemangle.h
@@ -123,7 +123,7 @@ template <class T, size_t N> class PODSmallVector {
// NOLINTNEXTLINE(readability-identifier-naming)
void push_back(const T &Elem) {
if (Last == Cap)
- reserve(size() * 2);
+ reserve(std::max<size_t>(1, size() * 2));
*Last++ = Elem;
}
@@ -143,6 +143,7 @@ template <class T, size_t N> class PODSmallVector {
bool empty() const { return First == Last; }
size_t size() const { return static_cast<size_t>(Last - First); }
+ size_t capacity() const { return static_cast<size_t>(Cap - First); }
T &back() {
DEMANGLE_ASSERT(Last != First, "Calling back() on empty vector!");
return *(Last - 1);
>From f7439f85c84db36efa33021e96a20cfcbbf57ca6 Mon Sep 17 00:00:00 2001
From: Zaara Syeda <syzaara at ca.ibm.com>
Date: Mon, 10 Aug 2026 17:42:17 -0400
Subject: [PATCH 2/3] Address review comments
---
libcxxabi/src/demangle/ItaniumDemangle.h | 2 +-
llvm/include/llvm/Demangle/ItaniumDemangle.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h
index e24941987eecc..0db933b3314bc 100644
--- a/libcxxabi/src/demangle/ItaniumDemangle.h
+++ b/libcxxabi/src/demangle/ItaniumDemangle.h
@@ -123,7 +123,7 @@ template <class T, size_t N> class PODSmallVector {
// NOLINTNEXTLINE(readability-identifier-naming)
void push_back(const T &Elem) {
if (Last == Cap)
- reserve(std::max<size_t>(1, size() * 2));
+ reserve(N == 0 && size() == 0 ? 1 : size() * 2);
*Last++ = Elem;
}
diff --git a/llvm/include/llvm/Demangle/ItaniumDemangle.h b/llvm/include/llvm/Demangle/ItaniumDemangle.h
index 6187926907176..8b410dd8b1d6a 100644
--- a/llvm/include/llvm/Demangle/ItaniumDemangle.h
+++ b/llvm/include/llvm/Demangle/ItaniumDemangle.h
@@ -123,7 +123,7 @@ template <class T, size_t N> class PODSmallVector {
// NOLINTNEXTLINE(readability-identifier-naming)
void push_back(const T &Elem) {
if (Last == Cap)
- reserve(std::max<size_t>(1, size() * 2));
+ reserve(N == 0 && size() == 0 ? 1 : size() * 2);
*Last++ = Elem;
}
>From 3eaa0c8786060e5ff57739ff5546dc2cff40334e Mon Sep 17 00:00:00 2001
From: Zaara Syeda <syzaara at ca.ibm.com>
Date: Tue, 11 Aug 2026 17:54:53 -0400
Subject: [PATCH 3/3] Address review comments
---
libcxxabi/src/demangle/ItaniumDemangle.h | 3 ++-
libcxxabi/test/unittest_demangle.pass.cpp | 7 -------
llvm/include/llvm/Demangle/ItaniumDemangle.h | 3 ++-
3 files changed, 4 insertions(+), 9 deletions(-)
diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h
index 0db933b3314bc..c3d2dbf32ac28 100644
--- a/libcxxabi/src/demangle/ItaniumDemangle.h
+++ b/libcxxabi/src/demangle/ItaniumDemangle.h
@@ -43,6 +43,7 @@ template <class T, size_t N> class PODSmallVector {
"T is required to be a trivially copyable type");
static_assert(std::is_trivially_default_constructible<T>::value,
"T is required to be trivially default constructible");
+ static_assert(N > 0, "PODSmallVector requires a non-zero inline capacity");
T *First = nullptr;
T *Last = nullptr;
T *Cap = nullptr;
@@ -123,7 +124,7 @@ template <class T, size_t N> class PODSmallVector {
// NOLINTNEXTLINE(readability-identifier-naming)
void push_back(const T &Elem) {
if (Last == Cap)
- reserve(N == 0 && size() == 0 ? 1 : size() * 2);
+ reserve(size() * 2);
*Last++ = Elem;
}
diff --git a/libcxxabi/test/unittest_demangle.pass.cpp b/libcxxabi/test/unittest_demangle.pass.cpp
index 5df4f1d0cf62c..3f86e9c49a8a5 100644
--- a/libcxxabi/test/unittest_demangle.pass.cpp
+++ b/libcxxabi/test/unittest_demangle.pass.cpp
@@ -81,13 +81,6 @@ void testPODSmallVector() {
(void)x;
}
}
-
- {
- itanium_demangle::PODSmallVector<int, 0> PSV;
- PSV.push_back(10);
- assert(PSV.size() == 1);
- assert(PSV.capacity() >= PSV.size());
- }
}
int main(int, char**) {
diff --git a/llvm/include/llvm/Demangle/ItaniumDemangle.h b/llvm/include/llvm/Demangle/ItaniumDemangle.h
index 8b410dd8b1d6a..3aecb3042268b 100644
--- a/llvm/include/llvm/Demangle/ItaniumDemangle.h
+++ b/llvm/include/llvm/Demangle/ItaniumDemangle.h
@@ -43,6 +43,7 @@ template <class T, size_t N> class PODSmallVector {
"T is required to be a trivially copyable type");
static_assert(std::is_trivially_default_constructible<T>::value,
"T is required to be trivially default constructible");
+ static_assert(N > 0, "PODSmallVector requires a non-zero inline capacity");
T *First = nullptr;
T *Last = nullptr;
T *Cap = nullptr;
@@ -123,7 +124,7 @@ template <class T, size_t N> class PODSmallVector {
// NOLINTNEXTLINE(readability-identifier-naming)
void push_back(const T &Elem) {
if (Last == Cap)
- reserve(N == 0 && size() == 0 ? 1 : size() * 2);
+ reserve(size() * 2);
*Last++ = Elem;
}
More information about the llvm-commits
mailing list