aboutsummaryrefslogtreecommitdiff
path: root/libcxx
diff options
context:
space:
mode:
Diffstat (limited to 'libcxx')
-rw-r--r--libcxx/docs/ReleaseNotes/22.rst4
-rw-r--r--libcxx/include/CMakeLists.txt1
-rw-r--r--libcxx/include/__algorithm/fill.h22
-rw-r--r--libcxx/include/__algorithm/fill_n.h41
-rw-r--r--libcxx/include/__algorithm/for_each.h30
-rw-r--r--libcxx/include/__algorithm/for_each_n.h67
-rw-r--r--libcxx/include/__chrono/is_clock.h72
-rw-r--r--libcxx/include/__iterator/distance.h35
-rw-r--r--libcxx/include/__iterator/segmented_iterator.h5
-rw-r--r--libcxx/include/chrono4
-rw-r--r--libcxx/include/fstream13
-rw-r--r--libcxx/include/module.modulemap.in4
-rw-r--r--libcxx/modules/std/chrono.inc4
-rw-r--r--libcxx/test/benchmarks/streams/fstream.bench.cpp (renamed from libcxx/test/benchmarks/streams/ofstream.bench.cpp)22
-rw-r--r--libcxx/test/libcxx/input.output/file.streams/fstreams/filebuf/traits_mismatch.verify.cpp2
-rw-r--r--libcxx/test/libcxx/input.output/file.streams/fstreams/traits_mismatch.verify.cpp2
-rw-r--r--libcxx/test/libcxx/time/time.traits.is.clock/trait.is.clock.compile.verify.cpp24
-rw-r--r--libcxx/test/std/time/time.traits.is.clock/trait.is.clock.compile.pass.cpp225
18 files changed, 437 insertions, 140 deletions
diff --git a/libcxx/docs/ReleaseNotes/22.rst b/libcxx/docs/ReleaseNotes/22.rst
index 58e0ee9..a6a0ac8 100644
--- a/libcxx/docs/ReleaseNotes/22.rst
+++ b/libcxx/docs/ReleaseNotes/22.rst
@@ -66,8 +66,8 @@ Improvements and New Features
by up to 2.5x
- The performance of ``erase(iterator, iterator)`` in the unordered containers has been improved by up to 1.9x
- The performance of ``map::insert_or_assign`` has been improved by up to 2x
-- ``ofstream::write`` has been optimized to pass through large strings to system calls directly instead of copying them
- in chunks into a buffer.
+- ``ofstream::write`` and ``ifstream::read`` have been optimized to pass through large reads and writes to system calls
+ directly instead of copying them in chunks.
- Multiple internal types have been refactored to use ``[[no_unique_address]]``, resulting in faster compile times and
reduced debug information.
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 57032ce..46e17b5 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -262,6 +262,7 @@ set(files
__chrono/gps_clock.h
__chrono/hh_mm_ss.h
__chrono/high_resolution_clock.h
+ __chrono/is_clock.h
__chrono/leap_second.h
__chrono/literals.h
__chrono/local_info.h
diff --git a/libcxx/include/__algorithm/fill.h b/libcxx/include/__algorithm/fill.h
index 328ebb6..37732cc 100644
--- a/libcxx/include/__algorithm/fill.h
+++ b/libcxx/include/__algorithm/fill.h
@@ -15,6 +15,7 @@
#include <__iterator/iterator_traits.h>
#include <__iterator/segmented_iterator.h>
#include <__type_traits/enable_if.h>
+#include <__type_traits/is_same.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -27,6 +28,15 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _ForwardIterator, class _Sentinel, class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
__fill(_ForwardIterator __first, _Sentinel __last, const _Tp& __value) {
+#ifndef _LIBCPP_CXX03_LANG
+ if constexpr (is_same<_ForwardIterator, _Sentinel>::value && __is_segmented_iterator_v<_ForwardIterator>) {
+ using __local_iterator_t = typename __segmented_iterator_traits<_ForwardIterator>::__local_iterator;
+ std::__for_each_segment(__first, __last, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) {
+ std::__fill(__lfirst, __llast, __value);
+ });
+ return __last;
+ }
+#endif
for (; __first != __last; ++__first)
*__first = __value;
return __first;
@@ -42,18 +52,6 @@ __fill(_RandomAccessIterator __first, _RandomAccessIterator __last, const _Tp& _
return std::__fill_n(__first, __last - __first, __value);
}
-#ifndef _LIBCPP_CXX03_LANG
-template <class _SegmentedIterator, class _Tp, __enable_if_t<__is_segmented_iterator_v<_SegmentedIterator>, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
-_SegmentedIterator __fill(_SegmentedIterator __first, _SegmentedIterator __last, const _Tp& __value) {
- using __local_iterator_t = typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator;
- std::__for_each_segment(__first, __last, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) {
- std::__fill(__lfirst, __llast, __value);
- });
- return __last;
-}
-#endif // !_LIBCPP_CXX03_LANG
-
template <class _ForwardIterator, class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) {
diff --git a/libcxx/include/__algorithm/fill_n.h b/libcxx/include/__algorithm/fill_n.h
index 2bfacf3..426fe22 100644
--- a/libcxx/include/__algorithm/fill_n.h
+++ b/libcxx/include/__algorithm/fill_n.h
@@ -16,10 +16,6 @@
#include <__iterator/iterator_traits.h>
#include <__iterator/segmented_iterator.h>
#include <__memory/pointer_traits.h>
-#include <__type_traits/conjunction.h>
-#include <__type_traits/enable_if.h>
-#include <__type_traits/integral_constant.h>
-#include <__type_traits/negation.h>
#include <__utility/convert_to_integral.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -33,39 +29,24 @@ _LIBCPP_BEGIN_NAMESPACE_STD
// fill_n isn't specialized for std::memset, because the compiler already optimizes the loop to a call to std::memset.
-template <class _OutputIterator,
- class _Size,
- class _Tp
-#ifndef _LIBCPP_CXX03_LANG
- ,
- __enable_if_t<!_And<_BoolConstant<__is_segmented_iterator_v<_OutputIterator>>,
- __has_random_access_local_iterator<_OutputIterator>>::value,
- int> = 0
-#endif
- >
+template <class _OutputIterator, class _Size, class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
__fill_n(_OutputIterator __first, _Size __n, const _Tp& __value) {
+#ifndef _LIBCPP_CXX03_LANG
+ if constexpr (__is_segmented_iterator_v<_OutputIterator>) {
+ using __local_iterator = typename __segmented_iterator_traits<_OutputIterator>::__local_iterator;
+ if constexpr (__has_random_access_iterator_category<__local_iterator>::value) {
+ return std::__for_each_n_segment(__first, __n, [&](__local_iterator __lfirst, __local_iterator __llast) {
+ std::__fill_n(__lfirst, __llast - __lfirst, __value);
+ });
+ }
+ }
+#endif
for (; __n > 0; ++__first, (void)--__n)
*__first = __value;
return __first;
}
-#ifndef _LIBCPP_CXX03_LANG
-template < class _OutputIterator,
- class _Size,
- class _Tp,
- __enable_if_t<_And<_BoolConstant<__is_segmented_iterator_v<_OutputIterator>>,
- __has_random_access_local_iterator<_OutputIterator>>::value,
- int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI
-_LIBCPP_CONSTEXPR_SINCE_CXX14 _OutputIterator __fill_n(_OutputIterator __first, _Size __n, const _Tp& __value) {
- using __local_iterator_t = typename __segmented_iterator_traits<_OutputIterator>::__local_iterator;
- return std::__for_each_n_segment(__first, __n, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) {
- std::__fill_n(__lfirst, __llast - __lfirst, __value);
- });
-}
-#endif // !_LIBCPP_CXX03_LANG
-
template <bool _FillVal, class _Cp>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
__fill_n_bool(__bit_iterator<_Cp, false> __first, typename __size_difference_type_traits<_Cp>::size_type __n) {
diff --git a/libcxx/include/__algorithm/for_each.h b/libcxx/include/__algorithm/for_each.h
index 6fb66d2..cb26aa4 100644
--- a/libcxx/include/__algorithm/for_each.h
+++ b/libcxx/include/__algorithm/for_each.h
@@ -14,8 +14,8 @@
#include <__config>
#include <__functional/identity.h>
#include <__iterator/segmented_iterator.h>
-#include <__type_traits/enable_if.h>
#include <__type_traits/invoke.h>
+#include <__type_traits/is_same.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -25,27 +25,21 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _Sent, class _Func, class _Proj>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
-__for_each(_InputIterator __first, _Sent __last, _Func& __f, _Proj& __proj) {
+__for_each(_InputIterator __first, _Sent __last, _Func& __func, _Proj& __proj) {
+#ifndef _LIBCPP_CXX03_LANG
+ if constexpr (is_same<_InputIterator, _Sent>::value && __is_segmented_iterator_v<_InputIterator>) {
+ using __local_iterator_t = typename __segmented_iterator_traits<_InputIterator>::__local_iterator;
+ std::__for_each_segment(__first, __last, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) {
+ std::__for_each(__lfirst, __llast, __func, __proj);
+ });
+ return __last;
+ }
+#endif
for (; __first != __last; ++__first)
- std::__invoke(__f, std::__invoke(__proj, *__first));
+ std::__invoke(__func, std::__invoke(__proj, *__first));
return __first;
}
-#ifndef _LIBCPP_CXX03_LANG
-template <class _SegmentedIterator,
- class _Func,
- class _Proj,
- __enable_if_t<__is_segmented_iterator_v<_SegmentedIterator>, int> = 0>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _SegmentedIterator
-__for_each(_SegmentedIterator __first, _SegmentedIterator __last, _Func& __func, _Proj& __proj) {
- using __local_iterator_t = typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator;
- std::__for_each_segment(__first, __last, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) {
- std::__for_each(__lfirst, __llast, __func, __proj);
- });
- return __last;
-}
-#endif // !_LIBCPP_CXX03_LANG
-
template <class _InputIterator, class _Func>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Func
for_each(_InputIterator __first, _InputIterator __last, _Func __f) {
diff --git a/libcxx/include/__algorithm/for_each_n.h b/libcxx/include/__algorithm/for_each_n.h
index 04650e1..72c7adb 100644
--- a/libcxx/include/__algorithm/for_each_n.h
+++ b/libcxx/include/__algorithm/for_each_n.h
@@ -16,10 +16,7 @@
#include <__functional/identity.h>
#include <__iterator/iterator_traits.h>
#include <__iterator/segmented_iterator.h>
-#include <__type_traits/disjunction.h>
-#include <__type_traits/enable_if.h>
#include <__type_traits/invoke.h>
-#include <__type_traits/negation.h>
#include <__utility/convert_to_integral.h>
#include <__utility/move.h>
@@ -32,57 +29,33 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD
-template <class _InputIterator,
- class _Size,
- class _Func,
- class _Proj,
- __enable_if_t<!__has_random_access_iterator_category<_InputIterator>::value &&
- _Or<integral_constant<bool, !__is_segmented_iterator_v<_InputIterator> >,
- _Not<__has_random_access_local_iterator<_InputIterator> > >::value,
- int> = 0>
+template <class _InputIterator, class _Size, class _Func, class _Proj>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
__for_each_n(_InputIterator __first, _Size __orig_n, _Func& __f, _Proj& __proj) {
typedef decltype(std::__convert_to_integral(__orig_n)) _IntegralSize;
_IntegralSize __n = __orig_n;
- while (__n > 0) {
- std::__invoke(__f, std::__invoke(__proj, *__first));
- ++__first;
- --__n;
- }
- return std::move(__first);
-}
-
-template <class _RandIter,
- class _Size,
- class _Func,
- class _Proj,
- __enable_if_t<__has_random_access_iterator_category<_RandIter>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandIter
-__for_each_n(_RandIter __first, _Size __orig_n, _Func& __f, _Proj& __proj) {
- typename std::iterator_traits<_RandIter>::difference_type __n = __orig_n;
- auto __last = __first + __n;
- std::__for_each(__first, __last, __f, __proj);
- return __last;
-}
#ifndef _LIBCPP_CXX03_LANG
-template <class _SegmentedIterator,
- class _Size,
- class _Func,
- class _Proj,
- __enable_if_t<!__has_random_access_iterator_category<_SegmentedIterator>::value &&
- __is_segmented_iterator_v<_SegmentedIterator> &&
- __has_random_access_iterator_category<
- typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator>::value,
- int> = 0>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _SegmentedIterator
-__for_each_n(_SegmentedIterator __first, _Size __orig_n, _Func& __f, _Proj& __proj) {
- using __local_iterator_t = typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator;
- return std::__for_each_n_segment(__first, __orig_n, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) {
- std::__for_each(__lfirst, __llast, __f, __proj);
- });
+ if constexpr (__is_segmented_iterator_v<_InputIterator>) {
+ using __local_iterator = typename __segmented_iterator_traits<_InputIterator>::__local_iterator;
+ if constexpr (__has_random_access_iterator_category<__local_iterator>::value) {
+ return std::__for_each_n_segment(__first, __orig_n, [&](__local_iterator __lfirst, __local_iterator __llast) {
+ std::__for_each(__lfirst, __llast, __f, __proj);
+ });
+ } else {
+ return std::__for_each(__first, __first + __n, __f, __proj);
+ }
+ } else
+#endif
+ {
+ while (__n > 0) {
+ std::__invoke(__f, std::__invoke(__proj, *__first));
+ ++__first;
+ --__n;
+ }
+ return std::move(__first);
+ }
}
-#endif // !_LIBCPP_CXX03_LANG
#if _LIBCPP_STD_VER >= 17
diff --git a/libcxx/include/__chrono/is_clock.h b/libcxx/include/__chrono/is_clock.h
new file mode 100644
index 0000000..e63b848
--- /dev/null
+++ b/libcxx/include/__chrono/is_clock.h
@@ -0,0 +1,72 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___CHRONO_IS_CLOCK_H
+#define _LIBCPP___CHRONO_IS_CLOCK_H
+
+#include <__config>
+
+#include <__chrono/duration.h>
+#include <__chrono/time_point.h>
+#include <__concepts/same_as.h>
+#include <__type_traits/integral_constant.h>
+#include <__type_traits/is_arithmetic.h>
+#include <__type_traits/is_class.h>
+#include <__type_traits/is_union.h>
+#include <ratio>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+#if _LIBCPP_STD_VER >= 20
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+namespace chrono {
+
+// Helper to check that _Tp::time_point has the form time_point<_, typename _Tp::duration>.
+template <class _TimePoint, class _ClockType>
+inline constexpr bool __is_valid_clock_time_point_v = false;
+
+template <class _TimePointClock, class _ClockType>
+inline constexpr bool
+ __is_valid_clock_time_point_v<time_point<_TimePointClock, typename _ClockType::duration>, _ClockType> = true;
+
+// Check if a clock satisfies the Cpp17Clock requirements as defined in [time.clock.req]
+template <class _Tp>
+_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool is_clock_v = requires {
+ typename _Tp::rep;
+ requires is_arithmetic_v<typename _Tp::rep> || is_class_v<typename _Tp::rep> || is_union_v<typename _Tp::rep>;
+
+ typename _Tp::period;
+ requires __is_ratio_v<typename _Tp::period>;
+
+ typename _Tp::duration;
+ requires same_as<typename _Tp::duration, duration<typename _Tp::rep, typename _Tp::period>>;
+
+ typename _Tp::time_point;
+ requires __is_valid_clock_time_point_v<typename _Tp::time_point, _Tp>;
+
+ _Tp::is_steady;
+ requires same_as<decltype((_Tp::is_steady)), const bool&>;
+
+ _Tp::now();
+ requires same_as<decltype(_Tp::now()), typename _Tp::time_point>;
+};
+
+template <class _Tp>
+struct _LIBCPP_NO_SPECIALIZATIONS is_clock : bool_constant<is_clock_v<_Tp>> {};
+
+} // namespace chrono
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_STD_VER
+#endif // _LIBCPP___CHRONO_IS_CLOCK_H
diff --git a/libcxx/include/__iterator/distance.h b/libcxx/include/__iterator/distance.h
index 9be9db0..1a9fbf2 100644
--- a/libcxx/include/__iterator/distance.h
+++ b/libcxx/include/__iterator/distance.h
@@ -11,6 +11,7 @@
#define _LIBCPP___ITERATOR_DISTANCE_H
#include <__algorithm/for_each_segment.h>
+#include <__concepts/same_as.h>
#include <__config>
#include <__iterator/concepts.h>
#include <__iterator/incrementable_traits.h>
@@ -41,35 +42,29 @@ template <class _Iter>
using __iter_distance_t _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::difference_type;
#endif
-template <class _InputIter, class _Sent>
-inline _LIBCPP_HIDE_FROM_ABI
-_LIBCPP_CONSTEXPR_SINCE_CXX17 __iter_distance_t<_InputIter> __distance(_InputIter __first, _Sent __last) {
- __iter_distance_t<_InputIter> __r(0);
- for (; __first != __last; ++__first)
- ++__r;
- return __r;
-}
-
template <class _RandIter, __enable_if_t<__has_random_access_iterator_category<_RandIter>::value, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 __iter_distance_t<_RandIter>
__distance(_RandIter __first, _RandIter __last) {
return __last - __first;
}
+template <class _InputIter, class _Sent>
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 __iter_distance_t<_InputIter>
+__distance(_InputIter __first, _Sent __last) {
+ __iter_distance_t<_InputIter> __r(0);
#if _LIBCPP_STD_VER >= 20
-template <class _SegmentedIter,
- __enable_if_t<!__has_random_access_iterator_category<_SegmentedIter>::value &&
- __is_segmented_iterator_v<_SegmentedIter>,
- int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 __iter_distance_t<_SegmentedIter>
-__distance(_SegmentedIter __first, _SegmentedIter __last) {
- __iter_distance_t<_SegmentedIter> __r(0);
- std::__for_each_segment(__first, __last, [&__r](auto __lfirst, auto __llast) {
- __r += std::__distance(__lfirst, __llast);
- });
+ if constexpr (same_as<_InputIter, _Sent> && __is_segmented_iterator_v<_InputIter>) {
+ std::__for_each_segment(__first, __last, [&__r](auto __lfirst, auto __llast) {
+ __r += std::__distance(__lfirst, __llast);
+ });
+ } else
+#endif
+ {
+ for (; __first != __last; ++__first)
+ ++__r;
+ }
return __r;
}
-#endif // _LIBCPP_STD_VER >= 20
template <class _InputIter>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 typename iterator_traits<_InputIter>::difference_type
diff --git a/libcxx/include/__iterator/segmented_iterator.h b/libcxx/include/__iterator/segmented_iterator.h
index 5df9737..dc56a74 100644
--- a/libcxx/include/__iterator/segmented_iterator.h
+++ b/libcxx/include/__iterator/segmented_iterator.h
@@ -75,11 +75,6 @@ inline const bool __has_specialization_v<_Tp, sizeof(_Tp) * 0> = true;
template <class _Iterator>
inline const bool __is_segmented_iterator_v = __has_specialization_v<__segmented_iterator_traits<_Iterator> >;
-template <class _SegmentedIterator>
-struct __has_random_access_local_iterator
- : __has_random_access_iterator_category<
- typename __segmented_iterator_traits< _SegmentedIterator >::__local_iterator > {};
-
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP___SEGMENTED_ITERATOR_H
diff --git a/libcxx/include/chrono b/libcxx/include/chrono
index 82e99a3..aa4fc62 100644
--- a/libcxx/include/chrono
+++ b/libcxx/include/chrono
@@ -218,6 +218,9 @@ template <class ToDuration, class Rep, class Period>
template <class ToDuration, class Rep, class Period>
constexpr ToDuration round(const duration<Rep, Period>& d); // C++17
+template <class T> struct is_clock; // C++20
+template <class T> inline constexpr bool is_clock_v = is_clock<T>::value; // C++20
+
// duration I/O
template<class charT, class traits, class Rep, class Period> // C++20
basic_ostream<charT, traits>&
@@ -1057,6 +1060,7 @@ constexpr chrono::year operator ""y(unsigned lo
# include <__chrono/day.h>
# include <__chrono/exception.h>
# include <__chrono/hh_mm_ss.h>
+# include <__chrono/is_clock.h>
# include <__chrono/literals.h>
# include <__chrono/local_info.h>
# include <__chrono/month.h>
diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index 1f88d13..b07ca63 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -308,6 +308,19 @@ protected:
return basic_streambuf<_CharT, _Traits>::xsputn(__str, __len);
}
+ _LIBCPP_HIDE_FROM_ABI_VIRTUAL streamsize xsgetn(char_type* __str, streamsize __len) override {
+ if (__always_noconv_) {
+ const streamsize __n = std::min(this->egptr() - this->gptr(), __len);
+ if (__n != 0) {
+ traits_type::copy(__str, this->gptr(), __n);
+ this->__gbump_ptrdiff(__n);
+ }
+ if (__len - __n >= this->egptr() - this->eback())
+ return std::fread(__str + __n, sizeof(char_type), __len - __n, __file_);
+ }
+ return basic_streambuf<_CharT, _Traits>::xsgetn(__str, __len);
+ }
+
private:
char* __extbuf_;
const char* __extbufnext_;
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 24a2fe7..f77c885 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -973,6 +973,10 @@ module std [system] {
header "__chrono/high_resolution_clock.h"
export *
}
+ module is_clock {
+ header "__chrono/is_clock.h"
+ export std_core.type_traits.integral_constant
+ }
module leap_second {
header "__chrono/leap_second.h"
}
diff --git a/libcxx/modules/std/chrono.inc b/libcxx/modules/std/chrono.inc
index 66eccd8..db405d48 100644
--- a/libcxx/modules/std/chrono.inc
+++ b/libcxx/modules/std/chrono.inc
@@ -25,8 +25,8 @@ export namespace std {
using std::chrono::duration_values;
- // using std::chrono::is_clock;
- // using std::chrono::is_clock_v;
+ using std::chrono::is_clock;
+ using std::chrono::is_clock_v;
// [time.duration.nonmember], duration arithmetic
using std::chrono::operator+;
diff --git a/libcxx/test/benchmarks/streams/ofstream.bench.cpp b/libcxx/test/benchmarks/streams/fstream.bench.cpp
index 60606a9..3ca1801 100644
--- a/libcxx/test/benchmarks/streams/ofstream.bench.cpp
+++ b/libcxx/test/benchmarks/streams/fstream.bench.cpp
@@ -11,7 +11,7 @@
#include <benchmark/benchmark.h>
-static void bm_write(benchmark::State& state) {
+static void bm_ofstream_write(benchmark::State& state) {
std::vector<char> buffer;
buffer.resize(16384);
@@ -20,6 +20,24 @@ static void bm_write(benchmark::State& state) {
for (auto _ : state)
stream.write(buffer.data(), buffer.size());
}
-BENCHMARK(bm_write);
+BENCHMARK(bm_ofstream_write);
+
+static void bm_ifstream_read(benchmark::State& state) {
+ std::vector<char> buffer;
+ buffer.resize(16384);
+
+ std::ofstream gen_testfile("testfile");
+ gen_testfile.write(buffer.data(), buffer.size());
+
+ std::ifstream stream("testfile");
+ assert(stream);
+
+ for (auto _ : state) {
+ stream.read(buffer.data(), buffer.size());
+ benchmark::DoNotOptimize(buffer);
+ stream.seekg(0);
+ }
+}
+BENCHMARK(bm_ifstream_read);
BENCHMARK_MAIN();
diff --git a/libcxx/test/libcxx/input.output/file.streams/fstreams/filebuf/traits_mismatch.verify.cpp b/libcxx/test/libcxx/input.output/file.streams/fstreams/filebuf/traits_mismatch.verify.cpp
index 283adbc..30e7b66 100644
--- a/libcxx/test/libcxx/input.output/file.streams/fstreams/filebuf/traits_mismatch.verify.cpp
+++ b/libcxx/test/libcxx/input.output/file.streams/fstreams/filebuf/traits_mismatch.verify.cpp
@@ -19,4 +19,4 @@
std::basic_filebuf<char, std::char_traits<wchar_t> > f;
// expected-error-re@*:* {{static assertion failed{{.*}}traits_type::char_type must be the same type as CharT}}
-// expected-error@*:* 10 {{only virtual member functions can be marked 'override'}}
+// expected-error@*:* 11 {{only virtual member functions can be marked 'override'}}
diff --git a/libcxx/test/libcxx/input.output/file.streams/fstreams/traits_mismatch.verify.cpp b/libcxx/test/libcxx/input.output/file.streams/fstreams/traits_mismatch.verify.cpp
index ba6f3c3..daafb36 100644
--- a/libcxx/test/libcxx/input.output/file.streams/fstreams/traits_mismatch.verify.cpp
+++ b/libcxx/test/libcxx/input.output/file.streams/fstreams/traits_mismatch.verify.cpp
@@ -21,7 +21,7 @@ std::basic_fstream<char, std::char_traits<wchar_t> > f;
// expected-error-re@*:* {{static assertion failed{{.*}}traits_type::char_type must be the same type as CharT}}
// expected-error-re@*:* {{static assertion failed{{.*}}traits_type::char_type must be the same type as CharT}}
-// expected-error@*:* 12 {{only virtual member functions can be marked 'override'}}
+// expected-error@*:* 13 {{only virtual member functions can be marked 'override'}}
// FIXME: As of commit r324062 Clang incorrectly generates a diagnostic about mismatching
// exception specifications for types which are already invalid for one reason or another.
diff --git a/libcxx/test/libcxx/time/time.traits.is.clock/trait.is.clock.compile.verify.cpp b/libcxx/test/libcxx/time/time.traits.is.clock/trait.is.clock.compile.verify.cpp
new file mode 100644
index 0000000..e9ad59a
--- /dev/null
+++ b/libcxx/test/libcxx/time/time.traits.is.clock/trait.is.clock.compile.verify.cpp
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++20
+
+#include <chrono>
+#include <ratio>
+
+#if !__has_warning("-Winvalid-specializations")
+// expected-no-diagnostics
+#else
+
+template <>
+struct std::chrono::is_clock<int> : std::false_type {}; // expected-error@*:* {{'is_clock' cannot be specialized}}
+
+template <>
+constexpr bool std::chrono::is_clock_v<float> = false; // expected-error@*:* {{'is_clock_v' cannot be specialized}}
+
+#endif
diff --git a/libcxx/test/std/time/time.traits.is.clock/trait.is.clock.compile.pass.cpp b/libcxx/test/std/time/time.traits.is.clock/trait.is.clock.compile.pass.cpp
new file mode 100644
index 0000000..4168fa7
--- /dev/null
+++ b/libcxx/test/std/time/time.traits.is.clock/trait.is.clock.compile.pass.cpp
@@ -0,0 +1,225 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++20
+
+#include <chrono>
+#include <ratio>
+
+#include "test_macros.h"
+
+struct EmptyStruct {};
+
+// Test structs missing required members
+struct MissingRep {
+ using period = std::ratio<1>;
+ using duration = std::chrono::seconds;
+ using time_point = std::chrono::time_point<MissingRep>;
+ static constexpr bool is_steady = false;
+ static time_point now();
+};
+
+struct MissingPeriod {
+ using rep = long;
+ using duration = std::chrono::seconds;
+ using time_point = std::chrono::time_point<MissingPeriod>;
+ static constexpr bool is_steady = false;
+ static time_point now();
+};
+
+struct MissingDuration {
+ using rep = long;
+ using time_point = long;
+ static constexpr bool is_steady = false;
+ static time_point now();
+};
+
+struct MissingTimePoint {
+ using rep = long;
+ using period = std::ratio<1>;
+ using duration = std::chrono::seconds;
+ static constexpr bool is_steady = false;
+ static std::chrono::time_point<MissingTimePoint> now();
+};
+
+struct MissingIsSteady {
+ using rep = long;
+ using period = std::ratio<1>;
+ using duration = std::chrono::seconds;
+ using time_point = std::chrono::time_point<MissingIsSteady>;
+ static time_point now();
+};
+
+struct MissingNow {
+ using rep = long;
+ using period = std::ratio<1>;
+ using duration = std::chrono::seconds;
+ using time_point = std::chrono::time_point<MissingNow>;
+ static constexpr bool is_steady = false;
+};
+
+// Valid clock types
+struct ValidSteadyClock {
+ using rep = long long;
+ using period = std::nano;
+ using duration = std::chrono::nanoseconds;
+ using time_point = std::chrono::time_point<ValidSteadyClock>;
+ static constexpr bool is_steady = true;
+ static time_point now();
+};
+
+struct ValidSystemClock {
+ using rep = long long;
+ using period = std::micro;
+ using duration = std::chrono::microseconds;
+ using time_point = std::chrono::time_point<ValidSystemClock>;
+ static constexpr bool is_steady = false;
+ static time_point now();
+};
+
+// Test clocks with invalid is_steady type
+struct WrongIsSteadyType {
+ using rep = long;
+ using period = std::ratio<1>;
+ using duration = std::chrono::seconds;
+ using time_point = std::chrono::time_point<WrongIsSteadyType>;
+ static bool is_steady; // Not const bool
+ static time_point now();
+};
+
+struct WrongIsSteadyNonBool {
+ using rep = long;
+ using period = std::ratio<1>;
+ using duration = std::chrono::seconds;
+ using time_point = std::chrono::time_point<WrongIsSteadyNonBool>;
+ static constexpr int is_steady = 1; // Not bool
+ static time_point now();
+};
+
+// Test clocks with invalid now() return type
+struct WrongNowReturnType {
+ using rep = long;
+ using period = std::ratio<1>;
+ using duration = std::chrono::seconds;
+ using time_point = std::chrono::time_point<WrongNowReturnType>;
+ static constexpr bool is_steady = false;
+ static int now(); // Wrong return type
+};
+
+// Test clocks with invalid period type
+struct WrongPeriodType {
+ using rep = long;
+ using period = int; // Not a ratio
+ using duration = std::chrono::seconds;
+ using time_point = std::chrono::time_point<WrongPeriodType>;
+ static constexpr bool is_steady = false;
+ static time_point now();
+};
+
+// Test clocks with wrong duration type
+struct WrongDurationType {
+ using rep = long;
+ using period = std::ratio<1>;
+ using duration = std::chrono::milliseconds; // Should be duration<long, ratio<1>>
+ using time_point = std::chrono::time_point<WrongDurationType>;
+ static constexpr bool is_steady = false;
+ static time_point now();
+};
+
+// Test clocks with wrong time_point type
+struct WrongTimePointType {
+ using rep = long;
+ using period = std::ratio<1>;
+ using duration = std::chrono::duration<long, std::ratio<1>>;
+ using time_point = int; // Not a time_point
+ static constexpr bool is_steady = false;
+ static time_point now();
+};
+
+struct WrongTimePointClock {
+ using rep = long;
+ using period = std::ratio<1>;
+ using duration = std::chrono::duration<long, std::ratio<1>>;
+ using time_point = std::chrono::time_point<ValidSystemClock>; // Wrong clock type
+ static constexpr bool is_steady = false;
+ static time_point now();
+};
+
+// Valid clock with time_point that has matching duration instead of matching clock
+struct ValidClockWithDurationMatch {
+ using rep = int;
+ using period = std::milli;
+ using duration = std::chrono::duration<int, std::milli>;
+ using time_point = std::chrono::time_point<ValidSystemClock, duration>; // Valid: matches duration
+ static constexpr bool is_steady = false;
+ static time_point now();
+};
+
+// Test both is_clock and is_clock_v
+static_assert(std::chrono::is_clock<std::chrono::system_clock>::value);
+static_assert(std::chrono::is_clock_v<std::chrono::system_clock>);
+
+// Test standard clock types
+static_assert(std::chrono::is_clock_v<std::chrono::system_clock>);
+static_assert(std::chrono::is_clock_v<std::chrono::high_resolution_clock>);
+
+// Test non-clock types
+static_assert(!std::chrono::is_clock_v<EmptyStruct>);
+static_assert(!std::chrono::is_clock_v<int>);
+static_assert(!std::chrono::is_clock_v<void>);
+static_assert(!std::chrono::is_clock_v<std::chrono::system_clock::time_point>);
+static_assert(!std::chrono::is_clock_v<std::chrono::seconds>);
+static_assert(!std::chrono::is_clock_v<std::chrono::milliseconds>);
+
+// Test structs missing required members
+static_assert(!std::chrono::is_clock_v<MissingRep>);
+static_assert(!std::chrono::is_clock_v<MissingPeriod>);
+static_assert(!std::chrono::is_clock_v<MissingDuration>);
+static_assert(!std::chrono::is_clock_v<MissingTimePoint>);
+static_assert(!std::chrono::is_clock_v<MissingIsSteady>);
+static_assert(!std::chrono::is_clock_v<MissingNow>);
+
+// Test valid custom clocks
+static_assert(std::chrono::is_clock_v<ValidSteadyClock>);
+static_assert(std::chrono::is_clock_v<ValidSystemClock>);
+static_assert(std::chrono::is_clock_v<ValidClockWithDurationMatch>);
+
+// cv-qualified and reference types
+static_assert(std::chrono::is_clock_v<const std::chrono::system_clock>);
+static_assert(std::chrono::is_clock_v<volatile std::chrono::system_clock>);
+static_assert(std::chrono::is_clock_v<const volatile std::chrono::system_clock>);
+static_assert(!std::chrono::is_clock_v<std::chrono::system_clock&>);
+static_assert(!std::chrono::is_clock_v<std::chrono::system_clock&&>);
+static_assert(!std::chrono::is_clock_v<const std::chrono::system_clock&>);
+
+// array and pointer types
+static_assert(!std::chrono::is_clock_v<std::chrono::system_clock[]>);
+static_assert(!std::chrono::is_clock_v<std::chrono::system_clock[10]>);
+static_assert(!std::chrono::is_clock_v<std::chrono::system_clock*>);
+static_assert(!std::chrono::is_clock_v<std::chrono::system_clock* const>);
+
+// The Standard defined a minimum set of checks and allowed implementation to perform stricter checks. The following
+// static asserts are implementation specific and a conforming standard library implementation doesn't have to produce
+// the same outcome.
+
+// Test clocks with invalid is_steady type
+LIBCPP_STATIC_ASSERT(!std::chrono::is_clock_v<WrongIsSteadyType>); // is_steady not const bool
+LIBCPP_STATIC_ASSERT(!std::chrono::is_clock_v<WrongIsSteadyNonBool>); // is_steady not bool type
+
+// Test clocks with invalid now() return type
+LIBCPP_STATIC_ASSERT(!std::chrono::is_clock_v<WrongNowReturnType>); // now() doesn't return time_point
+
+// Test clocks with invalid period type
+LIBCPP_STATIC_ASSERT(!std::chrono::is_clock_v<WrongPeriodType>); // period is not a ratio
+
+// Test clocks with wrong duration type
+LIBCPP_STATIC_ASSERT(!std::chrono::is_clock_v<WrongDurationType>); // duration doesn't match duration<rep, period>
+
+// Test clocks with wrong time_point type
+LIBCPP_STATIC_ASSERT(!std::chrono::is_clock_v<WrongTimePointType>); // time_point is not a time_point
+LIBCPP_STATIC_ASSERT(!std::chrono::is_clock_v<WrongTimePointClock>); // time_point has wrong clock and wrong duration