[PATCH] libstdc++: Value-initialize hashtable helper objects [PR126949]

Marco Falke falke.marco@gmail.com
Mon Aug 31 15:57:07 GMT 2026


libstdc++15 and 16 do not allow to construct an unordered set with a
hasher whose ctor is explicit.

This is an issue with Clang, or with GCC -Wsystem-headers. See
https://godbolt.org/z/EGzKbjh84

Fix this by using value-init, similar to commit
f8f0193b5b83f6e85d65015e79c803295baf5166. However, that likely
regressed again in commit 689d4abc0b836aaf1c8ecd38091dde6b14373c60?

patch is attached and copied later.

I'd say the unit test could be expanded by adding
// { dg-additional-options "-Werror -Wsystem-headers" }
, but I wasn't sure if this is recommended.

Best, Marco




>From 2bd4a6218ff9ca10f1d11b6b19411c9556df90ed Mon Sep 17 00:00:00 2001
From: MarcoFalke <falke.marco@gmail.com>
Date: Sun, 26 Jul 2026 14:30:58 +0000
Subject: [PATCH] libstdc++: Value-initialize hashtable helper objects
 [PR126949]

Value-initialize the object stored in _Hashtable_ebo_helper so that hash
containers can be default constructed when the hash function has an
explicit default constructor.

A default member initializer prevents aggregate initialization in C++11,
so add constructors that preserve initialization from hash, equality, and
allocator objects.

libstdc++-v3/ChangeLog:

PR libstdc++/126949
* include/bits/hashtable_policy.h (_Hashtable_ebo_helper):
Value-initialize the stored object. Add default and forwarding
constructors.
* testsuite/23_containers/unordered_map/cons/default.cc: Check
default construction with an explicit hash constructor.
* testsuite/23_containers/unordered_set/cons/default.cc: Likewise.
---
 libstdc++-v3/include/bits/hashtable_policy.h   | 18 ++++++++++++++++--
 .../unordered_map/cons/default.cc              | 15 +++++++++++++++
 .../unordered_set/cons/default.cc              | 15 +++++++++++++++
 3 files changed, 46 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/include/bits/hashtable_policy.h
b/libstdc++-v3/include/bits/hashtable_policy.h
index 6e4b365d592..396214ed4bb 100644
--- a/libstdc++-v3/include/bits/hashtable_policy.h
+++ b/libstdc++-v3/include/bits/hashtable_policy.h
@@ -1033,7 +1033,14 @@ namespace __detail
    bool __use_ebo = !__is_final(_Tp) && __is_empty(_Tp)>
     struct _Hashtable_ebo_helper
     {
-      [[__no_unique_address__]] _Tp _M_obj;
+      [[__no_unique_address__]] _Tp _M_obj{};
+
+      _Hashtable_ebo_helper() = default;
+
+      template<typename _Up>
+ _Hashtable_ebo_helper(_Up&& __obj)
+ : _M_obj(std::forward<_Up>(__obj))
+ { }
     };

 #if ! _GLIBCXX_INLINE_VERSION
@@ -1042,7 +1049,14 @@ namespace __detail
   template<typename _Tp>
     struct _Hashtable_ebo_helper<_Tp, false>
     {
-      _Tp _M_obj;
+      _Tp _M_obj{};
+
+      _Hashtable_ebo_helper() = default;
+
+      template<typename _Up>
+ _Hashtable_ebo_helper(_Up&& __obj)
+ : _M_obj(std::forward<_Up>(__obj))
+ { }
     };
 #endif

diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/cons/default.cc
b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/default.cc
index 7a785e980b1..07089c36bcf 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_map/cons/default.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/default.cc
@@ -49,3 +49,18 @@ Map4 m4{m};
 Map4 m5{m, a};
 Map4 m6{std::move(m)};
 Map4 m7{std::move(m6), a};
+
+// PR libstdc++/126949
+struct ExplicitHash
+{
+  explicit ExplicitHash(bool = false) { }
+
+  std::size_t operator()(int value) const
+  { return value; }
+};
+
+void
+test_explicit_hash()
+{
+  std::unordered_map<int, int, ExplicitHash> map;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/cons/default.cc
b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/default.cc
index fb87c96ce9d..8949b202125 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_set/cons/default.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/default.cc
@@ -48,3 +48,18 @@ Set4 s4{s};
 Set4 s5{s, a};
 Set4 s6{std::move(s)};
 Set4 s7{std::move(s6), a};
+
+// PR libstdc++/126949
+struct ExplicitHash
+{
+  explicit ExplicitHash(bool = false) { }
+
+  std::size_t operator()(int value) const
+  { return value; }
+};
+
+void
+test_explicit_hash()
+{
+  std::unordered_set<int, ExplicitHash> set;
+}
-- 
2.53.0
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-libstdc-Value-initialize-hashtable-helper-objects-PR.patch
Type: text/x-patch
Size: 3594 bytes
Desc: not available
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20260831/e968eb1f/attachment.bin>


More information about the Libstdc++ mailing list