[libcxx-commits] [libcxx] [libc++] Remove UB from std::map __tree_node construction (PR #153908)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Mon Aug 18 02:02:32 PDT 2025


================
@@ -582,10 +585,37 @@ class _LIBCPP_STANDALONE_DEBUG __tree_node : public __tree_node_base<_VoidPtr> {
 public:
   using __node_value_type _LIBCPP_NODEBUG = __get_node_value_type_t<_Tp>;
 
-  __node_value_type __value_;
+// We use a union to avoid initialization during member initialization, which allows us
+// to use the allocator from the container to allocate the node itself
+#ifndef _LIBCPP_CXX03_LANG
 
+private:
+  union {
+    __node_value_type __value_;
+  };
+
+public:
   _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { return __value_; }
+#else
+
+private:
+  _ALIGNAS_TYPE(__node_value_type) unsigned char __buffer_[sizeof(__node_value_type)];
+
+public:
+  _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() {
+    return *std::__launder(reinterpret_cast<__node_value_type*>(&__buffer_));
+  }
+#endif
 
+  template <class _Alloc, class... _Args>
+  _LIBCPP_HIDE_FROM_ABI explicit __tree_node(_Alloc& __na, _Args&&... __args) {
----------------
philnik777 wrote:

We have something very similar in `__hash_table` and I think it would be better to match the implementations. I'm not sure which implementation is better, but I think I'd lean towards this, since it makes it clearer that this is actually intended and not a weird hacky thing. (I mean it is, but this type expects it)

https://github.com/llvm/llvm-project/pull/153908


More information about the libcxx-commits mailing list