diff options
author | hiddenpath <hiddenpath@yandex-team.com> | 2024-02-21 23:16:42 +0300 |
---|---|---|
committer | hiddenpath <hiddenpath@yandex-team.com> | 2024-02-21 23:33:25 +0300 |
commit | 9052eb5cc304b8da8885fc4e3364ebddc16945f3 (patch) | |
tree | 3c252f6161dd0745c7732d74c9304c000645ab47 /contrib/libs/cxxsupp/libcxx/src | |
parent | f5eb715f103692e7c7536e13bef3f281fd78e5e7 (diff) | |
download | ydb-9052eb5cc304b8da8885fc4e3364ebddc16945f3.tar.gz |
Update libcxx to llvmorg-17.0.6
Update libcxx to llvmorg-17.0.6
c871ef572c71b4fef22d4a9e65bcebc57e625aea
Diffstat (limited to 'contrib/libs/cxxsupp/libcxx/src')
60 files changed, 2731 insertions, 2603 deletions
diff --git a/contrib/libs/cxxsupp/libcxx/src/algorithm.cpp b/contrib/libs/cxxsupp/libcxx/src/algorithm.cpp index bd47e08b38..af9d60a8e2 100644 --- a/contrib/libs/cxxsupp/libcxx/src/algorithm.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/algorithm.cpp @@ -7,11 +7,25 @@ //===----------------------------------------------------------------------===// #include <algorithm> +#include <bit> _LIBCPP_BEGIN_NAMESPACE_STD -// TODO(varconst): this currently doesn't benefit `ranges::sort` because it uses `ranges::less` instead of `__less`. +template <class Comp, class RandomAccessIterator> +void __sort(RandomAccessIterator first, RandomAccessIterator last, Comp comp) { + auto depth_limit = 2 * std::__bit_log2(static_cast<size_t>(last - first)); + // Only use bitset partitioning for arithmetic types. We should also check + // that the default comparator is in use so that we are sure that there are no + // branches in the comparator. + std::__introsort<_ClassicAlgPolicy, + ranges::less, + RandomAccessIterator, + __use_branchless_sort<ranges::less, RandomAccessIterator>::value>( + first, last, ranges::less{}, depth_limit); +} + +// clang-format off template void __sort<__less<char>&, char*>(char*, char*, __less<char>&); #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template void __sort<__less<wchar_t>&, wchar_t*>(wchar_t*, wchar_t*, __less<wchar_t>&); @@ -29,25 +43,6 @@ template void __sort<__less<unsigned long long>&, unsigned long long*>(unsigned template void __sort<__less<float>&, float*>(float*, float*, __less<float>&); template void __sort<__less<double>&, double*>(double*, double*, __less<double>&); template void __sort<__less<long double>&, long double*>(long double*, long double*, __less<long double>&); - -template bool __insertion_sort_incomplete<__less<char>&, char*>(char*, char*, __less<char>&); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template bool __insertion_sort_incomplete<__less<wchar_t>&, wchar_t*>(wchar_t*, wchar_t*, __less<wchar_t>&); -#endif -template bool __insertion_sort_incomplete<__less<signed char>&, signed char*>(signed char*, signed char*, __less<signed char>&); -template bool __insertion_sort_incomplete<__less<unsigned char>&, unsigned char*>(unsigned char*, unsigned char*, __less<unsigned char>&); -template bool __insertion_sort_incomplete<__less<short>&, short*>(short*, short*, __less<short>&); -template bool __insertion_sort_incomplete<__less<unsigned short>&, unsigned short*>(unsigned short*, unsigned short*, __less<unsigned short>&); -template bool __insertion_sort_incomplete<__less<int>&, int*>(int*, int*, __less<int>&); -template bool __insertion_sort_incomplete<__less<unsigned>&, unsigned*>(unsigned*, unsigned*, __less<unsigned>&); -template bool __insertion_sort_incomplete<__less<long>&, long*>(long*, long*, __less<long>&); -template bool __insertion_sort_incomplete<__less<unsigned long>&, unsigned long*>(unsigned long*, unsigned long*, __less<unsigned long>&); -template bool __insertion_sort_incomplete<__less<long long>&, long long*>(long long*, long long*, __less<long long>&); -template bool __insertion_sort_incomplete<__less<unsigned long long>&, unsigned long long*>(unsigned long long*, unsigned long long*, __less<unsigned long long>&); -template bool __insertion_sort_incomplete<__less<float>&, float*>(float*, float*, __less<float>&); -template bool __insertion_sort_incomplete<__less<double>&, double*>(double*, double*, __less<double>&); -template bool __insertion_sort_incomplete<__less<long double>&, long double*>(long double*, long double*, __less<long double>&); - -template unsigned __sort5<__less<long double>&, long double*>(long double*, long double*, long double*, long double*, long double*, __less<long double>&); +// clang-format on _LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/algorithm_old.cpp b/contrib/libs/cxxsupp/libcxx/src/algorithm_old.cpp new file mode 100644 index 0000000000..90cb7785cd --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/src/algorithm_old.cpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include <algorithm> + +namespace old_sort { + +// TODO(varconst): this currently doesn't benefit `ranges::sort` because it uses `ranges::less` instead of `__less`. + +template void __sort<std::__less<>&, char*>(char*, char*, std::__less<>&); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template void __sort<std::__less<>&, wchar_t*>(wchar_t*, wchar_t*, std::__less<>&); +#endif +template void __sort<std::__less<>&, signed char*>(signed char*, signed char*, std::__less<>&); +template void __sort<std::__less<>&, unsigned char*>(unsigned char*, unsigned char*, std::__less<>&); +template void __sort<std::__less<>&, short*>(short*, short*, std::__less<>&); +template void __sort<std::__less<>&, unsigned short*>(unsigned short*, unsigned short*, std::__less<>&); +template void __sort<std::__less<>&, int*>(int*, int*, std::__less<>&); +template void __sort<std::__less<>&, unsigned*>(unsigned*, unsigned*, std::__less<>&); +template void __sort<std::__less<>&, long*>(long*, long*, std::__less<>&); +template void __sort<std::__less<>&, unsigned long*>(unsigned long*, unsigned long*, std::__less<>&); +template void __sort<std::__less<>&, long long*>(long long*, long long*, std::__less<>&); +template void __sort<std::__less<>&, unsigned long long*>(unsigned long long*, unsigned long long*, std::__less<>&); +template void __sort<std::__less<>&, float*>(float*, float*, std::__less<>&); +template void __sort<std::__less<>&, double*>(double*, double*, std::__less<>&); +template void __sort<std::__less<>&, long double*>(long double*, long double*, std::__less<>&); + +template bool __insertion_sort_incomplete<std::__less<>&, char*>(char*, char*, std::__less<>&); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template bool __insertion_sort_incomplete<std::__less<>&, wchar_t*>(wchar_t*, wchar_t*, std::__less<>&); +#endif +template bool __insertion_sort_incomplete<std::__less<>&, signed char*>(signed char*, signed char*, std::__less<>&); +template bool __insertion_sort_incomplete<std::__less<>&, unsigned char*>(unsigned char*, unsigned char*, std::__less<>&); +template bool __insertion_sort_incomplete<std::__less<>&, short*>(short*, short*, std::__less<>&); +template bool __insertion_sort_incomplete<std::__less<>&, unsigned short*>(unsigned short*, unsigned short*, std::__less<>&); +template bool __insertion_sort_incomplete<std::__less<>&, int*>(int*, int*, std::__less<>&); +template bool __insertion_sort_incomplete<std::__less<>&, unsigned*>(unsigned*, unsigned*, std::__less<>&); +template bool __insertion_sort_incomplete<std::__less<>&, long*>(long*, long*, std::__less<>&); +template bool __insertion_sort_incomplete<std::__less<>&, unsigned long*>(unsigned long*, unsigned long*, std::__less<>&); +template bool __insertion_sort_incomplete<std::__less<>&, long long*>(long long*, long long*, std::__less<>&); +template bool __insertion_sort_incomplete<std::__less<>&, unsigned long long*>(unsigned long long*, unsigned long long*, std::__less<>&); +template bool __insertion_sort_incomplete<std::__less<>&, float*>(float*, float*, std::__less<>&); +template bool __insertion_sort_incomplete<std::__less<>&, double*>(double*, double*, std::__less<>&); +template bool __insertion_sort_incomplete<std::__less<>&, long double*>(long double*, long double*, std::__less<>&); + +template unsigned __sort5<std::__less<>&, long double*>(long double*, long double*, long double*, long double*, long double*, std::__less<>&); + +} // namespace old_sort diff --git a/contrib/libs/cxxsupp/libcxx/src/any.cpp b/contrib/libs/cxxsupp/libcxx/src/any.cpp index 9a101b44a7..36f95c0ec4 100644 --- a/contrib/libs/cxxsupp/libcxx/src/any.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/any.cpp @@ -21,7 +21,7 @@ const char* bad_any_cast::what() const noexcept { // Even though it no longer exists in a header file _LIBCPP_BEGIN_NAMESPACE_LFTS -class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_ANY_CAST bad_any_cast : public bad_cast +class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_BAD_ANY_CAST bad_any_cast : public bad_cast { public: virtual const char* what() const noexcept; diff --git a/contrib/libs/cxxsupp/libcxx/src/atomic.cpp b/contrib/libs/cxxsupp/libcxx/src/atomic.cpp index 7777e888c0..a55249a15c 100644 --- a/contrib/libs/cxxsupp/libcxx/src/atomic.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/atomic.cpp @@ -9,11 +9,14 @@ #include <__config> #ifndef _LIBCPP_HAS_NO_THREADS +#include <__thread/timed_backoff_policy.h> #include <atomic> #include <climits> #include <functional> #include <thread> +#include "include/apple_availability.h" + #ifdef __linux__ #include <unistd.h> @@ -77,20 +80,25 @@ static void __libcpp_platform_wake_by_address(__cxx_atomic_contention_t const vo const_cast<__cxx_atomic_contention_t*>(__ptr), 0); } -#elif defined(__FreeBSD__) +#elif defined(__FreeBSD__) && __SIZEOF_LONG__ == 8 +/* + * Since __cxx_contention_t is int64_t even on 32bit FreeBSD + * platforms, we have to use umtx ops that work on the long type, and + * limit its use to architectures where long and int64_t are synonyms. + */ static void __libcpp_platform_wait_on_address(__cxx_atomic_contention_t const volatile* __ptr, __cxx_contention_t __val) { _umtx_op(const_cast<__cxx_atomic_contention_t*>(__ptr), - UMTX_OP_WAIT_UINT_PRIVATE, __val, NULL, NULL); + UMTX_OP_WAIT, __val, NULL, NULL); } static void __libcpp_platform_wake_by_address(__cxx_atomic_contention_t const volatile* __ptr, bool __notify_one) { _umtx_op(const_cast<__cxx_atomic_contention_t*>(__ptr), - UMTX_OP_WAKE_PRIVATE, __notify_one ? 1 : INT_MAX, NULL, NULL); + UMTX_OP_WAKE, __notify_one ? 1 : INT_MAX, NULL, NULL); } #else // <- Add other operating systems here diff --git a/contrib/libs/cxxsupp/libcxx/src/charconv.cpp b/contrib/libs/cxxsupp/libcxx/src/charconv.cpp index d01ecddc46..aa52220413 100644 --- a/contrib/libs/cxxsupp/libcxx/src/charconv.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/charconv.cpp @@ -18,13 +18,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace __itoa { -_LIBCPP_FUNC_VIS char* +_LIBCPP_EXPORTED_FROM_ABI char* __u32toa(uint32_t value, char* buffer) noexcept { return __base_10_u32(buffer, value); } -_LIBCPP_FUNC_VIS char* +_LIBCPP_EXPORTED_FROM_ABI char* __u64toa(uint64_t value, char* buffer) noexcept { return __base_10_u64(buffer, value); diff --git a/contrib/libs/cxxsupp/libcxx/src/chrono.cpp b/contrib/libs/cxxsupp/libcxx/src/chrono.cpp index 0af89d6a52..f159613202 100644 --- a/contrib/libs/cxxsupp/libcxx/src/chrono.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/chrono.cpp @@ -12,9 +12,9 @@ #define _LARGE_TIME_API #endif -#include <cerrno> // errno +#include <__system_error/system_error.h> +#include <cerrno> // errno #include <chrono> -#include <system_error> // __throw_system_error #if defined(__MVS__) #include <__support/ibm/gettod_zos.h> // gettimeofdayMonotonic @@ -24,15 +24,15 @@ #include "include/apple_availability.h" #if __has_include(<unistd.h>) -# include <unistd.h> +# include <unistd.h> // _POSIX_TIMERS #endif #if __has_include(<sys/time.h>) # include <sys/time.h> // for gettimeofday and timeval #endif -#if !defined(__APPLE__) && defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 -# define _LIBCPP_USE_CLOCK_GETTIME +#if defined(__APPLE__) || defined (__gnu_hurd__) || (defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0) +# define _LIBCPP_HAS_CLOCK_GETTIME #endif #if defined(_LIBCPP_WIN32API) @@ -116,7 +116,7 @@ static system_clock::time_point __libcpp_system_clock_now() { return system_clock::time_point(duration_cast<system_clock::duration>(d - nt_to_unix_epoch)); } -#elif defined(CLOCK_REALTIME) && defined(_LIBCPP_USE_CLOCK_GETTIME) +#elif defined(_LIBCPP_HAS_CLOCK_GETTIME) static system_clock::time_point __libcpp_system_clock_now() { struct timespec tp; @@ -167,59 +167,6 @@ system_clock::from_time_t(time_t t) noexcept #if defined(__APPLE__) -// TODO(ldionne): -// This old implementation of steady_clock is retained until Chrome drops supports -// for macOS < 10.12. The issue is that they link libc++ statically into their -// application, which means that libc++ must support being built for such deployment -// targets. See https://llvm.org/D74489 for details. -#if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200) || \ - (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 100000) || \ - (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 100000) || \ - (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 30000) -# define _LIBCPP_USE_OLD_MACH_ABSOLUTE_TIME -#endif - -#if defined(_LIBCPP_USE_OLD_MACH_ABSOLUTE_TIME) - -// mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of -// nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom -// are run time constants supplied by the OS. This clock has no relationship -// to the Gregorian calendar. It's main use is as a high resolution timer. - -// MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize -// for that case as an optimization. - -static steady_clock::rep steady_simplified() { - return static_cast<steady_clock::rep>(mach_absolute_time()); -} -static double compute_steady_factor() { - mach_timebase_info_data_t MachInfo; - mach_timebase_info(&MachInfo); - return static_cast<double>(MachInfo.numer) / MachInfo.denom; -} - -static steady_clock::rep steady_full() { - static const double factor = compute_steady_factor(); - return static_cast<steady_clock::rep>(mach_absolute_time() * factor); -} - -typedef steady_clock::rep (*FP)(); - -static FP init_steady_clock() { - mach_timebase_info_data_t MachInfo; - mach_timebase_info(&MachInfo); - if (MachInfo.numer == MachInfo.denom) - return &steady_simplified; - return &steady_full; -} - -static steady_clock::time_point __libcpp_steady_clock_now() { - static FP fp = init_steady_clock(); - return steady_clock::time_point(steady_clock::duration(fp())); -} - -#else // vvvvv default behavior for Apple platforms vvvvv - // On Apple platforms, only CLOCK_UPTIME_RAW, CLOCK_MONOTONIC_RAW or // mach_absolute_time are able to time functions in the nanosecond range. // Furthermore, only CLOCK_MONOTONIC_RAW is truly monotonic, because it @@ -232,8 +179,6 @@ static steady_clock::time_point __libcpp_steady_clock_now() { return steady_clock::time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec)); } -#endif - #elif defined(_LIBCPP_WIN32API) // https://msdn.microsoft.com/en-us/library/windows/desktop/ms644905(v=vs.85).aspx says: @@ -281,7 +226,7 @@ static steady_clock::time_point __libcpp_steady_clock_now() noexcept { return steady_clock::time_point(nanoseconds(_zx_clock_get_monotonic())); } -# elif defined(CLOCK_MONOTONIC) +# elif defined(_LIBCPP_HAS_CLOCK_GETTIME) static steady_clock::time_point __libcpp_steady_clock_now() { struct timespec tp; diff --git a/contrib/libs/cxxsupp/libcxx/src/condition_variable.cpp b/contrib/libs/cxxsupp/libcxx/src/condition_variable.cpp index b17c4cf645..85f334e024 100644 --- a/contrib/libs/cxxsupp/libcxx/src/condition_variable.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/condition_variable.cpp @@ -12,7 +12,6 @@ #include <condition_variable> #include <thread> -#include <system_error> #if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) # pragma comment(lib, "pthread") diff --git a/contrib/libs/cxxsupp/libcxx/src/condition_variable_destructor.cpp b/contrib/libs/cxxsupp/libcxx/src/condition_variable_destructor.cpp index c217a09394..333face19d 100644 --- a/contrib/libs/cxxsupp/libcxx/src/condition_variable_destructor.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/condition_variable_destructor.cpp @@ -24,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #ifdef NEEDS_CONDVAR_DESTRUCTOR -class _LIBCPP_TYPE_VIS condition_variable +class _LIBCPP_EXPORTED_FROM_ABI condition_variable { __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER; public: diff --git a/contrib/libs/cxxsupp/libcxx/src/debug.cpp b/contrib/libs/cxxsupp/libcxx/src/debug.cpp deleted file mode 100644 index 8f1d328f0e..0000000000 --- a/contrib/libs/cxxsupp/libcxx/src/debug.cpp +++ /dev/null @@ -1,559 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include <__assert> -#include <__config> -#include <__debug> -#include <__hash_table> -#include <algorithm> -#include <cstdio> -#include <functional> -#include <string> - -#ifndef _LIBCPP_HAS_NO_THREADS -# include <mutex> -# if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) -# pragma comment(lib, "pthread") -# endif -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -_LIBCPP_FUNC_VIS -__libcpp_db* -__get_db() -{ - static _LIBCPP_NO_DESTROY __libcpp_db db; - return &db; -} - -_LIBCPP_FUNC_VIS -const __libcpp_db* -__get_const_db() -{ - return __get_db(); -} - -namespace -{ - -#ifndef _LIBCPP_HAS_NO_THREADS -typedef mutex mutex_type; -typedef lock_guard<mutex_type> WLock; -typedef lock_guard<mutex_type> RLock; - -mutex_type& -mut() -{ - static _LIBCPP_NO_DESTROY mutex_type m; - return m; -} -#endif // !_LIBCPP_HAS_NO_THREADS - -} // unnamed namespace - -__i_node::~__i_node() -{ - if (__next_) - { - __next_->~__i_node(); - free(__next_); - } -} - -__c_node::~__c_node() -{ - free(beg_); - if (__next_) - { - __next_->~__c_node(); - free(__next_); - } -} - -__libcpp_db::__libcpp_db() - : __cbeg_(nullptr), - __cend_(nullptr), - __csz_(0), - __ibeg_(nullptr), - __iend_(nullptr), - __isz_(0) -{ -} - -__libcpp_db::~__libcpp_db() -{ - if (__cbeg_) - { - for (__c_node** p = __cbeg_; p != __cend_; ++p) - { - if (*p != nullptr) - { - (*p)->~__c_node(); - free(*p); - } - } - free(__cbeg_); - } - if (__ibeg_) - { - for (__i_node** p = __ibeg_; p != __iend_; ++p) - { - if (*p != nullptr) - { - (*p)->~__i_node(); - free(*p); - } - } - free(__ibeg_); - } -} - -void* -__libcpp_db::__find_c_from_i(void* __i) const -{ -#ifndef _LIBCPP_HAS_NO_THREADS - RLock _(mut()); -#endif - __i_node* i = __find_iterator(__i); - _LIBCPP_ASSERT(i != nullptr, "iterator not found in debug database."); - return i->__c_ != nullptr ? i->__c_->__c_ : nullptr; -} - -void -__libcpp_db::__insert_ic(void* __i, const void* __c) -{ -#ifndef _LIBCPP_HAS_NO_THREADS - WLock _(mut()); -#endif - if (__cbeg_ == __cend_) - return; - size_t hc = hash<const void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); - __c_node* c = __cbeg_[hc]; - if (c == nullptr) - return; - while (c->__c_ != __c) - { - c = c->__next_; - if (c == nullptr) - return; - } - __i_node* i = __insert_iterator(__i); - c->__add(i); - i->__c_ = c; -} - -void -__libcpp_db::__insert_c(void* __c, __libcpp_db::_InsertConstruct *__fn) -{ -#ifndef _LIBCPP_HAS_NO_THREADS - WLock _(mut()); -#endif - if (__csz_ + 1 > static_cast<size_t>(__cend_ - __cbeg_)) - { - size_t nc = __next_prime(2*static_cast<size_t>(__cend_ - __cbeg_) + 1); - __c_node** cbeg = static_cast<__c_node**>(calloc(nc, sizeof(__c_node*))); - if (cbeg == nullptr) - __throw_bad_alloc(); - - for (__c_node** p = __cbeg_; p != __cend_; ++p) - { - __c_node* q = *p; - while (q != nullptr) - { - size_t h = hash<void*>()(q->__c_) % nc; - __c_node* r = q->__next_; - q->__next_ = cbeg[h]; - cbeg[h] = q; - q = r; - } - } - free(__cbeg_); - __cbeg_ = cbeg; - __cend_ = __cbeg_ + nc; - } - size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); - __c_node* p = __cbeg_[hc]; - void *buf = malloc(sizeof(__c_node)); - if (buf == nullptr) - __throw_bad_alloc(); - __cbeg_[hc] = __fn(buf, __c, p); - - ++__csz_; -} - -void -__libcpp_db::__erase_i(void* __i) -{ -#ifndef _LIBCPP_HAS_NO_THREADS - WLock _(mut()); -#endif - if (__ibeg_ != __iend_) - { - size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_); - __i_node* p = __ibeg_[hi]; - if (p != nullptr) - { - __i_node* q = nullptr; - while (p->__i_ != __i) - { - q = p; - p = p->__next_; - if (p == nullptr) - return; - } - if (q == nullptr) - __ibeg_[hi] = p->__next_; - else - q->__next_ = p->__next_; - __c_node* c = p->__c_; - --__isz_; - if (c != nullptr) - c->__remove(p); - free(p); - } - } -} - -void -__libcpp_db::__invalidate_all(void* __c) -{ -#ifndef _LIBCPP_HAS_NO_THREADS - WLock _(mut()); -#endif - if (__cend_ != __cbeg_) - { - size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); - __c_node* p = __cbeg_[hc]; - if (p == nullptr) - return; - while (p->__c_ != __c) - { - p = p->__next_; - if (p == nullptr) - return; - } - while (p->end_ != p->beg_) - { - --p->end_; - (*p->end_)->__c_ = nullptr; - } - } -} - -__c_node* -__libcpp_db::__find_c_and_lock(void* __c) const -{ -#ifndef _LIBCPP_HAS_NO_THREADS - mut().lock(); -#endif - if (__cend_ == __cbeg_) - { -#ifndef _LIBCPP_HAS_NO_THREADS - mut().unlock(); -#endif - return nullptr; - } - size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); - __c_node* p = __cbeg_[hc]; - if (p == nullptr) - { -#ifndef _LIBCPP_HAS_NO_THREADS - mut().unlock(); -#endif - return nullptr; - } - while (p->__c_ != __c) - { - p = p->__next_; - if (p == nullptr) - { -#ifndef _LIBCPP_HAS_NO_THREADS - mut().unlock(); -#endif - return nullptr; - } - } - return p; -} - -__c_node* -__libcpp_db::__find_c(void* __c) const -{ - size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); - __c_node* p = __cbeg_[hc]; - _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c A"); - while (p->__c_ != __c) - { - p = p->__next_; - _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c B"); - } - return p; -} - -void -__libcpp_db::unlock() const -{ -#ifndef _LIBCPP_HAS_NO_THREADS - mut().unlock(); -#endif -} - -void -__libcpp_db::__erase_c(void* __c) -{ -#ifndef _LIBCPP_HAS_NO_THREADS - WLock _(mut()); -#endif - if (__cend_ != __cbeg_) - { - size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); - __c_node* p = __cbeg_[hc]; - if (p == nullptr) - return; - __c_node* q = nullptr; - _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c A"); - while (p->__c_ != __c) - { - q = p; - p = p->__next_; - if (p == nullptr) - return; - _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c B"); - } - if (q == nullptr) - __cbeg_[hc] = p->__next_; - else - q->__next_ = p->__next_; - while (p->end_ != p->beg_) - { - --p->end_; - (*p->end_)->__c_ = nullptr; - } - free(p->beg_); - free(p); - --__csz_; - } -} - -void -__libcpp_db::__iterator_copy(void* __i, const void* __i0) -{ -#ifndef _LIBCPP_HAS_NO_THREADS - WLock _(mut()); -#endif - __i_node* i = __find_iterator(__i); - __i_node* i0 = __find_iterator(__i0); - __c_node* c0 = i0 != nullptr ? i0->__c_ : nullptr; - if (i == nullptr && i0 != nullptr) - i = __insert_iterator(__i); - __c_node* c = i != nullptr ? i->__c_ : nullptr; - if (c != c0) - { - if (c != nullptr) - c->__remove(i); - if (i != nullptr) - { - i->__c_ = nullptr; - if (c0 != nullptr) - { - i->__c_ = c0; - i->__c_->__add(i); - } - } - } -} - -bool -__libcpp_db::__dereferenceable(const void* __i) const -{ -#ifndef _LIBCPP_HAS_NO_THREADS - RLock _(mut()); -#endif - __i_node* i = __find_iterator(__i); - return i != nullptr && i->__c_ != nullptr && i->__c_->__dereferenceable(__i); -} - -bool -__libcpp_db::__decrementable(const void* __i) const -{ -#ifndef _LIBCPP_HAS_NO_THREADS - RLock _(mut()); -#endif - __i_node* i = __find_iterator(__i); - return i != nullptr && i->__c_ != nullptr && i->__c_->__decrementable(__i); -} - -bool -__libcpp_db::__addable(const void* __i, ptrdiff_t __n) const -{ -#ifndef _LIBCPP_HAS_NO_THREADS - RLock _(mut()); -#endif - __i_node* i = __find_iterator(__i); - return i != nullptr && i->__c_ != nullptr && i->__c_->__addable(__i, __n); -} - -bool -__libcpp_db::__subscriptable(const void* __i, ptrdiff_t __n) const -{ -#ifndef _LIBCPP_HAS_NO_THREADS - RLock _(mut()); -#endif - __i_node* i = __find_iterator(__i); - return i != nullptr && i->__c_ != nullptr && i->__c_->__subscriptable(__i, __n); -} - -bool -__libcpp_db::__less_than_comparable(const void* __i, const void* __j) const -{ -#ifndef _LIBCPP_HAS_NO_THREADS - RLock _(mut()); -#endif - __i_node* i = __find_iterator(__i); - __i_node* j = __find_iterator(__j); - __c_node* ci = i != nullptr ? i->__c_ : nullptr; - __c_node* cj = j != nullptr ? j->__c_ : nullptr; - return ci == cj; -} - -void -__libcpp_db::swap(void* c1, void* c2) -{ -#ifndef _LIBCPP_HAS_NO_THREADS - WLock _(mut()); -#endif - size_t hc = hash<void*>()(c1) % static_cast<size_t>(__cend_ - __cbeg_); - __c_node* p1 = __cbeg_[hc]; - _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap A"); - while (p1->__c_ != c1) - { - p1 = p1->__next_; - _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap B"); - } - hc = hash<void*>()(c2) % static_cast<size_t>(__cend_ - __cbeg_); - __c_node* p2 = __cbeg_[hc]; - _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap C"); - while (p2->__c_ != c2) - { - p2 = p2->__next_; - _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap D"); - } - std::swap(p1->beg_, p2->beg_); - std::swap(p1->end_, p2->end_); - std::swap(p1->cap_, p2->cap_); - for (__i_node** p = p1->beg_; p != p1->end_; ++p) - (*p)->__c_ = p1; - for (__i_node** p = p2->beg_; p != p2->end_; ++p) - (*p)->__c_ = p2; -} - -void -__libcpp_db::__insert_i(void* __i) -{ -#ifndef _LIBCPP_HAS_NO_THREADS - WLock _(mut()); -#endif - __insert_iterator(__i); -} - -void -__c_node::__add(__i_node* i) -{ - if (end_ == cap_) - { - size_t nc = 2*static_cast<size_t>(cap_ - beg_); - if (nc == 0) - nc = 1; - __i_node** beg = - static_cast<__i_node**>(malloc(nc * sizeof(__i_node*))); - if (beg == nullptr) - __throw_bad_alloc(); - - if (nc > 1) - memcpy(beg, beg_, nc/2*sizeof(__i_node*)); - free(beg_); - beg_ = beg; - end_ = beg_ + nc/2; - cap_ = beg_ + nc; - } - *end_++ = i; -} - -// private api - -_LIBCPP_HIDDEN -__i_node* -__libcpp_db::__insert_iterator(void* __i) -{ - if (__isz_ + 1 > static_cast<size_t>(__iend_ - __ibeg_)) - { - size_t nc = __next_prime(2*static_cast<size_t>(__iend_ - __ibeg_) + 1); - __i_node** ibeg = static_cast<__i_node**>(calloc(nc, sizeof(__i_node*))); - if (ibeg == nullptr) - __throw_bad_alloc(); - - for (__i_node** p = __ibeg_; p != __iend_; ++p) - { - __i_node* q = *p; - while (q != nullptr) - { - size_t h = hash<void*>()(q->__i_) % nc; - __i_node* r = q->__next_; - q->__next_ = ibeg[h]; - ibeg[h] = q; - q = r; - } - } - free(__ibeg_); - __ibeg_ = ibeg; - __iend_ = __ibeg_ + nc; - } - size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_); - __i_node* p = __ibeg_[hi]; - __i_node* r = __ibeg_[hi] = - static_cast<__i_node*>(malloc(sizeof(__i_node))); - if (r == nullptr) - __throw_bad_alloc(); - - ::new(r) __i_node(__i, p, nullptr); - ++__isz_; - return r; -} - -_LIBCPP_HIDDEN -__i_node* -__libcpp_db::__find_iterator(const void* __i) const -{ - __i_node* r = nullptr; - if (__ibeg_ != __iend_) - { - size_t h = hash<const void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_); - for (__i_node* nd = __ibeg_[h]; nd != nullptr; nd = nd->__next_) - { - if (nd->__i_ == __i) - { - r = nd; - break; - } - } - } - return r; -} - -_LIBCPP_HIDDEN -void -__c_node::__remove(__i_node* p) -{ - __i_node** r = find(beg_, end_, p); - _LIBCPP_ASSERT(r != end_, "debug mode internal logic error __c_node::__remove"); - if (--end_ != r) - memmove(r, r+1, static_cast<size_t>(end_ - r)*sizeof(__i_node*)); -} - -_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/filesystem/directory_entry.cpp b/contrib/libs/cxxsupp/libcxx/src/filesystem/directory_entry.cpp new file mode 100644 index 0000000000..4910d390d1 --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/src/filesystem/directory_entry.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include <__config> +#include <cstdint> +#include <filesystem> +#include <system_error> + +#include "file_descriptor.h" +#include "posix_compat.h" +#include "time_utils.h" + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +error_code directory_entry::__do_refresh() noexcept { + __data_.__reset(); + error_code failure_ec; + + detail::StatT full_st; + file_status st = detail::posix_lstat(__p_, full_st, &failure_ec); + if (!status_known(st)) { + __data_.__reset(); + return failure_ec; + } + + if (!_VSTD_FS::exists(st) || !_VSTD_FS::is_symlink(st)) { + __data_.__cache_type_ = directory_entry::_RefreshNonSymlink; + __data_.__type_ = st.type(); + __data_.__non_sym_perms_ = st.permissions(); + } else { // we have a symlink + __data_.__sym_perms_ = st.permissions(); + // Get the information about the linked entity. + // Ignore errors from stat, since we don't want errors regarding symlink + // resolution to be reported to the user. + error_code ignored_ec; + st = detail::posix_stat(__p_, full_st, &ignored_ec); + + __data_.__type_ = st.type(); + __data_.__non_sym_perms_ = st.permissions(); + + // If we failed to resolve the link, then only partially populate the + // cache. + if (!status_known(st)) { + __data_.__cache_type_ = directory_entry::_RefreshSymlinkUnresolved; + return error_code{}; + } + // Otherwise, we resolved the link, potentially as not existing. + // That's OK. + __data_.__cache_type_ = directory_entry::_RefreshSymlink; + } + + if (_VSTD_FS::is_regular_file(st)) + __data_.__size_ = static_cast<uintmax_t>(full_st.st_size); + + if (_VSTD_FS::exists(st)) { + __data_.__nlink_ = static_cast<uintmax_t>(full_st.st_nlink); + + // Attempt to extract the mtime, and fail if it's not representable using + // file_time_type. For now we ignore the error, as we'll report it when + // the value is actually used. + error_code ignored_ec; + __data_.__write_time_ = + detail::__extract_last_write_time(__p_, full_st, &ignored_ec); + } + + return failure_ec; +} + +_LIBCPP_END_NAMESPACE_FILESYSTEM diff --git a/contrib/libs/cxxsupp/libcxx/src/filesystem/directory_iterator.cpp b/contrib/libs/cxxsupp/libcxx/src/filesystem/directory_iterator.cpp index 8d069cc080..151fb2fb62 100644 --- a/contrib/libs/cxxsupp/libcxx/src/filesystem/directory_iterator.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/filesystem/directory_iterator.cpp @@ -11,8 +11,18 @@ #include <errno.h> #include <filesystem> #include <stack> +#include <utility> -#include "filesystem_common.h" +#include "error.h" +#include "file_descriptor.h" + +#if defined(_LIBCPP_WIN32API) +# define WIN32_LEAN_AND_MEAN +# define NOMINMAX +# include <windows.h> +#else +# include <dirent.h> // for DIR & friends +#endif _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM @@ -182,7 +192,7 @@ directory_iterator::directory_iterator(const path& p, error_code* ec, } directory_iterator& directory_iterator::__increment(error_code* ec) { - _LIBCPP_ASSERT(__imp_, "Attempting to increment an invalid iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(__imp_, "Attempting to increment an invalid iterator"); ErrorHandler<void> err("directory_iterator::operator++()", ec); error_code m_ec; @@ -196,7 +206,7 @@ directory_iterator& directory_iterator::__increment(error_code* ec) { } directory_entry const& directory_iterator::__dereference() const { - _LIBCPP_ASSERT(__imp_, "Attempting to dereference an invalid iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(__imp_, "Attempting to dereference an invalid iterator"); return __imp_->__entry_; } @@ -225,7 +235,7 @@ recursive_directory_iterator::recursive_directory_iterator( } void recursive_directory_iterator::__pop(error_code* ec) { - _LIBCPP_ASSERT(__imp_, "Popping the end iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(__imp_, "Popping the end iterator"); if (ec) ec->clear(); __imp_->__stack_.pop(); diff --git a/contrib/libs/cxxsupp/libcxx/src/filesystem/error.h b/contrib/libs/cxxsupp/libcxx/src/filesystem/error.h new file mode 100644 index 0000000000..965e0eadcd --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/src/filesystem/error.h @@ -0,0 +1,238 @@ +//===----------------------------------------------------------------------===//// +// +// 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 FILESYSTEM_ERROR_H +#define FILESYSTEM_ERROR_H + +#include <__assert> +#include <__config> +#include <cerrno> +#include <cstdarg> +#include <cstddef> +#include <cstdint> +#include <filesystem> +#include <string> +#include <system_error> +#include <utility> // __libcpp_unreachable + +#include "format_string.h" + +#if defined(_LIBCPP_WIN32API) +# define WIN32_LEAN_AND_MEAN +# define NOMINMAX +# include <windows.h> // ERROR_* macros +#endif + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +namespace detail { + +#if defined(_LIBCPP_WIN32API) + +inline errc __win_err_to_errc(int err) { + constexpr struct { + DWORD win; + errc errc; + } win_error_mapping[] = { + {ERROR_ACCESS_DENIED, errc::permission_denied}, + {ERROR_ALREADY_EXISTS, errc::file_exists}, + {ERROR_BAD_NETPATH, errc::no_such_file_or_directory}, + {ERROR_BAD_PATHNAME, errc::no_such_file_or_directory}, + {ERROR_BAD_UNIT, errc::no_such_device}, + {ERROR_BROKEN_PIPE, errc::broken_pipe}, + {ERROR_BUFFER_OVERFLOW, errc::filename_too_long}, + {ERROR_BUSY, errc::device_or_resource_busy}, + {ERROR_BUSY_DRIVE, errc::device_or_resource_busy}, + {ERROR_CANNOT_MAKE, errc::permission_denied}, + {ERROR_CANTOPEN, errc::io_error}, + {ERROR_CANTREAD, errc::io_error}, + {ERROR_CANTWRITE, errc::io_error}, + {ERROR_CURRENT_DIRECTORY, errc::permission_denied}, + {ERROR_DEV_NOT_EXIST, errc::no_such_device}, + {ERROR_DEVICE_IN_USE, errc::device_or_resource_busy}, + {ERROR_DIR_NOT_EMPTY, errc::directory_not_empty}, + {ERROR_DIRECTORY, errc::invalid_argument}, + {ERROR_DISK_FULL, errc::no_space_on_device}, + {ERROR_FILE_EXISTS, errc::file_exists}, + {ERROR_FILE_NOT_FOUND, errc::no_such_file_or_directory}, + {ERROR_HANDLE_DISK_FULL, errc::no_space_on_device}, + {ERROR_INVALID_ACCESS, errc::permission_denied}, + {ERROR_INVALID_DRIVE, errc::no_such_device}, + {ERROR_INVALID_FUNCTION, errc::function_not_supported}, + {ERROR_INVALID_HANDLE, errc::invalid_argument}, + {ERROR_INVALID_NAME, errc::no_such_file_or_directory}, + {ERROR_INVALID_PARAMETER, errc::invalid_argument}, + {ERROR_LOCK_VIOLATION, errc::no_lock_available}, + {ERROR_LOCKED, errc::no_lock_available}, + {ERROR_NEGATIVE_SEEK, errc::invalid_argument}, + {ERROR_NOACCESS, errc::permission_denied}, + {ERROR_NOT_ENOUGH_MEMORY, errc::not_enough_memory}, + {ERROR_NOT_READY, errc::resource_unavailable_try_again}, + {ERROR_NOT_SAME_DEVICE, errc::cross_device_link}, + {ERROR_NOT_SUPPORTED, errc::not_supported}, + {ERROR_OPEN_FAILED, errc::io_error}, + {ERROR_OPEN_FILES, errc::device_or_resource_busy}, + {ERROR_OPERATION_ABORTED, errc::operation_canceled}, + {ERROR_OUTOFMEMORY, errc::not_enough_memory}, + {ERROR_PATH_NOT_FOUND, errc::no_such_file_or_directory}, + {ERROR_READ_FAULT, errc::io_error}, + {ERROR_REPARSE_TAG_INVALID, errc::invalid_argument}, + {ERROR_RETRY, errc::resource_unavailable_try_again}, + {ERROR_SEEK, errc::io_error}, + {ERROR_SHARING_VIOLATION, errc::permission_denied}, + {ERROR_TOO_MANY_OPEN_FILES, errc::too_many_files_open}, + {ERROR_WRITE_FAULT, errc::io_error}, + {ERROR_WRITE_PROTECT, errc::permission_denied}, + }; + + for (const auto &pair : win_error_mapping) + if (pair.win == static_cast<DWORD>(err)) + return pair.errc; + return errc::invalid_argument; +} + +#endif // _LIBCPP_WIN32API + +inline error_code capture_errno() { + _LIBCPP_ASSERT_UNCATEGORIZED(errno != 0, "Expected errno to be non-zero"); + return error_code(errno, generic_category()); +} + +#if defined(_LIBCPP_WIN32API) +inline error_code make_windows_error(int err) { + return make_error_code(__win_err_to_errc(err)); +} +#endif + +template <class T> +T error_value(); +template <> +inline _LIBCPP_CONSTEXPR_SINCE_CXX14 void error_value<void>() {} +template <> +inline bool error_value<bool>() { + return false; +} +#if __SIZEOF_SIZE_T__ != __SIZEOF_LONG_LONG__ +template <> +inline size_t error_value<size_t>() { + return size_t(-1); +} +#endif +template <> +inline uintmax_t error_value<uintmax_t>() { + return uintmax_t(-1); +} +template <> +inline _LIBCPP_CONSTEXPR_SINCE_CXX14 file_time_type error_value<file_time_type>() { + return file_time_type::min(); +} +template <> +inline path error_value<path>() { + return {}; +} + +template <class T> +struct ErrorHandler { + const char* func_name_; + error_code* ec_ = nullptr; + const path* p1_ = nullptr; + const path* p2_ = nullptr; + + ErrorHandler(const char* fname, error_code* ec, const path* p1 = nullptr, + const path* p2 = nullptr) + : func_name_(fname), ec_(ec), p1_(p1), p2_(p2) { + if (ec_) + ec_->clear(); + } + + T report(const error_code& ec) const { + if (ec_) { + *ec_ = ec; + return error_value<T>(); + } + string what = string("in ") + func_name_; + switch (bool(p1_) + bool(p2_)) { + case 0: + __throw_filesystem_error(what, ec); + case 1: + __throw_filesystem_error(what, *p1_, ec); + case 2: + __throw_filesystem_error(what, *p1_, *p2_, ec); + } + __libcpp_unreachable(); + } + + _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 3, 0) + void report_impl(const error_code& ec, const char* msg, va_list ap) const { + if (ec_) { + *ec_ = ec; + return; + } + string what = + string("in ") + func_name_ + ": " + detail::vformat_string(msg, ap); + switch (bool(p1_) + bool(p2_)) { + case 0: + __throw_filesystem_error(what, ec); + case 1: + __throw_filesystem_error(what, *p1_, ec); + case 2: + __throw_filesystem_error(what, *p1_, *p2_, ec); + } + __libcpp_unreachable(); + } + + _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 3, 4) + T report(const error_code& ec, const char* msg, ...) const { + va_list ap; + va_start(ap, msg); +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + report_impl(ec, msg, ap); +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + va_end(ap); + throw; + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + va_end(ap); + return error_value<T>(); + } + + T report(errc const& err) const { + return report(make_error_code(err)); + } + + _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 3, 4) + T report(errc const& err, const char* msg, ...) const { + va_list ap; + va_start(ap, msg); +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + report_impl(make_error_code(err), msg, ap); +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + va_end(ap); + throw; + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + va_end(ap); + return error_value<T>(); + } + +private: + ErrorHandler(ErrorHandler const&) = delete; + ErrorHandler& operator=(ErrorHandler const&) = delete; +}; + +} // end namespace detail + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // FILESYSTEM_ERROR_H diff --git a/contrib/libs/cxxsupp/libcxx/src/filesystem/file_descriptor.h b/contrib/libs/cxxsupp/libcxx/src/filesystem/file_descriptor.h new file mode 100644 index 0000000000..d3a668fa2e --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/src/filesystem/file_descriptor.h @@ -0,0 +1,298 @@ +//===----------------------------------------------------------------------===//// +// +// 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 FILESYSTEM_FILE_DESCRIPTOR_H +#define FILESYSTEM_FILE_DESCRIPTOR_H + +#include <__config> +#include <cstdint> +#include <filesystem> +#include <string_view> +#include <system_error> +#include <utility> + +#include "error.h" +#include "posix_compat.h" +#include "time_utils.h" + +#if defined(_LIBCPP_WIN32API) +# define WIN32_LEAN_AND_MEAN +# define NOMINMAX +# include <windows.h> +#else +# include <dirent.h> // for DIR & friends +# include <fcntl.h> // values for fchmodat +# include <sys/stat.h> +# include <sys/statvfs.h> +# include <unistd.h> +#endif // defined(_LIBCPP_WIN32API) + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +namespace detail { + +#if !defined(_LIBCPP_WIN32API) + +#if defined(DT_BLK) +template <class DirEntT, class = decltype(DirEntT::d_type)> +file_type get_file_type(DirEntT* ent, int) { + switch (ent->d_type) { + case DT_BLK: + return file_type::block; + case DT_CHR: + return file_type::character; + case DT_DIR: + return file_type::directory; + case DT_FIFO: + return file_type::fifo; + case DT_LNK: + return file_type::symlink; + case DT_REG: + return file_type::regular; + case DT_SOCK: + return file_type::socket; + // Unlike in lstat, hitting "unknown" here simply means that the underlying + // filesystem doesn't support d_type. Report is as 'none' so we correctly + // set the cache to empty. + case DT_UNKNOWN: + break; + } + return file_type::none; +} +#endif // defined(DT_BLK) + +template <class DirEntT> +file_type get_file_type(DirEntT*, long) { + return file_type::none; +} + +inline pair<string_view, file_type> posix_readdir(DIR* dir_stream, + error_code& ec) { + struct dirent* dir_entry_ptr = nullptr; + errno = 0; // zero errno in order to detect errors + ec.clear(); + if ((dir_entry_ptr = ::readdir(dir_stream)) == nullptr) { + if (errno) + ec = capture_errno(); + return {}; + } else { + return {dir_entry_ptr->d_name, get_file_type(dir_entry_ptr, 0)}; + } +} + +#else // _LIBCPP_WIN32API + +inline file_type get_file_type(const WIN32_FIND_DATAW& data) { + if (data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT && + data.dwReserved0 == IO_REPARSE_TAG_SYMLINK) + return file_type::symlink; + if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + return file_type::directory; + return file_type::regular; +} +inline uintmax_t get_file_size(const WIN32_FIND_DATAW& data) { + return (static_cast<uint64_t>(data.nFileSizeHigh) << 32) + data.nFileSizeLow; +} +inline file_time_type get_write_time(const WIN32_FIND_DATAW& data) { + ULARGE_INTEGER tmp; + const FILETIME& time = data.ftLastWriteTime; + tmp.u.LowPart = time.dwLowDateTime; + tmp.u.HighPart = time.dwHighDateTime; + return file_time_type(file_time_type::duration(tmp.QuadPart)); +} + +#endif // !_LIBCPP_WIN32API + +// POSIX HELPERS + +using value_type = path::value_type; +using string_type = path::string_type; + +struct FileDescriptor { + const path& name; + int fd = -1; + StatT m_stat; + file_status m_status; + + template <class... Args> + static FileDescriptor create(const path* p, error_code& ec, Args... args) { + ec.clear(); + int fd; +#ifdef _LIBCPP_WIN32API + // TODO: most of the filesystem implementation uses native Win32 calls + // (mostly via posix_compat.h). However, here we use the C-runtime APIs to + // open a file, because we subsequently pass the C-runtime fd to + // `std::[io]fstream::__open(int fd)` in order to implement copy_file. + // + // Because we're calling the windows C-runtime, win32 error codes are + // translated into C error numbers by the C runtime, and returned in errno, + // rather than being accessible directly via GetLastError. + // + // Ideally copy_file should be calling the Win32 CopyFile2 function, which + // works on paths, not open files -- at which point this FileDescriptor type + // will no longer be needed on windows at all. + fd = ::_wopen(p->c_str(), args...); +#else + fd = open(p->c_str(), args...); +#endif + + if (fd == -1) { + ec = capture_errno(); + return FileDescriptor{p}; + } + return FileDescriptor(p, fd); + } + + template <class... Args> + static FileDescriptor create_with_status(const path* p, error_code& ec, + Args... args) { + FileDescriptor fd = create(p, ec, args...); + if (!ec) + fd.refresh_status(ec); + + return fd; + } + + file_status get_status() const { return m_status; } + StatT const& get_stat() const { return m_stat; } + + bool status_known() const { return _VSTD_FS::status_known(m_status); } + + file_status refresh_status(error_code& ec); + + void close() noexcept { + if (fd != -1) { +#ifdef _LIBCPP_WIN32API + ::_close(fd); +#else + ::close(fd); +#endif + // FIXME: shouldn't this return an error_code? + } + fd = -1; + } + + FileDescriptor(FileDescriptor&& other) + : name(other.name), fd(other.fd), m_stat(other.m_stat), + m_status(other.m_status) { + other.fd = -1; + other.m_status = file_status{}; + } + + ~FileDescriptor() { close(); } + + FileDescriptor(FileDescriptor const&) = delete; + FileDescriptor& operator=(FileDescriptor const&) = delete; + +private: + explicit FileDescriptor(const path* p, int descriptor = -1) : name(*p), fd(descriptor) {} +}; + +inline perms posix_get_perms(const StatT& st) noexcept { + return static_cast<perms>(st.st_mode) & perms::mask; +} + +inline file_status create_file_status(error_code& m_ec, path const& p, + const StatT& path_stat, error_code* ec) { + if (ec) + *ec = m_ec; + if (m_ec && (m_ec.value() == ENOENT || m_ec.value() == ENOTDIR)) { + return file_status(file_type::not_found); + } else if (m_ec) { + ErrorHandler<void> err("posix_stat", ec, &p); + err.report(m_ec, "failed to determine attributes for the specified path"); + return file_status(file_type::none); + } + // else + + file_status fs_tmp; + auto const mode = path_stat.st_mode; + if (S_ISLNK(mode)) + fs_tmp.type(file_type::symlink); + else if (S_ISREG(mode)) + fs_tmp.type(file_type::regular); + else if (S_ISDIR(mode)) + fs_tmp.type(file_type::directory); + else if (S_ISBLK(mode)) + fs_tmp.type(file_type::block); + else if (S_ISCHR(mode)) + fs_tmp.type(file_type::character); + else if (S_ISFIFO(mode)) + fs_tmp.type(file_type::fifo); + else if (S_ISSOCK(mode)) + fs_tmp.type(file_type::socket); + else + fs_tmp.type(file_type::unknown); + + fs_tmp.permissions(detail::posix_get_perms(path_stat)); + return fs_tmp; +} + +inline file_status posix_stat(path const& p, StatT& path_stat, error_code* ec) { + error_code m_ec; + if (detail::stat(p.c_str(), &path_stat) == -1) + m_ec = detail::capture_errno(); + return create_file_status(m_ec, p, path_stat, ec); +} + +inline file_status posix_stat(path const& p, error_code* ec) { + StatT path_stat; + return posix_stat(p, path_stat, ec); +} + +inline file_status posix_lstat(path const& p, StatT& path_stat, error_code* ec) { + error_code m_ec; + if (detail::lstat(p.c_str(), &path_stat) == -1) + m_ec = detail::capture_errno(); + return create_file_status(m_ec, p, path_stat, ec); +} + +inline file_status posix_lstat(path const& p, error_code* ec) { + StatT path_stat; + return posix_lstat(p, path_stat, ec); +} + +// http://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html +inline bool posix_ftruncate(const FileDescriptor& fd, off_t to_size, error_code& ec) { + if (detail::ftruncate(fd.fd, to_size) == -1) { + ec = capture_errno(); + return true; + } + ec.clear(); + return false; +} + +inline bool posix_fchmod(const FileDescriptor& fd, const StatT& st, error_code& ec) { + if (detail::fchmod(fd.fd, st.st_mode) == -1) { + ec = capture_errno(); + return true; + } + ec.clear(); + return false; +} + +inline bool stat_equivalent(const StatT& st1, const StatT& st2) { + return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino); +} + +inline file_status FileDescriptor::refresh_status(error_code& ec) { + // FD must be open and good. + m_status = file_status{}; + m_stat = {}; + error_code m_ec; + if (detail::fstat(fd, &m_stat) == -1) + m_ec = capture_errno(); + m_status = create_file_status(m_ec, name, m_stat, &ec); + return m_status; +} + +} // end namespace detail + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // FILESYSTEM_FILE_DESCRIPTOR_H diff --git a/contrib/libs/cxxsupp/libcxx/src/filesystem/filesystem_clock.cpp b/contrib/libs/cxxsupp/libcxx/src/filesystem/filesystem_clock.cpp new file mode 100644 index 0000000000..fbb19ac68d --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/src/filesystem/filesystem_clock.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include <__config> +#include <chrono> +#include <filesystem> +#include <time.h> + +#if defined(_LIBCPP_WIN32API) +# include "time_utils.h" +#endif + +#if defined(_LIBCPP_WIN32API) +# define WIN32_LEAN_AND_MEAN +# define NOMINMAX +# include <windows.h> +#endif + +#if __has_include(<unistd.h>) +# include <unistd.h> // _POSIX_TIMERS +#endif + +#if __has_include(<sys/time.h>) +# include <sys/time.h> // for gettimeofday and timeval +#endif + +#if defined(__APPLE__) || defined (__gnu_hurd__) || (defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0) +# define _LIBCPP_HAS_CLOCK_GETTIME +#endif + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +const bool _FilesystemClock::is_steady; + +_FilesystemClock::time_point _FilesystemClock::now() noexcept { + typedef chrono::duration<rep> __secs; +#if defined(_LIBCPP_WIN32API) + typedef chrono::duration<rep, nano> __nsecs; + FILETIME time; + GetSystemTimeAsFileTime(&time); + detail::TimeSpec tp = detail::filetime_to_timespec(time); + return time_point(__secs(tp.tv_sec) + + chrono::duration_cast<duration>(__nsecs(tp.tv_nsec))); +#elif defined(_LIBCPP_HAS_CLOCK_GETTIME) + typedef chrono::duration<rep, nano> __nsecs; + struct timespec tp; + if (0 != clock_gettime(CLOCK_REALTIME, &tp)) + __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed"); + return time_point(__secs(tp.tv_sec) + + chrono::duration_cast<duration>(__nsecs(tp.tv_nsec))); +#else + typedef chrono::duration<rep, micro> __microsecs; + timeval tv; + gettimeofday(&tv, 0); + return time_point(__secs(tv.tv_sec) + __microsecs(tv.tv_usec)); +#endif +} + +_LIBCPP_END_NAMESPACE_FILESYSTEM diff --git a/contrib/libs/cxxsupp/libcxx/src/filesystem/filesystem_error.cpp b/contrib/libs/cxxsupp/libcxx/src/filesystem/filesystem_error.cpp new file mode 100644 index 0000000000..5faed3b89e --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/src/filesystem/filesystem_error.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include <__config> +#include <__utility/unreachable.h> +#include <filesystem> +#include <system_error> + +#include "format_string.h" + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +filesystem_error::~filesystem_error() {} + +void filesystem_error::__create_what(int __num_paths) { + const char* derived_what = system_error::what(); + __storage_->__what_ = [&]() -> string { + switch (__num_paths) { + case 0: + return detail::format_string("filesystem error: %s", derived_what); + case 1: + return detail::format_string("filesystem error: %s [" PATH_CSTR_FMT "]", + derived_what, path1().c_str()); + case 2: + return detail::format_string("filesystem error: %s [" PATH_CSTR_FMT "] [" PATH_CSTR_FMT "]", + derived_what, path1().c_str(), path2().c_str()); + } + __libcpp_unreachable(); + }(); +} + +_LIBCPP_END_NAMESPACE_FILESYSTEM diff --git a/contrib/libs/cxxsupp/libcxx/src/filesystem/format_string.h b/contrib/libs/cxxsupp/libcxx/src/filesystem/format_string.h new file mode 100644 index 0000000000..215d42421b --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/src/filesystem/format_string.h @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===//// +// +// 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 FILESYSTEM_FORMAT_STRING_H +#define FILESYSTEM_FORMAT_STRING_H + +#include <__assert> +#include <__config> +#include <array> +#include <cstdarg> +#include <cstddef> +#include <cstdio> +#include <string> + +#if defined(_LIBCPP_WIN32API) +# define PATHSTR(x) (L##x) +# define PATH_CSTR_FMT "\"%ls\"" +#else +# define PATHSTR(x) (x) +# define PATH_CSTR_FMT "\"%s\"" +#endif + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +namespace detail { + +inline _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 1, 0) string vformat_string(const char* msg, va_list ap) { + array<char, 256> buf; + + va_list apcopy; + va_copy(apcopy, ap); + int ret = ::vsnprintf(buf.data(), buf.size(), msg, apcopy); + va_end(apcopy); + + string result; + if (static_cast<size_t>(ret) < buf.size()) { + result.assign(buf.data(), static_cast<size_t>(ret)); + } else { + // we did not provide a long enough buffer on our first attempt. The + // return value is the number of bytes (excluding the null byte) that are + // needed for formatting. + size_t size_with_null = static_cast<size_t>(ret) + 1; + result.__resize_default_init(size_with_null - 1); + ret = ::vsnprintf(&result[0], size_with_null, msg, ap); + _LIBCPP_ASSERT_UNCATEGORIZED(static_cast<size_t>(ret) == (size_with_null - 1), "TODO"); + } + return result; +} + +inline _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 1, 2) string format_string(const char* msg, ...) { + string ret; + va_list ap; + va_start(ap, msg); +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + ret = detail::vformat_string(msg, ap); +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + va_end(ap); + throw; + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + va_end(ap); + return ret; +} + +} // end namespace detail + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // FILESYSTEM_FORMAT_STRING_H diff --git a/contrib/libs/cxxsupp/libcxx/src/filesystem/operations.cpp b/contrib/libs/cxxsupp/libcxx/src/filesystem/operations.cpp index f9b74120e0..61f2cc572e 100644 --- a/contrib/libs/cxxsupp/libcxx/src/filesystem/operations.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/filesystem/operations.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include <__assert> +#include <__config> #include <__utility/unreachable.h> #include <array> #include <climits> @@ -17,9 +18,11 @@ #include <type_traits> #include <vector> -#include "filesystem_common.h" - +#include "error.h" +#include "file_descriptor.h" +#include "path_parser.h" #include "posix_compat.h" +#include "time_utils.h" #if defined(_LIBCPP_WIN32API) # define WIN32_LEAN_AND_MEAN @@ -45,599 +48,12 @@ # define _LIBCPP_FILESYSTEM_USE_FSTREAM #endif -#if !defined(CLOCK_REALTIME) && !defined(_LIBCPP_WIN32API) -# include <sys/time.h> // for gettimeofday and timeval -#endif - #if defined(__ELF__) && defined(_LIBCPP_LINK_RT_LIB) # pragma comment(lib, "rt") #endif _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -namespace { - -bool isSeparator(path::value_type C) { - if (C == '/') - return true; -#if defined(_LIBCPP_WIN32API) - if (C == '\\') - return true; -#endif - return false; -} - -bool isDriveLetter(path::value_type C) { - return (C >= 'a' && C <= 'z') || (C >= 'A' && C <= 'Z'); -} - -namespace parser { - -using string_view_t = path::__string_view; -using string_view_pair = pair<string_view_t, string_view_t>; -using PosPtr = path::value_type const*; - -struct PathParser { - enum ParserState : unsigned char { - // Zero is a special sentinel value used by default constructed iterators. - PS_BeforeBegin = path::iterator::_BeforeBegin, - PS_InRootName = path::iterator::_InRootName, - PS_InRootDir = path::iterator::_InRootDir, - PS_InFilenames = path::iterator::_InFilenames, - PS_InTrailingSep = path::iterator::_InTrailingSep, - PS_AtEnd = path::iterator::_AtEnd - }; - - const string_view_t Path; - string_view_t RawEntry; - ParserState State; - -private: - PathParser(string_view_t P, ParserState State) noexcept : Path(P), - State(State) {} - -public: - PathParser(string_view_t P, string_view_t E, unsigned char S) - : Path(P), RawEntry(E), State(static_cast<ParserState>(S)) { - // S cannot be '0' or PS_BeforeBegin. - } - - static PathParser CreateBegin(string_view_t P) noexcept { - PathParser PP(P, PS_BeforeBegin); - PP.increment(); - return PP; - } - - static PathParser CreateEnd(string_view_t P) noexcept { - PathParser PP(P, PS_AtEnd); - return PP; - } - - PosPtr peek() const noexcept { - auto TkEnd = getNextTokenStartPos(); - auto End = getAfterBack(); - return TkEnd == End ? nullptr : TkEnd; - } - - void increment() noexcept { - const PosPtr End = getAfterBack(); - const PosPtr Start = getNextTokenStartPos(); - if (Start == End) - return makeState(PS_AtEnd); - - switch (State) { - case PS_BeforeBegin: { - PosPtr TkEnd = consumeRootName(Start, End); - if (TkEnd) - return makeState(PS_InRootName, Start, TkEnd); - } - _LIBCPP_FALLTHROUGH(); - case PS_InRootName: { - PosPtr TkEnd = consumeAllSeparators(Start, End); - if (TkEnd) - return makeState(PS_InRootDir, Start, TkEnd); - else - return makeState(PS_InFilenames, Start, consumeName(Start, End)); - } - case PS_InRootDir: - return makeState(PS_InFilenames, Start, consumeName(Start, End)); - - case PS_InFilenames: { - PosPtr SepEnd = consumeAllSeparators(Start, End); - if (SepEnd != End) { - PosPtr TkEnd = consumeName(SepEnd, End); - if (TkEnd) - return makeState(PS_InFilenames, SepEnd, TkEnd); - } - return makeState(PS_InTrailingSep, Start, SepEnd); - } - - case PS_InTrailingSep: - return makeState(PS_AtEnd); - - case PS_AtEnd: - __libcpp_unreachable(); - } - } - - void decrement() noexcept { - const PosPtr REnd = getBeforeFront(); - const PosPtr RStart = getCurrentTokenStartPos() - 1; - if (RStart == REnd) // we're decrementing the begin - return makeState(PS_BeforeBegin); - - switch (State) { - case PS_AtEnd: { - // Try to consume a trailing separator or root directory first. - if (PosPtr SepEnd = consumeAllSeparators(RStart, REnd)) { - if (SepEnd == REnd) - return makeState(PS_InRootDir, Path.data(), RStart + 1); - PosPtr TkStart = consumeRootName(SepEnd, REnd); - if (TkStart == REnd) - return makeState(PS_InRootDir, RStart, RStart + 1); - return makeState(PS_InTrailingSep, SepEnd + 1, RStart + 1); - } else { - PosPtr TkStart = consumeRootName(RStart, REnd); - if (TkStart == REnd) - return makeState(PS_InRootName, TkStart + 1, RStart + 1); - TkStart = consumeName(RStart, REnd); - return makeState(PS_InFilenames, TkStart + 1, RStart + 1); - } - } - case PS_InTrailingSep: - return makeState(PS_InFilenames, consumeName(RStart, REnd) + 1, - RStart + 1); - case PS_InFilenames: { - PosPtr SepEnd = consumeAllSeparators(RStart, REnd); - if (SepEnd == REnd) - return makeState(PS_InRootDir, Path.data(), RStart + 1); - PosPtr TkStart = consumeRootName(SepEnd ? SepEnd : RStart, REnd); - if (TkStart == REnd) { - if (SepEnd) - return makeState(PS_InRootDir, SepEnd + 1, RStart + 1); - return makeState(PS_InRootName, TkStart + 1, RStart + 1); - } - TkStart = consumeName(SepEnd, REnd); - return makeState(PS_InFilenames, TkStart + 1, SepEnd + 1); - } - case PS_InRootDir: - return makeState(PS_InRootName, Path.data(), RStart + 1); - case PS_InRootName: - case PS_BeforeBegin: - __libcpp_unreachable(); - } - } - - /// \brief Return a view with the "preferred representation" of the current - /// element. For example trailing separators are represented as a '.' - string_view_t operator*() const noexcept { - switch (State) { - case PS_BeforeBegin: - case PS_AtEnd: - return PATHSTR(""); - case PS_InRootDir: - if (RawEntry[0] == '\\') - return PATHSTR("\\"); - else - return PATHSTR("/"); - case PS_InTrailingSep: - return PATHSTR(""); - case PS_InRootName: - case PS_InFilenames: - return RawEntry; - } - __libcpp_unreachable(); - } - - explicit operator bool() const noexcept { - return State != PS_BeforeBegin && State != PS_AtEnd; - } - - PathParser& operator++() noexcept { - increment(); - return *this; - } - - PathParser& operator--() noexcept { - decrement(); - return *this; - } - - bool atEnd() const noexcept { - return State == PS_AtEnd; - } - - bool inRootDir() const noexcept { - return State == PS_InRootDir; - } - - bool inRootName() const noexcept { - return State == PS_InRootName; - } - - bool inRootPath() const noexcept { - return inRootName() || inRootDir(); - } - -private: - void makeState(ParserState NewState, PosPtr Start, PosPtr End) noexcept { - State = NewState; - RawEntry = string_view_t(Start, End - Start); - } - void makeState(ParserState NewState) noexcept { - State = NewState; - RawEntry = {}; - } - - PosPtr getAfterBack() const noexcept { return Path.data() + Path.size(); } - - PosPtr getBeforeFront() const noexcept { return Path.data() - 1; } - - /// \brief Return a pointer to the first character after the currently - /// lexed element. - PosPtr getNextTokenStartPos() const noexcept { - switch (State) { - case PS_BeforeBegin: - return Path.data(); - case PS_InRootName: - case PS_InRootDir: - case PS_InFilenames: - return &RawEntry.back() + 1; - case PS_InTrailingSep: - case PS_AtEnd: - return getAfterBack(); - } - __libcpp_unreachable(); - } - - /// \brief Return a pointer to the first character in the currently lexed - /// element. - PosPtr getCurrentTokenStartPos() const noexcept { - switch (State) { - case PS_BeforeBegin: - case PS_InRootName: - return &Path.front(); - case PS_InRootDir: - case PS_InFilenames: - case PS_InTrailingSep: - return &RawEntry.front(); - case PS_AtEnd: - return &Path.back() + 1; - } - __libcpp_unreachable(); - } - - // Consume all consecutive separators. - PosPtr consumeAllSeparators(PosPtr P, PosPtr End) const noexcept { - if (P == nullptr || P == End || !isSeparator(*P)) - return nullptr; - const int Inc = P < End ? 1 : -1; - P += Inc; - while (P != End && isSeparator(*P)) - P += Inc; - return P; - } - - // Consume exactly N separators, or return nullptr. - PosPtr consumeNSeparators(PosPtr P, PosPtr End, int N) const noexcept { - PosPtr Ret = consumeAllSeparators(P, End); - if (Ret == nullptr) - return nullptr; - if (P < End) { - if (Ret == P + N) - return Ret; - } else { - if (Ret == P - N) - return Ret; - } - return nullptr; - } - - PosPtr consumeName(PosPtr P, PosPtr End) const noexcept { - PosPtr Start = P; - if (P == nullptr || P == End || isSeparator(*P)) - return nullptr; - const int Inc = P < End ? 1 : -1; - P += Inc; - while (P != End && !isSeparator(*P)) - P += Inc; - if (P == End && Inc < 0) { - // Iterating backwards and consumed all the rest of the input. - // Check if the start of the string would have been considered - // a root name. - PosPtr RootEnd = consumeRootName(End + 1, Start); - if (RootEnd) - return RootEnd - 1; - } - return P; - } - - PosPtr consumeDriveLetter(PosPtr P, PosPtr End) const noexcept { - if (P == End) - return nullptr; - if (P < End) { - if (P + 1 == End || !isDriveLetter(P[0]) || P[1] != ':') - return nullptr; - return P + 2; - } else { - if (P - 1 == End || !isDriveLetter(P[-1]) || P[0] != ':') - return nullptr; - return P - 2; - } - } - - PosPtr consumeNetworkRoot(PosPtr P, PosPtr End) const noexcept { - if (P == End) - return nullptr; - if (P < End) - return consumeName(consumeNSeparators(P, End, 2), End); - else - return consumeNSeparators(consumeName(P, End), End, 2); - } - -#if defined(_LIBCPP_WIN32API) - PosPtr consumeRootName(PosPtr P, PosPtr End) const noexcept { - if (PosPtr Ret = consumeDriveLetter(P, End)) - return Ret; - if (PosPtr Ret = consumeNetworkRoot(P, End)) - return Ret; - return nullptr; - } -#else - PosPtr consumeRootName(PosPtr /*P*/, PosPtr /*End*/) const noexcept { - return nullptr; - } -#endif -}; - -string_view_pair separate_filename(string_view_t const& s) { - if (s == PATHSTR(".") || s == PATHSTR("..") || s.empty()) - return string_view_pair{s, PATHSTR("")}; - auto pos = s.find_last_of('.'); - if (pos == string_view_t::npos || pos == 0) - return string_view_pair{s, string_view_t{}}; - return string_view_pair{s.substr(0, pos), s.substr(pos)}; -} - -string_view_t createView(PosPtr S, PosPtr E) noexcept { - return {S, static_cast<size_t>(E - S) + 1}; -} - -} // namespace parser -} // namespace - -// POSIX HELPERS - -#if defined(_LIBCPP_WIN32API) -namespace detail { - -errc __win_err_to_errc(int err) { - constexpr struct { - DWORD win; - errc errc; - } win_error_mapping[] = { - {ERROR_ACCESS_DENIED, errc::permission_denied}, - {ERROR_ALREADY_EXISTS, errc::file_exists}, - {ERROR_BAD_NETPATH, errc::no_such_file_or_directory}, - {ERROR_BAD_PATHNAME, errc::no_such_file_or_directory}, - {ERROR_BAD_UNIT, errc::no_such_device}, - {ERROR_BROKEN_PIPE, errc::broken_pipe}, - {ERROR_BUFFER_OVERFLOW, errc::filename_too_long}, - {ERROR_BUSY, errc::device_or_resource_busy}, - {ERROR_BUSY_DRIVE, errc::device_or_resource_busy}, - {ERROR_CANNOT_MAKE, errc::permission_denied}, - {ERROR_CANTOPEN, errc::io_error}, - {ERROR_CANTREAD, errc::io_error}, - {ERROR_CANTWRITE, errc::io_error}, - {ERROR_CURRENT_DIRECTORY, errc::permission_denied}, - {ERROR_DEV_NOT_EXIST, errc::no_such_device}, - {ERROR_DEVICE_IN_USE, errc::device_or_resource_busy}, - {ERROR_DIR_NOT_EMPTY, errc::directory_not_empty}, - {ERROR_DIRECTORY, errc::invalid_argument}, - {ERROR_DISK_FULL, errc::no_space_on_device}, - {ERROR_FILE_EXISTS, errc::file_exists}, - {ERROR_FILE_NOT_FOUND, errc::no_such_file_or_directory}, - {ERROR_HANDLE_DISK_FULL, errc::no_space_on_device}, - {ERROR_INVALID_ACCESS, errc::permission_denied}, - {ERROR_INVALID_DRIVE, errc::no_such_device}, - {ERROR_INVALID_FUNCTION, errc::function_not_supported}, - {ERROR_INVALID_HANDLE, errc::invalid_argument}, - {ERROR_INVALID_NAME, errc::no_such_file_or_directory}, - {ERROR_INVALID_PARAMETER, errc::invalid_argument}, - {ERROR_LOCK_VIOLATION, errc::no_lock_available}, - {ERROR_LOCKED, errc::no_lock_available}, - {ERROR_NEGATIVE_SEEK, errc::invalid_argument}, - {ERROR_NOACCESS, errc::permission_denied}, - {ERROR_NOT_ENOUGH_MEMORY, errc::not_enough_memory}, - {ERROR_NOT_READY, errc::resource_unavailable_try_again}, - {ERROR_NOT_SAME_DEVICE, errc::cross_device_link}, - {ERROR_NOT_SUPPORTED, errc::not_supported}, - {ERROR_OPEN_FAILED, errc::io_error}, - {ERROR_OPEN_FILES, errc::device_or_resource_busy}, - {ERROR_OPERATION_ABORTED, errc::operation_canceled}, - {ERROR_OUTOFMEMORY, errc::not_enough_memory}, - {ERROR_PATH_NOT_FOUND, errc::no_such_file_or_directory}, - {ERROR_READ_FAULT, errc::io_error}, - {ERROR_REPARSE_TAG_INVALID, errc::invalid_argument}, - {ERROR_RETRY, errc::resource_unavailable_try_again}, - {ERROR_SEEK, errc::io_error}, - {ERROR_SHARING_VIOLATION, errc::permission_denied}, - {ERROR_TOO_MANY_OPEN_FILES, errc::too_many_files_open}, - {ERROR_WRITE_FAULT, errc::io_error}, - {ERROR_WRITE_PROTECT, errc::permission_denied}, - }; - - for (const auto &pair : win_error_mapping) - if (pair.win == static_cast<DWORD>(err)) - return pair.errc; - return errc::invalid_argument; -} - -} // namespace detail -#endif - -namespace detail { -namespace { - -using value_type = path::value_type; -using string_type = path::string_type; - -struct FileDescriptor { - const path& name; - int fd = -1; - StatT m_stat; - file_status m_status; - - template <class... Args> - static FileDescriptor create(const path* p, error_code& ec, Args... args) { - ec.clear(); - int fd; - if ((fd = detail::open(p->c_str(), args...)) == -1) { - ec = capture_errno(); - return FileDescriptor{p}; - } - return FileDescriptor(p, fd); - } - - template <class... Args> - static FileDescriptor create_with_status(const path* p, error_code& ec, - Args... args) { - FileDescriptor fd = create(p, ec, args...); - if (!ec) - fd.refresh_status(ec); - - return fd; - } - - file_status get_status() const { return m_status; } - StatT const& get_stat() const { return m_stat; } - - bool status_known() const { return _VSTD_FS::status_known(m_status); } - - file_status refresh_status(error_code& ec); - - void close() noexcept { - if (fd != -1) - detail::close(fd); - fd = -1; - } - - FileDescriptor(FileDescriptor&& other) - : name(other.name), fd(other.fd), m_stat(other.m_stat), - m_status(other.m_status) { - other.fd = -1; - other.m_status = file_status{}; - } - - ~FileDescriptor() { close(); } - - FileDescriptor(FileDescriptor const&) = delete; - FileDescriptor& operator=(FileDescriptor const&) = delete; - -private: - explicit FileDescriptor(const path* p, int fd = -1) : name(*p), fd(fd) {} -}; - -perms posix_get_perms(const StatT& st) noexcept { - return static_cast<perms>(st.st_mode) & perms::mask; -} - -file_status create_file_status(error_code& m_ec, path const& p, - const StatT& path_stat, error_code* ec) { - if (ec) - *ec = m_ec; - if (m_ec && (m_ec.value() == ENOENT || m_ec.value() == ENOTDIR)) { - return file_status(file_type::not_found); - } else if (m_ec) { - ErrorHandler<void> err("posix_stat", ec, &p); - err.report(m_ec, "failed to determine attributes for the specified path"); - return file_status(file_type::none); - } - // else - - file_status fs_tmp; - auto const mode = path_stat.st_mode; - if (S_ISLNK(mode)) - fs_tmp.type(file_type::symlink); - else if (S_ISREG(mode)) - fs_tmp.type(file_type::regular); - else if (S_ISDIR(mode)) - fs_tmp.type(file_type::directory); - else if (S_ISBLK(mode)) - fs_tmp.type(file_type::block); - else if (S_ISCHR(mode)) - fs_tmp.type(file_type::character); - else if (S_ISFIFO(mode)) - fs_tmp.type(file_type::fifo); - else if (S_ISSOCK(mode)) - fs_tmp.type(file_type::socket); - else - fs_tmp.type(file_type::unknown); - - fs_tmp.permissions(detail::posix_get_perms(path_stat)); - return fs_tmp; -} - -file_status posix_stat(path const& p, StatT& path_stat, error_code* ec) { - error_code m_ec; - if (detail::stat(p.c_str(), &path_stat) == -1) - m_ec = detail::capture_errno(); - return create_file_status(m_ec, p, path_stat, ec); -} - -file_status posix_stat(path const& p, error_code* ec) { - StatT path_stat; - return posix_stat(p, path_stat, ec); -} - -file_status posix_lstat(path const& p, StatT& path_stat, error_code* ec) { - error_code m_ec; - if (detail::lstat(p.c_str(), &path_stat) == -1) - m_ec = detail::capture_errno(); - return create_file_status(m_ec, p, path_stat, ec); -} - -file_status posix_lstat(path const& p, error_code* ec) { - StatT path_stat; - return posix_lstat(p, path_stat, ec); -} - -// http://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html -bool posix_ftruncate(const FileDescriptor& fd, off_t to_size, error_code& ec) { - if (detail::ftruncate(fd.fd, to_size) == -1) { - ec = capture_errno(); - return true; - } - ec.clear(); - return false; -} - -bool posix_fchmod(const FileDescriptor& fd, const StatT& st, error_code& ec) { - if (detail::fchmod(fd.fd, st.st_mode) == -1) { - ec = capture_errno(); - return true; - } - ec.clear(); - return false; -} - -bool stat_equivalent(const StatT& st1, const StatT& st2) { - return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino); -} - -file_status FileDescriptor::refresh_status(error_code& ec) { - // FD must be open and good. - m_status = file_status{}; - m_stat = {}; - error_code m_ec; - if (detail::fstat(fd, &m_stat) == -1) - m_ec = capture_errno(); - m_status = create_file_status(m_ec, name, m_stat, &ec); - return m_status; -} -} // namespace -} // end namespace detail - using detail::capture_errno; using detail::ErrorHandler; using detail::StatT; @@ -646,51 +62,6 @@ using parser::createView; using parser::PathParser; using parser::string_view_t; -const bool _FilesystemClock::is_steady; - -_FilesystemClock::time_point _FilesystemClock::now() noexcept { - typedef chrono::duration<rep> __secs; -#if defined(_LIBCPP_WIN32API) - typedef chrono::duration<rep, nano> __nsecs; - FILETIME time; - GetSystemTimeAsFileTime(&time); - TimeSpec tp = detail::filetime_to_timespec(time); - return time_point(__secs(tp.tv_sec) + - chrono::duration_cast<duration>(__nsecs(tp.tv_nsec))); -#elif defined(CLOCK_REALTIME) - typedef chrono::duration<rep, nano> __nsecs; - struct timespec tp; - if (0 != clock_gettime(CLOCK_REALTIME, &tp)) - __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed"); - return time_point(__secs(tp.tv_sec) + - chrono::duration_cast<duration>(__nsecs(tp.tv_nsec))); -#else - typedef chrono::duration<rep, micro> __microsecs; - timeval tv; - gettimeofday(&tv, 0); - return time_point(__secs(tv.tv_sec) + __microsecs(tv.tv_usec)); -#endif // CLOCK_REALTIME -} - -filesystem_error::~filesystem_error() {} - -void filesystem_error::__create_what(int __num_paths) { - const char* derived_what = system_error::what(); - __storage_->__what_ = [&]() -> string { - switch (__num_paths) { - case 0: - return detail::format_string("filesystem error: %s", derived_what); - case 1: - return detail::format_string("filesystem error: %s [" PATH_CSTR_FMT "]", - derived_what, path1().c_str()); - case 2: - return detail::format_string("filesystem error: %s [" PATH_CSTR_FMT "] [" PATH_CSTR_FMT "]", - derived_what, path1().c_str(), path2().c_str()); - } - __libcpp_unreachable(); - }(); -} - static path __do_absolute(const path& p, path* cwd, error_code* ec) { if (ec) ec->clear(); @@ -979,7 +350,7 @@ bool __copy_file(const path& from, const path& to, copy_options options, return err.report(m_ec); } - if (!copy_file_impl(from_fd, to_fd, m_ec)) { + if (!detail::copy_file_impl(from_fd, to_fd, m_ec)) { // FIXME: Remove the dest file if we failed, and it didn't exist previously. return err.report(m_ec); } @@ -1108,7 +479,7 @@ path __current_path(error_code* ec) { Deleter deleter = &::free; #else auto size = ::pathconf(".", _PC_PATH_MAX); - _LIBCPP_ASSERT(size >= 0, "pathconf returned a 0 as max size"); + _LIBCPP_ASSERT_UNCATEGORIZED(size >= 0, "pathconf returned a 0 as max size"); auto buff = unique_ptr<path::value_type[]>(new path::value_type[size + 1]); path::value_type* ptr = buff.get(); @@ -1197,18 +568,6 @@ bool __fs_is_empty(const path& p, error_code* ec) { __libcpp_unreachable(); } -static file_time_type __extract_last_write_time(const path& p, const StatT& st, - error_code* ec) { - using detail::fs_time; - ErrorHandler<file_time_type> err("last_write_time", ec, &p); - - auto ts = detail::extract_mtime(st); - if (!fs_time::is_representable(ts)) - return err.report(errc::value_too_large); - - return fs_time::convert_from_timespec(ts); -} - file_time_type __last_write_time(const path& p, error_code* ec) { using namespace chrono; ErrorHandler<file_time_type> err("last_write_time", ec, &p); @@ -1218,7 +577,7 @@ file_time_type __last_write_time(const path& p, error_code* ec) { detail::posix_stat(p, st, &m_ec); if (m_ec) return err.report(m_ec); - return __extract_last_write_time(p, st, ec); + return detail::__extract_last_write_time(p, st, ec); } void __last_write_time(const path& p, file_time_type new_time, error_code* ec) { @@ -1268,7 +627,7 @@ void __permissions(const path& p, perms prms, perm_options opts, const bool resolve_symlinks = !has_opt(perm_options::nofollow); const bool add_perms = has_opt(perm_options::add); const bool remove_perms = has_opt(perm_options::remove); - _LIBCPP_ASSERT( + _LIBCPP_ASSERT_UNCATEGORIZED( (add_perms + remove_perms + has_opt(perm_options::replace)) == 1, "One and only one of the perm_options constants replace, add, or remove " "is present in opts"); @@ -1282,7 +641,7 @@ void __permissions(const path& p, perms prms, perm_options opts, set_sym_perms = is_symlink(st); if (m_ec) return err.report(m_ec); - _LIBCPP_ASSERT(st.permissions() != perms::unknown, + _LIBCPP_ASSERT_UNCATEGORIZED(st.permissions() != perms::unknown, "Permissions unexpectedly unknown"); if (add_perms) prms |= st.permissions(); @@ -1328,7 +687,7 @@ path __read_symlink(const path& p, error_code* ec) { detail::SSizeT ret; if ((ret = detail::readlink(p.c_str(), buff.get(), size)) == -1) return err.report(capture_errno()); - _LIBCPP_ASSERT(ret > 0, "TODO"); + _LIBCPP_ASSERT_UNCATEGORIZED(ret > 0, "TODO"); if (static_cast<size_t>(ret) >= size) return err.report(errc::value_too_large); buff[ret] = 0; @@ -1554,8 +913,13 @@ path __temp_directory_path(error_code* ec) { for (auto& ep : env_paths) if ((ret = getenv(ep))) break; - if (ret == nullptr) + if (ret == nullptr) { +#if defined(__ANDROID__) + ret = "/data/local/tmp"; +#else ret = "/tmp"; +#endif + } path p(ret); #endif @@ -1608,500 +972,4 @@ path __weakly_canonical(const path& p, error_code* ec) { return result.lexically_normal(); } -/////////////////////////////////////////////////////////////////////////////// -// path definitions -/////////////////////////////////////////////////////////////////////////////// - -constexpr path::value_type path::preferred_separator; - -path& path::replace_extension(path const& replacement) { - path p = extension(); - if (not p.empty()) { - __pn_.erase(__pn_.size() - p.native().size()); - } - if (!replacement.empty()) { - if (replacement.native()[0] != '.') { - __pn_ += PATHSTR("."); - } - __pn_.append(replacement.__pn_); - } - return *this; -} - -/////////////////////////////////////////////////////////////////////////////// -// path.decompose - -string_view_t path::__root_name() const { - auto PP = PathParser::CreateBegin(__pn_); - if (PP.State == PathParser::PS_InRootName) - return *PP; - return {}; -} - -string_view_t path::__root_directory() const { - auto PP = PathParser::CreateBegin(__pn_); - if (PP.State == PathParser::PS_InRootName) - ++PP; - if (PP.State == PathParser::PS_InRootDir) - return *PP; - return {}; -} - -string_view_t path::__root_path_raw() const { - auto PP = PathParser::CreateBegin(__pn_); - if (PP.State == PathParser::PS_InRootName) { - auto NextCh = PP.peek(); - if (NextCh && isSeparator(*NextCh)) { - ++PP; - return createView(__pn_.data(), &PP.RawEntry.back()); - } - return PP.RawEntry; - } - if (PP.State == PathParser::PS_InRootDir) - return *PP; - return {}; -} - -static bool ConsumeRootName(PathParser *PP) { - static_assert(PathParser::PS_BeforeBegin == 1 && - PathParser::PS_InRootName == 2, - "Values for enums are incorrect"); - while (PP->State <= PathParser::PS_InRootName) - ++(*PP); - return PP->State == PathParser::PS_AtEnd; -} - -static bool ConsumeRootDir(PathParser* PP) { - static_assert(PathParser::PS_BeforeBegin == 1 && - PathParser::PS_InRootName == 2 && - PathParser::PS_InRootDir == 3, "Values for enums are incorrect"); - while (PP->State <= PathParser::PS_InRootDir) - ++(*PP); - return PP->State == PathParser::PS_AtEnd; -} - -string_view_t path::__relative_path() const { - auto PP = PathParser::CreateBegin(__pn_); - if (ConsumeRootDir(&PP)) - return {}; - return createView(PP.RawEntry.data(), &__pn_.back()); -} - -string_view_t path::__parent_path() const { - if (empty()) - return {}; - // Determine if we have a root path but not a relative path. In that case - // return *this. - { - auto PP = PathParser::CreateBegin(__pn_); - if (ConsumeRootDir(&PP)) - return __pn_; - } - // Otherwise remove a single element from the end of the path, and return - // a string representing that path - { - auto PP = PathParser::CreateEnd(__pn_); - --PP; - if (PP.RawEntry.data() == __pn_.data()) - return {}; - --PP; - return createView(__pn_.data(), &PP.RawEntry.back()); - } -} - -string_view_t path::__filename() const { - if (empty()) - return {}; - { - PathParser PP = PathParser::CreateBegin(__pn_); - if (ConsumeRootDir(&PP)) - return {}; - } - return *(--PathParser::CreateEnd(__pn_)); -} - -string_view_t path::__stem() const { - return parser::separate_filename(__filename()).first; -} - -string_view_t path::__extension() const { - return parser::separate_filename(__filename()).second; -} - -//////////////////////////////////////////////////////////////////////////// -// path.gen - -enum PathPartKind : unsigned char { - PK_None, - PK_RootSep, - PK_Filename, - PK_Dot, - PK_DotDot, - PK_TrailingSep -}; - -static PathPartKind ClassifyPathPart(string_view_t Part) { - if (Part.empty()) - return PK_TrailingSep; - if (Part == PATHSTR(".")) - return PK_Dot; - if (Part == PATHSTR("..")) - return PK_DotDot; - if (Part == PATHSTR("/")) - return PK_RootSep; -#if defined(_LIBCPP_WIN32API) - if (Part == PATHSTR("\\")) - return PK_RootSep; -#endif - return PK_Filename; -} - -path path::lexically_normal() const { - if (__pn_.empty()) - return *this; - - using PartKindPair = pair<string_view_t, PathPartKind>; - vector<PartKindPair> Parts; - // Guess as to how many elements the path has to avoid reallocating. - Parts.reserve(32); - - // Track the total size of the parts as we collect them. This allows the - // resulting path to reserve the correct amount of memory. - size_t NewPathSize = 0; - auto AddPart = [&](PathPartKind K, string_view_t P) { - NewPathSize += P.size(); - Parts.emplace_back(P, K); - }; - auto LastPartKind = [&]() { - if (Parts.empty()) - return PK_None; - return Parts.back().second; - }; - - bool MaybeNeedTrailingSep = false; - // Build a stack containing the remaining elements of the path, popping off - // elements which occur before a '..' entry. - for (auto PP = PathParser::CreateBegin(__pn_); PP; ++PP) { - auto Part = *PP; - PathPartKind Kind = ClassifyPathPart(Part); - switch (Kind) { - case PK_Filename: - case PK_RootSep: { - // Add all non-dot and non-dot-dot elements to the stack of elements. - AddPart(Kind, Part); - MaybeNeedTrailingSep = false; - break; - } - case PK_DotDot: { - // Only push a ".." element if there are no elements preceding the "..", - // or if the preceding element is itself "..". - auto LastKind = LastPartKind(); - if (LastKind == PK_Filename) { - NewPathSize -= Parts.back().first.size(); - Parts.pop_back(); - } else if (LastKind != PK_RootSep) - AddPart(PK_DotDot, PATHSTR("..")); - MaybeNeedTrailingSep = LastKind == PK_Filename; - break; - } - case PK_Dot: - case PK_TrailingSep: { - MaybeNeedTrailingSep = true; - break; - } - case PK_None: - __libcpp_unreachable(); - } - } - // [fs.path.generic]p6.8: If the path is empty, add a dot. - if (Parts.empty()) - return PATHSTR("."); - - // [fs.path.generic]p6.7: If the last filename is dot-dot, remove any - // trailing directory-separator. - bool NeedTrailingSep = MaybeNeedTrailingSep && LastPartKind() == PK_Filename; - - path Result; - Result.__pn_.reserve(Parts.size() + NewPathSize + NeedTrailingSep); - for (auto& PK : Parts) - Result /= PK.first; - - if (NeedTrailingSep) - Result /= PATHSTR(""); - - Result.make_preferred(); - return Result; -} - -static int DetermineLexicalElementCount(PathParser PP) { - int Count = 0; - for (; PP; ++PP) { - auto Elem = *PP; - if (Elem == PATHSTR("..")) - --Count; - else if (Elem != PATHSTR(".") && Elem != PATHSTR("")) - ++Count; - } - return Count; -} - -path path::lexically_relative(const path& base) const { - { // perform root-name/root-directory mismatch checks - auto PP = PathParser::CreateBegin(__pn_); - auto PPBase = PathParser::CreateBegin(base.__pn_); - auto CheckIterMismatchAtBase = [&]() { - return PP.State != PPBase.State && - (PP.inRootPath() || PPBase.inRootPath()); - }; - if (PP.inRootName() && PPBase.inRootName()) { - if (*PP != *PPBase) - return {}; - } else if (CheckIterMismatchAtBase()) - return {}; - - if (PP.inRootPath()) - ++PP; - if (PPBase.inRootPath()) - ++PPBase; - if (CheckIterMismatchAtBase()) - return {}; - } - - // Find the first mismatching element - auto PP = PathParser::CreateBegin(__pn_); - auto PPBase = PathParser::CreateBegin(base.__pn_); - while (PP && PPBase && PP.State == PPBase.State && *PP == *PPBase) { - ++PP; - ++PPBase; - } - - // If there is no mismatch, return ".". - if (!PP && !PPBase) - return "."; - - // Otherwise, determine the number of elements, 'n', which are not dot or - // dot-dot minus the number of dot-dot elements. - int ElemCount = DetermineLexicalElementCount(PPBase); - if (ElemCount < 0) - return {}; - - // if n == 0 and (a == end() || a->empty()), returns path("."); otherwise - if (ElemCount == 0 && (PP.atEnd() || *PP == PATHSTR(""))) - return PATHSTR("."); - - // return a path constructed with 'n' dot-dot elements, followed by the - // elements of '*this' after the mismatch. - path Result; - // FIXME: Reserve enough room in Result that it won't have to re-allocate. - while (ElemCount--) - Result /= PATHSTR(".."); - for (; PP; ++PP) - Result /= *PP; - return Result; -} - -//////////////////////////////////////////////////////////////////////////// -// path.comparisons -static int CompareRootName(PathParser *LHS, PathParser *RHS) { - if (!LHS->inRootName() && !RHS->inRootName()) - return 0; - - auto GetRootName = [](PathParser *Parser) -> string_view_t { - return Parser->inRootName() ? **Parser : PATHSTR(""); - }; - int res = GetRootName(LHS).compare(GetRootName(RHS)); - ConsumeRootName(LHS); - ConsumeRootName(RHS); - return res; -} - -static int CompareRootDir(PathParser *LHS, PathParser *RHS) { - if (!LHS->inRootDir() && RHS->inRootDir()) - return -1; - else if (LHS->inRootDir() && !RHS->inRootDir()) - return 1; - else { - ConsumeRootDir(LHS); - ConsumeRootDir(RHS); - return 0; - } -} - -static int CompareRelative(PathParser *LHSPtr, PathParser *RHSPtr) { - auto &LHS = *LHSPtr; - auto &RHS = *RHSPtr; - - int res; - while (LHS && RHS) { - if ((res = (*LHS).compare(*RHS)) != 0) - return res; - ++LHS; - ++RHS; - } - return 0; -} - -static int CompareEndState(PathParser *LHS, PathParser *RHS) { - if (LHS->atEnd() && !RHS->atEnd()) - return -1; - else if (!LHS->atEnd() && RHS->atEnd()) - return 1; - return 0; -} - -int path::__compare(string_view_t __s) const { - auto LHS = PathParser::CreateBegin(__pn_); - auto RHS = PathParser::CreateBegin(__s); - int res; - - if ((res = CompareRootName(&LHS, &RHS)) != 0) - return res; - - if ((res = CompareRootDir(&LHS, &RHS)) != 0) - return res; - - if ((res = CompareRelative(&LHS, &RHS)) != 0) - return res; - - return CompareEndState(&LHS, &RHS); -} - -//////////////////////////////////////////////////////////////////////////// -// path.nonmembers -size_t hash_value(const path& __p) noexcept { - auto PP = PathParser::CreateBegin(__p.native()); - size_t hash_value = 0; - hash<string_view_t> hasher; - while (PP) { - hash_value = __hash_combine(hash_value, hasher(*PP)); - ++PP; - } - return hash_value; -} - -//////////////////////////////////////////////////////////////////////////// -// path.itr -path::iterator path::begin() const { - auto PP = PathParser::CreateBegin(__pn_); - iterator it; - it.__path_ptr_ = this; - it.__state_ = static_cast<path::iterator::_ParserState>(PP.State); - it.__entry_ = PP.RawEntry; - it.__stashed_elem_.__assign_view(*PP); - return it; -} - -path::iterator path::end() const { - iterator it{}; - it.__state_ = path::iterator::_AtEnd; - it.__path_ptr_ = this; - return it; -} - -path::iterator& path::iterator::__increment() { - PathParser PP(__path_ptr_->native(), __entry_, __state_); - ++PP; - __state_ = static_cast<_ParserState>(PP.State); - __entry_ = PP.RawEntry; - __stashed_elem_.__assign_view(*PP); - return *this; -} - -path::iterator& path::iterator::__decrement() { - PathParser PP(__path_ptr_->native(), __entry_, __state_); - --PP; - __state_ = static_cast<_ParserState>(PP.State); - __entry_ = PP.RawEntry; - __stashed_elem_.__assign_view(*PP); - return *this; -} - -#if defined(_LIBCPP_WIN32API) -//////////////////////////////////////////////////////////////////////////// -// Windows path conversions -size_t __wide_to_char(const wstring &str, char *out, size_t outlen) { - if (str.empty()) - return 0; - ErrorHandler<size_t> err("__wide_to_char", nullptr); - UINT codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; - BOOL used_default = FALSE; - int ret = WideCharToMultiByte(codepage, 0, str.data(), str.size(), out, - outlen, nullptr, &used_default); - if (ret <= 0 || used_default) - return err.report(errc::illegal_byte_sequence); - return ret; -} - -size_t __char_to_wide(const string &str, wchar_t *out, size_t outlen) { - if (str.empty()) - return 0; - ErrorHandler<size_t> err("__char_to_wide", nullptr); - UINT codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; - int ret = MultiByteToWideChar(codepage, MB_ERR_INVALID_CHARS, str.data(), - str.size(), out, outlen); - if (ret <= 0) - return err.report(errc::illegal_byte_sequence); - return ret; -} -#endif - - -/////////////////////////////////////////////////////////////////////////////// -// directory entry definitions -/////////////////////////////////////////////////////////////////////////////// - -error_code directory_entry::__do_refresh() noexcept { - __data_.__reset(); - error_code failure_ec; - - StatT full_st; - file_status st = detail::posix_lstat(__p_, full_st, &failure_ec); - if (!status_known(st)) { - __data_.__reset(); - return failure_ec; - } - - if (!_VSTD_FS::exists(st) || !_VSTD_FS::is_symlink(st)) { - __data_.__cache_type_ = directory_entry::_RefreshNonSymlink; - __data_.__type_ = st.type(); - __data_.__non_sym_perms_ = st.permissions(); - } else { // we have a symlink - __data_.__sym_perms_ = st.permissions(); - // Get the information about the linked entity. - // Ignore errors from stat, since we don't want errors regarding symlink - // resolution to be reported to the user. - error_code ignored_ec; - st = detail::posix_stat(__p_, full_st, &ignored_ec); - - __data_.__type_ = st.type(); - __data_.__non_sym_perms_ = st.permissions(); - - // If we failed to resolve the link, then only partially populate the - // cache. - if (!status_known(st)) { - __data_.__cache_type_ = directory_entry::_RefreshSymlinkUnresolved; - return error_code{}; - } - // Otherwise, we resolved the link, potentially as not existing. - // That's OK. - __data_.__cache_type_ = directory_entry::_RefreshSymlink; - } - - if (_VSTD_FS::is_regular_file(st)) - __data_.__size_ = static_cast<uintmax_t>(full_st.st_size); - - if (_VSTD_FS::exists(st)) { - __data_.__nlink_ = static_cast<uintmax_t>(full_st.st_nlink); - - // Attempt to extract the mtime, and fail if it's not representable using - // file_time_type. For now we ignore the error, as we'll report it when - // the value is actually used. - error_code ignored_ec; - __data_.__write_time_ = - __extract_last_write_time(__p_, full_st, &ignored_ec); - } - - return failure_ec; -} - _LIBCPP_END_NAMESPACE_FILESYSTEM diff --git a/contrib/libs/cxxsupp/libcxx/src/filesystem/path.cpp b/contrib/libs/cxxsupp/libcxx/src/filesystem/path.cpp new file mode 100644 index 0000000000..82f1ba7ba6 --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/src/filesystem/path.cpp @@ -0,0 +1,460 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include <__config> +#include <filesystem> +#include <vector> + +#include "error.h" +#include "path_parser.h" + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +using detail::ErrorHandler; +using parser::createView; +using parser::PathParser; +using parser::string_view_t; + +/////////////////////////////////////////////////////////////////////////////// +// path definitions +/////////////////////////////////////////////////////////////////////////////// + +constexpr path::value_type path::preferred_separator; + +path& path::replace_extension(path const& replacement) { + path p = extension(); + if (not p.empty()) { + __pn_.erase(__pn_.size() - p.native().size()); + } + if (!replacement.empty()) { + if (replacement.native()[0] != '.') { + __pn_ += PATHSTR("."); + } + __pn_.append(replacement.__pn_); + } + return *this; +} + +/////////////////////////////////////////////////////////////////////////////// +// path.decompose + +string_view_t path::__root_name() const { + auto PP = PathParser::CreateBegin(__pn_); + if (PP.State == PathParser::PS_InRootName) + return *PP; + return {}; +} + +string_view_t path::__root_directory() const { + auto PP = PathParser::CreateBegin(__pn_); + if (PP.State == PathParser::PS_InRootName) + ++PP; + if (PP.State == PathParser::PS_InRootDir) + return *PP; + return {}; +} + +string_view_t path::__root_path_raw() const { + auto PP = PathParser::CreateBegin(__pn_); + if (PP.State == PathParser::PS_InRootName) { + auto NextCh = PP.peek(); + if (NextCh && isSeparator(*NextCh)) { + ++PP; + return createView(__pn_.data(), &PP.RawEntry.back()); + } + return PP.RawEntry; + } + if (PP.State == PathParser::PS_InRootDir) + return *PP; + return {}; +} + +static bool ConsumeRootName(PathParser *PP) { + static_assert(PathParser::PS_BeforeBegin == 1 && + PathParser::PS_InRootName == 2, + "Values for enums are incorrect"); + while (PP->State <= PathParser::PS_InRootName) + ++(*PP); + return PP->State == PathParser::PS_AtEnd; +} + +static bool ConsumeRootDir(PathParser* PP) { + static_assert(PathParser::PS_BeforeBegin == 1 && + PathParser::PS_InRootName == 2 && + PathParser::PS_InRootDir == 3, "Values for enums are incorrect"); + while (PP->State <= PathParser::PS_InRootDir) + ++(*PP); + return PP->State == PathParser::PS_AtEnd; +} + +string_view_t path::__relative_path() const { + auto PP = PathParser::CreateBegin(__pn_); + if (ConsumeRootDir(&PP)) + return {}; + return createView(PP.RawEntry.data(), &__pn_.back()); +} + +string_view_t path::__parent_path() const { + if (empty()) + return {}; + // Determine if we have a root path but not a relative path. In that case + // return *this. + { + auto PP = PathParser::CreateBegin(__pn_); + if (ConsumeRootDir(&PP)) + return __pn_; + } + // Otherwise remove a single element from the end of the path, and return + // a string representing that path + { + auto PP = PathParser::CreateEnd(__pn_); + --PP; + if (PP.RawEntry.data() == __pn_.data()) + return {}; + --PP; + return createView(__pn_.data(), &PP.RawEntry.back()); + } +} + +string_view_t path::__filename() const { + if (empty()) + return {}; + { + PathParser PP = PathParser::CreateBegin(__pn_); + if (ConsumeRootDir(&PP)) + return {}; + } + return *(--PathParser::CreateEnd(__pn_)); +} + +string_view_t path::__stem() const { + return parser::separate_filename(__filename()).first; +} + +string_view_t path::__extension() const { + return parser::separate_filename(__filename()).second; +} + +//////////////////////////////////////////////////////////////////////////// +// path.gen + +enum PathPartKind : unsigned char { + PK_None, + PK_RootSep, + PK_Filename, + PK_Dot, + PK_DotDot, + PK_TrailingSep +}; + +static PathPartKind ClassifyPathPart(string_view_t Part) { + if (Part.empty()) + return PK_TrailingSep; + if (Part == PATHSTR(".")) + return PK_Dot; + if (Part == PATHSTR("..")) + return PK_DotDot; + if (Part == PATHSTR("/")) + return PK_RootSep; +#if defined(_LIBCPP_WIN32API) + if (Part == PATHSTR("\\")) + return PK_RootSep; +#endif + return PK_Filename; +} + +path path::lexically_normal() const { + if (__pn_.empty()) + return *this; + + using PartKindPair = pair<string_view_t, PathPartKind>; + vector<PartKindPair> Parts; + // Guess as to how many elements the path has to avoid reallocating. + Parts.reserve(32); + + // Track the total size of the parts as we collect them. This allows the + // resulting path to reserve the correct amount of memory. + size_t NewPathSize = 0; + auto AddPart = [&](PathPartKind K, string_view_t P) { + NewPathSize += P.size(); + Parts.emplace_back(P, K); + }; + auto LastPartKind = [&]() { + if (Parts.empty()) + return PK_None; + return Parts.back().second; + }; + + bool MaybeNeedTrailingSep = false; + // Build a stack containing the remaining elements of the path, popping off + // elements which occur before a '..' entry. + for (auto PP = PathParser::CreateBegin(__pn_); PP; ++PP) { + auto Part = *PP; + PathPartKind Kind = ClassifyPathPart(Part); + switch (Kind) { + case PK_Filename: + case PK_RootSep: { + // Add all non-dot and non-dot-dot elements to the stack of elements. + AddPart(Kind, Part); + MaybeNeedTrailingSep = false; + break; + } + case PK_DotDot: { + // Only push a ".." element if there are no elements preceding the "..", + // or if the preceding element is itself "..". + auto LastKind = LastPartKind(); + if (LastKind == PK_Filename) { + NewPathSize -= Parts.back().first.size(); + Parts.pop_back(); + } else if (LastKind != PK_RootSep) + AddPart(PK_DotDot, PATHSTR("..")); + MaybeNeedTrailingSep = LastKind == PK_Filename; + break; + } + case PK_Dot: + case PK_TrailingSep: { + MaybeNeedTrailingSep = true; + break; + } + case PK_None: + __libcpp_unreachable(); + } + } + // [fs.path.generic]p6.8: If the path is empty, add a dot. + if (Parts.empty()) + return PATHSTR("."); + + // [fs.path.generic]p6.7: If the last filename is dot-dot, remove any + // trailing directory-separator. + bool NeedTrailingSep = MaybeNeedTrailingSep && LastPartKind() == PK_Filename; + + path Result; + Result.__pn_.reserve(Parts.size() + NewPathSize + NeedTrailingSep); + for (auto& PK : Parts) + Result /= PK.first; + + if (NeedTrailingSep) + Result /= PATHSTR(""); + + Result.make_preferred(); + return Result; +} + +static int DetermineLexicalElementCount(PathParser PP) { + int Count = 0; + for (; PP; ++PP) { + auto Elem = *PP; + if (Elem == PATHSTR("..")) + --Count; + else if (Elem != PATHSTR(".") && Elem != PATHSTR("")) + ++Count; + } + return Count; +} + +path path::lexically_relative(const path& base) const { + { // perform root-name/root-directory mismatch checks + auto PP = PathParser::CreateBegin(__pn_); + auto PPBase = PathParser::CreateBegin(base.__pn_); + auto CheckIterMismatchAtBase = [&]() { + return PP.State != PPBase.State && + (PP.inRootPath() || PPBase.inRootPath()); + }; + if (PP.inRootName() && PPBase.inRootName()) { + if (*PP != *PPBase) + return {}; + } else if (CheckIterMismatchAtBase()) + return {}; + + if (PP.inRootPath()) + ++PP; + if (PPBase.inRootPath()) + ++PPBase; + if (CheckIterMismatchAtBase()) + return {}; + } + + // Find the first mismatching element + auto PP = PathParser::CreateBegin(__pn_); + auto PPBase = PathParser::CreateBegin(base.__pn_); + while (PP && PPBase && PP.State == PPBase.State && *PP == *PPBase) { + ++PP; + ++PPBase; + } + + // If there is no mismatch, return ".". + if (!PP && !PPBase) + return "."; + + // Otherwise, determine the number of elements, 'n', which are not dot or + // dot-dot minus the number of dot-dot elements. + int ElemCount = DetermineLexicalElementCount(PPBase); + if (ElemCount < 0) + return {}; + + // if n == 0 and (a == end() || a->empty()), returns path("."); otherwise + if (ElemCount == 0 && (PP.atEnd() || *PP == PATHSTR(""))) + return PATHSTR("."); + + // return a path constructed with 'n' dot-dot elements, followed by the + // elements of '*this' after the mismatch. + path Result; + // FIXME: Reserve enough room in Result that it won't have to re-allocate. + while (ElemCount--) + Result /= PATHSTR(".."); + for (; PP; ++PP) + Result /= *PP; + return Result; +} + +//////////////////////////////////////////////////////////////////////////// +// path.comparisons +static int CompareRootName(PathParser *LHS, PathParser *RHS) { + if (!LHS->inRootName() && !RHS->inRootName()) + return 0; + + auto GetRootName = [](PathParser *Parser) -> string_view_t { + return Parser->inRootName() ? **Parser : PATHSTR(""); + }; + int res = GetRootName(LHS).compare(GetRootName(RHS)); + ConsumeRootName(LHS); + ConsumeRootName(RHS); + return res; +} + +static int CompareRootDir(PathParser *LHS, PathParser *RHS) { + if (!LHS->inRootDir() && RHS->inRootDir()) + return -1; + else if (LHS->inRootDir() && !RHS->inRootDir()) + return 1; + else { + ConsumeRootDir(LHS); + ConsumeRootDir(RHS); + return 0; + } +} + +static int CompareRelative(PathParser *LHSPtr, PathParser *RHSPtr) { + auto &LHS = *LHSPtr; + auto &RHS = *RHSPtr; + + int res; + while (LHS && RHS) { + if ((res = (*LHS).compare(*RHS)) != 0) + return res; + ++LHS; + ++RHS; + } + return 0; +} + +static int CompareEndState(PathParser *LHS, PathParser *RHS) { + if (LHS->atEnd() && !RHS->atEnd()) + return -1; + else if (!LHS->atEnd() && RHS->atEnd()) + return 1; + return 0; +} + +int path::__compare(string_view_t __s) const { + auto LHS = PathParser::CreateBegin(__pn_); + auto RHS = PathParser::CreateBegin(__s); + int res; + + if ((res = CompareRootName(&LHS, &RHS)) != 0) + return res; + + if ((res = CompareRootDir(&LHS, &RHS)) != 0) + return res; + + if ((res = CompareRelative(&LHS, &RHS)) != 0) + return res; + + return CompareEndState(&LHS, &RHS); +} + +//////////////////////////////////////////////////////////////////////////// +// path.nonmembers +size_t hash_value(const path& __p) noexcept { + auto PP = PathParser::CreateBegin(__p.native()); + size_t hash_value = 0; + hash<string_view_t> hasher; + while (PP) { + hash_value = __hash_combine(hash_value, hasher(*PP)); + ++PP; + } + return hash_value; +} + +//////////////////////////////////////////////////////////////////////////// +// path.itr +path::iterator path::begin() const { + auto PP = PathParser::CreateBegin(__pn_); + iterator it; + it.__path_ptr_ = this; + it.__state_ = static_cast<path::iterator::_ParserState>(PP.State); + it.__entry_ = PP.RawEntry; + it.__stashed_elem_.__assign_view(*PP); + return it; +} + +path::iterator path::end() const { + iterator it{}; + it.__state_ = path::iterator::_AtEnd; + it.__path_ptr_ = this; + return it; +} + +path::iterator& path::iterator::__increment() { + PathParser PP(__path_ptr_->native(), __entry_, __state_); + ++PP; + __state_ = static_cast<_ParserState>(PP.State); + __entry_ = PP.RawEntry; + __stashed_elem_.__assign_view(*PP); + return *this; +} + +path::iterator& path::iterator::__decrement() { + PathParser PP(__path_ptr_->native(), __entry_, __state_); + --PP; + __state_ = static_cast<_ParserState>(PP.State); + __entry_ = PP.RawEntry; + __stashed_elem_.__assign_view(*PP); + return *this; +} + +#if defined(_LIBCPP_WIN32API) +//////////////////////////////////////////////////////////////////////////// +// Windows path conversions +size_t __wide_to_char(const wstring &str, char *out, size_t outlen) { + if (str.empty()) + return 0; + ErrorHandler<size_t> err("__wide_to_char", nullptr); + UINT codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; + BOOL used_default = FALSE; + int ret = WideCharToMultiByte(codepage, 0, str.data(), str.size(), out, + outlen, nullptr, &used_default); + if (ret <= 0 || used_default) + return err.report(errc::illegal_byte_sequence); + return ret; +} + +size_t __char_to_wide(const string &str, wchar_t *out, size_t outlen) { + if (str.empty()) + return 0; + ErrorHandler<size_t> err("__char_to_wide", nullptr); + UINT codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; + int ret = MultiByteToWideChar(codepage, MB_ERR_INVALID_CHARS, str.data(), + str.size(), out, outlen); + if (ret <= 0) + return err.report(errc::illegal_byte_sequence); + return ret; +} +#endif + +_LIBCPP_END_NAMESPACE_FILESYSTEM diff --git a/contrib/libs/cxxsupp/libcxx/src/filesystem/path_parser.h b/contrib/libs/cxxsupp/libcxx/src/filesystem/path_parser.h new file mode 100644 index 0000000000..630391fe6b --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/src/filesystem/path_parser.h @@ -0,0 +1,372 @@ +//===----------------------------------------------------------------------===// +// +// 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 PATH_PARSER_H +#define PATH_PARSER_H + +#include <__config> +#include <__utility/unreachable.h> +#include <cstddef> +#include <filesystem> +#include <utility> + +#include "format_string.h" + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +inline bool isSeparator(path::value_type C) { + if (C == '/') + return true; +#if defined(_LIBCPP_WIN32API) + if (C == '\\') + return true; +#endif + return false; +} + +inline bool isDriveLetter(path::value_type C) { + return (C >= 'a' && C <= 'z') || (C >= 'A' && C <= 'Z'); +} + +namespace parser { + +using string_view_t = path::__string_view; +using string_view_pair = pair<string_view_t, string_view_t>; +using PosPtr = path::value_type const*; + +struct PathParser { + enum ParserState : unsigned char { + // Zero is a special sentinel value used by default constructed iterators. + PS_BeforeBegin = path::iterator::_BeforeBegin, + PS_InRootName = path::iterator::_InRootName, + PS_InRootDir = path::iterator::_InRootDir, + PS_InFilenames = path::iterator::_InFilenames, + PS_InTrailingSep = path::iterator::_InTrailingSep, + PS_AtEnd = path::iterator::_AtEnd + }; + + const string_view_t Path; + string_view_t RawEntry; + ParserState State; + +private: + PathParser(string_view_t P, ParserState State) noexcept : Path(P), + State(State) {} + +public: + PathParser(string_view_t P, string_view_t E, unsigned char S) + : Path(P), RawEntry(E), State(static_cast<ParserState>(S)) { + // S cannot be '0' or PS_BeforeBegin. + } + + static PathParser CreateBegin(string_view_t P) noexcept { + PathParser PP(P, PS_BeforeBegin); + PP.increment(); + return PP; + } + + static PathParser CreateEnd(string_view_t P) noexcept { + PathParser PP(P, PS_AtEnd); + return PP; + } + + PosPtr peek() const noexcept { + auto TkEnd = getNextTokenStartPos(); + auto End = getAfterBack(); + return TkEnd == End ? nullptr : TkEnd; + } + + void increment() noexcept { + const PosPtr End = getAfterBack(); + const PosPtr Start = getNextTokenStartPos(); + if (Start == End) + return makeState(PS_AtEnd); + + switch (State) { + case PS_BeforeBegin: { + PosPtr TkEnd = consumeRootName(Start, End); + if (TkEnd) + return makeState(PS_InRootName, Start, TkEnd); + } + _LIBCPP_FALLTHROUGH(); + case PS_InRootName: { + PosPtr TkEnd = consumeAllSeparators(Start, End); + if (TkEnd) + return makeState(PS_InRootDir, Start, TkEnd); + else + return makeState(PS_InFilenames, Start, consumeName(Start, End)); + } + case PS_InRootDir: + return makeState(PS_InFilenames, Start, consumeName(Start, End)); + + case PS_InFilenames: { + PosPtr SepEnd = consumeAllSeparators(Start, End); + if (SepEnd != End) { + PosPtr TkEnd = consumeName(SepEnd, End); + if (TkEnd) + return makeState(PS_InFilenames, SepEnd, TkEnd); + } + return makeState(PS_InTrailingSep, Start, SepEnd); + } + + case PS_InTrailingSep: + return makeState(PS_AtEnd); + + case PS_AtEnd: + __libcpp_unreachable(); + } + } + + void decrement() noexcept { + const PosPtr REnd = getBeforeFront(); + const PosPtr RStart = getCurrentTokenStartPos() - 1; + if (RStart == REnd) // we're decrementing the begin + return makeState(PS_BeforeBegin); + + switch (State) { + case PS_AtEnd: { + // Try to consume a trailing separator or root directory first. + if (PosPtr SepEnd = consumeAllSeparators(RStart, REnd)) { + if (SepEnd == REnd) + return makeState(PS_InRootDir, Path.data(), RStart + 1); + PosPtr TkStart = consumeRootName(SepEnd, REnd); + if (TkStart == REnd) + return makeState(PS_InRootDir, RStart, RStart + 1); + return makeState(PS_InTrailingSep, SepEnd + 1, RStart + 1); + } else { + PosPtr TkStart = consumeRootName(RStart, REnd); + if (TkStart == REnd) + return makeState(PS_InRootName, TkStart + 1, RStart + 1); + TkStart = consumeName(RStart, REnd); + return makeState(PS_InFilenames, TkStart + 1, RStart + 1); + } + } + case PS_InTrailingSep: + return makeState(PS_InFilenames, consumeName(RStart, REnd) + 1, + RStart + 1); + case PS_InFilenames: { + PosPtr SepEnd = consumeAllSeparators(RStart, REnd); + if (SepEnd == REnd) + return makeState(PS_InRootDir, Path.data(), RStart + 1); + PosPtr TkStart = consumeRootName(SepEnd ? SepEnd : RStart, REnd); + if (TkStart == REnd) { + if (SepEnd) + return makeState(PS_InRootDir, SepEnd + 1, RStart + 1); + return makeState(PS_InRootName, TkStart + 1, RStart + 1); + } + TkStart = consumeName(SepEnd, REnd); + return makeState(PS_InFilenames, TkStart + 1, SepEnd + 1); + } + case PS_InRootDir: + return makeState(PS_InRootName, Path.data(), RStart + 1); + case PS_InRootName: + case PS_BeforeBegin: + __libcpp_unreachable(); + } + } + + /// \brief Return a view with the "preferred representation" of the current + /// element. For example trailing separators are represented as a '.' + string_view_t operator*() const noexcept { + switch (State) { + case PS_BeforeBegin: + case PS_AtEnd: + return PATHSTR(""); + case PS_InRootDir: + if (RawEntry[0] == '\\') + return PATHSTR("\\"); + else + return PATHSTR("/"); + case PS_InTrailingSep: + return PATHSTR(""); + case PS_InRootName: + case PS_InFilenames: + return RawEntry; + } + __libcpp_unreachable(); + } + + explicit operator bool() const noexcept { + return State != PS_BeforeBegin && State != PS_AtEnd; + } + + PathParser& operator++() noexcept { + increment(); + return *this; + } + + PathParser& operator--() noexcept { + decrement(); + return *this; + } + + bool atEnd() const noexcept { + return State == PS_AtEnd; + } + + bool inRootDir() const noexcept { + return State == PS_InRootDir; + } + + bool inRootName() const noexcept { + return State == PS_InRootName; + } + + bool inRootPath() const noexcept { + return inRootName() || inRootDir(); + } + +private: + void makeState(ParserState NewState, PosPtr Start, PosPtr End) noexcept { + State = NewState; + RawEntry = string_view_t(Start, End - Start); + } + void makeState(ParserState NewState) noexcept { + State = NewState; + RawEntry = {}; + } + + PosPtr getAfterBack() const noexcept { return Path.data() + Path.size(); } + + PosPtr getBeforeFront() const noexcept { return Path.data() - 1; } + + /// \brief Return a pointer to the first character after the currently + /// lexed element. + PosPtr getNextTokenStartPos() const noexcept { + switch (State) { + case PS_BeforeBegin: + return Path.data(); + case PS_InRootName: + case PS_InRootDir: + case PS_InFilenames: + return &RawEntry.back() + 1; + case PS_InTrailingSep: + case PS_AtEnd: + return getAfterBack(); + } + __libcpp_unreachable(); + } + + /// \brief Return a pointer to the first character in the currently lexed + /// element. + PosPtr getCurrentTokenStartPos() const noexcept { + switch (State) { + case PS_BeforeBegin: + case PS_InRootName: + return &Path.front(); + case PS_InRootDir: + case PS_InFilenames: + case PS_InTrailingSep: + return &RawEntry.front(); + case PS_AtEnd: + return &Path.back() + 1; + } + __libcpp_unreachable(); + } + + // Consume all consecutive separators. + PosPtr consumeAllSeparators(PosPtr P, PosPtr End) const noexcept { + if (P == nullptr || P == End || !isSeparator(*P)) + return nullptr; + const int Inc = P < End ? 1 : -1; + P += Inc; + while (P != End && isSeparator(*P)) + P += Inc; + return P; + } + + // Consume exactly N separators, or return nullptr. + PosPtr consumeNSeparators(PosPtr P, PosPtr End, int N) const noexcept { + PosPtr Ret = consumeAllSeparators(P, End); + if (Ret == nullptr) + return nullptr; + if (P < End) { + if (Ret == P + N) + return Ret; + } else { + if (Ret == P - N) + return Ret; + } + return nullptr; + } + + PosPtr consumeName(PosPtr P, PosPtr End) const noexcept { + PosPtr Start = P; + if (P == nullptr || P == End || isSeparator(*P)) + return nullptr; + const int Inc = P < End ? 1 : -1; + P += Inc; + while (P != End && !isSeparator(*P)) + P += Inc; + if (P == End && Inc < 0) { + // Iterating backwards and consumed all the rest of the input. + // Check if the start of the string would have been considered + // a root name. + PosPtr RootEnd = consumeRootName(End + 1, Start); + if (RootEnd) + return RootEnd - 1; + } + return P; + } + + PosPtr consumeDriveLetter(PosPtr P, PosPtr End) const noexcept { + if (P == End) + return nullptr; + if (P < End) { + if (P + 1 == End || !isDriveLetter(P[0]) || P[1] != ':') + return nullptr; + return P + 2; + } else { + if (P - 1 == End || !isDriveLetter(P[-1]) || P[0] != ':') + return nullptr; + return P - 2; + } + } + + PosPtr consumeNetworkRoot(PosPtr P, PosPtr End) const noexcept { + if (P == End) + return nullptr; + if (P < End) + return consumeName(consumeNSeparators(P, End, 2), End); + else + return consumeNSeparators(consumeName(P, End), End, 2); + } + +#if defined(_LIBCPP_WIN32API) + PosPtr consumeRootName(PosPtr P, PosPtr End) const noexcept { + if (PosPtr Ret = consumeDriveLetter(P, End)) + return Ret; + if (PosPtr Ret = consumeNetworkRoot(P, End)) + return Ret; + return nullptr; + } +#else + PosPtr consumeRootName(PosPtr /*P*/, PosPtr /*End*/) const noexcept { + return nullptr; + } +#endif +}; + +inline string_view_pair separate_filename(string_view_t const& s) { + if (s == PATHSTR(".") || s == PATHSTR("..") || s.empty()) + return string_view_pair{s, PATHSTR("")}; + auto pos = s.find_last_of('.'); + if (pos == string_view_t::npos || pos == 0) + return string_view_pair{s, string_view_t{}}; + return string_view_pair{s.substr(0, pos), s.substr(pos)}; +} + +inline string_view_t createView(PosPtr S, PosPtr E) noexcept { + return {S, static_cast<size_t>(E - S) + 1}; +} + +} // namespace parser + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // PATH_PARSER_H diff --git a/contrib/libs/cxxsupp/libcxx/src/filesystem/posix_compat.h b/contrib/libs/cxxsupp/libcxx/src/filesystem/posix_compat.h index 36116ec5a3..f11f41552e 100644 --- a/contrib/libs/cxxsupp/libcxx/src/filesystem/posix_compat.h +++ b/contrib/libs/cxxsupp/libcxx/src/filesystem/posix_compat.h @@ -24,9 +24,11 @@ #define POSIX_COMPAT_H #include <__assert> +#include <__config> #include <filesystem> -#include "filesystem_common.h" +#include "error.h" +#include "time_utils.h" #if defined(_LIBCPP_WIN32API) # define WIN32_LEAN_AND_MEAN @@ -35,10 +37,13 @@ # include <io.h> # include <winioctl.h> #else +# include <fcntl.h> # include <unistd.h> # include <sys/stat.h> # include <sys/statvfs.h> +# include <sys/time.h> #endif +#include <stdlib.h> #include <time.h> #if defined(_LIBCPP_WIN32API) @@ -74,7 +79,6 @@ struct LIBCPP_REPARSE_DATA_BUFFER { _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM namespace detail { -namespace { #if defined(_LIBCPP_WIN32API) @@ -118,36 +122,7 @@ namespace { #define O_NONBLOCK 0 - -// There were 369 years and 89 leap days from the Windows epoch -// (1601) to the Unix epoch (1970). -#define FILE_TIME_OFFSET_SECS (uint64_t(369 * 365 + 89) * (24 * 60 * 60)) - -TimeSpec filetime_to_timespec(LARGE_INTEGER li) { - TimeSpec ret; - ret.tv_sec = li.QuadPart / 10000000 - FILE_TIME_OFFSET_SECS; - ret.tv_nsec = (li.QuadPart % 10000000) * 100; - return ret; -} - -TimeSpec filetime_to_timespec(FILETIME ft) { - LARGE_INTEGER li; - li.LowPart = ft.dwLowDateTime; - li.HighPart = ft.dwHighDateTime; - return filetime_to_timespec(li); -} - -FILETIME timespec_to_filetime(TimeSpec ts) { - LARGE_INTEGER li; - li.QuadPart = - ts.tv_nsec / 100 + (ts.tv_sec + FILE_TIME_OFFSET_SECS) * 10000000; - FILETIME ft; - ft.dwLowDateTime = li.LowPart; - ft.dwHighDateTime = li.HighPart; - return ft; -} - -int set_errno(int e = GetLastError()) { +inline int set_errno(int e = GetLastError()) { errno = static_cast<int>(__win_err_to_errc(e)); return -1; } @@ -170,7 +145,7 @@ private: HANDLE h; }; -int stat_handle(HANDLE h, StatT *buf) { +inline int stat_handle(HANDLE h, StatT *buf) { FILE_BASIC_INFO basic; if (!GetFileInformationByHandleEx(h, FileBasicInfo, &basic, sizeof(basic))) return set_errno(); @@ -208,7 +183,7 @@ int stat_handle(HANDLE h, StatT *buf) { return 0; } -int stat_file(const wchar_t *path, StatT *buf, DWORD flags) { +inline int stat_file(const wchar_t *path, StatT *buf, DWORD flags) { WinHandle h(path, FILE_READ_ATTRIBUTES, flags); if (!h) return set_errno(); @@ -216,24 +191,26 @@ int stat_file(const wchar_t *path, StatT *buf, DWORD flags) { return ret; } -int stat(const wchar_t *path, StatT *buf) { return stat_file(path, buf, 0); } +inline int stat(const wchar_t *path, StatT *buf) { return stat_file(path, buf, 0); } -int lstat(const wchar_t *path, StatT *buf) { +inline int lstat(const wchar_t *path, StatT *buf) { return stat_file(path, buf, FILE_FLAG_OPEN_REPARSE_POINT); } -int fstat(int fd, StatT *buf) { +inline int fstat(int fd, StatT *buf) { HANDLE h = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); return stat_handle(h, buf); } -int mkdir(const wchar_t *path, int permissions) { +inline int mkdir(const wchar_t *path, int permissions) { (void)permissions; - return _wmkdir(path); + if (!CreateDirectoryW(path, nullptr)) + return set_errno(); + return 0; } -int symlink_file_dir(const wchar_t *oldname, const wchar_t *newname, - bool is_dir) { +inline int symlink_file_dir(const wchar_t *oldname, const wchar_t *newname, + bool is_dir) { path dest(oldname); dest.make_preferred(); oldname = dest.c_str(); @@ -249,21 +226,21 @@ int symlink_file_dir(const wchar_t *oldname, const wchar_t *newname, return set_errno(); } -int symlink_file(const wchar_t *oldname, const wchar_t *newname) { +inline int symlink_file(const wchar_t *oldname, const wchar_t *newname) { return symlink_file_dir(oldname, newname, false); } -int symlink_dir(const wchar_t *oldname, const wchar_t *newname) { +inline int symlink_dir(const wchar_t *oldname, const wchar_t *newname) { return symlink_file_dir(oldname, newname, true); } -int link(const wchar_t *oldname, const wchar_t *newname) { +inline int link(const wchar_t *oldname, const wchar_t *newname) { if (CreateHardLinkW(newname, oldname, nullptr)) return 0; return set_errno(); } -int remove(const wchar_t *path) { +inline int remove(const wchar_t *path) { detail::WinHandle h(path, DELETE, FILE_FLAG_OPEN_REPARSE_POINT); if (!h) return set_errno(); @@ -274,7 +251,7 @@ int remove(const wchar_t *path) { return 0; } -int truncate_handle(HANDLE h, off_t length) { +inline int truncate_handle(HANDLE h, off_t length) { LARGE_INTEGER size_param; size_param.QuadPart = length; if (!SetFilePointerEx(h, size_param, 0, FILE_BEGIN)) @@ -284,19 +261,19 @@ int truncate_handle(HANDLE h, off_t length) { return 0; } -int ftruncate(int fd, off_t length) { +inline int ftruncate(int fd, off_t length) { HANDLE h = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); return truncate_handle(h, length); } -int truncate(const wchar_t *path, off_t length) { +inline int truncate(const wchar_t *path, off_t length) { detail::WinHandle h(path, GENERIC_WRITE, 0); if (!h) return set_errno(); return truncate_handle(h, length); } -int rename(const wchar_t *from, const wchar_t *to) { +inline int rename(const wchar_t *from, const wchar_t *to) { if (!(MoveFileExW(from, to, MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH))) @@ -304,11 +281,11 @@ int rename(const wchar_t *from, const wchar_t *to) { return 0; } -template <class... Args> int open(const wchar_t *filename, Args... args) { - return _wopen(filename, args...); +inline int chdir(const wchar_t* path) { + if (!SetCurrentDirectoryW(path)) + return set_errno(); + return 0; } -int close(int fd) { return _close(fd); } -int chdir(const wchar_t *path) { return _wchdir(path); } struct StatVFS { uint64_t f_frsize; @@ -317,7 +294,7 @@ struct StatVFS { uint64_t f_bavail; }; -int statvfs(const wchar_t *p, StatVFS *buf) { +inline int statvfs(const wchar_t *p, StatVFS *buf) { path dir = p; while (true) { error_code local_ec; @@ -343,11 +320,29 @@ int statvfs(const wchar_t *p, StatVFS *buf) { return 0; } -wchar_t *getcwd(wchar_t *buff, size_t size) { return _wgetcwd(buff, size); } +inline wchar_t* getcwd([[maybe_unused]] wchar_t* in_buf, [[maybe_unused]] size_t in_size) { + // Only expected to be used with us allocating the buffer. + _LIBCPP_ASSERT(in_buf == nullptr, "Windows getcwd() assumes in_buf==nullptr"); + _LIBCPP_ASSERT(in_size == 0, "Windows getcwd() assumes in_size==0"); + + size_t buff_size = MAX_PATH + 10; + std::unique_ptr<wchar_t, decltype(&::free)> buff(static_cast<wchar_t*>(malloc(buff_size * sizeof(wchar_t))), &::free); + DWORD retval = GetCurrentDirectoryW(buff_size, buff.get()); + if (retval > buff_size) { + buff_size = retval; + buff.reset(static_cast<wchar_t*>(malloc(buff_size * sizeof(wchar_t)))); + retval = GetCurrentDirectoryW(buff_size, buff.get()); + } + if (!retval) { + set_errno(); + return nullptr; + } + return buff.release(); +} -wchar_t *realpath(const wchar_t *path, wchar_t *resolved_name) { +inline wchar_t *realpath(const wchar_t *path, [[maybe_unused]] wchar_t *resolved_name) { // Only expected to be used with us allocating the buffer. - _LIBCPP_ASSERT(resolved_name == nullptr, + _LIBCPP_ASSERT_UNCATEGORIZED(resolved_name == nullptr, "Windows realpath() assumes a null resolved_name"); WinHandle h(path, FILE_READ_ATTRIBUTES, 0); @@ -386,7 +381,7 @@ wchar_t *realpath(const wchar_t *path, wchar_t *resolved_name) { #define AT_SYMLINK_NOFOLLOW 1 using ModeT = int; -int fchmod_handle(HANDLE h, int perms) { +inline int fchmod_handle(HANDLE h, int perms) { FILE_BASIC_INFO basic; if (!GetFileInformationByHandleEx(h, FileBasicInfo, &basic, sizeof(basic))) return set_errno(); @@ -400,7 +395,7 @@ int fchmod_handle(HANDLE h, int perms) { return 0; } -int fchmodat(int fd, const wchar_t *path, int perms, int flag) { +inline int fchmodat(int /*fd*/, const wchar_t *path, int perms, int flag) { DWORD attributes = GetFileAttributesW(path); if (attributes == INVALID_FILE_ATTRIBUTES) return set_errno(); @@ -427,7 +422,7 @@ int fchmodat(int fd, const wchar_t *path, int perms, int flag) { return 0; } -int fchmod(int fd, int perms) { +inline int fchmod(int fd, int perms) { HANDLE h = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); return fchmod_handle(h, perms); } @@ -435,7 +430,7 @@ int fchmod(int fd, int perms) { #define MAX_SYMLINK_SIZE MAXIMUM_REPARSE_DATA_BUFFER_SIZE using SSizeT = ::int64_t; -SSizeT readlink(const wchar_t *path, wchar_t *ret_buf, size_t bufsize) { +inline SSizeT readlink(const wchar_t *path, wchar_t *ret_buf, size_t bufsize) { uint8_t buf[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; detail::WinHandle h(path, FILE_READ_ATTRIBUTES, FILE_FLAG_OPEN_REPARSE_POINT); if (!h) @@ -479,14 +474,13 @@ SSizeT readlink(const wchar_t *path, wchar_t *ret_buf, size_t bufsize) { } #else -int symlink_file(const char *oldname, const char *newname) { +inline int symlink_file(const char *oldname, const char *newname) { return ::symlink(oldname, newname); } -int symlink_dir(const char *oldname, const char *newname) { +inline int symlink_dir(const char *oldname, const char *newname) { return ::symlink(oldname, newname); } using ::chdir; -using ::close; using ::fchmod; #if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_FDCWD) using ::fchmodat; @@ -497,7 +491,6 @@ using ::getcwd; using ::link; using ::lstat; using ::mkdir; -using ::open; using ::readlink; using ::realpath; using ::remove; @@ -514,7 +507,6 @@ using SSizeT = ::ssize_t; #endif -} // namespace } // end namespace detail _LIBCPP_END_NAMESPACE_FILESYSTEM diff --git a/contrib/libs/cxxsupp/libcxx/src/filesystem/filesystem_common.h b/contrib/libs/cxxsupp/libcxx/src/filesystem/time_utils.h index 0e71569d87..9177e1013d 100644 --- a/contrib/libs/cxxsupp/libcxx/src/filesystem/filesystem_common.h +++ b/contrib/libs/cxxsupp/libcxx/src/filesystem/time_utils.h @@ -6,54 +6,35 @@ // //===----------------------------------------------------------------------===//// -#ifndef FILESYSTEM_COMMON_H -#define FILESYSTEM_COMMON_H +#ifndef FILESYSTEM_TIME_UTILS_H +#define FILESYSTEM_TIME_UTILS_H -#include <__assert> #include <__config> #include <array> #include <chrono> -#include <climits> -#include <cstdarg> -#include <ctime> #include <filesystem> +#include <limits> #include <ratio> #include <system_error> +#include <type_traits> #include <utility> +#include "error.h" +#include "format_string.h" + #if defined(_LIBCPP_WIN32API) # define WIN32_LEAN_AND_MEAN # define NOMINMAX # include <windows.h> #else -# include <dirent.h> // for DIR & friends -# include <fcntl.h> /* values for fchmodat */ +# include <fcntl.h> # include <sys/stat.h> -# include <sys/statvfs.h> # include <sys/time.h> // for ::utimes as used in __last_write_time -# include <unistd.h> -#endif // defined(_LIBCPP_WIN32API) - -#include "../include/apple_availability.h" - -#if !defined(__APPLE__) -// We can use the presence of UTIME_OMIT to detect platforms that provide -// utimensat. -#if defined(UTIME_OMIT) -#define _LIBCPP_USE_UTIMENSAT #endif -#endif - -_LIBCPP_DIAGNOSTIC_PUSH -_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wunused-function") -_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wunused-function") -#if defined(_LIBCPP_WIN32API) -# define PATHSTR(x) (L##x) -# define PATH_CSTR_FMT "\"%ls\"" -#else -# define PATHSTR(x) (x) -# define PATH_CSTR_FMT "\"%s\"" +// We can use the presence of UTIME_OMIT to detect platforms that provide utimensat. +#if defined(UTIME_OMIT) +# define _LIBCPP_USE_UTIMENSAT #endif _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM @@ -61,198 +42,11 @@ _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM namespace detail { #if defined(_LIBCPP_WIN32API) -// Non anonymous, to allow access from two translation units. -errc __win_err_to_errc(int err); -#endif - -namespace { - -static _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 1, 0) string -format_string_impl(const char* msg, va_list ap) { - array<char, 256> buf; - - va_list apcopy; - va_copy(apcopy, ap); - int ret = ::vsnprintf(buf.data(), buf.size(), msg, apcopy); - va_end(apcopy); - - string result; - if (static_cast<size_t>(ret) < buf.size()) { - result.assign(buf.data(), static_cast<size_t>(ret)); - } else { - // we did not provide a long enough buffer on our first attempt. The - // return value is the number of bytes (excluding the null byte) that are - // needed for formatting. - size_t size_with_null = static_cast<size_t>(ret) + 1; - result.__resize_default_init(size_with_null - 1); - ret = ::vsnprintf(&result[0], size_with_null, msg, ap); - _LIBCPP_ASSERT(static_cast<size_t>(ret) == (size_with_null - 1), "TODO"); - } - return result; -} - -static _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 1, 2) string -format_string(const char* msg, ...) { - string ret; - va_list ap; - va_start(ap, msg); -#ifndef _LIBCPP_NO_EXCEPTIONS - try { -#endif // _LIBCPP_NO_EXCEPTIONS - ret = format_string_impl(msg, ap); -#ifndef _LIBCPP_NO_EXCEPTIONS - } catch (...) { - va_end(ap); - throw; - } -#endif // _LIBCPP_NO_EXCEPTIONS - va_end(ap); - return ret; -} - -error_code capture_errno() { - _LIBCPP_ASSERT(errno != 0, "Expected errno to be non-zero"); - return error_code(errno, generic_category()); -} - -#if defined(_LIBCPP_WIN32API) -error_code make_windows_error(int err) { - return make_error_code(__win_err_to_errc(err)); -} -#endif - -template <class T> -T error_value(); -template <> -_LIBCPP_CONSTEXPR_SINCE_CXX14 void error_value<void>() {} -template <> -bool error_value<bool>() { - return false; -} -#if __SIZEOF_SIZE_T__ != __SIZEOF_LONG_LONG__ -template <> -size_t error_value<size_t>() { - return size_t(-1); -} -#endif -template <> -uintmax_t error_value<uintmax_t>() { - return uintmax_t(-1); -} -template <> -_LIBCPP_CONSTEXPR_SINCE_CXX14 file_time_type error_value<file_time_type>() { - return file_time_type::min(); -} -template <> -path error_value<path>() { - return {}; -} - -template <class T> -struct ErrorHandler { - const char* func_name_; - error_code* ec_ = nullptr; - const path* p1_ = nullptr; - const path* p2_ = nullptr; - - ErrorHandler(const char* fname, error_code* ec, const path* p1 = nullptr, - const path* p2 = nullptr) - : func_name_(fname), ec_(ec), p1_(p1), p2_(p2) { - if (ec_) - ec_->clear(); - } - - T report(const error_code& ec) const { - if (ec_) { - *ec_ = ec; - return error_value<T>(); - } - string what = string("in ") + func_name_; - switch (bool(p1_) + bool(p2_)) { - case 0: - __throw_filesystem_error(what, ec); - case 1: - __throw_filesystem_error(what, *p1_, ec); - case 2: - __throw_filesystem_error(what, *p1_, *p2_, ec); - } - __libcpp_unreachable(); - } - - _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 3, 0) - void report_impl(const error_code& ec, const char* msg, va_list ap) const { - if (ec_) { - *ec_ = ec; - return; - } - string what = - string("in ") + func_name_ + ": " + format_string_impl(msg, ap); - switch (bool(p1_) + bool(p2_)) { - case 0: - __throw_filesystem_error(what, ec); - case 1: - __throw_filesystem_error(what, *p1_, ec); - case 2: - __throw_filesystem_error(what, *p1_, *p2_, ec); - } - __libcpp_unreachable(); - } - - _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 3, 4) - T report(const error_code& ec, const char* msg, ...) const { - va_list ap; - va_start(ap, msg); -#ifndef _LIBCPP_NO_EXCEPTIONS - try { -#endif // _LIBCPP_NO_EXCEPTIONS - report_impl(ec, msg, ap); -#ifndef _LIBCPP_NO_EXCEPTIONS - } catch (...) { - va_end(ap); - throw; - } -#endif // _LIBCPP_NO_EXCEPTIONS - va_end(ap); - return error_value<T>(); - } - - T report(errc const& err) const { - return report(make_error_code(err)); - } - - _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 3, 4) - T report(errc const& err, const char* msg, ...) const { - va_list ap; - va_start(ap, msg); -#ifndef _LIBCPP_NO_EXCEPTIONS - try { -#endif // _LIBCPP_NO_EXCEPTIONS - report_impl(make_error_code(err), msg, ap); -#ifndef _LIBCPP_NO_EXCEPTIONS - } catch (...) { - va_end(ap); - throw; - } -#endif // _LIBCPP_NO_EXCEPTIONS - va_end(ap); - return error_value<T>(); - } - -private: - ErrorHandler(ErrorHandler const&) = delete; - ErrorHandler& operator=(ErrorHandler const&) = delete; -}; - -using chrono::duration; -using chrono::duration_cast; - -#if defined(_LIBCPP_WIN32API) // Various C runtime versions (UCRT, or the legacy msvcrt.dll used by // some mingw toolchains) provide different stat function implementations, // with a number of limitations with respect to what we want from the -// stat function. Instead provide our own (in the anonymous detail namespace -// in posix_compat.h) which does exactly what we want, along with our own -// stat structure and flag macros. +// stat function. Instead provide our own which does exactly what we want, +// along with our own stat structure and flag macros. struct TimeSpec { int64_t tv_sec; @@ -276,12 +70,56 @@ struct StatT { uintmax_t st_size; }; +// There were 369 years and 89 leap days from the Windows epoch +// (1601) to the Unix epoch (1970). +#define FILE_TIME_OFFSET_SECS (uint64_t(369 * 365 + 89) * (24 * 60 * 60)) + +inline TimeSpec filetime_to_timespec(LARGE_INTEGER li) { + TimeSpec ret; + ret.tv_sec = li.QuadPart / 10000000 - FILE_TIME_OFFSET_SECS; + ret.tv_nsec = (li.QuadPart % 10000000) * 100; + return ret; +} + +inline TimeSpec filetime_to_timespec(FILETIME ft) { + LARGE_INTEGER li; + li.LowPart = ft.dwLowDateTime; + li.HighPart = ft.dwHighDateTime; + return filetime_to_timespec(li); +} + +inline FILETIME timespec_to_filetime(TimeSpec ts) { + LARGE_INTEGER li; + li.QuadPart = + ts.tv_nsec / 100 + (ts.tv_sec + FILE_TIME_OFFSET_SECS) * 10000000; + FILETIME ft; + ft.dwLowDateTime = li.LowPart; + ft.dwHighDateTime = li.HighPart; + return ft; +} + #else using TimeSpec = struct timespec; using TimeVal = struct timeval; using StatT = struct stat; + +inline TimeVal make_timeval(TimeSpec const& ts) { + using namespace chrono; + auto Convert = [](long nsec) { + using int_type = decltype(std::declval<TimeVal>().tv_usec); + auto dur = duration_cast<microseconds>(nanoseconds(nsec)).count(); + return static_cast<int_type>(dur); + }; + TimeVal TV = {}; + TV.tv_sec = ts.tv_sec; + TV.tv_usec = Convert(ts.tv_nsec); + return TV; +} #endif +using chrono::duration; +using chrono::duration_cast; + template <class FileTimeT, class TimeT, bool IsFloat = is_floating_point<typename FileTimeT::rep>::value> struct time_util_base { @@ -309,7 +147,7 @@ struct time_util_base { .count(); private: - static _LIBCPP_CONSTEXPR_SINCE_CXX14 fs_duration get_min_nsecs() { + static _LIBCPP_CONSTEXPR fs_duration get_min_nsecs() { return duration_cast<fs_duration>( fs_nanoseconds(min_nsec_timespec) - duration_cast<fs_nanoseconds>(fs_seconds(1))); @@ -329,7 +167,9 @@ private: return max_seconds >= numeric_limits<TimeT>::max() && min_seconds <= numeric_limits<TimeT>::min(); } +#if _LIBCPP_STD_VER >= 14 static_assert(check_range(), "the representable range is unacceptable small"); +#endif }; template <class FileTimeT, class TimeT> @@ -489,20 +329,9 @@ inline TimeSpec extract_mtime(StatT const& st) { return st.st_mtim; } inline TimeSpec extract_atime(StatT const& st) { return st.st_atim; } #endif -#if !defined(_LIBCPP_WIN32API) -inline TimeVal make_timeval(TimeSpec const& ts) { - using namespace chrono; - auto Convert = [](long nsec) { - using int_type = decltype(std::declval<TimeVal>().tv_usec); - auto dur = duration_cast<microseconds>(nanoseconds(nsec)).count(); - return static_cast<int_type>(dur); - }; - TimeVal TV = {}; - TV.tv_sec = ts.tv_sec; - TV.tv_usec = Convert(ts.tv_nsec); - return TV; -} +#ifndef _LIBCPP_HAS_NO_FILESYSTEM +#if !defined(_LIBCPP_WIN32API) inline bool posix_utimes(const path& p, std::array<TimeSpec, 2> const& TS, error_code& ec) { TimeVal ConvertedTS[2] = {make_timeval(TS[0]), make_timeval(TS[1])}; @@ -514,8 +343,8 @@ inline bool posix_utimes(const path& p, std::array<TimeSpec, 2> const& TS, } #if defined(_LIBCPP_USE_UTIMENSAT) -bool posix_utimensat(const path& p, std::array<TimeSpec, 2> const& TS, - error_code& ec) { +inline bool posix_utimensat(const path& p, std::array<TimeSpec, 2> const& TS, + error_code& ec) { if (::utimensat(AT_FDCWD, p.c_str(), TS.data(), 0) == -1) { ec = capture_errno(); return true; @@ -524,8 +353,8 @@ bool posix_utimensat(const path& p, std::array<TimeSpec, 2> const& TS, } #endif -bool set_file_times(const path& p, std::array<TimeSpec, 2> const& TS, - error_code& ec) { +inline bool set_file_times(const path& p, std::array<TimeSpec, 2> const& TS, + error_code& ec) { #if !defined(_LIBCPP_USE_UTIMENSAT) return posix_utimes(p, TS, ec); #else @@ -533,81 +362,24 @@ bool set_file_times(const path& p, std::array<TimeSpec, 2> const& TS, #endif } -#if defined(DT_BLK) -template <class DirEntT, class = decltype(DirEntT::d_type)> -static file_type get_file_type(DirEntT* ent, int) { - switch (ent->d_type) { - case DT_BLK: - return file_type::block; - case DT_CHR: - return file_type::character; - case DT_DIR: - return file_type::directory; - case DT_FIFO: - return file_type::fifo; - case DT_LNK: - return file_type::symlink; - case DT_REG: - return file_type::regular; - case DT_SOCK: - return file_type::socket; - // Unlike in lstat, hitting "unknown" here simply means that the underlying - // filesystem doesn't support d_type. Report is as 'none' so we correctly - // set the cache to empty. - case DT_UNKNOWN: - break; - } - return file_type::none; -} -#endif // defined(DT_BLK) +#endif // !_LIBCPP_WIN32API -template <class DirEntT> -static file_type get_file_type(DirEntT*, long) { - return file_type::none; -} +inline file_time_type __extract_last_write_time(const path& p, const StatT& st, + error_code* ec) { + using detail::fs_time; + ErrorHandler<file_time_type> err("last_write_time", ec, &p); -static pair<string_view, file_type> posix_readdir(DIR* dir_stream, - error_code& ec) { - struct dirent* dir_entry_ptr = nullptr; - errno = 0; // zero errno in order to detect errors - ec.clear(); - if ((dir_entry_ptr = ::readdir(dir_stream)) == nullptr) { - if (errno) - ec = capture_errno(); - return {}; - } else { - return {dir_entry_ptr->d_name, get_file_type(dir_entry_ptr, 0)}; - } -} - -#else // _LIBCPP_WIN32API + auto ts = detail::extract_mtime(st); + if (!fs_time::is_representable(ts)) + return err.report(errc::value_too_large); -static file_type get_file_type(const WIN32_FIND_DATAW& data) { - if (data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT && - data.dwReserved0 == IO_REPARSE_TAG_SYMLINK) - return file_type::symlink; - if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - return file_type::directory; - return file_type::regular; -} -static uintmax_t get_file_size(const WIN32_FIND_DATAW& data) { - return (static_cast<uint64_t>(data.nFileSizeHigh) << 32) + data.nFileSizeLow; -} -static file_time_type get_write_time(const WIN32_FIND_DATAW& data) { - ULARGE_INTEGER tmp; - const FILETIME& time = data.ftLastWriteTime; - tmp.u.LowPart = time.dwLowDateTime; - tmp.u.HighPart = time.dwHighDateTime; - return file_time_type(file_time_type::duration(tmp.QuadPart)); + return fs_time::convert_from_timespec(ts); } -#endif // !_LIBCPP_WIN32API +#endif // !_LIBCPP_HAS_NO_FILESYSTEM -} // namespace } // end namespace detail _LIBCPP_END_NAMESPACE_FILESYSTEM -_LIBCPP_DIAGNOSTIC_POP - -#endif // FILESYSTEM_COMMON_H +#endif // FILESYSTEM_TIME_UTILS_H diff --git a/contrib/libs/cxxsupp/libcxx/src/format.cpp b/contrib/libs/cxxsupp/libcxx/src/format.cpp deleted file mode 100644 index 401cccf172..0000000000 --- a/contrib/libs/cxxsupp/libcxx/src/format.cpp +++ /dev/null @@ -1,17 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include <format> - -_LIBCPP_BEGIN_NAMESPACE_STD - -#ifndef _LIBCPP_INLINE_FORMAT_ERROR_DTOR -format_error::~format_error() noexcept = default; -#endif - -_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/future.cpp b/contrib/libs/cxxsupp/libcxx/src/future.cpp index cdaa938275..f8f466bd5a 100644 --- a/contrib/libs/cxxsupp/libcxx/src/future.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/future.cpp @@ -197,12 +197,12 @@ promise<void>::~promise() { if (__state_) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS if (!__state_->__has_value() && __state_->use_count() > 1) __state_->set_exception(make_exception_ptr( future_error(make_error_code(future_errc::broken_promise)) )); -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS __state_->__release_shared(); } } diff --git a/contrib/libs/cxxsupp/libcxx/src/include/apple_availability.h b/contrib/libs/cxxsupp/libcxx/src/include/apple_availability.h index 75bf79658d..c8d158e990 100644 --- a/contrib/libs/cxxsupp/libcxx/src/include/apple_availability.h +++ b/contrib/libs/cxxsupp/libcxx/src/include/apple_availability.h @@ -12,24 +12,6 @@ #if defined(__APPLE__) #if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101300 -#define _LIBCPP_USE_UTIMENSAT -#endif -#elif defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 110000 -#define _LIBCPP_USE_UTIMENSAT -#endif -#elif defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 110000 -#define _LIBCPP_USE_UTIMENSAT -#endif -#elif defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 40000 -#define _LIBCPP_USE_UTIMENSAT -#endif -#endif // __ENVIRONMENT_.*_VERSION_MIN_REQUIRED__ - -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101500 #define _LIBCPP_USE_ULOCK #endif diff --git a/contrib/libs/cxxsupp/libcxx/src/include/config_elast.h b/contrib/libs/cxxsupp/libcxx/src/include/config_elast.h index bef26ec501..a772ea7a01 100644 --- a/contrib/libs/cxxsupp/libcxx/src/include/config_elast.h +++ b/contrib/libs/cxxsupp/libcxx/src/include/config_elast.h @@ -35,8 +35,6 @@ #define _LIBCPP_ELAST 4095 #elif defined(__APPLE__) // No _LIBCPP_ELAST needed on Apple -#elif defined(__sun__) -#define _LIBCPP_ELAST ESTALE #elif defined(__MVS__) #define _LIBCPP_ELAST 1160 #elif defined(_LIBCPP_MSVCRT_LIKE) diff --git a/contrib/libs/cxxsupp/libcxx/src/include/ryu/common.h b/contrib/libs/cxxsupp/libcxx/src/include/ryu/common.h index c24115c233..23cb7d3b77 100644 --- a/contrib/libs/cxxsupp/libcxx/src/include/ryu/common.h +++ b/contrib/libs/cxxsupp/libcxx/src/include/ryu/common.h @@ -43,7 +43,8 @@ // clang-format off #include <__assert> -#include "__config" +#include <__config> +#include <cstring> _LIBCPP_BEGIN_NAMESPACE_STD @@ -51,7 +52,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // Function precondition: __v is not a 10-digit number. // (f2s: 9 digits are sufficient for round-tripping.) // (d2fixed: We print 9-digit blocks.) - _LIBCPP_ASSERT(__v < 1000000000, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__v < 1000000000, ""); if (__v >= 100000000) { return 9; } if (__v >= 10000000) { return 8; } if (__v >= 1000000) { return 7; } @@ -68,36 +69,36 @@ _LIBCPP_BEGIN_NAMESPACE_STD // This approximation works up to the point that the multiplication overflows at __e = 3529. // If the multiplication were done in 64 bits, it would fail at 5^4004 which is just greater // than 2^9297. - _LIBCPP_ASSERT(__e >= 0, ""); - _LIBCPP_ASSERT(__e <= 3528, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__e >= 0, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__e <= 3528, ""); return static_cast<int32_t>(((static_cast<uint32_t>(__e) * 1217359) >> 19) + 1); } // Returns floor(log_10(2^__e)). [[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __log10Pow2(const int32_t __e) { // The first value this approximation fails for is 2^1651 which is just greater than 10^297. - _LIBCPP_ASSERT(__e >= 0, ""); - _LIBCPP_ASSERT(__e <= 1650, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__e >= 0, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__e <= 1650, ""); return (static_cast<uint32_t>(__e) * 78913) >> 18; } // Returns floor(log_10(5^__e)). [[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __log10Pow5(const int32_t __e) { // The first value this approximation fails for is 5^2621 which is just greater than 10^1832. - _LIBCPP_ASSERT(__e >= 0, ""); - _LIBCPP_ASSERT(__e <= 2620, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__e >= 0, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__e <= 2620, ""); return (static_cast<uint32_t>(__e) * 732923) >> 20; } [[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __float_to_bits(const float __f) { uint32_t __bits = 0; - _VSTD::memcpy(&__bits, &__f, sizeof(float)); + std::memcpy(&__bits, &__f, sizeof(float)); return __bits; } [[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint64_t __double_to_bits(const double __d) { uint64_t __bits = 0; - _VSTD::memcpy(&__bits, &__d, sizeof(double)); + std::memcpy(&__bits, &__d, sizeof(double)); return __bits; } diff --git a/contrib/libs/cxxsupp/libcxx/src/include/ryu/d2s_intrinsics.h b/contrib/libs/cxxsupp/libcxx/src/include/ryu/d2s_intrinsics.h index 762763f9b9..7697c32ff6 100644 --- a/contrib/libs/cxxsupp/libcxx/src/include/ryu/d2s_intrinsics.h +++ b/contrib/libs/cxxsupp/libcxx/src/include/ryu/d2s_intrinsics.h @@ -63,7 +63,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // (The shift value is in the range [49, 58].) // Check this here in case a future change requires larger shift // values. In this case this function needs to be adjusted. - _LIBCPP_ASSERT(__dist < 64, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__dist < 64, ""); return __shiftright128(__lo, __hi, static_cast<unsigned char>(__dist)); } @@ -85,7 +85,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // (The shift value is in the range [49, 58].) // Check this here in case a future change requires larger shift // values. In this case this function needs to be adjusted. - _LIBCPP_ASSERT(__dist < 64, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__dist < 64, ""); auto __temp = __lo | ((unsigned __int128)__hi << 64); // For x64 128-bit shfits using the `shrd` instruction and two 64-bit // registers, the shift value is modulo 64. Thus the `& 63` is free. @@ -126,13 +126,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD [[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint64_t __ryu_shiftright128(const uint64_t __lo, const uint64_t __hi, const uint32_t __dist) { // We don't need to handle the case __dist >= 64 here (see above). - _LIBCPP_ASSERT(__dist < 64, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__dist < 64, ""); #ifdef _LIBCPP_64_BIT - _LIBCPP_ASSERT(__dist > 0, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__dist > 0, ""); return (__hi << (64 - __dist)) | (__lo >> __dist); #else // ^^^ 64-bit ^^^ / vvv 32-bit vvv // Avoid a 64-bit shift by taking advantage of the range of shift values. - _LIBCPP_ASSERT(__dist >= 32, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__dist >= 32, ""); return (__hi << (64 - __dist)) | (static_cast<uint32_t>(__lo >> 32) >> (__dist - 32)); #endif // ^^^ 32-bit ^^^ } @@ -227,7 +227,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD [[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __pow5Factor(uint64_t __value) { uint32_t __count = 0; for (;;) { - _LIBCPP_ASSERT(__value != 0, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__value != 0, ""); const uint64_t __q = __div5(__value); const uint32_t __r = static_cast<uint32_t>(__value) - 5 * static_cast<uint32_t>(__q); if (__r != 0) { @@ -247,8 +247,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD // Returns true if __value is divisible by 2^__p. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline bool __multipleOfPowerOf2(const uint64_t __value, const uint32_t __p) { - _LIBCPP_ASSERT(__value != 0, ""); - _LIBCPP_ASSERT(__p < 64, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__value != 0, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__p < 64, ""); // __builtin_ctzll doesn't appear to be faster here. return (__value & ((1ull << __p) - 1)) == 0; } diff --git a/contrib/libs/cxxsupp/libcxx/src/include/ryu/ryu.h b/contrib/libs/cxxsupp/libcxx/src/include/ryu/ryu.h index cb44bd3fef..3f4afa5d60 100644 --- a/contrib/libs/cxxsupp/libcxx/src/include/ryu/ryu.h +++ b/contrib/libs/cxxsupp/libcxx/src/include/ryu/ryu.h @@ -47,8 +47,7 @@ #include <__charconv/chars_format.h> #include <__charconv/to_chars_result.h> #include <__config> -#include <__debug> -#include <__errc> +#include <__system_error/errc.h> #include <cstdint> #include <cstring> #include <type_traits> diff --git a/contrib/libs/cxxsupp/libcxx/src/include/to_chars_floating_point.h b/contrib/libs/cxxsupp/libcxx/src/include/to_chars_floating_point.h index b99d790f65..e2409338b9 100644 --- a/contrib/libs/cxxsupp/libcxx/src/include/to_chars_floating_point.h +++ b/contrib/libs/cxxsupp/libcxx/src/include/to_chars_floating_point.h @@ -269,7 +269,7 @@ to_chars_result _Floating_to_chars_hex_precision( // * Print the leading hexit, then mask it away. { const uint32_t _Nibble = static_cast<uint32_t>(_Adjusted_mantissa >> _Adjusted_explicit_bits); - _LIBCPP_ASSERT(_Nibble < 3, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(_Nibble < 3, ""); const char _Leading_hexit = static_cast<char>('0' + _Nibble); *_First++ = _Leading_hexit; @@ -288,12 +288,12 @@ to_chars_result _Floating_to_chars_hex_precision( int32_t _Number_of_bits_remaining = _Adjusted_explicit_bits; // 24 for float, 52 for double for (;;) { - _LIBCPP_ASSERT(_Number_of_bits_remaining >= 4, ""); - _LIBCPP_ASSERT(_Number_of_bits_remaining % 4 == 0, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(_Number_of_bits_remaining >= 4, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(_Number_of_bits_remaining % 4 == 0, ""); _Number_of_bits_remaining -= 4; const uint32_t _Nibble = static_cast<uint32_t>(_Adjusted_mantissa >> _Number_of_bits_remaining); - _LIBCPP_ASSERT(_Nibble < 16, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(_Nibble < 16, ""); const char _Hexit = __itoa::_Charconv_digits[_Nibble]; *_First++ = _Hexit; @@ -415,12 +415,12 @@ to_chars_result _Floating_to_chars_hex_shortest( // '0' hexits, the same condition works (as we print the final hexit and mask it away); we don't need to test // _Number_of_bits_remaining. do { - _LIBCPP_ASSERT(_Number_of_bits_remaining >= 4, ""); - _LIBCPP_ASSERT(_Number_of_bits_remaining % 4 == 0, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(_Number_of_bits_remaining >= 4, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(_Number_of_bits_remaining % 4 == 0, ""); _Number_of_bits_remaining -= 4; const uint32_t _Nibble = static_cast<uint32_t>(_Adjusted_mantissa >> _Number_of_bits_remaining); - _LIBCPP_ASSERT(_Nibble < 16, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(_Nibble < 16, ""); const char _Hexit = __itoa::_Charconv_digits[_Nibble]; if (_First == _Last) { @@ -940,13 +940,13 @@ to_chars_result _Floating_to_chars_general_precision( _Effective_precision = _VSTD::min(_Precision - (_Scientific_exponent_X + 1), _Max_fixed_precision); const to_chars_result _Buf_result = _Floating_to_chars_fixed_precision(_Buffer, _VSTD::end(_Buffer), _Value, _Effective_precision); - _LIBCPP_ASSERT(_Buf_result.ec == errc{}, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(_Buf_result.ec == errc{}, ""); _Significand_last = _Buf_result.ptr; } else { _Effective_precision = _VSTD::min(_Precision - 1, _Max_scientific_precision); const to_chars_result _Buf_result = _Floating_to_chars_scientific_precision(_Buffer, _VSTD::end(_Buffer), _Value, _Effective_precision); - _LIBCPP_ASSERT(_Buf_result.ec == errc{}, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(_Buf_result.ec == errc{}, ""); _Significand_last = _VSTD::find(_Buffer, _Buf_result.ptr, 'e'); _Exponent_first = _Significand_last; _Exponent_last = _Buf_result.ptr; @@ -992,10 +992,10 @@ to_chars_result _Floating_to_chars( char* _First, char* const _Last, _Floating _Value, const chars_format _Fmt, const int _Precision) noexcept { if constexpr (_Overload == _Floating_to_chars_overload::_Plain) { - _LIBCPP_ASSERT(_Fmt == chars_format{}, ""); // plain overload must pass chars_format{} internally + _LIBCPP_ASSERT_UNCATEGORIZED(_Fmt == chars_format{}, ""); // plain overload must pass chars_format{} internally } else { - _LIBCPP_ASSERT(_Fmt == chars_format::general || _Fmt == chars_format::scientific || _Fmt == chars_format::fixed - || _Fmt == chars_format::hex, + _LIBCPP_ASSERT_UNCATEGORIZED(_Fmt == chars_format::general || _Fmt == chars_format::scientific + || _Fmt == chars_format::fixed || _Fmt == chars_format::hex, "invalid format in to_chars()"); } diff --git a/contrib/libs/cxxsupp/libcxx/src/ios.cpp b/contrib/libs/cxxsupp/libcxx/src/ios.cpp index 870406b554..bb62eb9948 100644 --- a/contrib/libs/cxxsupp/libcxx/src/ios.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/ios.cpp @@ -413,20 +413,20 @@ void ios_base::__set_badbit_and_consider_rethrow() { __rdstate_ |= badbit; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS if (__exceptions_ & badbit) throw; -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } void ios_base::__set_failbit_and_consider_rethrow() { __rdstate_ |= failbit; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS if (__exceptions_ & failbit) throw; -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } bool diff --git a/contrib/libs/cxxsupp/libcxx/src/ios.instantiations.cpp b/contrib/libs/cxxsupp/libcxx/src/ios.instantiations.cpp index ca77ce11fd..01fe199acb 100644 --- a/contrib/libs/cxxsupp/libcxx/src/ios.instantiations.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/ios.instantiations.cpp @@ -37,7 +37,7 @@ template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_stringstream<char> template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ostringstream<char>; template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_istringstream<char>; -#ifndef _LIBCPP_HAS_NO_FSTREAM +#ifndef _LIBCPP_HAS_NO_FILESYSTEM template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ifstream<char>; template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ofstream<char>; template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_filebuf<char>; diff --git a/contrib/libs/cxxsupp/libcxx/src/iostream.cpp b/contrib/libs/cxxsupp/libcxx/src/iostream.cpp index 79dbd9a52b..b0686c9099 100644 --- a/contrib/libs/cxxsupp/libcxx/src/iostream.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/iostream.cpp @@ -7,10 +7,14 @@ //===----------------------------------------------------------------------===// #include <__locale> -#include <__std_stream> +#include "std_stream.h" #include <new> #include <string> +#ifdef _LIBCPP_MSVCRT_LIKE +# include <__locale_dir/locale_base_api/locale_guard.h> +#endif + #define _str(s) #s #define str(s) _str(s) #define _LIBCPP_ABI_NAMESPACE_STR str(_LIBCPP_ABI_NAMESPACE) @@ -19,9 +23,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if defined(_LIBCPP_ABI_MICROSOFT) && !defined(__clang__) _ALIGNAS_TYPE (istream) char _cin [sizeof(istream)]; -_LIBCPP_FUNC_VIS istream& cin = *reinterpret_cast<istream*>(_cin); +_LIBCPP_EXPORTED_FROM_ABI istream& cin = *reinterpret_cast<istream*>(_cin); #else -_ALIGNAS_TYPE (istream) _LIBCPP_FUNC_VIS char cin[sizeof(istream)] +_ALIGNAS_TYPE (istream) _LIBCPP_EXPORTED_FROM_ABI char cin[sizeof(istream)] #if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) __asm__("?cin@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_istream@DU?$char_traits@D@" _LIBCPP_ABI_NAMESPACE_STR "@std@@@12@A") #endif @@ -33,9 +37,9 @@ static mbstate_t mb_cin; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS #if defined(_LIBCPP_ABI_MICROSOFT) && !defined(__clang__) _ALIGNAS_TYPE (wistream) char _wcin [sizeof(wistream)]; -_LIBCPP_FUNC_VIS wistream& wcin = *reinterpret_cast<wistream*>(_wcin); +_LIBCPP_EXPORTED_FROM_ABI wistream& wcin = *reinterpret_cast<wistream*>(_wcin); #else -_ALIGNAS_TYPE (wistream) _LIBCPP_FUNC_VIS char wcin[sizeof(wistream)] +_ALIGNAS_TYPE (wistream) _LIBCPP_EXPORTED_FROM_ABI char wcin[sizeof(wistream)] #if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) __asm__("?wcin@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_istream@_WU?$char_traits@_W@" _LIBCPP_ABI_NAMESPACE_STR "@std@@@12@A") #endif @@ -47,9 +51,9 @@ static mbstate_t mb_wcin; #if defined(_LIBCPP_ABI_MICROSOFT) && !defined(__clang__) _ALIGNAS_TYPE (ostream) char _cout[sizeof(ostream)]; -_LIBCPP_FUNC_VIS ostream& cout = *reinterpret_cast<ostream*>(_cout); +_LIBCPP_EXPORTED_FROM_ABI ostream& cout = *reinterpret_cast<ostream*>(_cout); #else -_ALIGNAS_TYPE (ostream) _LIBCPP_FUNC_VIS char cout[sizeof(ostream)] +_ALIGNAS_TYPE (ostream) _LIBCPP_EXPORTED_FROM_ABI char cout[sizeof(ostream)] #if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) __asm__("?cout@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_ostream@DU?$char_traits@D@" _LIBCPP_ABI_NAMESPACE_STR "@std@@@12@A") #endif @@ -61,9 +65,9 @@ static mbstate_t mb_cout; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS #if defined(_LIBCPP_ABI_MICROSOFT) && !defined(__clang__) _ALIGNAS_TYPE (wostream) char _wcout[sizeof(wostream)]; -_LIBCPP_FUNC_VIS wostream& wcout = *reinterpret_cast<wostream*>(_wcout); +_LIBCPP_EXPORTED_FROM_ABI wostream& wcout = *reinterpret_cast<wostream*>(_wcout); #else -_ALIGNAS_TYPE (wostream) _LIBCPP_FUNC_VIS char wcout[sizeof(wostream)] +_ALIGNAS_TYPE (wostream) _LIBCPP_EXPORTED_FROM_ABI char wcout[sizeof(wostream)] #if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) __asm__("?wcout@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_ostream@_WU?$char_traits@_W@" _LIBCPP_ABI_NAMESPACE_STR "@std@@@12@A") #endif @@ -75,9 +79,9 @@ static mbstate_t mb_wcout; #if defined(_LIBCPP_ABI_MICROSOFT) && !defined(__clang__) _ALIGNAS_TYPE (ostream) char _cerr[sizeof(ostream)]; -_LIBCPP_FUNC_VIS ostream& cerr = *reinterpret_cast<ostream*>(_cerr); +_LIBCPP_EXPORTED_FROM_ABI ostream& cerr = *reinterpret_cast<ostream*>(_cerr); #else -_ALIGNAS_TYPE (ostream) _LIBCPP_FUNC_VIS char cerr[sizeof(ostream)] +_ALIGNAS_TYPE (ostream) _LIBCPP_EXPORTED_FROM_ABI char cerr[sizeof(ostream)] #if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) __asm__("?cerr@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_ostream@DU?$char_traits@D@" _LIBCPP_ABI_NAMESPACE_STR "@std@@@12@A") #endif @@ -89,9 +93,9 @@ static mbstate_t mb_cerr; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS #if defined(_LIBCPP_ABI_MICROSOFT) && !defined(__clang__) _ALIGNAS_TYPE (wostream) char _wcerr[sizeof(wostream)]; -_LIBCPP_FUNC_VIS wostream& wcerr = *reinterpret_cast<wostream*>(_wcerr); +_LIBCPP_EXPORTED_FROM_ABI wostream& wcerr = *reinterpret_cast<wostream*>(_wcerr); #else -_ALIGNAS_TYPE (wostream) _LIBCPP_FUNC_VIS char wcerr[sizeof(wostream)] +_ALIGNAS_TYPE (wostream) _LIBCPP_EXPORTED_FROM_ABI char wcerr[sizeof(wostream)] #if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) __asm__("?wcerr@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_ostream@_WU?$char_traits@_W@" _LIBCPP_ABI_NAMESPACE_STR "@std@@@12@A") #endif @@ -103,9 +107,9 @@ static mbstate_t mb_wcerr; #if defined(_LIBCPP_ABI_MICROSOFT) && !defined(__clang__) _ALIGNAS_TYPE (ostream) char _clog[sizeof(ostream)]; -_LIBCPP_FUNC_VIS ostream& clog = *reinterpret_cast<ostream*>(_clog); +_LIBCPP_EXPORTED_FROM_ABI ostream& clog = *reinterpret_cast<ostream*>(_clog); #else -_ALIGNAS_TYPE (ostream) _LIBCPP_FUNC_VIS char clog[sizeof(ostream)] +_ALIGNAS_TYPE (ostream) _LIBCPP_EXPORTED_FROM_ABI char clog[sizeof(ostream)] #if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) __asm__("?clog@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_ostream@DU?$char_traits@D@" _LIBCPP_ABI_NAMESPACE_STR "@std@@@12@A") #endif @@ -115,9 +119,9 @@ __asm__("?clog@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_ostream@DU?$char_tra #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS #if defined(_LIBCPP_ABI_MICROSOFT) && !defined(__clang__) _ALIGNAS_TYPE (wostream) char _wclog[sizeof(wostream)]; -_LIBCPP_FUNC_VIS wostream& wclog = *reinterpret_cast<wostream*>(_wclog); +_LIBCPP_EXPORTED_FROM_ABI wostream& wclog = *reinterpret_cast<wostream*>(_wclog); #else -_ALIGNAS_TYPE (wostream) _LIBCPP_FUNC_VIS char wclog[sizeof(wostream)] +_ALIGNAS_TYPE (wostream) _LIBCPP_EXPORTED_FROM_ABI char wclog[sizeof(wostream)] #if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) __asm__("?wclog@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_ostream@_WU?$char_traits@_W@" _LIBCPP_ABI_NAMESPACE_STR "@std@@@12@A") #endif diff --git a/contrib/libs/cxxsupp/libcxx/src/legacy_pointer_safety.cpp b/contrib/libs/cxxsupp/libcxx/src/legacy_pointer_safety.cpp index 5d2b04c121..a9361ca879 100644 --- a/contrib/libs/cxxsupp/libcxx/src/legacy_pointer_safety.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/legacy_pointer_safety.cpp @@ -15,9 +15,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD -_LIBCPP_FUNC_VIS void declare_reachable(void*) {} -_LIBCPP_FUNC_VIS void declare_no_pointers(char*, size_t) {} -_LIBCPP_FUNC_VIS void undeclare_no_pointers(char*, size_t) {} -_LIBCPP_FUNC_VIS void* __undeclare_reachable(void* p) { return p; } +_LIBCPP_EXPORTED_FROM_ABI void declare_reachable(void*) {} +_LIBCPP_EXPORTED_FROM_ABI void declare_no_pointers(char*, size_t) {} +_LIBCPP_EXPORTED_FROM_ABI void undeclare_no_pointers(char*, size_t) {} +_LIBCPP_EXPORTED_FROM_ABI void* __undeclare_reachable(void* p) { return p; } _LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/locale.cpp b/contrib/libs/cxxsupp/libcxx/src/locale.cpp index c756c6fadf..e274ede995 100644 --- a/contrib/libs/cxxsupp/libcxx/src/locale.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/locale.cpp @@ -6,13 +6,8 @@ // //===----------------------------------------------------------------------===// -// On Solaris, we need to define something to make the C99 parts of localeconv -// visible. -#ifdef __sun__ -#define _LCONV_C99 -#endif - #include <__utility/unreachable.h> +#include <__verbose_abort> #include <algorithm> #include <clocale> #include <codecvt> @@ -118,16 +113,27 @@ countof(const T * const begin, const T * const end) _LIBCPP_NORETURN static void __throw_runtime_error(const string &msg) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw runtime_error(msg); #else - (void)msg; - _VSTD::abort(); + _LIBCPP_VERBOSE_ABORT("runtime_error was thrown in -fno-exceptions mode with message \"%s\"", msg.c_str()); #endif } } +string +build_name(const string& other, const string& one, locale::category c) { + if (other == "*" || one == "*") + return "*"; + if (c == locale::none || other == one) + return other; + + // FIXME: Handle the more complicated cases, such as when the locale has + // different names for different categories. + return "*"; +} + const locale::category locale::none; const locale::category locale::collate; const locale::category locale::ctype; @@ -236,10 +242,10 @@ locale::__imp::__imp(const string& name, size_t refs) facets_(N), name_(name) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS facets_ = locale::classic().__locale_->facets_; for (unsigned i = 0; i < facets_.size(); ++i) if (facets_[i]) @@ -286,7 +292,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS install(new messages_byname<wchar_t>(name_)); #endif -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -295,7 +301,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP facets_[i]->__release_shared(); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } locale::__imp::__imp(const __imp& other) @@ -309,17 +315,16 @@ locale::__imp::__imp(const __imp& other) } locale::__imp::__imp(const __imp& other, const string& name, locale::category c) - : facets_(N), - name_("*") + : facets_(N), name_(build_name(other.name_, name, c)) { facets_ = other.facets_; for (unsigned i = 0; i < facets_.size(); ++i) if (facets_[i]) facets_[i]->__add_shared(); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS if (c & locale::collate) { install(new collate_byname<char>(name)); @@ -380,7 +385,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP install(new messages_byname<wchar_t>(name)); #endif } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -389,7 +394,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP facets_[i]->__release_shared(); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } template<class F> @@ -402,17 +407,16 @@ locale::__imp::install_from(const locale::__imp& one) } locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c) - : facets_(N), - name_("*") + : facets_(N), name_(build_name(other.name_, one.name_, c)) { facets_ = other.facets_; for (unsigned i = 0; i < facets_.size(); ++i) if (facets_[i]) facets_[i]->__add_shared(); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS if (c & locale::collate) { install_from<_VSTD::collate<char> >(one); @@ -489,7 +493,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP install_from<_VSTD::messages<wchar_t> >(one); #endif } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -498,7 +502,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP facets_[i]->__release_shared(); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } locale::__imp::__imp(const __imp& other, facet* f, long id) @@ -1197,8 +1201,6 @@ ctype<char>::classic_table() noexcept return _C_ctype_tab_ + 1; #elif defined(__GLIBC__) return _LIBCPP_GET_C_LOCALE->__ctype_b; -#elif defined(__sun__) - return __ctype_mask; #elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) return __pctype_func(); #elif defined(__EMSCRIPTEN__) @@ -1421,10 +1423,8 @@ ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* if (iswxdigit_l(ch, __l_)) *vec |= xdigit; #endif -#if !defined(__sun__) if (iswblank_l(ch, __l_)) *vec |= blank; -#endif } } return low; @@ -6556,11 +6556,10 @@ void __do_nothing(void*) {} void __throw_runtime_error(const char* msg) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw runtime_error(msg); #else - (void)msg; - _VSTD::abort(); + _LIBCPP_VERBOSE_ABORT("runtime_error was thrown in -fno-exceptions mode with message \"%s\"", msg); #endif } diff --git a/contrib/libs/cxxsupp/libcxx/src/memory.cpp b/contrib/libs/cxxsupp/libcxx/src/memory.cpp index 9c0ee5d6f3..4682f1267a 100644 --- a/contrib/libs/cxxsupp/libcxx/src/memory.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/memory.cpp @@ -29,8 +29,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD -const allocator_arg_t allocator_arg = allocator_arg_t(); - bad_weak_ptr::~bad_weak_ptr() noexcept {} const char* diff --git a/contrib/libs/cxxsupp/libcxx/src/memory_resource.cpp b/contrib/libs/cxxsupp/libcxx/src/memory_resource.cpp index e00611dd1c..3a80b84efa 100644 --- a/contrib/libs/cxxsupp/libcxx/src/memory_resource.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/memory_resource.cpp @@ -37,7 +37,7 @@ static bool is_aligned_to(void* ptr, size_t align) { } #endif -class _LIBCPP_TYPE_VIS __new_delete_memory_resource_imp : public memory_resource { +class _LIBCPP_EXPORTED_FROM_ABI __new_delete_memory_resource_imp : public memory_resource { void* do_allocate(size_t bytes, size_t align) override { #ifndef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION return std::__libcpp_allocate(bytes, align); @@ -60,7 +60,7 @@ class _LIBCPP_TYPE_VIS __new_delete_memory_resource_imp : public memory_resource // null_memory_resource() -class _LIBCPP_TYPE_VIS __null_memory_resource_imp : public memory_resource { +class _LIBCPP_EXPORTED_FROM_ABI __null_memory_resource_imp : public memory_resource { void* do_allocate(size_t, size_t) override { __throw_bad_alloc(); } void do_deallocate(void*, size_t, size_t) override {} bool do_is_equal(const memory_resource& other) const noexcept override { return &other == this; } @@ -107,7 +107,7 @@ static memory_resource* __default_memory_resource(bool set = false, memory_resou new_res = new_res ? new_res : new_delete_resource(); lock_guard<mutex> guard(res_lock); memory_resource* old_res = res; - res = new_res; + res = new_res; return old_res; } else { lock_guard<mutex> guard(res_lock); @@ -175,7 +175,7 @@ void* unsynchronized_pool_resource::__adhoc_pool::__do_allocate(memory_resource* void unsynchronized_pool_resource::__adhoc_pool::__do_deallocate( memory_resource* upstream, void* p, size_t bytes, size_t align) { - _LIBCPP_ASSERT(__first_ != nullptr, "deallocating a block that was not allocated with this allocator"); + _LIBCPP_ASSERT_UNCATEGORIZED(__first_ != nullptr, "deallocating a block that was not allocated with this allocator"); if (__first_->__start_ == p) { __chunk_footer* next = __first_->__next_; upstream->deallocate(p, __first_->__allocation_size(), __first_->__align_); @@ -189,7 +189,7 @@ void unsynchronized_pool_resource::__adhoc_pool::__do_deallocate( return; } } - _LIBCPP_ASSERT(false, "deallocating a block that was not allocated with this allocator"); + _LIBCPP_ASSERT_UNCATEGORIZED(false, "deallocating a block that was not allocated with this allocator"); } } @@ -230,7 +230,7 @@ public: } void* __allocate_in_new_chunk(memory_resource* upstream, size_t block_size, size_t chunk_size) { - _LIBCPP_ASSERT(chunk_size % block_size == 0, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(chunk_size % block_size == 0, ""); static_assert(__default_alignment >= alignof(std::max_align_t), ""); static_assert(__default_alignment >= alignof(__chunk_footer), ""); static_assert(__default_alignment >= alignof(__vacancy_header), ""); @@ -401,7 +401,8 @@ void unsynchronized_pool_resource::do_deallocate(void* p, size_t bytes, size_t a if (i == __num_fixed_pools_) return __adhoc_pool_.__do_deallocate(__res_, p, bytes, align); else { - _LIBCPP_ASSERT(__fixed_pools_ != nullptr, "deallocating a block that was not allocated with this allocator"); + _LIBCPP_ASSERT_UNCATEGORIZED( + __fixed_pools_ != nullptr, "deallocating a block that was not allocated with this allocator"); __fixed_pools_[i].__evacuate(p); } } diff --git a/contrib/libs/cxxsupp/libcxx/src/mutex.cpp b/contrib/libs/cxxsupp/libcxx/src/mutex.cpp index f738cc013b..e304b97e6e 100644 --- a/contrib/libs/cxxsupp/libcxx/src/mutex.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/mutex.cpp @@ -7,9 +7,9 @@ //===----------------------------------------------------------------------===// #include <__assert> +#include <__thread/id.h> #include <limits> #include <mutex> -#include <system_error> #if !defined(_LIBCPP_ABI_MICROSOFT) #include "include/atomic_support.h" @@ -28,10 +28,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD #ifndef _LIBCPP_HAS_NO_THREADS -const defer_lock_t defer_lock{}; -const try_to_lock_t try_to_lock{}; -const adopt_lock_t adopt_lock{}; - // ~mutex is defined elsewhere void @@ -53,7 +49,7 @@ mutex::unlock() noexcept { int ec = __libcpp_mutex_unlock(&__m_); (void)ec; - _LIBCPP_ASSERT(ec == 0, "call to mutex::unlock failed"); + _LIBCPP_ASSERT_UNCATEGORIZED(ec == 0, "call to mutex::unlock failed"); } // recursive_mutex @@ -69,7 +65,7 @@ recursive_mutex::~recursive_mutex() { int e = __libcpp_recursive_mutex_destroy(&__m_); (void)e; - _LIBCPP_ASSERT(e == 0, "call to ~recursive_mutex() failed"); + _LIBCPP_ASSERT_UNCATEGORIZED(e == 0, "call to ~recursive_mutex() failed"); } void @@ -85,7 +81,7 @@ recursive_mutex::unlock() noexcept { int e = __libcpp_recursive_mutex_unlock(&__m_); (void)e; - _LIBCPP_ASSERT(e == 0, "call to recursive_mutex::unlock() failed"); + _LIBCPP_ASSERT_UNCATEGORIZED(e == 0, "call to recursive_mutex::unlock() failed"); } bool @@ -218,21 +214,21 @@ void __call_once(volatile once_flag::_State_type& flag, void* arg, #if defined(_LIBCPP_HAS_NO_THREADS) if (flag == 0) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS flag = 1; func(arg); flag = ~once_flag::_State_type(0); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { flag = 0; throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } #else // !_LIBCPP_HAS_NO_THREADS __libcpp_mutex_lock(&mut); @@ -240,10 +236,10 @@ void __call_once(volatile once_flag::_State_type& flag, void* arg, __libcpp_condvar_wait(&cv, &mut); if (flag == 0) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS #ifdef _LIBCPP_ABI_MICROSOFT flag.store(once_flag::_State_type(1)); #else @@ -260,7 +256,7 @@ void __call_once(volatile once_flag::_State_type& flag, void* arg, #endif __libcpp_mutex_unlock(&mut); __libcpp_condvar_broadcast(&cv); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -274,7 +270,7 @@ void __call_once(volatile once_flag::_State_type& flag, void* arg, __libcpp_condvar_broadcast(&cv); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } else __libcpp_mutex_unlock(&mut); diff --git a/contrib/libs/cxxsupp/libcxx/src/mutex_destructor.cpp b/contrib/libs/cxxsupp/libcxx/src/mutex_destructor.cpp index 6850b6e6f4..d366a4e1b3 100644 --- a/contrib/libs/cxxsupp/libcxx/src/mutex_destructor.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/mutex_destructor.cpp @@ -28,7 +28,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #ifdef NEEDS_MUTEX_DESTRUCTOR -class _LIBCPP_TYPE_VIS mutex +class _LIBCPP_EXPORTED_FROM_ABI mutex { __libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER; diff --git a/contrib/libs/cxxsupp/libcxx/src/new.cpp b/contrib/libs/cxxsupp/libcxx/src/new.cpp index 4351923cb5..6d5b221198 100644 --- a/contrib/libs/cxxsupp/libcxx/src/new.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/new.cpp @@ -6,53 +6,16 @@ // //===----------------------------------------------------------------------===// +#include <__memory/aligned_alloc.h> +#include <cstdlib> #include <new> -#include <stdlib.h> -#include "include/atomic_support.h" +#if !defined(__GLIBCXX__) && !defined(_LIBCPP_ABI_VCRUNTIME) -#if defined(_LIBCPP_ABI_MICROSOFT) -# if !defined(_LIBCPP_ABI_VCRUNTIME) -# include "support/runtime/new_handler_fallback.ipp" -# endif -#elif defined(LIBCXX_BUILDING_LIBCXXABI) -# include <cxxabi.h> -#elif defined(LIBCXX_BUILDING_LIBCXXRT) -# include <cxxabi.h> -# include "support/runtime/new_handler_fallback.ipp" -#elif defined(__GLIBCXX__) - // nothing to do -#else -# include "support/runtime/new_handler_fallback.ipp" -#endif - -namespace std -{ - -#ifndef __GLIBCXX__ -const nothrow_t nothrow{}; -#endif - -#ifndef LIBSTDCXX - -void -__throw_bad_alloc() -{ -#ifndef _LIBCPP_NO_EXCEPTIONS - throw bad_alloc(); -#else - _VSTD::abort(); -#endif -} - -#endif // !LIBSTDCXX - -} // std - -#if !defined(__GLIBCXX__) && \ - !defined(_LIBCPP_ABI_VCRUNTIME) && \ - !defined(_LIBCPP_DISABLE_NEW_DELETE_DEFINITIONS) +// The code below is copied as-is into libc++abi's libcxxabi/src/stdlib_new_delete.cpp +// file. The version in this file is the canonical one. +// ------------------ BEGIN COPY ------------------ // Implement all new and delete operators as weak definitions // in this shared library, so that they can be overridden by programs // that define non-weak copies of the functions. @@ -64,7 +27,7 @@ operator new(std::size_t size) _THROW_BAD_ALLOC if (size == 0) size = 1; void* p; - while ((p = ::malloc(size)) == nullptr) + while ((p = std::malloc(size)) == nullptr) { // If malloc fails and there is a new_handler, // call it to try free up memory. @@ -72,7 +35,7 @@ operator new(std::size_t size) _THROW_BAD_ALLOC if (nh) nh(); else -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw std::bad_alloc(); #else #ifdef __EMSCRIPTEN__ @@ -95,17 +58,17 @@ void* operator new(size_t size, const std::nothrow_t&) noexcept { void* p = nullptr; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS p = ::operator new(size); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return p; } @@ -121,17 +84,17 @@ void* operator new[](size_t size, const std::nothrow_t&) noexcept { void* p = nullptr; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS p = ::operator new[](size); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return p; } @@ -139,7 +102,7 @@ _LIBCPP_WEAK void operator delete(void* ptr) noexcept { - ::free(ptr); + std::free(ptr); } _LIBCPP_WEAK @@ -201,7 +164,7 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC if (nh) nh(); else { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw std::bad_alloc(); #else break; @@ -216,17 +179,17 @@ void* operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept { void* p = nullptr; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS p = ::operator new(size, alignment); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return p; } @@ -242,17 +205,17 @@ void* operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept { void* p = nullptr; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS p = ::operator new[](size, alignment); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return p; } @@ -299,4 +262,6 @@ operator delete[] (void* ptr, size_t, std::align_val_t alignment) noexcept } #endif // !_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION -#endif // !__GLIBCXX__ && !_LIBCPP_ABI_VCRUNTIME && !_LIBCPP_DISABLE_NEW_DELETE_DEFINITIONS +// ------------------ END COPY ------------------ + +#endif // !__GLIBCXX__ && !_LIBCPP_ABI_VCRUNTIME diff --git a/contrib/libs/cxxsupp/libcxx/src/new_handler.cpp b/contrib/libs/cxxsupp/libcxx/src/new_handler.cpp new file mode 100644 index 0000000000..49c21d85f5 --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/src/new_handler.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include <new> + +#include "include/atomic_support.h" + +#if defined(_LIBCPP_ABI_MICROSOFT) +# if !defined(_LIBCPP_ABI_VCRUNTIME) +# define _LIBPCPP_DEFINE_NEW_HANDLER +# endif +#elif defined(LIBCXX_BUILDING_LIBCXXABI) +// nothing to do, we use the one from libc++abi +#elif defined(LIBCXXRT) +# define _LIBPCPP_DEFINE_NEW_HANDLER +#elif defined(__GLIBCXX__) +// nothing to do, we use the one from libstdc++/libsupc++ +#else +# define _LIBPCPP_DEFINE_NEW_HANDLER +#endif + +#if defined(_LIBPCPP_DEFINE_NEW_HANDLER) + +namespace std { // purposefully not versioned + +static constinit std::new_handler __new_handler = nullptr; + +new_handler set_new_handler(new_handler handler) noexcept { return __libcpp_atomic_exchange(&__new_handler, handler); } + +new_handler get_new_handler() noexcept { return __libcpp_atomic_load(&__new_handler); } + +} // namespace std + +#endif // _LIBPCPP_DEFINE_NEW_HANDLER diff --git a/contrib/libs/cxxsupp/libcxx/src/support/runtime/new_handler_fallback.ipp b/contrib/libs/cxxsupp/libcxx/src/new_helpers.cpp index 2ec408327d..45a0a661db 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/runtime/new_handler_fallback.ipp +++ b/contrib/libs/cxxsupp/libcxx/src/new_helpers.cpp @@ -1,4 +1,3 @@ -// -*- C++ -*- //===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. @@ -7,20 +6,25 @@ // //===----------------------------------------------------------------------===// -namespace std { +#include <cstdlib> +#include <new> -static constinit std::new_handler __new_handler = nullptr; +namespace std { // purposefully not versioned -new_handler -set_new_handler(new_handler handler) noexcept -{ - return __libcpp_atomic_exchange(&__new_handler, handler); -} +#ifndef __GLIBCXX__ +const nothrow_t nothrow{}; +#endif + +#ifndef LIBSTDCXX -new_handler -get_new_handler() noexcept -{ - return __libcpp_atomic_load(&__new_handler); +void __throw_bad_alloc() { +# ifndef _LIBCPP_HAS_NO_EXCEPTIONS + throw bad_alloc(); +# else + std::abort(); +# endif } +#endif // !LIBSTDCXX + } // namespace std diff --git a/contrib/libs/cxxsupp/libcxx/src/optional.cpp b/contrib/libs/cxxsupp/libcxx/src/optional.cpp index e2b5ccef99..d0214981a2 100644 --- a/contrib/libs/cxxsupp/libcxx/src/optional.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/optional.cpp @@ -27,7 +27,7 @@ const char* bad_optional_access::what() const noexcept { // Even though it no longer exists in a header file _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL -class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access +class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access : public std::logic_error { public: diff --git a/contrib/libs/cxxsupp/libcxx/src/print.cpp b/contrib/libs/cxxsupp/libcxx/src/print.cpp new file mode 100644 index 0000000000..3d8a4c291e --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/src/print.cpp @@ -0,0 +1,62 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include <__config> +#include <cstdlib> +#include <print> + +#if defined(_LIBCPP_WIN32API) +# define WIN32_LEAN_AND_MEAN +# define NOMINMAX +# include <io.h> +# include <windows.h> + +# include <__system_error/system_error.h> + +# include "filesystem/error.h" +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#ifdef _WIN32 +_LIBCPP_EXPORTED_FROM_ABI bool __is_windows_terminal(FILE* __stream) { + // Note the Standard does this in one call, but it's unclear whether + // an invalid handle is allowed when calling GetConsoleMode. + // + // https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle?view=msvc-170 + // https://learn.microsoft.com/en-us/windows/console/getconsolemode + intptr_t __handle = _get_osfhandle(fileno(__stream)); + if (__handle == -1) + return false; + + unsigned long __mode; + return GetConsoleMode(reinterpret_cast<void*>(__handle), &__mode); +} + +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +_LIBCPP_EXPORTED_FROM_ABI void +__write_to_windows_console([[maybe_unused]] FILE* __stream, [[maybe_unused]] wstring_view __view) { + // https://learn.microsoft.com/en-us/windows/console/writeconsole + if (WriteConsoleW(reinterpret_cast<void*>(_get_osfhandle(fileno(__stream))), // clang-format aid + __view.data(), + __view.size(), + nullptr, + nullptr) == 0) { +# ifndef _LIBCPP_HAS_NO_EXCEPTIONS + // There is no __throw_system_error overload that takes an error code. + throw system_error{filesystem::detail::make_windows_error(GetLastError()), "failed to write formatted output"}; +# else // _LIBCPP_HAS_NO_EXCEPTIONS + std::abort(); +# endif // _LIBCPP_HAS_NO_EXCEPTIONS + } +} +# endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +#endif // _WIN32 + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/random.cpp b/contrib/libs/cxxsupp/libcxx/src/random.cpp index 38732462cf..dfac89f75b 100644 --- a/contrib/libs/cxxsupp/libcxx/src/random.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/random.cpp @@ -13,13 +13,9 @@ # define _CRT_RAND_S #endif // defined(_LIBCPP_USING_WIN32_RANDOM) +#include <__system_error/system_error.h> #include <limits> #include <random> -#include <system_error> - -#if defined(__sun__) -# define rename solaris_headers_are_broken -#endif // defined(__sun__) #include <errno.h> #include <stdio.h> diff --git a/contrib/libs/cxxsupp/libcxx/src/ryu/d2fixed.cpp b/contrib/libs/cxxsupp/libcxx/src/ryu/d2fixed.cpp index c1a1f6cf9e..3ae515d1dc 100644 --- a/contrib/libs/cxxsupp/libcxx/src/ryu/d2fixed.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/ryu/d2fixed.cpp @@ -43,7 +43,6 @@ #include <__config> #include <charconv> #include <cstring> -#include <system_error> #include "include/ryu/common.h" #include "include/ryu/d2fixed.h" @@ -103,8 +102,8 @@ inline constexpr int __POW10_ADDITIONAL_BITS = 120; const uint64_t __s1low = __low2 + __high1 + __c1; // 128 const uint32_t __c2 = __s1low < __low2; // __high1 + __c1 can't overflow, so compare against __low2 const uint64_t __s1high = __high2 + __c2; // 192 - _LIBCPP_ASSERT(__j >= 128, ""); - _LIBCPP_ASSERT(__j <= 180, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__j >= 128, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__j <= 180, ""); #ifdef _LIBCPP_INTRINSIC128 const uint32_t __dist = static_cast<uint32_t>(__j - 128); // __dist: [0, 52] const uint64_t __shiftedhigh = __s1high >> __dist; @@ -135,19 +134,19 @@ void __append_n_digits(const uint32_t __olength, uint32_t __digits, char* const __digits /= 10000; const uint32_t __c0 = (__c % 100) << 1; const uint32_t __c1 = (__c / 100) << 1; - _VSTD::memcpy(__result + __olength - __i - 2, __DIGIT_TABLE + __c0, 2); - _VSTD::memcpy(__result + __olength - __i - 4, __DIGIT_TABLE + __c1, 2); + std::memcpy(__result + __olength - __i - 2, __DIGIT_TABLE + __c0, 2); + std::memcpy(__result + __olength - __i - 4, __DIGIT_TABLE + __c1, 2); __i += 4; } if (__digits >= 100) { const uint32_t __c = (__digits % 100) << 1; __digits /= 100; - _VSTD::memcpy(__result + __olength - __i - 2, __DIGIT_TABLE + __c, 2); + std::memcpy(__result + __olength - __i - 2, __DIGIT_TABLE + __c, 2); __i += 2; } if (__digits >= 10) { const uint32_t __c = __digits << 1; - _VSTD::memcpy(__result + __olength - __i - 2, __DIGIT_TABLE + __c, 2); + std::memcpy(__result + __olength - __i - 2, __DIGIT_TABLE + __c, 2); } else { __result[0] = static_cast<char>('0' + __digits); } @@ -164,14 +163,14 @@ _LIBCPP_HIDE_FROM_ABI inline void __append_d_digits(const uint32_t __olength, ui __digits /= 10000; const uint32_t __c0 = (__c % 100) << 1; const uint32_t __c1 = (__c / 100) << 1; - _VSTD::memcpy(__result + __olength + 1 - __i - 2, __DIGIT_TABLE + __c0, 2); - _VSTD::memcpy(__result + __olength + 1 - __i - 4, __DIGIT_TABLE + __c1, 2); + std::memcpy(__result + __olength + 1 - __i - 2, __DIGIT_TABLE + __c0, 2); + std::memcpy(__result + __olength + 1 - __i - 4, __DIGIT_TABLE + __c1, 2); __i += 4; } if (__digits >= 100) { const uint32_t __c = (__digits % 100) << 1; __digits /= 100; - _VSTD::memcpy(__result + __olength + 1 - __i - 2, __DIGIT_TABLE + __c, 2); + std::memcpy(__result + __olength + 1 - __i - 2, __DIGIT_TABLE + __c, 2); __i += 2; } if (__digits >= 10) { @@ -190,7 +189,7 @@ _LIBCPP_HIDE_FROM_ABI inline void __append_c_digits(const uint32_t __count, uint for (; __i < __count - 1; __i += 2) { const uint32_t __c = (__digits % 100) << 1; __digits /= 100; - _VSTD::memcpy(__result + __count - __i - 2, __DIGIT_TABLE + __c, 2); + std::memcpy(__result + __count - __i - 2, __DIGIT_TABLE + __c, 2); } if (__i < __count) { const char __c = static_cast<char>('0' + (__digits % 10)); @@ -200,7 +199,7 @@ _LIBCPP_HIDE_FROM_ABI inline void __append_c_digits(const uint32_t __count, uint void __append_nine_digits(uint32_t __digits, char* const __result) { if (__digits == 0) { - _VSTD::memset(__result, '0', 9); + std::memset(__result, '0', 9); return; } @@ -213,8 +212,8 @@ void __append_nine_digits(uint32_t __digits, char* const __result) { __digits /= 10000; const uint32_t __c0 = (__c % 100) << 1; const uint32_t __c1 = (__c / 100) << 1; - _VSTD::memcpy(__result + 7 - __i, __DIGIT_TABLE + __c0, 2); - _VSTD::memcpy(__result + 5 - __i, __DIGIT_TABLE + __c1, 2); + std::memcpy(__result + 7 - __i, __DIGIT_TABLE + __c0, 2); + std::memcpy(__result + 5 - __i, __DIGIT_TABLE + __c1, 2); } __result[0] = static_cast<char>('0' + __digits); } @@ -251,7 +250,7 @@ void __append_nine_digits(uint32_t __digits, char* const __result) { *_First++ = '0'; if (__precision > 0) { *_First++ = '.'; - _VSTD::memset(_First, '0', __precision); + std::memset(_First, '0', __precision); _First += __precision; } return { _First, errc{} }; @@ -322,14 +321,14 @@ void __append_nine_digits(uint32_t __digits, char* const __result) { if (_Last - _First < static_cast<ptrdiff_t>(__precision)) { return { _Last, errc::value_too_large }; } - _VSTD::memset(_First, '0', __precision); + std::memset(_First, '0', __precision); _First += __precision; } else if (__i < __MIN_BLOCK_2[__idx]) { __i = __MIN_BLOCK_2[__idx]; if (_Last - _First < static_cast<ptrdiff_t>(9 * __i)) { return { _Last, errc::value_too_large }; } - _VSTD::memset(_First, '0', 9 * __i); + std::memset(_First, '0', 9 * __i); _First += 9 * __i; } for (; __i < __blocks; ++__i) { @@ -342,7 +341,7 @@ void __append_nine_digits(uint32_t __digits, char* const __result) { if (_Last - _First < static_cast<ptrdiff_t>(__fill)) { return { _Last, errc::value_too_large }; } - _VSTD::memset(_First, '0', __fill); + std::memset(_First, '0', __fill); _First += __fill; break; } @@ -416,7 +415,7 @@ void __append_nine_digits(uint32_t __digits, char* const __result) { if (_Last - _First < static_cast<ptrdiff_t>(__precision)) { return { _Last, errc::value_too_large }; } - _VSTD::memset(_First, '0', __precision); + std::memset(_First, '0', __precision); _First += __precision; } return { _First, errc{} }; @@ -440,10 +439,10 @@ void __append_nine_digits(uint32_t __digits, char* const __result) { *_First++ = '0'; if (__precision > 0) { *_First++ = '.'; - _VSTD::memset(_First, '0', __precision); + std::memset(_First, '0', __precision); _First += __precision; } - _VSTD::memcpy(_First, "e+00", 4); + std::memcpy(_First, "e+00", 4); _First += 4; return { _First, errc{} }; } @@ -589,7 +588,7 @@ void __append_nine_digits(uint32_t __digits, char* const __result) { return { _Last, errc::value_too_large }; } if (__digits == 0) { - _VSTD::memset(_First, '0', __maximum); + std::memset(_First, '0', __maximum); } else { __append_c_digits(__maximum, __digits, _First); } @@ -654,11 +653,11 @@ void __append_nine_digits(uint32_t __digits, char* const __result) { if (__exp >= 100) { const int32_t __c = __exp % 10; - _VSTD::memcpy(_First, __DIGIT_TABLE + 2 * (__exp / 10), 2); + std::memcpy(_First, __DIGIT_TABLE + 2 * (__exp / 10), 2); _First[2] = static_cast<char>('0' + __c); _First += 3; } else { - _VSTD::memcpy(_First, __DIGIT_TABLE + 2 * __exp, 2); + std::memcpy(_First, __DIGIT_TABLE + 2 * __exp, 2); _First += 2; } diff --git a/contrib/libs/cxxsupp/libcxx/src/ryu/d2s.cpp b/contrib/libs/cxxsupp/libcxx/src/ryu/d2s.cpp index 245c2eb590..86d0b61848 100644 --- a/contrib/libs/cxxsupp/libcxx/src/ryu/d2s.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/ryu/d2s.cpp @@ -154,7 +154,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // The average output length is 16.38 digits, so we check high-to-low. // Function precondition: __v is not an 18, 19, or 20-digit number. // (17 digits are sufficient for round-tripping.) - _LIBCPP_ASSERT(__v < 100000000000000000u, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__v < 100000000000000000u, ""); if (__v >= 10000000000000000u) { return 17; } if (__v >= 1000000000000000u) { return 16; } if (__v >= 100000000000000u) { return 15; } @@ -527,10 +527,10 @@ struct __floating_decimal_64 { const uint32_t __d0 = (__d % 100) << 1; const uint32_t __d1 = (__d / 100) << 1; - _VSTD::memcpy(_Mid -= 2, __DIGIT_TABLE + __c0, 2); - _VSTD::memcpy(_Mid -= 2, __DIGIT_TABLE + __c1, 2); - _VSTD::memcpy(_Mid -= 2, __DIGIT_TABLE + __d0, 2); - _VSTD::memcpy(_Mid -= 2, __DIGIT_TABLE + __d1, 2); + std::memcpy(_Mid -= 2, __DIGIT_TABLE + __c0, 2); + std::memcpy(_Mid -= 2, __DIGIT_TABLE + __c1, 2); + std::memcpy(_Mid -= 2, __DIGIT_TABLE + __d0, 2); + std::memcpy(_Mid -= 2, __DIGIT_TABLE + __d1, 2); } uint32_t __output2 = static_cast<uint32_t>(_Output); while (__output2 >= 10000) { @@ -542,35 +542,35 @@ struct __floating_decimal_64 { __output2 /= 10000; const uint32_t __c0 = (__c % 100) << 1; const uint32_t __c1 = (__c / 100) << 1; - _VSTD::memcpy(_Mid -= 2, __DIGIT_TABLE + __c0, 2); - _VSTD::memcpy(_Mid -= 2, __DIGIT_TABLE + __c1, 2); + std::memcpy(_Mid -= 2, __DIGIT_TABLE + __c0, 2); + std::memcpy(_Mid -= 2, __DIGIT_TABLE + __c1, 2); } if (__output2 >= 100) { const uint32_t __c = (__output2 % 100) << 1; __output2 /= 100; - _VSTD::memcpy(_Mid -= 2, __DIGIT_TABLE + __c, 2); + std::memcpy(_Mid -= 2, __DIGIT_TABLE + __c, 2); } if (__output2 >= 10) { const uint32_t __c = __output2 << 1; - _VSTD::memcpy(_Mid -= 2, __DIGIT_TABLE + __c, 2); + std::memcpy(_Mid -= 2, __DIGIT_TABLE + __c, 2); } else { *--_Mid = static_cast<char>('0' + __output2); } if (_Ryu_exponent > 0) { // case "172900" with _Can_use_ryu // Performance note: it might be more efficient to do this immediately after setting _Mid. - _VSTD::memset(_First + __olength, '0', static_cast<size_t>(_Ryu_exponent)); + std::memset(_First + __olength, '0', static_cast<size_t>(_Ryu_exponent)); } else if (_Ryu_exponent == 0) { // case "1729" // Done! } else if (_Whole_digits > 0) { // case "17.29" // Performance note: moving digits might not be optimal. - _VSTD::memmove(_First, _First + 1, static_cast<size_t>(_Whole_digits)); + std::memmove(_First, _First + 1, static_cast<size_t>(_Whole_digits)); _First[_Whole_digits] = '.'; } else { // case "0.001729" // Performance note: a larger memset() followed by overwriting '.' might be more efficient. _First[0] = '0'; _First[1] = '.'; - _VSTD::memset(_First + 2, '0', static_cast<size_t>(-_Whole_digits)); + std::memset(_First + 2, '0', static_cast<size_t>(-_Whole_digits)); } return { _First + _Total_fixed_length, errc{} }; @@ -602,10 +602,10 @@ struct __floating_decimal_64 { const uint32_t __c1 = (__c / 100) << 1; const uint32_t __d0 = (__d % 100) << 1; const uint32_t __d1 = (__d / 100) << 1; - _VSTD::memcpy(__result + __olength - __i - 1, __DIGIT_TABLE + __c0, 2); - _VSTD::memcpy(__result + __olength - __i - 3, __DIGIT_TABLE + __c1, 2); - _VSTD::memcpy(__result + __olength - __i - 5, __DIGIT_TABLE + __d0, 2); - _VSTD::memcpy(__result + __olength - __i - 7, __DIGIT_TABLE + __d1, 2); + std::memcpy(__result + __olength - __i - 1, __DIGIT_TABLE + __c0, 2); + std::memcpy(__result + __olength - __i - 3, __DIGIT_TABLE + __c1, 2); + std::memcpy(__result + __olength - __i - 5, __DIGIT_TABLE + __d0, 2); + std::memcpy(__result + __olength - __i - 7, __DIGIT_TABLE + __d1, 2); __i += 8; } uint32_t __output2 = static_cast<uint32_t>(_Output); @@ -618,14 +618,14 @@ struct __floating_decimal_64 { __output2 /= 10000; const uint32_t __c0 = (__c % 100) << 1; const uint32_t __c1 = (__c / 100) << 1; - _VSTD::memcpy(__result + __olength - __i - 1, __DIGIT_TABLE + __c0, 2); - _VSTD::memcpy(__result + __olength - __i - 3, __DIGIT_TABLE + __c1, 2); + std::memcpy(__result + __olength - __i - 1, __DIGIT_TABLE + __c0, 2); + std::memcpy(__result + __olength - __i - 3, __DIGIT_TABLE + __c1, 2); __i += 4; } if (__output2 >= 100) { const uint32_t __c = (__output2 % 100) << 1; __output2 /= 100; - _VSTD::memcpy(__result + __olength - __i - 1, __DIGIT_TABLE + __c, 2); + std::memcpy(__result + __olength - __i - 1, __DIGIT_TABLE + __c, 2); __i += 2; } if (__output2 >= 10) { @@ -657,11 +657,11 @@ struct __floating_decimal_64 { if (_Scientific_exponent >= 100) { const int32_t __c = _Scientific_exponent % 10; - _VSTD::memcpy(__result + __index, __DIGIT_TABLE + 2 * (_Scientific_exponent / 10), 2); + std::memcpy(__result + __index, __DIGIT_TABLE + 2 * (_Scientific_exponent / 10), 2); __result[__index + 2] = static_cast<char>('0' + __c); __index += 3; } else { - _VSTD::memcpy(__result + __index, __DIGIT_TABLE + 2 * _Scientific_exponent, 2); + std::memcpy(__result + __index, __DIGIT_TABLE + 2 * _Scientific_exponent, 2); __index += 2; } @@ -713,7 +713,7 @@ struct __floating_decimal_64 { return { _Last, errc::value_too_large }; } - _VSTD::memcpy(_First, "0e+00", 5); + std::memcpy(_First, "0e+00", 5); return { _First + 5, errc{} }; } diff --git a/contrib/libs/cxxsupp/libcxx/src/ryu/f2s.cpp b/contrib/libs/cxxsupp/libcxx/src/ryu/f2s.cpp index 3bcfe462c8..7470dc63d7 100644 --- a/contrib/libs/cxxsupp/libcxx/src/ryu/f2s.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/ryu/f2s.cpp @@ -86,7 +86,7 @@ inline constexpr uint64_t __FLOAT_POW5_SPLIT[47] = { [[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __pow5Factor(uint32_t __value) { uint32_t __count = 0; for (;;) { - _LIBCPP_ASSERT(__value != 0, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__value != 0, ""); const uint32_t __q = __value / 5; const uint32_t __r = __value % 5; if (__r != 0) { @@ -105,14 +105,14 @@ inline constexpr uint64_t __FLOAT_POW5_SPLIT[47] = { // Returns true if __value is divisible by 2^__p. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline bool __multipleOfPowerOf2(const uint32_t __value, const uint32_t __p) { - _LIBCPP_ASSERT(__value != 0, ""); - _LIBCPP_ASSERT(__p < 32, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__value != 0, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__p < 32, ""); // __builtin_ctz doesn't appear to be faster here. return (__value & ((1u << __p) - 1)) == 0; } [[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __mulShift(const uint32_t __m, const uint64_t __factor, const int32_t __shift) { - _LIBCPP_ASSERT(__shift > 32, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__shift > 32, ""); // The casts here help MSVC to avoid calls to the __allmul library // function. @@ -134,7 +134,7 @@ inline constexpr uint64_t __FLOAT_POW5_SPLIT[47] = { #else // ^^^ 32-bit ^^^ / vvv 64-bit vvv const uint64_t __sum = (__bits0 >> 32) + __bits1; const uint64_t __shiftedSum = __sum >> (__shift - 32); - _LIBCPP_ASSERT(__shiftedSum <= UINT32_MAX, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__shiftedSum <= UINT32_MAX, ""); return static_cast<uint32_t>(__shiftedSum); #endif // ^^^ 64-bit ^^^ } @@ -309,8 +309,8 @@ struct __floating_decimal_32 { // Performance note: Long division appears to be faster than losslessly widening float to double and calling // __d2fixed_buffered_n(). If __f2fixed_buffered_n() is implemented, it might be faster than long division. - _LIBCPP_ASSERT(_Exponent2 > 0, ""); - _LIBCPP_ASSERT(_Exponent2 <= 104, ""); // because __ieeeExponent <= 254 + _LIBCPP_ASSERT_UNCATEGORIZED(_Exponent2 > 0, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(_Exponent2 <= 104, ""); // because __ieeeExponent <= 254 // Manually represent _Mantissa2 * 2^_Exponent2 as a large integer. _Mantissa2 is always 24 bits // (due to the implicit bit), while _Exponent2 indicates a shift of at most 104 bits. @@ -328,7 +328,7 @@ struct __floating_decimal_32 { // _Maxidx is the index of the most significant nonzero element. uint32_t _Maxidx = ((24 + static_cast<uint32_t>(_Exponent2) + 31) / 32) - 1; - _LIBCPP_ASSERT(_Maxidx < _Data_size, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(_Maxidx < _Data_size, ""); const uint32_t _Bit_shift = static_cast<uint32_t>(_Exponent2) % 32; if (_Bit_shift <= 8) { // _Mantissa2's 24 bits don't cross an element boundary @@ -388,9 +388,9 @@ struct __floating_decimal_32 { } } - _LIBCPP_ASSERT(_Data[0] != 0, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(_Data[0] != 0, ""); for (uint32_t _Idx = 1; _Idx < _Data_size; ++_Idx) { - _LIBCPP_ASSERT(_Data[_Idx] == 0, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(_Data[_Idx] == 0, ""); } const uint32_t _Data_olength = _Data[0] >= 1000000000 ? 10 : __decimalLength9(_Data[0]); @@ -565,35 +565,35 @@ struct __floating_decimal_32 { _Output /= 10000; const uint32_t __c0 = (__c % 100) << 1; const uint32_t __c1 = (__c / 100) << 1; - _VSTD::memcpy(_Mid -= 2, __DIGIT_TABLE + __c0, 2); - _VSTD::memcpy(_Mid -= 2, __DIGIT_TABLE + __c1, 2); + std::memcpy(_Mid -= 2, __DIGIT_TABLE + __c0, 2); + std::memcpy(_Mid -= 2, __DIGIT_TABLE + __c1, 2); } if (_Output >= 100) { const uint32_t __c = (_Output % 100) << 1; _Output /= 100; - _VSTD::memcpy(_Mid -= 2, __DIGIT_TABLE + __c, 2); + std::memcpy(_Mid -= 2, __DIGIT_TABLE + __c, 2); } if (_Output >= 10) { const uint32_t __c = _Output << 1; - _VSTD::memcpy(_Mid -= 2, __DIGIT_TABLE + __c, 2); + std::memcpy(_Mid -= 2, __DIGIT_TABLE + __c, 2); } else { *--_Mid = static_cast<char>('0' + _Output); } if (_Ryu_exponent > 0) { // case "172900" with _Can_use_ryu // Performance note: it might be more efficient to do this immediately after setting _Mid. - _VSTD::memset(_First + __olength, '0', static_cast<size_t>(_Ryu_exponent)); + std::memset(_First + __olength, '0', static_cast<size_t>(_Ryu_exponent)); } else if (_Ryu_exponent == 0) { // case "1729" // Done! } else if (_Whole_digits > 0) { // case "17.29" // Performance note: moving digits might not be optimal. - _VSTD::memmove(_First, _First + 1, static_cast<size_t>(_Whole_digits)); + std::memmove(_First, _First + 1, static_cast<size_t>(_Whole_digits)); _First[_Whole_digits] = '.'; } else { // case "0.001729" // Performance note: a larger memset() followed by overwriting '.' might be more efficient. _First[0] = '0'; _First[1] = '.'; - _VSTD::memset(_First + 2, '0', static_cast<size_t>(-_Whole_digits)); + std::memset(_First + 2, '0', static_cast<size_t>(-_Whole_digits)); } return { _First + _Total_fixed_length, errc{} }; @@ -617,14 +617,14 @@ struct __floating_decimal_32 { _Output /= 10000; const uint32_t __c0 = (__c % 100) << 1; const uint32_t __c1 = (__c / 100) << 1; - _VSTD::memcpy(__result + __olength - __i - 1, __DIGIT_TABLE + __c0, 2); - _VSTD::memcpy(__result + __olength - __i - 3, __DIGIT_TABLE + __c1, 2); + std::memcpy(__result + __olength - __i - 1, __DIGIT_TABLE + __c0, 2); + std::memcpy(__result + __olength - __i - 3, __DIGIT_TABLE + __c1, 2); __i += 4; } if (_Output >= 100) { const uint32_t __c = (_Output % 100) << 1; _Output /= 100; - _VSTD::memcpy(__result + __olength - __i - 1, __DIGIT_TABLE + __c, 2); + std::memcpy(__result + __olength - __i - 1, __DIGIT_TABLE + __c, 2); __i += 2; } if (_Output >= 10) { @@ -654,7 +654,7 @@ struct __floating_decimal_32 { __result[__index++] = '+'; } - _VSTD::memcpy(__result + __index, __DIGIT_TABLE + 2 * _Scientific_exponent, 2); + std::memcpy(__result + __index, __DIGIT_TABLE + 2 * _Scientific_exponent, 2); __index += 2; return { _First + _Total_scientific_length, errc{} }; @@ -673,7 +673,7 @@ struct __floating_decimal_32 { return { _Last, errc::value_too_large }; } - _VSTD::memcpy(_First, "0e+00", 5); + std::memcpy(_First, "0e+00", 5); return { _First + 5, errc{} }; } diff --git a/contrib/libs/cxxsupp/libcxx/src/shared_mutex.cpp b/contrib/libs/cxxsupp/libcxx/src/shared_mutex.cpp index 73d4dc1c1c..49a51e0271 100644 --- a/contrib/libs/cxxsupp/libcxx/src/shared_mutex.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/shared_mutex.cpp @@ -10,106 +10,86 @@ #ifndef _LIBCPP_HAS_NO_THREADS -#include <shared_mutex> -#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) -# pragma comment(lib, "pthread") -#endif +# include <mutex> +# include <shared_mutex> +# if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) +# pragma comment(lib, "pthread") +# endif _LIBCPP_BEGIN_NAMESPACE_STD // Shared Mutex Base -__shared_mutex_base::__shared_mutex_base() - : __state_(0) -{ -} +__shared_mutex_base::__shared_mutex_base() : __state_(0) {} // Exclusive ownership -void -__shared_mutex_base::lock() -{ - unique_lock<mutex> lk(__mut_); - while (__state_ & __write_entered_) - __gate1_.wait(lk); - __state_ |= __write_entered_; - while (__state_ & __n_readers_) - __gate2_.wait(lk); +void __shared_mutex_base::lock() { + unique_lock<mutex> lk(__mut_); + while (__state_ & __write_entered_) + __gate1_.wait(lk); + __state_ |= __write_entered_; + while (__state_ & __n_readers_) + __gate2_.wait(lk); } -bool -__shared_mutex_base::try_lock() -{ - unique_lock<mutex> lk(__mut_); - if (__state_ == 0) - { - __state_ = __write_entered_; - return true; - } - return false; +bool __shared_mutex_base::try_lock() { + unique_lock<mutex> lk(__mut_); + if (__state_ == 0) { + __state_ = __write_entered_; + return true; + } + return false; } -void -__shared_mutex_base::unlock() -{ - lock_guard<mutex> _(__mut_); - __state_ = 0; - __gate1_.notify_all(); +void __shared_mutex_base::unlock() { + lock_guard<mutex> _(__mut_); + __state_ = 0; + __gate1_.notify_all(); } // Shared ownership -void -__shared_mutex_base::lock_shared() -{ - unique_lock<mutex> lk(__mut_); - while ((__state_ & __write_entered_) || (__state_ & __n_readers_) == __n_readers_) - __gate1_.wait(lk); - unsigned num_readers = (__state_ & __n_readers_) + 1; - __state_ &= ~__n_readers_; - __state_ |= num_readers; -} - -bool -__shared_mutex_base::try_lock_shared() -{ - unique_lock<mutex> lk(__mut_); - unsigned num_readers = __state_ & __n_readers_; - if (!(__state_ & __write_entered_) && num_readers != __n_readers_) - { - ++num_readers; - __state_ &= ~__n_readers_; - __state_ |= num_readers; - return true; - } - return false; +void __shared_mutex_base::lock_shared() { + unique_lock<mutex> lk(__mut_); + while ((__state_ & __write_entered_) || (__state_ & __n_readers_) == __n_readers_) + __gate1_.wait(lk); + unsigned num_readers = (__state_ & __n_readers_) + 1; + __state_ &= ~__n_readers_; + __state_ |= num_readers; } -void -__shared_mutex_base::unlock_shared() -{ - lock_guard<mutex> _(__mut_); - unsigned num_readers = (__state_ & __n_readers_) - 1; +bool __shared_mutex_base::try_lock_shared() { + unique_lock<mutex> lk(__mut_); + unsigned num_readers = __state_ & __n_readers_; + if (!(__state_ & __write_entered_) && num_readers != __n_readers_) { + ++num_readers; __state_ &= ~__n_readers_; __state_ |= num_readers; - if (__state_ & __write_entered_) - { - if (num_readers == 0) - __gate2_.notify_one(); - } - else - { - if (num_readers == __n_readers_ - 1) - __gate1_.notify_one(); - } + return true; + } + return false; } +void __shared_mutex_base::unlock_shared() { + lock_guard<mutex> _(__mut_); + unsigned num_readers = (__state_ & __n_readers_) - 1; + __state_ &= ~__n_readers_; + __state_ |= num_readers; + if (__state_ & __write_entered_) { + if (num_readers == 0) + __gate2_.notify_one(); + } else { + if (num_readers == __n_readers_ - 1) + __gate1_.notify_one(); + } +} // Shared Timed Mutex // These routines are here for ABI stability shared_timed_mutex::shared_timed_mutex() : __base_() {} -void shared_timed_mutex::lock() { return __base_.lock(); } +void shared_timed_mutex::lock() { return __base_.lock(); } bool shared_timed_mutex::try_lock() { return __base_.try_lock(); } -void shared_timed_mutex::unlock() { return __base_.unlock(); } +void shared_timed_mutex::unlock() { return __base_.unlock(); } void shared_timed_mutex::lock_shared() { return __base_.lock_shared(); } bool shared_timed_mutex::try_lock_shared() { return __base_.try_lock_shared(); } void shared_timed_mutex::unlock_shared() { return __base_.unlock_shared(); } diff --git a/contrib/libs/cxxsupp/libcxx/src/std_stream.h b/contrib/libs/cxxsupp/libcxx/src/std_stream.h new file mode 100644 index 0000000000..0febf42c9f --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/src/std_stream.h @@ -0,0 +1,447 @@ +// -*- 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_STD_STREAM_H +#define _LIBCPP_STD_STREAM_H + +#include <__config> +#include <__locale> +#include <cstdio> +#include <istream> +#include <ostream> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + + +_LIBCPP_BEGIN_NAMESPACE_STD + +static const int __limit = 8; + +// __stdinbuf + +template <class _CharT> +class _LIBCPP_HIDDEN __stdinbuf + : public basic_streambuf<_CharT, char_traits<_CharT> > +{ +public: + typedef _CharT char_type; + typedef char_traits<char_type> traits_type; + typedef typename traits_type::int_type int_type; + typedef typename traits_type::pos_type pos_type; + typedef typename traits_type::off_type off_type; + typedef typename traits_type::state_type state_type; + + __stdinbuf(FILE* __fp, state_type* __st); + +protected: + virtual int_type underflow(); + virtual int_type uflow(); + virtual int_type pbackfail(int_type __c = traits_type::eof()); + virtual void imbue(const locale& __loc); + +private: + + FILE* __file_; + const codecvt<char_type, char, state_type>* __cv_; + state_type* __st_; + int __encoding_; + int_type __last_consumed_; + bool __last_consumed_is_next_; + bool __always_noconv_; + +#if defined(_LIBCPP_WIN32API) + static constexpr bool __is_win32api_wide_char = !is_same_v<_CharT, char>; +#else + static constexpr bool __is_win32api_wide_char = false; +#endif + + __stdinbuf(const __stdinbuf&); + __stdinbuf& operator=(const __stdinbuf&); + + int_type __getchar(bool __consume); +}; + +template <class _CharT> +__stdinbuf<_CharT>::__stdinbuf(FILE* __fp, state_type* __st) + : __file_(__fp), + __st_(__st), + __last_consumed_(traits_type::eof()), + __last_consumed_is_next_(false) +{ + imbue(this->getloc()); + // On Windows, in wchar_t mode, ignore the codecvt from the locale by + // default and assume noconv; this passes wchar_t through unmodified from + // getwc. If the user sets a custom locale with imbue(), that gets honored, + // the IO is done with getc() and converted with the provided codecvt. + if constexpr (__is_win32api_wide_char) + __always_noconv_ = true; +} + +template <class _CharT> +void +__stdinbuf<_CharT>::imbue(const locale& __loc) +{ + __cv_ = &use_facet<codecvt<char_type, char, state_type> >(__loc); + __encoding_ = __cv_->encoding(); + __always_noconv_ = __cv_->always_noconv(); + if (__encoding_ > __limit) + __throw_runtime_error("unsupported locale for standard input"); +} + +template <class _CharT> +typename __stdinbuf<_CharT>::int_type +__stdinbuf<_CharT>::underflow() +{ + return __getchar(false); +} + +template <class _CharT> +typename __stdinbuf<_CharT>::int_type +__stdinbuf<_CharT>::uflow() +{ + return __getchar(true); +} + +static bool __do_getc(FILE *__fp, char *__pbuf) { + int __c = getc(__fp); + if (__c == EOF) + return false; + *__pbuf = static_cast<char>(__c); + return true; +} +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +static bool __do_getc(FILE *__fp, wchar_t *__pbuf) { + wint_t __c = getwc(__fp); + if (__c == WEOF) + return false; + *__pbuf = static_cast<wchar_t>(__c); + return true; +} +#endif + +static bool __do_ungetc(int __c, FILE *__fp, char __dummy) { + if (ungetc(__c, __fp) == EOF) + return false; + return true; +} +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +static bool __do_ungetc(std::wint_t __c, FILE *__fp, wchar_t __dummy) { + if (ungetwc(__c, __fp) == WEOF) + return false; + return true; +} +#endif + +template <class _CharT> +typename __stdinbuf<_CharT>::int_type +__stdinbuf<_CharT>::__getchar(bool __consume) +{ + if (__last_consumed_is_next_) + { + int_type __result = __last_consumed_; + if (__consume) + { + __last_consumed_ = traits_type::eof(); + __last_consumed_is_next_ = false; + } + return __result; + } + if (__always_noconv_) { + char_type __1buf; + if (!__do_getc(__file_, &__1buf)) + return traits_type::eof(); + if (!__consume) + { + if (!__do_ungetc(traits_type::to_int_type(__1buf), __file_, __1buf)) + return traits_type::eof(); + } + else + __last_consumed_ = traits_type::to_int_type(__1buf); + return traits_type::to_int_type(__1buf); + } + + char __extbuf[__limit]; + int __nread = _VSTD::max(1, __encoding_); + for (int __i = 0; __i < __nread; ++__i) + { + int __c = getc(__file_); + if (__c == EOF) + return traits_type::eof(); + __extbuf[__i] = static_cast<char>(__c); + } + char_type __1buf; + const char* __enxt; + char_type* __inxt; + codecvt_base::result __r; + do + { + state_type __sv_st = *__st_; + __r = __cv_->in(*__st_, __extbuf, __extbuf + __nread, __enxt, + &__1buf, &__1buf + 1, __inxt); + switch (__r) + { + case _VSTD::codecvt_base::ok: + break; + case codecvt_base::partial: + *__st_ = __sv_st; + if (__nread == sizeof(__extbuf)) + return traits_type::eof(); + { + int __c = getc(__file_); + if (__c == EOF) + return traits_type::eof(); + __extbuf[__nread] = static_cast<char>(__c); + } + ++__nread; + break; + case codecvt_base::error: + return traits_type::eof(); + case _VSTD::codecvt_base::noconv: + __1buf = static_cast<char_type>(__extbuf[0]); + break; + } + } while (__r == _VSTD::codecvt_base::partial); + if (!__consume) + { + for (int __i = __nread; __i > 0;) + { + if (ungetc(traits_type::to_int_type(__extbuf[--__i]), __file_) == EOF) + return traits_type::eof(); + } + } + else + __last_consumed_ = traits_type::to_int_type(__1buf); + return traits_type::to_int_type(__1buf); +} + +template <class _CharT> +typename __stdinbuf<_CharT>::int_type +__stdinbuf<_CharT>::pbackfail(int_type __c) +{ + if (traits_type::eq_int_type(__c, traits_type::eof())) + { + if (!__last_consumed_is_next_) + { + __c = __last_consumed_; + __last_consumed_is_next_ = !traits_type::eq_int_type(__last_consumed_, + traits_type::eof()); + } + return __c; + } + if (__always_noconv_ && __last_consumed_is_next_) { + if (!__do_ungetc(__last_consumed_, __file_, + traits_type::to_char_type(__last_consumed_))) + return traits_type::eof(); + } else if (__last_consumed_is_next_) { + char __extbuf[__limit]; + char* __enxt; + const char_type __ci = traits_type::to_char_type(__last_consumed_); + const char_type* __inxt; + switch (__cv_->out(*__st_, &__ci, &__ci + 1, __inxt, + __extbuf, __extbuf + sizeof(__extbuf), __enxt)) + { + case _VSTD::codecvt_base::ok: + break; + case _VSTD::codecvt_base::noconv: + __extbuf[0] = static_cast<char>(__last_consumed_); + __enxt = __extbuf + 1; + break; + case codecvt_base::partial: + case codecvt_base::error: + return traits_type::eof(); + } + while (__enxt > __extbuf) + if (ungetc(*--__enxt, __file_) == EOF) + return traits_type::eof(); + } + __last_consumed_ = __c; + __last_consumed_is_next_ = true; + return __c; +} + +// __stdoutbuf + +template <class _CharT> +class _LIBCPP_HIDDEN __stdoutbuf + : public basic_streambuf<_CharT, char_traits<_CharT> > +{ +public: + typedef _CharT char_type; + typedef char_traits<char_type> traits_type; + typedef typename traits_type::int_type int_type; + typedef typename traits_type::pos_type pos_type; + typedef typename traits_type::off_type off_type; + typedef typename traits_type::state_type state_type; + + __stdoutbuf(FILE* __fp, state_type* __st); + +protected: + virtual int_type overflow (int_type __c = traits_type::eof()); + virtual streamsize xsputn(const char_type* __s, streamsize __n); + virtual int sync(); + virtual void imbue(const locale& __loc); + +private: + FILE* __file_; + const codecvt<char_type, char, state_type>* __cv_; + state_type* __st_; + bool __always_noconv_; + +#if defined(_LIBCPP_WIN32API) + static constexpr bool __is_win32api_wide_char = !is_same_v<_CharT, char>; +#else + static constexpr bool __is_win32api_wide_char = false; +#endif + + __stdoutbuf(const __stdoutbuf&); + __stdoutbuf& operator=(const __stdoutbuf&); +}; + +template <class _CharT> +__stdoutbuf<_CharT>::__stdoutbuf(FILE* __fp, state_type* __st) + : __file_(__fp), + __cv_(&use_facet<codecvt<char_type, char, state_type> >(this->getloc())), + __st_(__st), + __always_noconv_(__cv_->always_noconv()) +{ + // On Windows, in wchar_t mode, ignore the codecvt from the locale by + // default and assume noconv; this passes wchar_t through unmodified to + // fputwc, which handles it correctly depending on the actual mode of the + // output stream. If the user sets a custom locale with imbue(), that + // gets honored. + if constexpr (__is_win32api_wide_char) + __always_noconv_ = true; +} + +static bool __do_fputc(char __c, FILE* __fp) { + if (fwrite(&__c, sizeof(__c), 1, __fp) != 1) + return false; + return true; +} +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +static bool __do_fputc(wchar_t __c, FILE* __fp) { + // fputwc works regardless of wide/narrow mode of stdout, while + // fwrite of wchar_t only works if the stream actually has been set + // into wide mode. + if (fputwc(__c, __fp) == WEOF) + return false; + return true; +} +#endif + +template <class _CharT> +typename __stdoutbuf<_CharT>::int_type +__stdoutbuf<_CharT>::overflow(int_type __c) +{ + char __extbuf[__limit]; + char_type __1buf; + if (!traits_type::eq_int_type(__c, traits_type::eof())) + { + __1buf = traits_type::to_char_type(__c); + if (__always_noconv_) + { + if (!__do_fputc(__1buf, __file_)) + return traits_type::eof(); + } + else + { + char* __extbe = __extbuf; + codecvt_base::result __r; + char_type* pbase = &__1buf; + char_type* pptr = pbase + 1; + do + { + const char_type* __e; + __r = __cv_->out(*__st_, pbase, pptr, __e, + __extbuf, + __extbuf + sizeof(__extbuf), + __extbe); + if (__e == pbase) + return traits_type::eof(); + if (__r == codecvt_base::noconv) + { + if (fwrite(pbase, 1, 1, __file_) != 1) + return traits_type::eof(); + } + else if (__r == codecvt_base::ok || __r == codecvt_base::partial) + { + size_t __nmemb = static_cast<size_t>(__extbe - __extbuf); + if (fwrite(__extbuf, 1, __nmemb, __file_) != __nmemb) + return traits_type::eof(); + if (__r == codecvt_base::partial) + { + pbase = const_cast<char_type*>(__e); + } + } + else + return traits_type::eof(); + } while (__r == codecvt_base::partial); + } + } + return traits_type::not_eof(__c); +} + +template <class _CharT> +streamsize +__stdoutbuf<_CharT>::xsputn(const char_type* __s, streamsize __n) +{ + // For wchar_t on Windows, don't call fwrite(), but write characters one + // at a time with fputwc(); that works both when stdout is in the default + // mode and when it is set to Unicode mode. + if (__always_noconv_ && !__is_win32api_wide_char) + return fwrite(__s, sizeof(char_type), __n, __file_); + streamsize __i = 0; + for (; __i < __n; ++__i, ++__s) + if (overflow(traits_type::to_int_type(*__s)) == traits_type::eof()) + break; + return __i; +} + +template <class _CharT> +int +__stdoutbuf<_CharT>::sync() +{ + char __extbuf[__limit]; + codecvt_base::result __r; + do + { + char* __extbe; + __r = __cv_->unshift(*__st_, __extbuf, + __extbuf + sizeof(__extbuf), + __extbe); + size_t __nmemb = static_cast<size_t>(__extbe - __extbuf); + if (fwrite(__extbuf, 1, __nmemb, __file_) != __nmemb) + return -1; + } while (__r == codecvt_base::partial); + if (__r == codecvt_base::error) + return -1; + if (fflush(__file_)) + return -1; + return 0; +} + +template <class _CharT> +void +__stdoutbuf<_CharT>::imbue(const locale& __loc) +{ + sync(); + __cv_ = &use_facet<codecvt<char_type, char, state_type> >(__loc); + __always_noconv_ = __cv_->always_noconv(); +} + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP_STD_STREAM_H diff --git a/contrib/libs/cxxsupp/libcxx/src/stdexcept.cpp b/contrib/libs/cxxsupp/libcxx/src/stdexcept.cpp index d08b6740db..d5c9173576 100644 --- a/contrib/libs/cxxsupp/libcxx/src/stdexcept.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/stdexcept.cpp @@ -9,7 +9,6 @@ #include <new> #include <stdexcept> #include <string> -#include <system_error> #ifdef _LIBCPP_ABI_VCRUNTIME #include "support/runtime/stdexcept_vcruntime.ipp" diff --git a/contrib/libs/cxxsupp/libcxx/src/string.cpp b/contrib/libs/cxxsupp/libcxx/src/string.cpp index db211b2242..4f3de555e3 100644 --- a/contrib/libs/cxxsupp/libcxx/src/string.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/string.cpp @@ -12,7 +12,6 @@ #include <cstdlib> #include <limits> #include <stdexcept> -#include <stdio.h> #include <string> #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS @@ -61,22 +60,12 @@ template string operator+<char, char_traits<char>, allocator<char>>(char const*, namespace { -template<typename T> -inline void throw_helper(const string& msg) { -#ifndef _LIBCPP_NO_EXCEPTIONS - throw T(msg); -#else - fprintf(stderr, "%s\n", msg.c_str()); - _VSTD::abort(); -#endif -} - inline void throw_from_string_out_of_range(const string& func) { - throw_helper<out_of_range>(func + ": out of range"); + std::__throw_out_of_range((func + ": out of range").c_str()); } inline void throw_from_string_invalid_arg(const string& func) { - throw_helper<invalid_argument>(func + ": no conversion"); + std::__throw_invalid_argument((func + ": no conversion").c_str()); } // as_integer @@ -357,7 +346,7 @@ S i_to_string(V v) { constexpr size_t bufsize = numeric_limits<V>::digits10 + 2; // +1 for minus, +1 for digits10 char buf[bufsize]; const auto res = to_chars(buf, buf + bufsize, v); - _LIBCPP_ASSERT(res.ec == errc(), "bufsize must be large enough to accomodate the value"); + _LIBCPP_ASSERT_INTERNAL(res.ec == errc(), "bufsize must be large enough to accomodate the value"); return S(buf, res.ptr); } diff --git a/contrib/libs/cxxsupp/libcxx/src/strstream.cpp b/contrib/libs/cxxsupp/libcxx/src/strstream.cpp index 87c235a97a..bc56cafa8f 100644 --- a/contrib/libs/cxxsupp/libcxx/src/strstream.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/strstream.cpp @@ -173,7 +173,7 @@ strstreambuf::overflow(int_type __c) if (buf == nullptr) return int_type(EOF); if (old_size != 0) { - _LIBCPP_ASSERT(eback(), "overflow copying from NULL"); + _LIBCPP_ASSERT_UNCATEGORIZED(eback(), "overflow copying from NULL"); memcpy(buf, eback(), static_cast<size_t>(old_size)); } ptrdiff_t ninp = gptr() - eback(); diff --git a/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_fallback.ipp b/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_fallback.ipp index 100ee6da5e..c14c375338 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_fallback.ipp +++ b/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_fallback.ipp @@ -52,15 +52,15 @@ _LIBCPP_NORETURN void terminate() noexcept { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS (*get_terminate())(); // handler should not return fprintf(stderr, "terminate_handler unexpectedly returned\n"); ::abort(); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -68,7 +68,7 @@ terminate() noexcept fprintf(stderr, "terminate_handler unexpectedly threw an exception\n"); ::abort(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } #endif // !__EMSCRIPTEN__ diff --git a/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_msvc.ipp b/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_msvc.ipp index 7e36c7068a..0114d5adee 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_msvc.ipp +++ b/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_msvc.ipp @@ -57,15 +57,15 @@ terminate_handler get_terminate() noexcept { _LIBCPP_NORETURN void terminate() noexcept { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS (*get_terminate())(); // handler should not return fprintf(stderr, "terminate_handler unexpectedly returned\n"); ::abort(); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -73,7 +73,7 @@ void terminate() noexcept fprintf(stderr, "terminate_handler unexpectedly threw an exception\n"); ::abort(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } bool uncaught_exception() noexcept { return uncaught_exceptions() > 0; } diff --git a/contrib/libs/cxxsupp/libcxx/src/support/solaris/README b/contrib/libs/cxxsupp/libcxx/src/support/solaris/README deleted file mode 100644 index 89c887a3b4..0000000000 --- a/contrib/libs/cxxsupp/libcxx/src/support/solaris/README +++ /dev/null @@ -1,4 +0,0 @@ -This directory contains a partial implementation of the xlocale APIs for -Solaris. Some portions are lifted from FreeBSD libc, and so are covered by a -2-clause BSD license instead of the MIT/UUIC license that the rest of libc++ is -distributed under. diff --git a/contrib/libs/cxxsupp/libcxx/src/support/win32/locale_win32.cpp b/contrib/libs/cxxsupp/libcxx/src/support/win32/locale_win32.cpp index 67f4d1341a..2543686c90 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/win32/locale_win32.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/support/win32/locale_win32.cpp @@ -11,6 +11,8 @@ #include <memory> #include <type_traits> +#include <__locale_dir/locale_base_api/locale_guard.h> + int __libcpp_vasprintf(char **sptr, const char *__restrict fmt, va_list ap); using std::__libcpp_locale_guard; diff --git a/contrib/libs/cxxsupp/libcxx/src/system_error.cpp b/contrib/libs/cxxsupp/libcxx/src/system_error.cpp index ba5fa8f30b..7875f59d88 100644 --- a/contrib/libs/cxxsupp/libcxx/src/system_error.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/system_error.cpp @@ -12,6 +12,7 @@ #endif #include <__assert> +#include <__verbose_abort> #include <cerrno> #include <cstdio> #include <cstdlib> @@ -103,7 +104,7 @@ handle_strerror_r_return(int strerror_return, char *buffer) { if (new_errno == EINVAL) return ""; - _LIBCPP_ASSERT(new_errno == ERANGE, "unexpected error from ::strerror_r"); + _LIBCPP_ASSERT_UNCATEGORIZED(new_errno == ERANGE, "unexpected error from ::strerror_r"); // FIXME maybe? 'strerror_buff_size' is likely to exceed the // maximum error size so ERANGE shouldn't be returned. std::abort(); @@ -286,12 +287,10 @@ system_error::~system_error() noexcept void __throw_system_error(int ev, const char* what_arg) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw system_error(error_code(ev, system_category()), what_arg); #else - (void)ev; - (void)what_arg; - _VSTD::abort(); + _LIBCPP_VERBOSE_ABORT("system_error was thrown in -fno-exceptions mode with error %i and message \"%s\"", ev, what_arg); #endif } diff --git a/contrib/libs/cxxsupp/libcxx/src/thread.cpp b/contrib/libs/cxxsupp/libcxx/src/thread.cpp index ec4f65f982..184b5ae8a1 100644 --- a/contrib/libs/cxxsupp/libcxx/src/thread.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/thread.cpp @@ -10,6 +10,8 @@ #ifndef _LIBCPP_HAS_NO_THREADS +#include <__thread/poll_with_backoff.h> +#include <__thread/timed_backoff_policy.h> #include <exception> #include <future> #include <limits> diff --git a/contrib/libs/cxxsupp/libcxx/src/utility.cpp b/contrib/libs/cxxsupp/libcxx/src/utility.cpp deleted file mode 100644 index 44433d11d7..0000000000 --- a/contrib/libs/cxxsupp/libcxx/src/utility.cpp +++ /dev/null @@ -1,15 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include <utility> - -_LIBCPP_BEGIN_NAMESPACE_STD - -const piecewise_construct_t piecewise_construct{}; - -_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/valarray.cpp b/contrib/libs/cxxsupp/libcxx/src/valarray.cpp index 5d63bc1184..f377e0f4e8 100644 --- a/contrib/libs/cxxsupp/libcxx/src/valarray.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/valarray.cpp @@ -12,8 +12,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD // These two symbols are part of the v1 ABI but not part of the >=v2 ABI. #if _LIBCPP_ABI_VERSION == 1 -template _LIBCPP_FUNC_VIS valarray<size_t>::valarray(size_t); -template _LIBCPP_FUNC_VIS valarray<size_t>::~valarray(); +template _LIBCPP_EXPORTED_FROM_ABI valarray<size_t>::valarray(size_t); +template _LIBCPP_EXPORTED_FROM_ABI valarray<size_t>::~valarray(); #endif template void valarray<size_t>::resize(size_t, size_t); |