[libcxx-commits] [libcxx] 03c7b93 - [libc++][format] Removes vector dependency.
Mark de Wever via libcxx-commits
libcxx-commits at lists.llvm.org
Sun Apr 30 04:33:52 PDT 2023
Author: Mark de Wever
Date: 2023-04-30T13:33:44+02:00
New Revision: 03c7b93aab35106834b6c8dac097ea6bd401ba1e
URL: https://github.com/llvm/llvm-project/commit/03c7b93aab35106834b6c8dac097ea6bd401ba1e
DIFF: https://github.com/llvm/llvm-project/commit/03c7b93aab35106834b6c8dac097ea6bd401ba1e.diff
LOG: [libc++][format] Removes vector dependency.
During the review of D140653 it was suggested to use vector in
__retarget_buffer instead of manually managing the memory. Due to the
requirements of the Standard it turns out format needs to include vector
leading to a cycle. Therefore switching back to manual memory
management.
This is a preparation to fix https://llvm.org/PR61314
Reviewed By: #libc, ldionne
Differential Revision: https://reviews.llvm.org/D148826
Added:
Modified:
libcxx/include/__format/buffer.h
libcxx/test/libcxx/transitive_includes/cxx03.csv
libcxx/test/libcxx/transitive_includes/cxx11.csv
libcxx/test/libcxx/transitive_includes/cxx14.csv
libcxx/test/libcxx/transitive_includes/cxx17.csv
libcxx/test/libcxx/transitive_includes/cxx20.csv
libcxx/test/libcxx/transitive_includes/cxx2b.csv
Removed:
################################################################################
diff --git a/libcxx/include/__format/buffer.h b/libcxx/include/__format/buffer.h
index 16db88aec7fbe..e74ca8f579d42 100644
--- a/libcxx/include/__format/buffer.h
+++ b/libcxx/include/__format/buffer.h
@@ -28,12 +28,17 @@
#include <__iterator/iterator_traits.h>
#include <__iterator/wrap_iter.h>
#include <__memory/addressof.h>
+#include <__memory/allocate_at_least.h>
+#include <__memory/allocator_traits.h>
+#include <__memory/construct_at.h>
+#include <__memory/ranges_construct_at.h>
+#include <__memory/uninitialized_algorithms.h>
#include <__type_traits/add_pointer.h>
#include <__type_traits/conditional.h>
+#include <__utility/exception_guard.h>
#include <__utility/move.h>
#include <cstddef>
#include <string_view>
-#include <vector>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -512,8 +517,13 @@ struct _LIBCPP_TEMPLATE_VIS __format_to_n_buffer final
// context and the format arguments need to be retargeted to the new context.
// This retargeting is done by a basic_format_context specialized for the
// __iterator of this container.
+//
+// This class uses its own buffer management, since using vector
+// would lead to a circular include with formatter for vector<bool>.
template <__fmt_char_type _CharT>
class _LIBCPP_TEMPLATE_VIS __retarget_buffer {
+ using _Alloc = allocator<_CharT>;
+
public:
using value_type = _CharT;
@@ -537,31 +547,89 @@ class _LIBCPP_TEMPLATE_VIS __retarget_buffer {
__retarget_buffer* __buffer_;
};
- _LIBCPP_HIDE_FROM_ABI explicit __retarget_buffer(size_t __size_hint) { __buffer_.reserve(__size_hint); }
+ __retarget_buffer(const __retarget_buffer&) = delete;
+ __retarget_buffer& operator=(const __retarget_buffer&) = delete;
+
+ _LIBCPP_HIDE_FROM_ABI explicit __retarget_buffer(size_t __size_hint) {
+ auto __result = std::__allocate_at_least(__alloc_, __size_hint ? __size_hint : 256 / sizeof(_CharT));
+ __ptr_ = __result.ptr;
+ __capacity_ = __result.count;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI ~__retarget_buffer() {
+ ranges::destroy_n(__ptr_, __size_);
+ allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __capacity_);
+ }
_LIBCPP_HIDE_FROM_ABI __iterator __make_output_iterator() { return __iterator{*this}; }
- _LIBCPP_HIDE_FROM_ABI void push_back(_CharT __c) { __buffer_.push_back(__c); }
+ _LIBCPP_HIDE_FROM_ABI void push_back(_CharT __c) {
+ std::construct_at(__ptr_ + __size_, __c);
+ ++__size_;
+
+ if (__size_ == __capacity_)
+ __grow_buffer();
+ }
template <__fmt_char_type _InCharT>
_LIBCPP_HIDE_FROM_ABI void __copy(basic_string_view<_InCharT> __str) {
- __buffer_.insert(__buffer_.end(), __str.begin(), __str.end());
+ size_t __n = __str.size();
+ if (__size_ + __n >= __capacity_)
+ // Push_back requires the buffer to have room for at least one character.
+ __grow_buffer(__size_ + __n + 1);
+
+ std::uninitialized_copy_n(__str.data(), __n, __ptr_ + __size_);
+ __size_ += __n;
}
template <__fmt_char_type _InCharT, class _UnaryOperation>
_LIBCPP_HIDE_FROM_ABI void __transform(const _InCharT* __first, const _InCharT* __last, _UnaryOperation __operation) {
_LIBCPP_ASSERT(__first <= __last, "not a valid range");
- std::transform(__first, __last, std::back_inserter(__buffer_), std::move(__operation));
+
+ size_t __n = static_cast<size_t>(__last - __first);
+ if (__size_ + __n >= __capacity_)
+ // Push_back requires the buffer to have room for at least one character.
+ __grow_buffer(__size_ + __n + 1);
+
+ std::uninitialized_default_construct_n(__ptr_ + __size_, __n);
+ std::transform(__first, __last, __ptr_ + __size_, std::move(__operation));
+ __size_ += __n;
}
- _LIBCPP_HIDE_FROM_ABI void __fill(size_t __n, _CharT __value) { __buffer_.insert(__buffer_.end(), __n, __value); }
+ _LIBCPP_HIDE_FROM_ABI void __fill(size_t __n, _CharT __value) {
+ if (__size_ + __n >= __capacity_)
+ // Push_back requires the buffer to have room for at least one character.
+ __grow_buffer(__size_ + __n + 1);
+
+ std::uninitialized_fill_n(__ptr_ + __size_, __n, __value);
+ __size_ += __n;
+ }
- _LIBCPP_HIDE_FROM_ABI basic_string_view<_CharT> __view() { return {__buffer_.data(), __buffer_.size()}; }
+ _LIBCPP_HIDE_FROM_ABI basic_string_view<_CharT> __view() { return {__ptr_, __size_}; }
private:
- // Use vector instead of string to avoid adding zeros after every append
- // operation. The buffer is exposed as a string_view and not as a c-string.
- vector<_CharT> __buffer_;
+ _LIBCPP_HIDE_FROM_ABI void __grow_buffer() { __grow_buffer(__capacity_ * 1.6); }
+
+ _LIBCPP_HIDE_FROM_ABI void __grow_buffer(size_t __capacity) {
+ _LIBCPP_ASSERT(__capacity > __capacity_, "the buffer must grow");
+ auto __result = std::__allocate_at_least(__alloc_, __capacity);
+ auto __guard = std::__make_exception_guard([&] {
+ allocator_traits<_Alloc>::deallocate(__alloc_, __result.ptr, __result.count);
+ });
+ // This shouldn't throw, but just to be safe. Not that at -O1 this
+ // guard is optimized away so there is no runtime overhead.
+ std::uninitialized_move_n(__ptr_, __size_, __result.ptr);
+ __guard.__complete();
+ ranges::destroy_n(__ptr_, __size_);
+ allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __capacity_);
+
+ __ptr_ = __result.ptr;
+ __capacity_ = __result.count;
+ }
+ _LIBCPP_NO_UNIQUE_ADDRESS _Alloc __alloc_;
+ _CharT* __ptr_;
+ size_t __capacity_;
+ size_t __size_{0};
};
} // namespace __format
diff --git a/libcxx/test/libcxx/transitive_includes/cxx03.csv b/libcxx/test/libcxx/transitive_includes/cxx03.csv
index efb07e748f562..e5aee81cc70d8 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx03.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv
@@ -333,7 +333,6 @@ format stdexcept
format string
format string_view
format tuple
-format vector
format version
forward_list algorithm
forward_list atomic
@@ -869,7 +868,6 @@ thread string_view
thread system_error
thread tuple
thread type_traits
-thread vector
thread version
tuple compare
tuple cstddef
diff --git a/libcxx/test/libcxx/transitive_includes/cxx11.csv b/libcxx/test/libcxx/transitive_includes/cxx11.csv
index 0cd572f402906..f696ff6c2b152 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx11.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx11.csv
@@ -333,7 +333,6 @@ format stdexcept
format string
format string_view
format tuple
-format vector
format version
forward_list algorithm
forward_list atomic
@@ -870,7 +869,6 @@ thread string_view
thread system_error
thread tuple
thread type_traits
-thread vector
thread version
tuple compare
tuple cstddef
diff --git a/libcxx/test/libcxx/transitive_includes/cxx14.csv b/libcxx/test/libcxx/transitive_includes/cxx14.csv
index a0d7ff076dcd8..5e7d9ca2700bf 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx14.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx14.csv
@@ -335,7 +335,6 @@ format stdexcept
format string
format string_view
format tuple
-format vector
format version
forward_list algorithm
forward_list atomic
@@ -872,7 +871,6 @@ thread string_view
thread system_error
thread tuple
thread type_traits
-thread vector
thread version
tuple compare
tuple cstddef
diff --git a/libcxx/test/libcxx/transitive_includes/cxx17.csv b/libcxx/test/libcxx/transitive_includes/cxx17.csv
index a0d7ff076dcd8..5e7d9ca2700bf 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx17.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx17.csv
@@ -335,7 +335,6 @@ format stdexcept
format string
format string_view
format tuple
-format vector
format version
forward_list algorithm
forward_list atomic
@@ -872,7 +871,6 @@ thread string_view
thread system_error
thread tuple
thread type_traits
-thread vector
thread version
tuple compare
tuple cstddef
diff --git a/libcxx/test/libcxx/transitive_includes/cxx20.csv b/libcxx/test/libcxx/transitive_includes/cxx20.csv
index 57a75bd9959b8..a96081233f326 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx20.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx20.csv
@@ -127,7 +127,6 @@ chrono string
chrono string_view
chrono tuple
chrono type_traits
-chrono vector
chrono version
cinttypes cstdint
cmath type_traits
@@ -343,7 +342,6 @@ format stdexcept
format string
format string_view
format tuple
-format vector
format version
forward_list algorithm
forward_list atomic
@@ -878,7 +876,6 @@ thread string_view
thread system_error
thread tuple
thread type_traits
-thread vector
thread version
tuple compare
tuple cstddef
diff --git a/libcxx/test/libcxx/transitive_includes/cxx2b.csv b/libcxx/test/libcxx/transitive_includes/cxx2b.csv
index aa2161fe38fbd..3f5758630f348 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx2b.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx2b.csv
@@ -71,6 +71,7 @@ chrono ctime
chrono initializer_list
chrono limits
chrono locale
+chrono new
chrono optional
chrono ostream
chrono ratio
@@ -79,7 +80,6 @@ chrono stdexcept
chrono string
chrono string_view
chrono tuple
-chrono vector
chrono version
cinttypes cstdint
cmath version
@@ -225,6 +225,7 @@ format cstdlib
format initializer_list
format limits
format locale
+format new
format optional
format queue
format stack
@@ -232,7 +233,6 @@ format stdexcept
format string
format string_view
format tuple
-format vector
format version
forward_list compare
forward_list cstddef
@@ -582,12 +582,12 @@ thread ctime
thread iosfwd
thread limits
thread locale
+thread new
thread ratio
thread stdexcept
thread string
thread string_view
thread tuple
-thread vector
thread version
tuple compare
tuple cstddef
More information about the libcxx-commits
mailing list