diff options
Diffstat (limited to 'libcxx')
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 |
