summaryrefslogtreecommitdiffstats
path: root/contrib/libs/cxxsupp/libcxx/src
diff options
context:
space:
mode:
authormikhnenko <[email protected]>2025-02-25 10:55:30 +0300
committermikhnenko <[email protected]>2025-02-25 11:10:50 +0300
commitba3f1646a3a22daceac94dd0cd330152b1d5b5b5 (patch)
tree16da0d516f0c768c219e6f0fc7351676e390873f /contrib/libs/cxxsupp/libcxx/src
parentdda9be9e1fde150b4473d9d10ec1a0d3829f7482 (diff)
Update libcxx to 8 July 2024
{% cut "Change log" %} ``` [libc++] Add a test case for std::bit_cast with std::complex (#97751) [libc++] Update status after the St. Louis meeting. (#97951) [libc++] Guard transitive include of `<locale>` with availability macro (#97869) [libc++] Restore `__synth_three_way` lambda (#90398) [libc++][TZDB] Makes implementation experimental. (#95657) [libc++] Remove dead code from the locale base API and support code (#89070) [libc++] Assume newer LLVM versions for not-yet-released macOS versions [libc++] Remove annotations for GCC 13 and update the documentation (#97744) [libc++][test] Updates sized deallocation tests. (#97833) [libc++] Adds a missing include. [libc++] Use __is_array if the builtin is fixed (#93037) [libc++] Use _Complex for multiplication and division of complex floating point types (#83575) [libc++] Adds a new feature-test macro generator class. (#90889) [libc++][chrono] Fixes leap seconds. (#90070) [libc++] Upgrade to GCC 14 (#97205) [libc++] Fix the signatures of `std::rethrow_if_nested` (#91365) [libc++] Use GCC compilers from compiler explorer (#97219) Add a regression test for recent regression in pair. (#97355) [libcxx][Docs] Correct link syntax in hardening docs [libc++] Don't use a ppa for GCC [libc++] Upgrade to GCC 14 in the CI (#95212) [libc++abi] Fix test failures with GCC 14 (#95759) [libc++] Clean up and update deployment target features (#96312) [libc++] Fix how we pass /MANIFEST flag on Windows without clang-cl (#96967) [libc++] Classify iota_view precondition (#96662) [libc++] restrict the expected conversion constructor not compete against copy constructor (#96101) "[libc++] Try again LWG3233 Broken requirements for shared_ptr converting constructors" (#96103) [libc++] LWG3382: NTTP for `pair` and `array` (#85811) [libc++] Get the GCC build mostly clean of warnings (#96604) [libc++] P3029R1: Better `mdspan`'s CTAD - `std::extents` (#89015) [libc++] Move allocator assertion into allocator_traits (#94750) [libc++] change the visibility of libc++ header to public in libcxx module (#91240) [libc++] Use _If for conditional_t (#96193) [libc++] Remove the allocator<const T> extension (#96319) [libc++] Fix incorrect overflow checking in std::lcm (#96310) [libc++] Use __is_nothrow_destructible (#95766) [libc++] Remove Windows-specific configuration from libcxx/test/CMakeLists.txt (#96330) [libc++] Build with -fsized-deallocation (#96217) [libc++] <experimental/simd> Add swap functions of simd reference (#86478) [libc++] Fix deployment target Lit features (#94791) [libc++] Workaround clang bug in __has_unique_object_representations (#95314) [libc++] Remove <ostream> include from <chrono> (#96035) [libc++] Fix triviality of std::pair for trivially copyable types without an assignment operator (#95444) [libc++] Install Python packaging to resolve LLDB data formatter issues (#95971) [libc++] Properly define _LIBCPP_HAS_NO_UNICODE in __config_site (#95138) [libc++] Refactor<__type_traits/is_swappable.h> (#86822) [libc++] Enable modernize-use-equals-delete (#93293) [libc++] Test suite adjustments on macOS (#95835) [libc++] Guard transitive include of `<locale>` with availability macro (#95686) [libc++] Mark more types as trivially relocatable (#89724) [libcxx] [ci] Simplify the mingw x86_64 configs (#95609) [libc++][TZDB] Disables a failing test. (#95659) [libc++] Add default copy ctor to "__chrono/exception.h" (#95338) [libcxx][test][AIX] address more platform differences in locale tests (#94826) [libc++] Remove unnecessary #ifdef guards around PSTL implementation details (#95268) [libc++] Mark local_time test as a long test (#95170) Update actions-runner version for libc++ builder images [libc++] Move the implementation of CPU-based basis operations to namespace __pstl (#95267) [libc++][modules] Mark as implemented. (#90091) [libc++] Adds __cpp_lib_three_way_comparison FTM. (#91515) [libc++] Overhaul the PSTL dispatching mechanism (#88131) [libcxx] Correct and clean-up filesystem operations error_code paths (#88341) [libc++][z/OS] Disable portion of formatter.char.funsigned-char.pass.cpp for no unicode (#94044) [libc++] Mark a few functions in the dylib as noexcept (#94098) [libc++] Fix UB in filesystem::__copy for non-existent destination. (#87615) [libc++] Simplify the definition of string::operator== (#95000) [libc++] Update with LWG issue number for shared-ptr constructor [libc++] Tweak how we check constraints on shared_ptr(nullptr_t) (#94996) [HWASan] make get_info.local_time.pass.cpp UNSUPPORTED [libc++] Fix endianness for algorithm mismatch (#93082) [HWASan] skip libcxx test that times out with hwasan [libc++][TZDB] Implements zoned_traits. (#91059) [libc++][test] Avoid `-Wunused-variable` warnings in mutex tests (#94907) [libc++] Fix invalid escape sequences in Python comments (#94032) [libc++][TZDB] Implements time_zone::to_local. (#91003) [libc++][TZDB] Implements time_zone::to_sys. (#90901) [libc++][TZDB] Implements time_zone::to_sys. (#90394) [libc++][TZDB] Implements time_zone get_info(local_time). (#89537) [libc++] Undeprecate shared_ptr atomic access APIs (#92920) [libc++][regex] Correctly adjust match prefix for zero-length matches. (#94550) [libc++][test][AIX] Only XFAIL atomic tests for before clang 19 (#94646) [libc++] Fix naming of value template parameters (#76888) [libc++][hardening] Finish documenting hardening. (#92021) Fix detection of __datasizeof with Clang. (#94174) [libc++] Fix SyntaxWarning messages from python 3.12 (#93637) [libc++] [test] Consistently use `REQUIRES: has-unix-headers` (#94122) [libc++] Add missing noexcept to span constructor (#94381) Remove act from builder image. It never turned out to be useful [libc++] Adjust XFAIL for quick_exit (#94274) [libc++] Properly detect whether C++20 modules are supported by the compiler (#94275) [libc++] Handle 0 size case for testing support operator new (#93834) [libc++] Fix regression about parsing leading decimal points (#93989) [libc++][test] Mark `optional` test functions as `TEST_CONSTEXPR_CXX20` (#94172) [clang][Modules] Remove unnecessary includes of `Module.h` (#93417) [libc++] Don't give functions C linkage (#94102) [libc++] [test] Cleanup compile-only tests (#94121) [libc++] [test] Fix `__has_include` usage, expand condvarany and spaceship coverage (#94120) [libc++] Fix `std::atomic::wait` ulock wait UL_COMPARE_AND_WAIT64 (#92783) Fix order of include flags for the target & regular include paths. (#93547) [libc++] Fix failures with GCC 14 (#92663) [libc++] Remove the inline namespace for std::filesystem in ABIv2 (#92971) [runtimes] Correctly apply libdir subdir for multilib (#93354) [clang] Preserve Qualifiers and type sugar in TemplateNames (#93433) [libc++][test] Close LWG3018 and add tests (#93047) [runtimes][CMake] Simplify the propagation of test dependencies (#93558) [runtimes] Reintroduce a way to select the compiler used for the test suite (#93542) [libc++] Make the __availability header a sub-header of __config (#93083) [libc++][test] Close LWG3238 and add tests (#93043) [libc++] LWG3223 Broken requirements for shared_ptr converting constructors (#93071) [libc++][test] Close LWG3382 and add tests (#93039) [libc++] [test] Fix portability issues for MSVC (#93259) [libc++] [test] Fix MSVC warnings (#93257) [libc++] Mark P2845R8 `__cpp_lib_format_path` and P2587R3 `__cpp_lib_to_string` as C++26 (#93255) [libc++] Split up ABI and platform configuration to their own headers (#90863) [libc++][pstl] Merge all frontend functions for the PSTL (#89219) [libcxx][test][AIX] Fix the thousands_sep expectation for fr_FR locales (#92312) [libcxx] [test] Use `shlex.quote()` to fix Python 3.13 compatibility (#93376) [libc++] Remove libcxx/include/libcxx.imp Revise IDE folder structure (#89755) [libc++][test] Close LWG3045 (#93053) [libc++] Remove a few unused includes of trivially_copyable.h (#93200) [test][libcxx] Update deallocation after #90373 (#93145) [libc++] Refactor tests for std::condition_variable (#91530) Removed redundant template in '__delete_node()' member function of '__forward_list_base' and '__list_imp' classes. (#84323) [libc++][pstl] Improve exception handling (#88998) [WebAssembly] Upstream misc. EH changes (#92990) [libc++] <experimental/simd> Add copy functions for class simd/simd_mask (#78935) [libc++][vector] Inline remaining constructors filling vector with the same value (#82068) Reland "[clang] Enable sized deallocation by default in C++14 onwards" (#90373) [libc++] Implement C++20 atomic_ref (#76647) [libc++] Refactor flaky tests for std::shared_lock (#91779) [libcxx] [test] Detect mingw-w64 headers compatible with C++ module builds (#92893) [libc++] LWG2381: Inconsistency in parsing floating point numbers (#77948) [libcxx] removes unnecessary traits from `has_unique_object_representations` (#69241) [libc++][z/OS] Switch to use TEST_HAS_NO_INT128 as per comment in PR 92261 (#92434) [libcxx] Add cast to avoid pointer casting warning on Windows (#92738) [libcxx] locale.cpp: Move build_name helper into unnamed namespace (#92461) [libcxx][libcxxabi] Fix build for OpenBSD (#92186) [libc++] LWG3672: `common_iterator::operator->()` should return by value (#87899) [libc++][z/OS] Correct a definition of __native_vector_size (#91995) [libc++][z/OS] Fixup two linear_congruential_engine tests (#92261) [libc++][test] `__cpp_lib_within_lifetime` -> `__cpp_lib_is_within_lifetime` (#91896) Fix typo "indicies" (#92232) [libcxx][test] Fix numpunct grouping tests on AIX (#91781) [libcxx] [test] Fix the locale ctype widen tests on AIX (#91744) [libc++] Vectorize std::mismatch with trivially equality comparable types (#87716) [libc++] Make `constexpr std::variant`. Implement P2231R1 (#83335) [libc++][doc] Updates Spaceship status page. [libc++][ASan] Fix std::basic_string trait type (#91590) [libc++][test] Fixes constexpr char_traits. (#90981) [libc++][functional] P2944R3 (partial): Comparisons for `reference_wrapper` (`reference_wrapper` operators only) (#88384) [libc++][CI] Reenables clang-tidy. (#90077) [libc++] Implement std::gcd using the binary version (#77747) [ASan][libc++] Turn on ASan annotations for short strings (#79536) [AIX][libc++] Enable clang_modules_include.gen.py tests (#90971) [libc++] Rename _LIBCPP_INTRODUCED_foo_MARKUP to _LIBCPP_INTRODUCED_foo_ATTRIBUTE (#91269) [libc++] Fix P1206R7 feature test macros (#90914) [libc++] Adjust some of the [rand.dist] critical values that are too strict (#88669) [libc++][modules] Uses _LIBCPP_USING_IF_EXISTS. (#90409) Bump actions runner image used for libc++'s builders. [libcxx] Align `__recommend() + 1` by __endian_factor (#90292) [libc++] Granularize <ostream> (#85537) [libc++] Remove a few __has_foo defines in __config (#90511) [libc++] Remove _LIBCPP_DISABLE_ADDITIONAL_DIAGNOSTICS (#90512) [libcxx][ci] In picolib build, ask clang for the normalised triple (#90722) [libc++][ranges] Implement LWG4053 and LWG4054 (#88612) [libc++] Some tests are missing include for `numeric_limits` (#90345) [libc++] Mark scoped_lock and unique_lock constructors as [[nodiscard]] (#89397) [libc++] Improve libc++ tests when using optimizations (#88897) [libc++][modules] Enable installation by default. (#90094) [libc++][format] Improves escaping performance. (#88533) [libcxx] Remove empty ~__no_destroy (#89882) [libc++][ranges] Exports operator|. (#90071) [C++17] Support __GCC_[CON|DE]STRUCTIVE_SIZE (#89446) [libc++][ranges] LWG3984: ranges::to's recursion branch may be ill-formed (#87964) [clang] Enable sized deallocation by default in C++14 onwards (#83774) [libc++][format] Improves escaping. (#88283) [libc++] Implement LWG4023 (#87513) [libc++] Reformulate availability in terms of LLVM releases (#87563) [libc++] Reorganize the std::variant macros (#89419) [libc++][format] Adds an escaped output benchmark. (#88020) [libc++] Makes saturation functions privately available. (#89503) [libcxx] [modules] Add _LIBCPP_USING_IF_EXISTS on aligned_alloc (#89827) [libc++][TZDB] Fixes reverse time lookups. (#89502) [libc++][doc] Updates module build instructions. (#89413) [libc++][chrono] Fixes format output of negative values. (#89408) [libc++][ranges] export `std::ranges::range_adaptor_closure` (#89793) [libc++][ranges] P2387R3: Pipe support for user-defined range adaptors (#89148) [libc++] Add some private headers to libcxx.imp (#89568) [libc++] Remove _LIBCPP_DISABLE_NODISCARD_EXTENSIONS and refactor the tests (#87094) [libc++] Remove stray CMake install step for modulemap file (#89394) [libc++] Don't commit libcxx.imp (#89391) [libc++] Removes a Clang 16 Windows workaround. (#88560) [libc++][TZDB] Renames incomplete. (#89250) [libc++] Optimize char_traits a bit (#72799) [libc++] Fix usage of 'exclude_from_explicit_instantiation' attribute on local class members (#89377) linear_congruential_engine: add using more precision to prevent overflow (#81583) CompilerRT: Normalize COMPILER_RT_DEFAULT_TARGET_TRIPLE (#89234) [libc++][TZDB] Adds local_info formatter. (#86256) [libc++][pstl] Move the CPU algorithm implementations to __pstl (#89109) [libc++][TZDB] Adds sys_info formatter. (#85896) [libc++][pstl] Promote CPU backends to top-level backends (#88968) [libc++][chrono] Improves date formatting. (#86127) [libc++] Add missing iterator requirement checks in the PSTL (#88127) [libc++][TZDB] Improves time zone format specifiers. (#85797) [libc++][chrono] Disables a test. [libc++][doc] Documents -DLIBCXX_INSTALL_MODULES=ON. (#88547) [libc++][test] Removes Clang 16 validation. (#88558) [libc++] Removes deprecated _LIBCPP_ENABLE_<VERSION>_REMOVED_FEATURES macros (#88548) [libc++][modules] Removes some validation quirks. (#88031) [libc++] Deprecate the C++20 synchronization library before C++20 (#86410) [libc++] Use availability to rely on key functions for bad_expected_access and bad_function_call (#87390) [libc++] Rename __cpu_traits functions (#88741) [libc++][CI] Tests LLDB libc++ data formatters. (#88312) [libc++] Add a utility to check whether a range is valid (#87665) [libc++][PSTL] Introduce cpu traits (#88134) [libc++][RFC] Only include what is required by-version in the umbrella headers (#83740) [libc++] Deprecated `shared_ptr` Atomic Access APIs as per P0718R2 & Implemented P2869R3: Remove Deprecated `shared_ptr` Atomic Access APIs from C++26 (#87111) [libc++][TZDB] Removes test_indian_kerguelen test. [libc++][TZDZ] Validates the database version. [libc++] Undeprecate POSIX STREAM macros. (#88296) [libc++] Marks a variable const. (#88562) [libc++][CMake] Removes LIBCXX_ENABLE_CLANG_TIDY. (#85794) [tzdb] Replace shared_mutex with mutex. (#87929) [libc++] P3029R1: Better `mdspan`'s CTAD (#87873) [libc++][ranges] LWG3736: move_iterator missing disable_sized_sentinel_for specialization (#85611) [libc++] LWG3643: Missing `constexpr` in `std::counted_iterator` (#87901) [libcxx] applies changes regarding post-commit feedback to #75259 (#76534) [libc++] Fix -Wgnu-include-next in stddef.h (#88214) [libcxx] Use generic builtins for popcount, clz and ctz (#86563) [libc++] Adds a global private constructor tag. (#87920) [libc++] Removes Clang-16 support. (#87810) [lib++][CI] Changes bootstrap build type. (#88175) [libc++][CI] Updates Docker LLDB dependencies. (#88174) [libc++][chrono] Adds the sys_info class. (#85619) [libc++][format] Switches to Unicode 15.1. (#86543) [libc++] Avoids using ENODATA. (#86165) [libc++][TZDB] Fixes relative path resolving. (#87882) [libc++][format] adds a basic fuzzer test. (#87883) [libc++] Add test coverage for our implementation of LWG4031 (#87508) [libc++] Implement `bind_back` (#81055) [libc++][format] Fixed `println.blank_line.sh.cpp` test on llvm-clang-win-x-* configurations (#88011) [libc++][doc] Updates format status page. [libc++][format] P3142R0: Printing Blank Lines with `println` (#87277) [libc++] Optimize ranges::minmax (#87335) [libc++] Implement LWG3430 disallow implicit conversion of the source arguments to `std::filesystem::path` when constructing `std::basic_*fstream` (#85079) [libc++] P2872R3: Remove ``wstring_convert`` From C++26 (#87100) Fix issue with never-constexpr __construct_at in C++ < 20. (#87403) [libcxx] coerce formatter precision to int (#87738) [libc++][CI] Updates to Clang 19. (#85301) [libc++][chrono] Completes the tzdb class. (#82157) [libc++][oss-fuzz] Updates C++ version used. (#87531) [libc++] P2867R1: Remove Deprecated `strstream`s From C++26 (#87107) [libc++] Fix copy/pasta error in atomic tests for `atomic_compare_exchange_{weak,strong}` (#87135) [libc++] Mark some recent LWG issues and papers as done (#87502) [libc++][chrono] Loads leap-seconds.list in tzdb. (#82113) [libc++] Disables -Wweak-vtables diagnostics. (#85577) [libc++] Update status page after the Tokyo meeting (#87395) [libc++] Upstream ptrauth support in libc++ and libc++abi (#84573) [libc++] Fix tests on musl (#85085) (#86934) [libc++] Add a static_assert for a Mandates in seed_seq (#86992) [libc++][ranges] Avoid using `distance` in `ranges::contains_subrange` (#87155) [libc++] `std::ranges::advance`: avoid unneeded bounds checks when advancing iterator (#84126) ``` {% endcut %} commit_hash:45feb9db5b173f12bf29de2a3ee73006d4371a4e
Diffstat (limited to 'contrib/libs/cxxsupp/libcxx/src')
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/atomic.cpp42
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/barrier.cpp22
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/chrono.cpp8
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/expected.cpp13
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/experimental/chrono_exception.cpp (renamed from contrib/libs/cxxsupp/libcxx/src/include/tzdb/time_zone_link_private.h)13
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/experimental/include/tzdb/time_zone_private.h (renamed from contrib/libs/cxxsupp/libcxx/src/include/tzdb/time_zone_private.h)11
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/experimental/include/tzdb/types_private.h (renamed from contrib/libs/cxxsupp/libcxx/src/include/tzdb/types_private.h)15
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/experimental/include/tzdb/tzdb_list_private.h (renamed from contrib/libs/cxxsupp/libcxx/src/include/tzdb/tzdb_list_private.h)11
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/experimental/include/tzdb/tzdb_private.h (renamed from contrib/libs/cxxsupp/libcxx/src/include/tzdb/tzdb_private.h)0
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/experimental/time_zone.cpp1055
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/experimental/tzdb.cpp (renamed from contrib/libs/cxxsupp/libcxx/src/tzdb.cpp)135
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/experimental/tzdb_list.cpp (renamed from contrib/libs/cxxsupp/libcxx/src/tzdb_list.cpp)0
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/filesystem/operations.cpp36
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/filesystem/path.cpp28
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/filesystem/path_parser.h28
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/functional.cpp2
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/include/overridable_function.h12
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/locale.cpp10
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/optional.cpp1
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/ostream.cpp1
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/pstl/libdispatch.cpp9
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/random.cpp4
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/support/win32/compiler_rt_shims.cpp110
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/time_zone.cpp32
24 files changed, 1452 insertions, 146 deletions
diff --git a/contrib/libs/cxxsupp/libcxx/src/atomic.cpp b/contrib/libs/cxxsupp/libcxx/src/atomic.cpp
index 2b67685c8a0..1babc953ef4 100644
--- a/contrib/libs/cxxsupp/libcxx/src/atomic.cpp
+++ b/contrib/libs/cxxsupp/libcxx/src/atomic.cpp
@@ -25,16 +25,28 @@
# if !defined(SYS_futex) && defined(SYS_futex_time64)
# define SYS_futex SYS_futex_time64
# endif
+# define _LIBCPP_FUTEX(...) syscall(SYS_futex, __VA_ARGS__)
#elif defined(__FreeBSD__)
# include <sys/types.h>
# include <sys/umtx.h>
+# define _LIBCPP_FUTEX(...) syscall(SYS_futex, __VA_ARGS__)
+
+#elif defined(__OpenBSD__)
+
+#error # include <sys/futex.h>
+
+// OpenBSD has no indirect syscalls
+# define _LIBCPP_FUTEX(...) futex(__VA_ARGS__)
+
#else // <- Add other operating systems here
// Baseline needs no new headers
+# define _LIBCPP_FUTEX(...) syscall(SYS_futex, __VA_ARGS__)
+
#endif
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -44,11 +56,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD
static void
__libcpp_platform_wait_on_address(__cxx_atomic_contention_t const volatile* __ptr, __cxx_contention_t __val) {
static constexpr timespec __timeout = {2, 0};
- syscall(SYS_futex, __ptr, FUTEX_WAIT_PRIVATE, __val, &__timeout, 0, 0);
+ _LIBCPP_FUTEX(__ptr, FUTEX_WAIT_PRIVATE, __val, &__timeout, 0, 0);
}
static void __libcpp_platform_wake_by_address(__cxx_atomic_contention_t const volatile* __ptr, bool __notify_one) {
- syscall(SYS_futex, __ptr, FUTEX_WAKE_PRIVATE, __notify_one ? 1 : INT_MAX, 0, 0, 0);
+ _LIBCPP_FUTEX(__ptr, FUTEX_WAKE_PRIVATE, __notify_one ? 1 : INT_MAX, 0, 0, 0);
}
#elif defined(__APPLE__) && defined(_LIBCPP_USE_ULOCK)
@@ -57,17 +69,20 @@ extern "C" int __ulock_wait(
uint32_t operation, void* addr, uint64_t value, uint32_t timeout); /* timeout is specified in microseconds */
extern "C" int __ulock_wake(uint32_t operation, void* addr, uint64_t wake_value);
-# define UL_COMPARE_AND_WAIT 1
+// https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/bsd/sys/ulock.h#L82
+# define UL_COMPARE_AND_WAIT64 5
# define ULF_WAKE_ALL 0x00000100
static void
__libcpp_platform_wait_on_address(__cxx_atomic_contention_t const volatile* __ptr, __cxx_contention_t __val) {
- __ulock_wait(UL_COMPARE_AND_WAIT, const_cast<__cxx_atomic_contention_t*>(__ptr), __val, 0);
+ static_assert(sizeof(__cxx_atomic_contention_t) == 8, "Waiting on 8 bytes value");
+ __ulock_wait(UL_COMPARE_AND_WAIT64, const_cast<__cxx_atomic_contention_t*>(__ptr), __val, 0);
}
static void __libcpp_platform_wake_by_address(__cxx_atomic_contention_t const volatile* __ptr, bool __notify_one) {
+ static_assert(sizeof(__cxx_atomic_contention_t) == 8, "Waking up on 8 bytes value");
__ulock_wake(
- UL_COMPARE_AND_WAIT | (__notify_one ? 0 : ULF_WAKE_ALL), const_cast<__cxx_atomic_contention_t*>(__ptr), 0);
+ UL_COMPARE_AND_WAIT64 | (__notify_one ? 0 : ULF_WAKE_ALL), const_cast<__cxx_atomic_contention_t*>(__ptr), 0);
}
#elif defined(__FreeBSD__) && __SIZEOF_LONG__ == 8
@@ -154,17 +169,18 @@ static void __libcpp_atomic_notify(void const volatile* __location) {
&__entry->__platform_state,
false /* when laundering, we can't handle notify_one */);
}
-_LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_one(void const volatile* __location) {
+_LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_one(void const volatile* __location) noexcept {
__libcpp_atomic_notify(__location);
}
-_LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_all(void const volatile* __location) {
+_LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_all(void const volatile* __location) noexcept {
__libcpp_atomic_notify(__location);
}
-_LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t __libcpp_atomic_monitor(void const volatile* __location) {
+_LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t __libcpp_atomic_monitor(void const volatile* __location) noexcept {
auto const __entry = __libcpp_contention_state(__location);
return __libcpp_contention_monitor_for_wait(&__entry->__contention_state, &__entry->__platform_state);
}
-_LIBCPP_EXPORTED_FROM_ABI void __libcpp_atomic_wait(void const volatile* __location, __cxx_contention_t __old_value) {
+_LIBCPP_EXPORTED_FROM_ABI void
+__libcpp_atomic_wait(void const volatile* __location, __cxx_contention_t __old_value) noexcept {
auto const __entry = __libcpp_contention_state(__location);
__libcpp_contention_wait(&__entry->__contention_state, &__entry->__platform_state, __old_value);
}
@@ -172,19 +188,19 @@ _LIBCPP_EXPORTED_FROM_ABI void __libcpp_atomic_wait(void const volatile* __locat
/* When the incoming atomic happens to be the platform wait size, we still need to use the
table for the contention detection, but we can use the atomic directly for the wait. */
-_LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_one(__cxx_atomic_contention_t const volatile* __location) {
+_LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_one(__cxx_atomic_contention_t const volatile* __location) noexcept {
__libcpp_contention_notify(&__libcpp_contention_state(__location)->__contention_state, __location, true);
}
-_LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_all(__cxx_atomic_contention_t const volatile* __location) {
+_LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_all(__cxx_atomic_contention_t const volatile* __location) noexcept {
__libcpp_contention_notify(&__libcpp_contention_state(__location)->__contention_state, __location, false);
}
// This function is never used, but still exported for ABI compatibility.
_LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t
-__libcpp_atomic_monitor(__cxx_atomic_contention_t const volatile* __location) {
+__libcpp_atomic_monitor(__cxx_atomic_contention_t const volatile* __location) noexcept {
return __libcpp_contention_monitor_for_wait(&__libcpp_contention_state(__location)->__contention_state, __location);
}
_LIBCPP_EXPORTED_FROM_ABI void
-__libcpp_atomic_wait(__cxx_atomic_contention_t const volatile* __location, __cxx_contention_t __old_value) {
+__libcpp_atomic_wait(__cxx_atomic_contention_t const volatile* __location, __cxx_contention_t __old_value) noexcept {
__libcpp_contention_wait(&__libcpp_contention_state(__location)->__contention_state, __location, __old_value);
}
diff --git a/contrib/libs/cxxsupp/libcxx/src/barrier.cpp b/contrib/libs/cxxsupp/libcxx/src/barrier.cpp
index baa26101cd5..69601bfeec0 100644
--- a/contrib/libs/cxxsupp/libcxx/src/barrier.cpp
+++ b/contrib/libs/cxxsupp/libcxx/src/barrier.cpp
@@ -21,17 +21,17 @@ public:
} __tickets[64];
};
- ptrdiff_t& __expected;
- unique_ptr<__state_t[]> __state;
+ ptrdiff_t& __expected_;
+ unique_ptr<__state_t[]> __state_;
- _LIBCPP_HIDDEN __barrier_algorithm_base(ptrdiff_t& __expected) : __expected(__expected) {
+ _LIBCPP_HIDDEN __barrier_algorithm_base(ptrdiff_t& __expected) : __expected_(__expected) {
size_t const __count = (__expected + 1) >> 1;
- __state = unique_ptr<__state_t[]>(new __state_t[__count]);
+ __state_ = unique_ptr<__state_t[]>(new __state_t[__count]);
}
_LIBCPP_HIDDEN bool __arrive(__barrier_phase_t __old_phase) {
__barrier_phase_t const __half_step = __old_phase + 1, __full_step = __old_phase + 2;
- size_t __current_expected = __expected,
- __current = hash<thread::id>()(this_thread::get_id()) % ((__expected + 1) >> 1);
+ size_t __current_expected = __expected_,
+ __current = hash<thread::id>()(this_thread::get_id()) % ((__expected_ + 1) >> 1);
for (int __round = 0;; ++__round) {
if (__current_expected <= 1)
return true;
@@ -41,14 +41,14 @@ public:
__current = 0;
__barrier_phase_t expect = __old_phase;
if (__current == __last_node && (__current_expected & 1)) {
- if (__state[__current].__tickets[__round].__phase.compare_exchange_strong(
+ if (__state_[__current].__tickets[__round].__phase.compare_exchange_strong(
expect, __full_step, memory_order_acq_rel))
break; // I'm 1 in 1, go to next __round
- } else if (__state[__current].__tickets[__round].__phase.compare_exchange_strong(
+ } else if (__state_[__current].__tickets[__round].__phase.compare_exchange_strong(
expect, __half_step, memory_order_acq_rel)) {
return false; // I'm 1 in 2, done with arrival
} else if (expect == __half_step) {
- if (__state[__current].__tickets[__round].__phase.compare_exchange_strong(
+ if (__state_[__current].__tickets[__round].__phase.compare_exchange_strong(
expect, __full_step, memory_order_acq_rel))
break; // I'm 2 in 2, go to next __round
}
@@ -63,10 +63,10 @@ _LIBCPP_EXPORTED_FROM_ABI __barrier_algorithm_base* __construct_barrier_algorith
return new __barrier_algorithm_base(__expected);
}
_LIBCPP_EXPORTED_FROM_ABI bool
-__arrive_barrier_algorithm_base(__barrier_algorithm_base* __barrier, __barrier_phase_t __old_phase) {
+__arrive_barrier_algorithm_base(__barrier_algorithm_base* __barrier, __barrier_phase_t __old_phase) noexcept {
return __barrier->__arrive(__old_phase);
}
-_LIBCPP_EXPORTED_FROM_ABI void __destroy_barrier_algorithm_base(__barrier_algorithm_base* __barrier) {
+_LIBCPP_EXPORTED_FROM_ABI void __destroy_barrier_algorithm_base(__barrier_algorithm_base* __barrier) noexcept {
delete __barrier;
}
diff --git a/contrib/libs/cxxsupp/libcxx/src/chrono.cpp b/contrib/libs/cxxsupp/libcxx/src/chrono.cpp
index c5e827c0cb5..83e8a64504a 100644
--- a/contrib/libs/cxxsupp/libcxx/src/chrono.cpp
+++ b/contrib/libs/cxxsupp/libcxx/src/chrono.cpp
@@ -31,7 +31,9 @@
# include <sys/time.h> // for gettimeofday and timeval
#endif
-#if defined(__APPLE__) || defined(__gnu_hurd__) || (defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0)
+// OpenBSD does not have a fully conformant suite of POSIX timers, but
+// it does have clock_gettime and CLOCK_MONOTONIC which is all we need.
+#if defined(__APPLE__) || defined(__gnu_hurd__) || defined(__OpenBSD__) || (defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0)
# define _LIBCPP_HAS_CLOCK_GETTIME
#endif
@@ -75,8 +77,8 @@ typedef void(WINAPI* GetSystemTimeAsFileTimePtr)(LPFILETIME);
class GetSystemTimeInit {
public:
GetSystemTimeInit() {
- fp =
- (GetSystemTimeAsFileTimePtr)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "GetSystemTimePreciseAsFileTime");
+ fp = (GetSystemTimeAsFileTimePtr)(void*)GetProcAddress(
+ GetModuleHandleW(L"kernel32.dll"), "GetSystemTimePreciseAsFileTime");
if (fp == nullptr)
fp = GetSystemTimeAsFileTime;
}
diff --git a/contrib/libs/cxxsupp/libcxx/src/expected.cpp b/contrib/libs/cxxsupp/libcxx/src/expected.cpp
new file mode 100644
index 00000000000..f30efb51647
--- /dev/null
+++ b/contrib/libs/cxxsupp/libcxx/src/expected.cpp
@@ -0,0 +1,13 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 <expected>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+const char* bad_expected_access<void>::what() const noexcept { return "bad access to std::expected"; }
+_LIBCPP_END_NAMESPACE_STD
diff --git a/contrib/libs/cxxsupp/libcxx/src/include/tzdb/time_zone_link_private.h b/contrib/libs/cxxsupp/libcxx/src/experimental/chrono_exception.cpp
index 13923762527..bea2ad11031 100644
--- a/contrib/libs/cxxsupp/libcxx/src/include/tzdb/time_zone_link_private.h
+++ b/contrib/libs/cxxsupp/libcxx/src/experimental/chrono_exception.cpp
@@ -1,4 +1,3 @@
-// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
@@ -7,21 +6,17 @@
//
//===----------------------------------------------------------------------===//
-// For information see https://libcxx.llvm.org/DesignDocs/TimeZone.html
-
-#ifndef _LIBCPP_SRC_INCLUDE_TZDB_TIME_ZONE_LINK_PRIVATE_H
-#define _LIBCPP_SRC_INCLUDE_TZDB_TIME_ZONE_LINK_PRIVATE_H
-
#include <chrono>
_LIBCPP_BEGIN_NAMESPACE_STD
namespace chrono {
-struct time_zone_link::__constructor_tag {};
+_LIBCPP_AVAILABILITY_TZDB
+_LIBCPP_EXPORTED_FROM_ABI nonexistent_local_time::~nonexistent_local_time() = default; // key function
+_LIBCPP_AVAILABILITY_TZDB
+_LIBCPP_EXPORTED_FROM_ABI ambiguous_local_time::~ambiguous_local_time() = default; // key function
} // namespace chrono
_LIBCPP_END_NAMESPACE_STD
-
-#endif // _LIBCPP_SRC_INCLUDE_TZDB_TIME_ZONE_LINK_PRIVATE_H
diff --git a/contrib/libs/cxxsupp/libcxx/src/include/tzdb/time_zone_private.h b/contrib/libs/cxxsupp/libcxx/src/experimental/include/tzdb/time_zone_private.h
index 039a3b0ffeb..2c47e9fdb13 100644
--- a/contrib/libs/cxxsupp/libcxx/src/include/tzdb/time_zone_private.h
+++ b/contrib/libs/cxxsupp/libcxx/src/experimental/include/tzdb/time_zone_private.h
@@ -24,7 +24,8 @@ namespace chrono {
class time_zone::__impl {
public:
- explicit _LIBCPP_HIDE_FROM_ABI __impl(string&& __name) : __name_(std::move(__name)) {}
+ explicit _LIBCPP_HIDE_FROM_ABI __impl(string&& __name, const __tz::__rules_storage_type& __rules_db)
+ : __name_(std::move(__name)), __rules_db_(__rules_db) {}
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI string_view __name() const noexcept { return __name_; }
@@ -33,12 +34,20 @@ public:
return __continuations_;
}
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI const __tz::__rules_storage_type& __rules_db() const { return __rules_db_; }
+
private:
string __name_;
// Note the first line has a name + __continuation, the other lines
// are just __continuations. So there is always at least one item in
// the vector.
vector<__tz::__continuation> __continuations_;
+
+ // Continuations often depend on a set of rules. The rules are stored in
+ // parallel data structurs in tzdb_list. From the time_zone it's not possible
+ // to find its associated tzdb entry and thus not possible to find its
+ // associated rules. Therefore a link to the rules in stored in this class.
+ const __tz::__rules_storage_type& __rules_db_;
};
} // namespace chrono
diff --git a/contrib/libs/cxxsupp/libcxx/src/include/tzdb/types_private.h b/contrib/libs/cxxsupp/libcxx/src/experimental/include/tzdb/types_private.h
index 4604b9fc881..c86982948b6 100644
--- a/contrib/libs/cxxsupp/libcxx/src/include/tzdb/types_private.h
+++ b/contrib/libs/cxxsupp/libcxx/src/experimental/include/tzdb/types_private.h
@@ -33,7 +33,17 @@ namespace chrono::__tz {
// Sun>=8 first Sunday on or after the eighth
// Sun<=25 last Sunday on or before the 25th
struct __constrained_weekday {
- /* year_month_day operator()(year __year, month __month);*/ // needed but not implemented
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI year_month_day operator()(year __year, month __month) const {
+ auto __result = static_cast<sys_days>(year_month_day{__year, __month, __day});
+ weekday __wd{static_cast<sys_days>(__result)};
+
+ if (__comparison == __le)
+ __result -= __wd - __weekday;
+ else
+ __result += __weekday - __wd;
+
+ return __result;
+ }
weekday __weekday;
enum __comparison_t { __le, __ge } __comparison;
@@ -85,7 +95,8 @@ struct __continuation {
// used.
// If this field contains - then standard time always
// applies. This is indicated by the monostate.
- using __rules_t = variant<monostate, __tz::__save, string, size_t>;
+ // TODO TZDB Investigate implantation the size_t based caching.
+ using __rules_t = variant<monostate, __tz::__save, string /*, size_t*/>;
__rules_t __rules;
diff --git a/contrib/libs/cxxsupp/libcxx/src/include/tzdb/tzdb_list_private.h b/contrib/libs/cxxsupp/libcxx/src/experimental/include/tzdb/tzdb_list_private.h
index 969b2b9f8a9..0be7b8e5a10 100644
--- a/contrib/libs/cxxsupp/libcxx/src/include/tzdb/tzdb_list_private.h
+++ b/contrib/libs/cxxsupp/libcxx/src/experimental/include/tzdb/tzdb_list_private.h
@@ -15,8 +15,11 @@
#include <forward_list>
// When threads are not available the locking is not required.
+// When threads are available, we use std::mutex over std::shared_mutex
+// due to the increased overhead of std::shared_mutex.
+// See shared_mutex_vs_mutex.bench.cpp
#ifndef _LIBCPP_HAS_NO_THREADS
-# include <shared_mutex>
+# include <mutex>
#endif
#include "types_private.h"
@@ -56,7 +59,7 @@ public:
const tzdb& __front() const noexcept {
#ifndef _LIBCPP_HAS_NO_THREADS
- shared_lock __lock{__mutex_};
+ unique_lock __lock{__mutex_};
#endif
return __tzdb_.front();
}
@@ -72,7 +75,7 @@ public:
const_iterator __begin() const noexcept {
#ifndef _LIBCPP_HAS_NO_THREADS
- shared_lock __lock{__mutex_};
+ unique_lock __lock{__mutex_};
#endif
return __tzdb_.begin();
}
@@ -87,7 +90,7 @@ private:
void __load_no_lock() { chrono::__init_tzdb(__tzdb_.emplace_front(), __rules_.emplace_front()); }
#ifndef _LIBCPP_HAS_NO_THREADS
- mutable shared_mutex __mutex_;
+ mutable mutex __mutex_;
#endif
forward_list<tzdb> __tzdb_;
diff --git a/contrib/libs/cxxsupp/libcxx/src/include/tzdb/tzdb_private.h b/contrib/libs/cxxsupp/libcxx/src/experimental/include/tzdb/tzdb_private.h
index 8ec3f890ef6..8ec3f890ef6 100644
--- a/contrib/libs/cxxsupp/libcxx/src/include/tzdb/tzdb_private.h
+++ b/contrib/libs/cxxsupp/libcxx/src/experimental/include/tzdb/tzdb_private.h
diff --git a/contrib/libs/cxxsupp/libcxx/src/experimental/time_zone.cpp b/contrib/libs/cxxsupp/libcxx/src/experimental/time_zone.cpp
new file mode 100644
index 00000000000..764a89ab513
--- /dev/null
+++ b/contrib/libs/cxxsupp/libcxx/src/experimental/time_zone.cpp
@@ -0,0 +1,1055 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// For information see https://libcxx.llvm.org/DesignDocs/TimeZone.html
+
+// TODO TZDB look at optimizations
+//
+// The current algorithm is correct but not efficient. For example, in a named
+// rule based continuation finding the next rule does quite a bit of work,
+// returns the next rule and "forgets" its state. This could be better.
+//
+// It would be possible to cache lookups. If a time for a zone is calculated its
+// sys_info could be kept and the next lookup could test whether the time is in
+// a "known" sys_info. The wording in the Standard hints at this slowness by
+// "suggesting" this could be implemented on the user's side.
+
+// TODO TZDB look at removing quirks
+//
+// The code has some special rules to adjust the timing at the continuation
+// switches. This works correctly, but some of the places feel odd. It would be
+// good to investigate this further and see whether all quirks are needed or
+// that there are better fixes.
+//
+// These quirks often use a 12h interval; this is the scan interval of zdump,
+// which implies there are no sys_info objects with a duration of less than 12h.
+
+#include <algorithm>
+#include <cctype>
+#include <chrono>
+#include <expected>
+#include <map>
+#include <numeric>
+#include <ranges>
+
+#include "include/tzdb/time_zone_private.h"
+#include "include/tzdb/tzdb_list_private.h"
+
+// TODO TZDB remove debug printing
+#ifdef PRINT
+# include <print>
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#ifdef PRINT
+template <>
+struct formatter<chrono::sys_info, char> {
+ template <class ParseContext>
+ constexpr typename ParseContext::iterator parse(ParseContext& ctx) {
+ return ctx.begin();
+ }
+
+ template <class FormatContext>
+ typename FormatContext::iterator format(const chrono::sys_info& info, FormatContext& ctx) const {
+ return std::format_to(
+ ctx.out(), "[{}, {}) {:%Q%q} {:%Q%q} {}", info.begin, info.end, info.offset, info.save, info.abbrev);
+ }
+};
+#endif
+
+namespace chrono {
+
+//===----------------------------------------------------------------------===//
+// Details
+//===----------------------------------------------------------------------===//
+
+struct __sys_info {
+ sys_info __info;
+ bool __can_merge; // Can the returned sys_info object be merged with
+};
+
+// Return type for helper function to get a sys_info.
+// - The expected result returns the "best" sys_info object. This object can be
+// before the requested time. Sometimes sys_info objects from different
+// continuations share their offset, save, and abbrev and these objects are
+// merged to one sys_info object. The __can_merge flag determines whether the
+// current result can be merged with the next result.
+// - The unexpected result means no sys_info object was found and the time is
+// the time to be used for the next search iteration.
+using __sys_info_result = expected<__sys_info, sys_seconds>;
+
+template <ranges::forward_range _Range,
+ class _Type,
+ class _Proj = identity,
+ indirect_strict_weak_order<const _Type*, projected<ranges::iterator_t<_Range>, _Proj>> _Comp = ranges::less>
+[[nodiscard]] static ranges::borrowed_iterator_t<_Range>
+__binary_find(_Range&& __r, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) {
+ auto __end = ranges::end(__r);
+ auto __ret = ranges::lower_bound(ranges::begin(__r), __end, __value, __comp, __proj);
+ if (__ret == __end)
+ return __end;
+
+ // When the value does not match the predicate it's equal and a valid result
+ // was found.
+ return !std::invoke(__comp, __value, std::invoke(__proj, *__ret)) ? __ret : __end;
+}
+
+// Format based on https://data.iana.org/time-zones/tz-how-to.html
+//
+// 1 a time zone abbreviation that is a string of three or more characters that
+// are either ASCII alphanumerics, "+", or "-"
+// 2 the string "%z", in which case the "%z" will be replaced by a numeric time
+// zone abbreviation
+// 3 a pair of time zone abbreviations separated by a slash ('/'), in which
+// case the first string is the abbreviation for the standard time name and
+// the second string is the abbreviation for the daylight saving time name
+// 4 a string containing "%s", in which case the "%s" will be replaced by the
+// text in the appropriate Rule's LETTER column, and the resulting string
+// should be a time zone abbreviation
+//
+// Rule 1 is not strictly validated since America/Barbados uses a two letter
+// abbreviation AT.
+[[nodiscard]] static string
+__format(const __tz::__continuation& __continuation, const string& __letters, seconds __save) {
+ bool __shift = false;
+ string __result;
+ for (char __c : __continuation.__format) {
+ if (__shift) {
+ switch (__c) {
+ case 's':
+ std::ranges::copy(__letters, std::back_inserter(__result));
+ break;
+
+ case 'z': {
+ if (__continuation.__format.size() != 2)
+ std::__throw_runtime_error(
+ std::format("corrupt tzdb FORMAT field: %z should be the entire contents, instead contains '{}'",
+ __continuation.__format)
+ .c_str());
+ chrono::hh_mm_ss __offset{__continuation.__stdoff + __save};
+ if (__offset.is_negative()) {
+ __result += '-';
+ __offset = chrono::hh_mm_ss{-(__continuation.__stdoff + __save)};
+ } else
+ __result += '+';
+
+ if (__offset.minutes() != 0min)
+ std::format_to(std::back_inserter(__result), "{:%H%M}", __offset);
+ else
+ std::format_to(std::back_inserter(__result), "{:%H}", __offset);
+ } break;
+
+ default:
+ std::__throw_runtime_error(
+ std::format("corrupt tzdb FORMAT field: invalid sequence '%{}' found, expected %s or %z", __c).c_str());
+ }
+ __shift = false;
+
+ } else if (__c == '/') {
+ if (__save != 0s)
+ __result.clear();
+ else
+ break;
+
+ } else if (__c == '%') {
+ __shift = true;
+ } else if (__c == '+' || __c == '-' || std::isalnum(__c)) {
+ __result.push_back(__c);
+ } else {
+ std::__throw_runtime_error(
+ std::format(
+ "corrupt tzdb FORMAT field: invalid character '{}' found, expected +, -, or an alphanumeric value", __c)
+ .c_str());
+ }
+ }
+
+ if (__shift)
+ std::__throw_runtime_error("corrupt tzdb FORMAT field: input ended with the start of the escape sequence '%'");
+
+ if (__result.empty())
+ std::__throw_runtime_error("corrupt tzdb FORMAT field: result is empty");
+
+ return __result;
+}
+
+[[nodiscard]] static sys_seconds __to_sys_seconds(year_month_day __ymd, seconds __seconds) {
+ seconds __result = static_cast<sys_days>(__ymd).time_since_epoch() + __seconds;
+ return sys_seconds{__result};
+}
+
+[[nodiscard]] static seconds __at_to_sys_seconds(const __tz::__continuation& __continuation) {
+ switch (__continuation.__at.__clock) {
+ case __tz::__clock::__local:
+ return __continuation.__at.__time - __continuation.__stdoff -
+ std::visit(
+ [](const auto& __value) {
+ using _Tp = decay_t<decltype(__value)>;
+ if constexpr (same_as<_Tp, monostate>)
+ return chrono::seconds{0};
+ else if constexpr (same_as<_Tp, __tz::__save>)
+ return chrono::duration_cast<seconds>(__value.__time);
+ else if constexpr (same_as<_Tp, std::string>)
+ // For a named rule based continuation the SAVE depends on the RULE
+ // active at the end. This should be determined separately.
+ return chrono::seconds{0};
+ else
+ static_assert(sizeof(_Tp) == 0); // TODO TZDB static_assert(false); after droping clang-16 support
+
+ std::__libcpp_unreachable();
+ },
+ __continuation.__rules);
+
+ case __tz::__clock::__universal:
+ return __continuation.__at.__time;
+
+ case __tz::__clock::__standard:
+ return __continuation.__at.__time - __continuation.__stdoff;
+ }
+ std::__libcpp_unreachable();
+}
+
+[[nodiscard]] static year_month_day __to_year_month_day(year __year, month __month, __tz::__on __on) {
+ return std::visit(
+ [&](const auto& __value) {
+ using _Tp = decay_t<decltype(__value)>;
+ if constexpr (same_as<_Tp, chrono::day>)
+ return year_month_day{__year, __month, __value};
+ else if constexpr (same_as<_Tp, weekday_last>)
+ return year_month_day{static_cast<sys_days>(year_month_weekday_last{__year, __month, __value})};
+ else if constexpr (same_as<_Tp, __tz::__constrained_weekday>)
+ return __value(__year, __month);
+ else
+ static_assert(sizeof(_Tp) == 0); // TODO TZDB static_assert(false); after droping clang-16 support
+
+ std::__libcpp_unreachable();
+ },
+ __on);
+}
+
+[[nodiscard]] static sys_seconds __until_to_sys_seconds(const __tz::__continuation& __continuation) {
+ // Does UNTIL contain the magic value for the last continuation?
+ if (__continuation.__year == chrono::year::min())
+ return sys_seconds::max();
+
+ year_month_day __ymd = chrono::__to_year_month_day(__continuation.__year, __continuation.__in, __continuation.__on);
+ return chrono::__to_sys_seconds(__ymd, chrono::__at_to_sys_seconds(__continuation));
+}
+
+// Holds the UNTIL time for a continuation with a named rule.
+//
+// Unlike continuations with an fixed SAVE named rules have a variable SAVE.
+// This means when the UNTIL uses the local wall time the actual UNTIL value can
+// only be determined when the SAVE is known. This class holds that abstraction.
+class __named_rule_until {
+public:
+ explicit __named_rule_until(const __tz::__continuation& __continuation)
+ : __until_{chrono::__until_to_sys_seconds(__continuation)},
+ __needs_adjustment_{
+ // The last continuation of a ZONE has no UNTIL which basically is
+ // until the end of _local_ time. This value is expressed by
+ // sys_seconds::max(). Subtracting the SAVE leaves large value.
+ // However SAVE can be negative, which would add a value to maximum
+ // leading to undefined behaviour. In practice this often results in
+ // an overflow to a very small value.
+ __until_ != sys_seconds::max() && __continuation.__at.__clock == __tz::__clock::__local} {}
+
+ // Gives the unadjusted until value, this is useful when the SAVE is not known
+ // at all.
+ sys_seconds __until() const noexcept { return __until_; }
+
+ bool __needs_adjustment() const noexcept { return __needs_adjustment_; }
+
+ // Returns the UNTIL adjusted for SAVE.
+ sys_seconds operator()(seconds __save) const noexcept { return __until_ - __needs_adjustment_ * __save; }
+
+private:
+ sys_seconds __until_;
+ bool __needs_adjustment_;
+};
+
+[[nodiscard]] static seconds __at_to_seconds(seconds __stdoff, const __tz::__rule& __rule) {
+ switch (__rule.__at.__clock) {
+ case __tz::__clock::__local:
+ // Local time and standard time behave the same. This is not
+ // correct. Local time needs to adjust for the current saved time.
+ // To know the saved time the rules need to be known and sorted.
+ // This needs a time so to avoid the chicken and egg adjust the
+ // saving of the local time later.
+ return __rule.__at.__time - __stdoff;
+
+ case __tz::__clock::__universal:
+ return __rule.__at.__time;
+
+ case __tz::__clock::__standard:
+ return __rule.__at.__time - __stdoff;
+ }
+ std::__libcpp_unreachable();
+}
+
+[[nodiscard]] static sys_seconds __from_to_sys_seconds(seconds __stdoff, const __tz::__rule& __rule, year __year) {
+ year_month_day __ymd = chrono::__to_year_month_day(__year, __rule.__in, __rule.__on);
+
+ seconds __at = chrono::__at_to_seconds(__stdoff, __rule);
+ return chrono::__to_sys_seconds(__ymd, __at);
+}
+
+[[nodiscard]] static sys_seconds __from_to_sys_seconds(seconds __stdoff, const __tz::__rule& __rule) {
+ return chrono::__from_to_sys_seconds(__stdoff, __rule, __rule.__from);
+}
+
+[[nodiscard]] static const vector<__tz::__rule>&
+__get_rules(const __tz::__rules_storage_type& __rules_db, const string& __rule_name) {
+ auto __result = chrono::__binary_find(__rules_db, __rule_name, {}, [](const auto& __p) { return __p.first; });
+ if (__result == std::end(__rules_db))
+ std::__throw_runtime_error(("corrupt tzdb: rule '" + __rule_name + " 'does not exist").c_str());
+
+ return __result->second;
+}
+
+// Returns the letters field for a time before the first rule.
+//
+// Per https://data.iana.org/time-zones/tz-how-to.html
+// One wrinkle, not fully explained in zic.8.txt, is what happens when switching
+// to a named rule. To what values should the SAVE and LETTER data be
+// initialized?
+//
+// 1 If at least one transition has happened, use the SAVE and LETTER data from
+// the most recent.
+// 2 If switching to a named rule before any transition has happened, assume
+// standard time (SAVE zero), and use the LETTER data from the earliest
+// transition with a SAVE of zero.
+//
+// This function implements case 2.
+[[nodiscard]] static string __letters_before_first_rule(const vector<__tz::__rule>& __rules) {
+ auto __letters =
+ __rules //
+ | views::filter([](const __tz::__rule& __rule) { return __rule.__save.__time == 0s; }) //
+ | views::transform([](const __tz::__rule& __rule) { return __rule.__letters; }) //
+ | views::take(1);
+
+ if (__letters.empty())
+ std::__throw_runtime_error("corrupt tzdb: rule has zero entries");
+
+ return __letters.front();
+}
+
+// Determines the information based on the continuation and the rules.
+//
+// There are several special cases to take into account
+//
+// === Entries before the first rule becomes active ===
+// Asia/Hong_Kong
+// 9 - JST 1945 N 18 2 // (1)
+// 8 HK HK%sT // (2)
+// R HK 1946 o - Ap 21 0 1 S // (3)
+// There (1) is active until Novemer 18th 1945 at 02:00, after this time
+// (2) becomes active. The first rule entry for HK (3) becomes active
+// from April 21st 1945 at 01:00. In the period between (2) is active.
+// This entry has an offset.
+// This entry has no save, letters, or dst flag. So in the period
+// after (1) and until (3) no rule entry is associated with the time.
+
+[[nodiscard]] static sys_info __get_sys_info_before_first_rule(
+ sys_seconds __begin,
+ sys_seconds __end,
+ const __tz::__continuation& __continuation,
+ const vector<__tz::__rule>& __rules) {
+ return sys_info{
+ __begin,
+ __end,
+ __continuation.__stdoff,
+ chrono::minutes(0),
+ chrono::__format(__continuation, __letters_before_first_rule(__rules), 0s)};
+}
+
+// Returns the sys_info object for a time before the first rule.
+// When this first rule has a SAVE of 0s the sys_info for the time before the
+// first rule and for the first rule are identical and will be merged.
+[[nodiscard]] static sys_info __get_sys_info_before_first_rule(
+ sys_seconds __begin,
+ sys_seconds __rule_end, // The end used when SAVE != 0s
+ sys_seconds __next_end, // The end used when SAVE == 0s the times are merged
+ const __tz::__continuation& __continuation,
+ const vector<__tz::__rule>& __rules,
+ vector<__tz::__rule>::const_iterator __rule) {
+ if (__rule->__save.__time != 0s)
+ return __get_sys_info_before_first_rule(__begin, __rule_end, __continuation, __rules);
+
+ return sys_info{
+ __begin, __next_end, __continuation.__stdoff, 0min, chrono::__format(__continuation, __rule->__letters, 0s)};
+}
+
+[[nodiscard]] static seconds __at_to_seconds(seconds __stdoff, seconds __save, const __tz::__rule& __rule) {
+ switch (__rule.__at.__clock) {
+ case __tz::__clock::__local:
+ return __rule.__at.__time - __stdoff - __save;
+
+ case __tz::__clock::__universal:
+ return __rule.__at.__time;
+
+ case __tz::__clock::__standard:
+ return __rule.__at.__time - __stdoff;
+ }
+ std::__libcpp_unreachable();
+}
+
+[[nodiscard]] static sys_seconds
+__rule_to_sys_seconds(seconds __stdoff, seconds __save, const __tz::__rule& __rule, year __year) {
+ year_month_day __ymd = chrono::__to_year_month_day(__year, __rule.__in, __rule.__on);
+
+ seconds __at = chrono::__at_to_seconds(__stdoff, __save, __rule);
+ return chrono::__to_sys_seconds(__ymd, __at);
+}
+
+// Returns the first rule after __time.
+// Note that a rule can be "active" in multiple years, this may result in an
+// infinite loop where the same rule is returned every time, use __current to
+// guard against that.
+//
+// When no next rule exists the returned time will be sys_seconds::max(). This
+// can happen in practice. For example,
+//
+// R So 1945 o - May 24 2 2 M
+// R So 1945 o - S 24 3 1 S
+// R So 1945 o - N 18 2s 0 -
+//
+// Has 3 rules that are all only active in 1945.
+[[nodiscard]] static pair<sys_seconds, vector<__tz::__rule>::const_iterator>
+__next_rule(sys_seconds __time,
+ seconds __stdoff,
+ seconds __save,
+ const vector<__tz::__rule>& __rules,
+ vector<__tz::__rule>::const_iterator __current) {
+ year __year = year_month_day{chrono::floor<days>(__time)}.year();
+
+ // Note it would probably be better to store the pairs in a vector and then
+ // use min() to get the smallest element
+ map<sys_seconds, vector<__tz::__rule>::const_iterator> __candidates;
+ // Note this evaluates all rules which is a waste of effort; when the entries
+ // are beyond the current year's "next year" (where "next year" is not always
+ // year + 1) the algorithm should end.
+ for (auto __it = __rules.begin(); __it != __rules.end(); ++__it) {
+ for (year __y = __it->__from; __y <= __it->__to; ++__y) {
+ // Adding the current entry for the current year may lead to infinite
+ // loops due to the SAVE adjustment. Skip these entries.
+ if (__y == __year && __it == __current)
+ continue;
+
+ sys_seconds __t = chrono::__rule_to_sys_seconds(__stdoff, __save, *__it, __y);
+ if (__t <= __time)
+ continue;
+
+ _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(!__candidates.contains(__t), "duplicated rule");
+ __candidates[__t] = __it;
+ break;
+ }
+ }
+
+ if (!__candidates.empty()) [[likely]] {
+ auto __it = __candidates.begin();
+
+ // When no rule is selected the time before the first rule and the first rule
+ // should not be merged.
+ if (__time == sys_seconds::min())
+ return *__it;
+
+ // There can be two constitutive rules that are the same. For example,
+ // Hong Kong
+ //
+ // R HK 1973 o - D 30 3:30 1 S (R1)
+ // R HK 1965 1976 - Ap Su>=16 3:30 1 S (R2)
+ //
+ // 1973-12-29 19:30:00 R1 becomes active.
+ // 1974-04-20 18:30:00 R2 becomes active.
+ // Both rules have a SAVE of 1 hour and LETTERS are S for both of them.
+ while (__it != __candidates.end()) {
+ if (__current->__save.__time != __it->second->__save.__time || __current->__letters != __it->second->__letters)
+ return *__it;
+
+ ++__it;
+ }
+ }
+
+ return {sys_seconds::max(), __rules.end()};
+}
+
+// Returns the first rule of a set of rules.
+// This is not always the first of the listed rules. For example
+// R Sa 2008 2009 - Mar Su>=8 0 0 -
+// R Sa 2007 2008 - O Su>=8 0 1 -
+// The transition in October 2007 happens before the transition in March 2008.
+[[nodiscard]] static vector<__tz::__rule>::const_iterator
+__first_rule(seconds __stdoff, const vector<__tz::__rule>& __rules) {
+ return chrono::__next_rule(sys_seconds::min(), __stdoff, 0s, __rules, __rules.end()).second;
+}
+
+[[nodiscard]] static __sys_info_result __get_sys_info_rule(
+ sys_seconds __time,
+ sys_seconds __continuation_begin,
+ const __tz::__continuation& __continuation,
+ const vector<__tz::__rule>& __rules) {
+ auto __rule = chrono::__first_rule(__continuation.__stdoff, __rules);
+ _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(__rule != __rules.end(), "the set of rules has no first rule");
+
+ // Avoid selecting a time before the start of the continuation
+ __time = std::max(__time, __continuation_begin);
+
+ sys_seconds __rule_begin = chrono::__from_to_sys_seconds(__continuation.__stdoff, *__rule);
+
+ // The time sought is very likely inside the current rule.
+ // When the continuation's UNTIL uses the local clock there are edge cases
+ // where this is not true.
+ //
+ // Start to walk the rules to find the proper one.
+ //
+ // For now we just walk all the rules TODO TZDB investigate whether a smarter
+ // algorithm would work.
+ auto __next = chrono::__next_rule(__rule_begin, __continuation.__stdoff, __rule->__save.__time, __rules, __rule);
+
+ // Ignore small steps, this happens with America/Punta_Arenas for the
+ // transition
+ // -4:42:46 - SMT 1927 S
+ // -5 x -05/-04 1932 S
+ // ...
+ //
+ // R x 1927 1931 - S 1 0 1 -
+ // R x 1928 1932 - Ap 1 0 0 -
+ //
+ // America/Punta_Arenas Thu Sep 1 04:42:45 1927 UT = Thu Sep 1 00:42:45 1927 -04 isdst=1 gmtoff=-14400
+ // America/Punta_Arenas Sun Apr 1 03:59:59 1928 UT = Sat Mar 31 23:59:59 1928 -04 isdst=1 gmtoff=-14400
+ // America/Punta_Arenas Sun Apr 1 04:00:00 1928 UT = Sat Mar 31 23:00:00 1928 -05 isdst=0 gmtoff=-18000
+ //
+ // Without this there will be a transition
+ // [1927-09-01 04:42:45, 1927-09-01 05:00:00) -05:00:00 0min -05
+
+ if (sys_seconds __begin = __rule->__save.__time != 0s ? __rule_begin : __next.first; __time < __begin) {
+ if (__continuation_begin == sys_seconds::min() || __begin - __continuation_begin > 12h)
+ return __sys_info{__get_sys_info_before_first_rule(
+ __continuation_begin, __rule_begin, __next.first, __continuation, __rules, __rule),
+ false};
+
+ // Europe/Berlin
+ // 1 c CE%sT 1945 May 24 2 (C1)
+ // 1 So CE%sT 1946 (C2)
+ //
+ // R c 1944 1945 - Ap M>=1 2s 1 S (R1)
+ //
+ // R So 1945 o - May 24 2 2 M (R2)
+ //
+ // When C2 becomes active the time would be before the first rule R2,
+ // giving a 1 hour sys_info.
+ seconds __save = __rule->__save.__time;
+ __named_rule_until __continuation_end{__continuation};
+ sys_seconds __sys_info_end = std::min(__continuation_end(__save), __next.first);
+
+ return __sys_info{
+ sys_info{__continuation_begin,
+ __sys_info_end,
+ __continuation.__stdoff + __save,
+ chrono::duration_cast<minutes>(__save),
+ chrono::__format(__continuation, __rule->__letters, __save)},
+ __sys_info_end == __continuation_end(__save)};
+ }
+
+ // See above for America/Asuncion
+ if (__rule->__save.__time == 0s && __time < __next.first) {
+ return __sys_info{
+ sys_info{__continuation_begin,
+ __next.first,
+ __continuation.__stdoff,
+ 0min,
+ chrono::__format(__continuation, __rule->__letters, 0s)},
+ false};
+ }
+
+ if (__rule->__save.__time != 0s) {
+ // another fix for America/Punta_Arenas when not at the start of the
+ // sys_info object.
+ seconds __save = __rule->__save.__time;
+ if (__continuation_begin >= __rule_begin - __save && __time < __next.first) {
+ return __sys_info{
+ sys_info{__continuation_begin,
+ __next.first,
+ __continuation.__stdoff + __save,
+ chrono::duration_cast<minutes>(__save),
+ chrono::__format(__continuation, __rule->__letters, __save)},
+ false};
+ }
+ }
+
+ __named_rule_until __continuation_end{__continuation};
+ while (__next.second != __rules.end()) {
+#ifdef PRINT
+ std::print(
+ stderr,
+ "Rule for {}: [{}, {}) off={} save={} duration={}\n",
+ __time,
+ __rule_begin,
+ __next.first,
+ __continuation.__stdoff,
+ __rule->__save.__time,
+ __next.first - __rule_begin);
+#endif
+
+ sys_seconds __end = __continuation_end(__rule->__save.__time);
+
+ sys_seconds __sys_info_begin = std::max(__continuation_begin, __rule_begin);
+ sys_seconds __sys_info_end = std::min(__end, __next.first);
+ seconds __diff = chrono::abs(__sys_info_end - __sys_info_begin);
+
+ if (__diff < 12h) {
+ // Z America/Argentina/Buenos_Aires -3:53:48 - LMT 1894 O 31
+ // -4:16:48 - CMT 1920 May
+ // -4 - -04 1930 D
+ // -4 A -04/-03 1969 O 5
+ // -3 A -03/-02 1999 O 3
+ // -4 A -04/-03 2000 Mar 3
+ // ...
+ //
+ // ...
+ // R A 1989 1992 - O Su>=15 0 1 -
+ // R A 1999 o - O Su>=1 0 1 -
+ // R A 2000 o - Mar 3 0 0 -
+ // R A 2007 o - D 30 0 1 -
+ // ...
+
+ // The 1999 switch uses the same rule, but with a different stdoff.
+ // R A 1999 o - O Su>=1 0 1 -
+ // stdoff -3 -> 1999-10-03 03:00:00
+ // stdoff -4 -> 1999-10-03 04:00:00
+ // This generates an invalid entry and this is evaluated as a transition.
+ // Looking at the zdump like output in libc++ this generates jumps in
+ // the UTC time.
+
+ __rule = __next.second;
+ __next = __next_rule(__next.first, __continuation.__stdoff, __rule->__save.__time, __rules, __rule);
+ __end = __continuation_end(__rule->__save.__time);
+ __sys_info_end = std::min(__end, __next.first);
+ }
+
+ if ((__time >= __rule_begin && __time < __next.first) || __next.first >= __end) {
+ __sys_info_begin = std::max(__continuation_begin, __rule_begin);
+ __sys_info_end = std::min(__end, __next.first);
+
+ return __sys_info{
+ sys_info{__sys_info_begin,
+ __sys_info_end,
+ __continuation.__stdoff + __rule->__save.__time,
+ chrono::duration_cast<minutes>(__rule->__save.__time),
+ chrono::__format(__continuation, __rule->__letters, __rule->__save.__time)},
+ __sys_info_end == __end};
+ }
+
+ __rule_begin = __next.first;
+ __rule = __next.second;
+ __next = __next_rule(__rule_begin, __continuation.__stdoff, __rule->__save.__time, __rules, __rule);
+ }
+
+ return __sys_info{
+ sys_info{std::max(__continuation_begin, __rule_begin),
+ __continuation_end(__rule->__save.__time),
+ __continuation.__stdoff + __rule->__save.__time,
+ chrono::duration_cast<minutes>(__rule->__save.__time),
+ chrono::__format(__continuation, __rule->__letters, __rule->__save.__time)},
+ true};
+}
+
+[[nodiscard]] static __sys_info_result __get_sys_info_basic(
+ sys_seconds __time, sys_seconds __continuation_begin, const __tz::__continuation& __continuation, seconds __save) {
+ sys_seconds __continuation_end = chrono::__until_to_sys_seconds(__continuation);
+ return __sys_info{
+ sys_info{__continuation_begin,
+ __continuation_end,
+ __continuation.__stdoff + __save,
+ chrono::duration_cast<minutes>(__save),
+ __continuation.__format},
+ true};
+}
+
+[[nodiscard]] static __sys_info_result
+__get_sys_info(sys_seconds __time,
+ sys_seconds __continuation_begin,
+ const __tz::__continuation& __continuation,
+ const __tz::__rules_storage_type& __rules_db) {
+ return std::visit(
+ [&](const auto& __value) {
+ using _Tp = decay_t<decltype(__value)>;
+ if constexpr (same_as<_Tp, std::string>)
+ return chrono::__get_sys_info_rule(
+ __time, __continuation_begin, __continuation, __get_rules(__rules_db, __value));
+ else if constexpr (same_as<_Tp, monostate>)
+ return chrono::__get_sys_info_basic(__time, __continuation_begin, __continuation, chrono::seconds(0));
+ else if constexpr (same_as<_Tp, __tz::__save>)
+ return chrono::__get_sys_info_basic(__time, __continuation_begin, __continuation, __value.__time);
+ else
+ static_assert(sizeof(_Tp) == 0); // TODO TZDB static_assert(false); after droping clang-16 support
+
+ std::__libcpp_unreachable();
+ },
+ __continuation.__rules);
+}
+
+// The transition from one continuation to the next continuation may result in
+// two constitutive continuations with the same "offset" information.
+// [time.zone.info.sys]/3
+// The begin and end data members indicate that, for the associated time_zone
+// and time_point, the offset and abbrev are in effect in the range
+// [begin, end). This information can be used to efficiently iterate the
+// transitions of a time_zone.
+//
+// Note that this does considers a change in the SAVE field not to be a
+// different sys_info, zdump does consider this different.
+// LWG XXXX The sys_info range should be affected by save
+// matches the behaviour of the Standard and zdump.
+//
+// Iff the "offsets" are the same '__current.__end' is replaced with
+// '__next.__end', which effectively merges the two objects in one object. The
+// function returns true if a merge occurred.
+[[nodiscard]] bool __merge_continuation(sys_info& __current, const sys_info& __next) {
+ if (__current.end != __next.begin)
+ return false;
+
+ if (__current.offset != __next.offset || __current.abbrev != __next.abbrev || __current.save != __next.save)
+ return false;
+
+ __current.end = __next.end;
+ return true;
+}
+
+//===----------------------------------------------------------------------===//
+// Public API
+//===----------------------------------------------------------------------===//
+
+[[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI time_zone time_zone::__create(unique_ptr<time_zone::__impl>&& __p) {
+ _LIBCPP_ASSERT_NON_NULL(__p != nullptr, "initialized time_zone without a valid pimpl object");
+ time_zone result;
+ result.__impl_ = std::move(__p);
+ return result;
+}
+
+_LIBCPP_EXPORTED_FROM_ABI time_zone::~time_zone() = default;
+
+[[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI string_view time_zone::__name() const noexcept { return __impl_->__name(); }
+
+[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI sys_info
+time_zone::__get_info(sys_seconds __time) const {
+ optional<sys_info> __result;
+ bool __valid_result = false; // true iff __result.has_value() is true and
+ // __result.begin <= __time < __result.end is true.
+ bool __can_merge = false;
+ sys_seconds __continuation_begin = sys_seconds::min();
+ // Iterates over the Zone entry and its continuations. Internally the Zone
+ // entry is split in a Zone information and the first continuation. The last
+ // continuation has no UNTIL field. This means the loop should always find a
+ // continuation.
+ //
+ // For more information on background of zone information please consult the
+ // following information
+ // [zic manual](https://www.man7.org/linux/man-pages/man8/zic.8.html)
+ // [tz source info](https://data.iana.org/time-zones/tz-how-to.html)
+ // On POSIX systems the zdump tool can be useful:
+ // zdump -v Asia/Hong_Kong
+ // Gives all transitions in the Hong Kong time zone.
+ //
+ // During iteration the result for the current continuation is returned. If
+ // no continuation is applicable it will return the end time as "error". When
+ // two continuations are contiguous and contain the "same" information these
+ // ranges are merged as one range.
+ // The merging requires keeping any result that occurs before __time,
+ // likewise when a valid result is found the algorithm needs to test the next
+ // continuation to see whether it can be merged. For example, Africa/Ceuta
+ // Continuations
+ // 0 s WE%sT 1929 (C1)
+ // 0 - WET 1967 (C2)
+ // 0 Sp WE%sT 1984 Mar 16 (C3)
+ //
+ // Rules
+ // R s 1926 1929 - O Sa>=1 24s 0 - (R1)
+ //
+ // R Sp 1967 o - Jun 3 12 1 S (R2)
+ //
+ // The rule R1 is the last rule used in C1. The rule R2 is the first rule in
+ // C3. Since R2 is the first rule this means when a continuation uses this
+ // rule its value prior to R2 will be SAVE 0 LETTERS of the first entry with a
+ // SAVE of 0, in this case WET.
+ // This gives the following changes in the information.
+ // 1928-10-07 00:00:00 C1 R1 becomes active: offset 0 save 0 abbrev WET
+ // 1929-01-01 00:00:00 C2 becomes active: offset 0 save 0 abbrev WET
+ // 1967-01-01 00:00:00 C3 becomes active: offset 0 save 0 abbrev WET
+ // 1967-06-03 12:00:00 C3 R2 becomes active: offset 0 save 1 abbrev WEST
+ //
+ // The first 3 entries are contiguous and contain the same information, this
+ // means the period [1928-10-07 00:00:00, 1967-06-03 12:00:00) should be
+ // returned in one sys_info object.
+
+ const auto& __continuations = __impl_->__continuations();
+ const __tz::__rules_storage_type& __rules_db = __impl_->__rules_db();
+ for (auto __it = __continuations.begin(); __it != __continuations.end(); ++__it) {
+ const auto& __continuation = *__it;
+ __sys_info_result __sys_info = chrono::__get_sys_info(__time, __continuation_begin, __continuation, __rules_db);
+
+ if (__sys_info) {
+ _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
+ __sys_info->__info.begin < __sys_info->__info.end, "invalid sys_info range");
+
+ // Filters out dummy entries
+ // Z America/Argentina/Buenos_Aires -3:53:48 - LMT 1894 O 31
+ // ...
+ // -4 A -04/-03 2000 Mar 3 (C1)
+ // -3 A -03/-02 (C2)
+ //
+ // ...
+ // R A 2000 o - Mar 3 0 0 -
+ // R A 2007 o - D 30 0 1 -
+ // ...
+ //
+ // This results in an entry
+ // [2000-03-03 03:00:00, 2000-03-03 04:00:00) -10800s 60min -03
+ // for [C1 & R1, C1, R2) which due to the end of the continuation is an
+ // one hour "sys_info". Instead the entry should be ignored and replaced
+ // by [C2 & R1, C2 & R2) which is the proper range
+ // "[2000-03-03 03:00:00, 2007-12-30 03:00:00) -02:00:00 60min -02
+
+ if (std::holds_alternative<string>(__continuation.__rules) && __sys_info->__can_merge &&
+ __sys_info->__info.begin + 12h > __sys_info->__info.end) {
+ __continuation_begin = __sys_info->__info.begin;
+ continue;
+ }
+
+ if (!__result) {
+ // First entry found, always keep it.
+ __result = __sys_info->__info;
+
+ __valid_result = __time >= __result->begin && __time < __result->end;
+ __can_merge = __sys_info->__can_merge;
+ } else if (__can_merge && chrono::__merge_continuation(*__result, __sys_info->__info)) {
+ // The results are merged, update the result state. This may
+ // "overwrite" a valid sys_info object with another valid sys_info
+ // object.
+ __valid_result = __time >= __result->begin && __time < __result->end;
+ __can_merge = __sys_info->__can_merge;
+ } else {
+ // Here things get interesting:
+ // For example, America/Argentina/San_Luis
+ //
+ // -3 A -03/-02 2008 Ja 21 (C1)
+ // -4 Sa -04/-03 2009 O 11 (C2)
+ //
+ // R A 2007 o - D 30 0 1 - (R1)
+ //
+ // R Sa 2007 2008 - O Su>=8 0 1 - (R2)
+ //
+ // Based on C1 & R1 the end time of C1 is 2008-01-21 03:00:00
+ // Based on C2 & R2 the end time of C1 is 2008-01-21 02:00:00
+ // In this case the earlier time is the real time of the transition.
+ // However the algorithm used gives 2008-01-21 03:00:00.
+ //
+ // So we need to calculate the previous UNTIL in the current context and
+ // see whether it's earlier.
+
+ // The results could not be merged.
+ // - When we have a valid result that result is the final result.
+ // - Otherwise the result we had is before __time and the result we got
+ // is at a later time (possibly valid). This result is always better
+ // than the previous result.
+ if (__valid_result) {
+ return *__result;
+ } else {
+ _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
+ __it != __continuations.begin(), "the first rule should always seed the result");
+ const auto& __last = *(__it - 1);
+ if (std::holds_alternative<string>(__last.__rules)) {
+ // Europe/Berlin
+ // 1 c CE%sT 1945 May 24 2 (C1)
+ // 1 So CE%sT 1946 (C2)
+ //
+ // R c 1944 1945 - Ap M>=1 2s 1 S (R1)
+ //
+ // R So 1945 o - May 24 2 2 M (R2)
+ //
+ // When C2 becomes active the time would be before the first rule R2,
+ // giving a 1 hour sys_info. This is not valid and the results need
+ // merging.
+
+ if (__result->end != __sys_info->__info.begin) {
+ // When the UTC gap between the rules is due to the change of
+ // offsets adjust the new time to remove the gap.
+ sys_seconds __end = __result->end - __result->offset;
+ sys_seconds __begin = __sys_info->__info.begin - __sys_info->__info.offset;
+ if (__end == __begin) {
+ __sys_info->__info.begin = __result->end;
+ }
+ }
+ }
+
+ __result = __sys_info->__info;
+ __valid_result = __time >= __result->begin && __time < __result->end;
+ __can_merge = __sys_info->__can_merge;
+ }
+ }
+ __continuation_begin = __result->end;
+ } else {
+ __continuation_begin = __sys_info.error();
+ }
+ }
+ if (__valid_result)
+ return *__result;
+
+ std::__throw_runtime_error("tzdb: corrupt db");
+}
+
+// Is the "__local_time" present in "__first" and "__second". If so the
+// local_info has an ambiguous result.
+[[nodiscard]] static bool
+__is_ambiguous(local_seconds __local_time, const sys_info& __first, const sys_info& __second) {
+ std::chrono::local_seconds __end_first{__first.end.time_since_epoch() + __first.offset};
+ std::chrono::local_seconds __begin_second{__second.begin.time_since_epoch() + __second.offset};
+
+ return __local_time < __end_first && __local_time >= __begin_second;
+}
+
+// Determines the result of the "__local_time". This expects the object
+// "__first" to be earlier in time than "__second".
+[[nodiscard]] static local_info
+__get_info(local_seconds __local_time, const sys_info& __first, const sys_info& __second) {
+ std::chrono::local_seconds __end_first{__first.end.time_since_epoch() + __first.offset};
+ std::chrono::local_seconds __begin_second{__second.begin.time_since_epoch() + __second.offset};
+
+ if (__local_time < __end_first) {
+ if (__local_time >= __begin_second)
+ // |--------|
+ // |------|
+ // ^
+ return {local_info::ambiguous, __first, __second};
+
+ // |--------|
+ // |------|
+ // ^
+ return {local_info::unique, __first, sys_info{}};
+ }
+
+ if (__local_time < __begin_second)
+ // |--------|
+ // |------|
+ // ^
+ return {local_info::nonexistent, __first, __second};
+
+ // |--------|
+ // |------|
+ // ^
+ return {local_info::unique, __second, sys_info{}};
+}
+
+[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI local_info
+time_zone::__get_info(local_seconds __local_time) const {
+ seconds __local_seconds = __local_time.time_since_epoch();
+
+ /* An example of a typical year with a DST switch displayed in local time.
+ *
+ * At the first of April the time goes forward one hour. This means the
+ * time marked with ~~ is not a valid local time. This is represented by the
+ * nonexistent value in local_info.result.
+ *
+ * At the first of November the time goes backward one hour. This means the
+ * time marked with ^^ happens twice. This is represented by the ambiguous
+ * value in local_info.result.
+ *
+ * 2020.11.01 2021.04.01 2021.11.01
+ * offset +05 offset +05 offset +05
+ * save 0s save 1h save 0s
+ * |------------//----------|
+ * |---------//--------------|
+ * |-------------
+ * ~~ ^^
+ *
+ * These shifts can happen due to changes in the current time zone for a
+ * location. For example, Indian/Kerguelen switched only once. In 1950 from an
+ * offset of 0 hours to an offset of +05 hours.
+ *
+ * During all these shifts the UTC time will not have gaps.
+ */
+
+ // The code needs to determine the system time for the local time. There is no
+ // information available. Assume the offset between system time and local time
+ // is 0s. This gives an initial estimate.
+ sys_seconds __guess{__local_seconds};
+ sys_info __info = __get_info(__guess);
+
+ // At this point the offset can be used to determine an estimate for the local
+ // time. Before doing that, determine the offset and validate whether the
+ // local time is the range [chrono::local_seconds::min(),
+ // chrono::local_seconds::max()).
+ if (__local_seconds < 0s && __info.offset > 0s)
+ if (__local_seconds - chrono::local_seconds::min().time_since_epoch() < __info.offset)
+ return {-1, __info, {}};
+
+ if (__local_seconds > 0s && __info.offset < 0s)
+ if (chrono::local_seconds::max().time_since_epoch() - __local_seconds < -__info.offset)
+ return {-2, __info, {}};
+
+ // Based on the information found in the sys_info, the local time can be
+ // converted to a system time. This resulting time can be in the following
+ // locations of the sys_info:
+ //
+ // |---------//--------------|
+ // 1 2.1 2.2 2.3 3
+ //
+ // 1. The estimate is before the returned sys_info object.
+ // The result is either non-existent or unique in the previous sys_info.
+ // 2. The estimate is in the sys_info object
+ // - If the sys_info begin is not sys_seconds::min(), then it might be at
+ // 2.1 and could be ambiguous with the previous or unique.
+ // - If sys_info end is not sys_seconds::max(), then it might be at 2.3
+ // and could be ambiguous with the next or unique.
+ // - Else it is at 2.2 and always unique. This case happens when a
+ // time zone has no transitions. For example, UTC or GMT+1.
+ // 3. The estimate is after the returned sys_info object.
+ // The result is either non-existent or unique in the next sys_info.
+ //
+ // There is no specification where the "middle" starts. Similar issues can
+ // happen when sys_info objects are "short", then "unique in the next" could
+ // become "ambiguous in the next and the one following". Theoretically there
+ // is the option of the following time-line
+ //
+ // |------------|
+ // |----|
+ // |-----------------|
+ //
+ // However the local_info object only has 2 sys_info objects, so this option
+ // is not tested.
+
+ sys_seconds __sys_time{__local_seconds - __info.offset};
+ if (__sys_time < __info.begin)
+ // Case 1 before __info
+ return chrono::__get_info(__local_time, __get_info(__info.begin - 1s), __info);
+
+ if (__sys_time >= __info.end)
+ // Case 3 after __info
+ return chrono::__get_info(__local_time, __info, __get_info(__info.end));
+
+ // Case 2 in __info
+ if (__info.begin != sys_seconds::min()) {
+ // Case 2.1 Not at the beginning, when not ambiguous the result should test
+ // case 2.3.
+ sys_info __prev = __get_info(__info.begin - 1s);
+ if (__is_ambiguous(__local_time, __prev, __info))
+ return {local_info::ambiguous, __prev, __info};
+ }
+
+ if (__info.end == sys_seconds::max())
+ // At the end so it's case 2.2
+ return {local_info::unique, __info, sys_info{}};
+
+ // This tests case 2.2 or case 2.3.
+ return chrono::__get_info(__local_time, __info, __get_info(__info.end));
+}
+
+} // namespace chrono
+
+_LIBCPP_END_NAMESPACE_STD
diff --git a/contrib/libs/cxxsupp/libcxx/src/tzdb.cpp b/contrib/libs/cxxsupp/libcxx/src/experimental/tzdb.cpp
index 0307f754caa..d22de21c998 100644
--- a/contrib/libs/cxxsupp/libcxx/src/tzdb.cpp
+++ b/contrib/libs/cxxsupp/libcxx/src/experimental/tzdb.cpp
@@ -15,7 +15,6 @@
#include <stdexcept>
#include <string>
-#include "include/tzdb/time_zone_link_private.h"
#include "include/tzdb/time_zone_private.h"
#include "include/tzdb/types_private.h"
#include "include/tzdb/tzdb_list_private.h"
@@ -560,7 +559,7 @@ static void __parse_rule(tzdb& __tzdb, __tz::__rules_storage_type& __rules, istr
static void __parse_zone(tzdb& __tzdb, __tz::__rules_storage_type& __rules, istream& __input) {
chrono::__skip_mandatory_whitespace(__input);
- auto __p = std::make_unique<time_zone::__impl>(chrono::__parse_string(__input));
+ auto __p = std::make_unique<time_zone::__impl>(chrono::__parse_string(__input), __rules);
vector<__tz::__continuation>& __continuations = __p->__continuations();
chrono::__skip_mandatory_whitespace(__input);
@@ -581,7 +580,7 @@ static void __parse_link(tzdb& __tzdb, istream& __input) {
string __name = chrono::__parse_string(__input);
chrono::__skip_line(__input);
- __tzdb.links.emplace_back(time_zone_link::__constructor_tag{}, std::move(__name), std::move(__target));
+ __tzdb.links.emplace_back(std::__private_constructor_tag{}, std::move(__name), std::move(__target));
}
static void __parse_tzdata(tzdb& __db, __tz::__rules_storage_type& __rules, istream& __input) {
@@ -622,26 +621,146 @@ static void __parse_tzdata(tzdb& __db, __tz::__rules_storage_type& __rules, istr
}
}
+static void __parse_leap_seconds(vector<leap_second>& __leap_seconds, istream&& __input) {
+ // The file stores dates since 1 January 1900, 00:00:00, we want
+ // seconds since 1 January 1970.
+ constexpr auto __offset = sys_days{1970y / January / 1} - sys_days{1900y / January / 1};
+
+ struct __entry {
+ sys_seconds __timestamp;
+ seconds __value;
+ };
+ vector<__entry> __entries;
+ [&] {
+ while (true) {
+ switch (__input.peek()) {
+ case istream::traits_type::eof():
+ return;
+
+ case ' ':
+ case '\t':
+ case '\n':
+ __input.get();
+ continue;
+
+ case '#':
+ chrono::__skip_line(__input);
+ continue;
+ }
+
+ sys_seconds __date = sys_seconds{seconds{chrono::__parse_integral(__input, false)}} - __offset;
+ chrono::__skip_mandatory_whitespace(__input);
+ seconds __value{chrono::__parse_integral(__input, false)};
+ chrono::__skip_line(__input);
+
+ __entries.emplace_back(__date, __value);
+ }
+ }();
+ // The Standard requires the leap seconds to be sorted. The file
+ // leap-seconds.list usually provides them in sorted order, but that is not
+ // guaranteed so we ensure it here.
+ ranges::sort(__entries, {}, &__entry::__timestamp);
+
+ // The database should contain the number of seconds inserted by a leap
+ // second (1 or -1). So the difference between the two elements is stored.
+ // std::ranges::views::adjacent has not been implemented yet.
+ (void)ranges::adjacent_find(__entries, [&](const __entry& __first, const __entry& __second) {
+ __leap_seconds.emplace_back(
+ std::__private_constructor_tag{}, __second.__timestamp, __second.__value - __first.__value);
+ return false;
+ });
+}
+
void __init_tzdb(tzdb& __tzdb, __tz::__rules_storage_type& __rules) {
filesystem::path __root = chrono::__libcpp_tzdb_directory();
ifstream __tzdata{__root / "tzdata.zi"};
__tzdb.version = chrono::__parse_version(__tzdata);
chrono::__parse_tzdata(__tzdb, __rules, __tzdata);
- std::ranges::sort(__tzdb.zones);
- std::ranges::sort(__tzdb.links);
- std::ranges::sort(__rules, {}, [](const auto& p) { return p.first; });
+ ranges::sort(__tzdb.zones);
+ ranges::sort(__tzdb.links);
+ ranges::sort(__rules, {}, [](const auto& p) { return p.first; });
+
+ // There are two files with the leap second information
+ // - leapseconds as specified by zic
+ // - leap-seconds.list the source data
+ // The latter is much easier to parse, it seems Howard shares that
+ // opinion.
+ chrono::__parse_leap_seconds(__tzdb.leap_seconds, ifstream{__root / "leap-seconds.list"});
+}
+
+#ifdef _WIN32
+[[nodiscard]] static const time_zone* __current_zone_windows(const tzdb& tzdb) {
+ // TODO TZDB Implement this on Windows.
+ std::__throw_runtime_error("unknown time zone");
+}
+#else // ifdef _WIN32
+[[nodiscard]] static const time_zone* __current_zone_posix(const tzdb& tzdb) {
+ // On POSIX systems there are several ways to configure the time zone.
+ // In order of priority they are:
+ // - TZ environment variable
+ // https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08
+ // The documentation is unclear whether or not it's allowed to
+ // change time zone information. For example the TZ string
+ // MST7MDT
+ // this is an entry in tzdata.zi. The value
+ // MST
+ // is also an entry. Is it allowed to use the following?
+ // MST-3
+ // Even when this is valid there is no time_zone record in the
+ // database. Since the library would need to return a valid pointer,
+ // this means the library needs to allocate and leak a pointer.
+ //
+ // - The time zone name is the target of the symlink /etc/localtime
+ // relative to /usr/share/zoneinfo/
+
+ // The algorithm is like this:
+ // - If the environment variable TZ is set and points to a valid
+ // record use this value.
+ // - Else use the name based on the `/etc/localtime` symlink.
+
+ if (const char* __tz = getenv("TZ"))
+ if (const time_zone* __result = tzdb.__locate_zone(__tz))
+ return __result;
+
+ filesystem::path __path = "/etc/localtime";
+ if (!filesystem::exists(__path))
+ std::__throw_runtime_error("tzdb: the symlink '/etc/localtime' does not exist");
+
+ if (!filesystem::is_symlink(__path))
+ std::__throw_runtime_error("tzdb: the path '/etc/localtime' is not a symlink");
+
+ filesystem::path __tz = filesystem::read_symlink(__path);
+ // The path may be a relative path, in that case convert it to an absolute
+ // path based on the proper initial directory.
+ if (__tz.is_relative())
+ __tz = filesystem::canonical("/etc" / __tz);
+
+ string __name = filesystem::relative(__tz, "/usr/share/zoneinfo/");
+ if (const time_zone* __result = tzdb.__locate_zone(__name))
+ return __result;
+
+ std::__throw_runtime_error(("tzdb: the time zone '" + __name + "' is not found in the database").c_str());
}
+#endif // ifdef _WIN32
//===----------------------------------------------------------------------===//
// Public API
//===----------------------------------------------------------------------===//
-_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI tzdb_list& get_tzdb_list() {
+_LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI tzdb_list& get_tzdb_list() {
static tzdb_list __result{new tzdb_list::__impl()};
return __result;
}
+[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI const time_zone* tzdb::__current_zone() const {
+#ifdef _WIN32
+ return chrono::__current_zone_windows(*this);
+#else
+ return chrono::__current_zone_posix(*this);
+#endif
+}
+
_LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI const tzdb& reload_tzdb() {
if (chrono::remote_version() == chrono::get_tzdb().version)
return chrono::get_tzdb();
@@ -649,7 +768,7 @@ _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI const tzdb& reload_tzdb() {
return chrono::get_tzdb_list().__implementation().__load();
}
-_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI string remote_version() {
+_LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI string remote_version() {
filesystem::path __root = chrono::__libcpp_tzdb_directory();
ifstream __tzdata{__root / "tzdata.zi"};
return chrono::__parse_version(__tzdata);
diff --git a/contrib/libs/cxxsupp/libcxx/src/tzdb_list.cpp b/contrib/libs/cxxsupp/libcxx/src/experimental/tzdb_list.cpp
index b99c30a9b9e..b99c30a9b9e 100644
--- a/contrib/libs/cxxsupp/libcxx/src/tzdb_list.cpp
+++ b/contrib/libs/cxxsupp/libcxx/src/experimental/tzdb_list.cpp
diff --git a/contrib/libs/cxxsupp/libcxx/src/filesystem/operations.cpp b/contrib/libs/cxxsupp/libcxx/src/filesystem/operations.cpp
index fa31f05b2d2..fd770e1a4e4 100644
--- a/contrib/libs/cxxsupp/libcxx/src/filesystem/operations.cpp
+++ b/contrib/libs/cxxsupp/libcxx/src/filesystem/operations.cpp
@@ -109,26 +109,23 @@ void __copy(const path& from, const path& to, copy_options options, error_code*
const bool sym_status2 = bool(options & copy_options::copy_symlinks);
error_code m_ec1;
- StatT f_st = {};
+ StatT f_st;
const file_status f =
sym_status || sym_status2 ? detail::posix_lstat(from, f_st, &m_ec1) : detail::posix_stat(from, f_st, &m_ec1);
if (m_ec1)
return err.report(m_ec1);
- StatT t_st = {};
+ StatT t_st;
const file_status t = sym_status ? detail::posix_lstat(to, t_st, &m_ec1) : detail::posix_stat(to, t_st, &m_ec1);
if (not status_known(t))
return err.report(m_ec1);
if (!exists(f) || is_other(f) || is_other(t) || (is_directory(f) && is_regular_file(t)) ||
- detail::stat_equivalent(f_st, t_st)) {
+ (exists(t) && detail::stat_equivalent(f_st, t_st))) {
return err.report(errc::function_not_supported);
}
- if (ec)
- ec->clear();
-
if (is_symlink(f)) {
if (bool(copy_options::skip_symlinks & options)) {
// do nothing
@@ -166,15 +163,15 @@ void __copy(const path& from, const path& to, copy_options options, error_code*
return;
}
error_code m_ec2;
- for (; it != directory_iterator(); it.increment(m_ec2)) {
- if (m_ec2) {
- return err.report(m_ec2);
- }
+ for (; !m_ec2 && it != directory_iterator(); it.increment(m_ec2)) {
__copy(it->path(), to / it->path().filename(), options | copy_options::__in_recursive_copy, ec);
if (ec && *ec) {
return;
}
}
+ if (m_ec2) {
+ return err.report(m_ec2);
+ }
}
}
@@ -936,23 +933,28 @@ path __weakly_canonical(const path& p, error_code* ec) {
--PP;
vector<string_view_t> DNEParts;
- while (PP.State != PathParser::PS_BeforeBegin) {
+ error_code m_ec;
+ while (PP.State_ != PathParser::PS_BeforeBegin) {
tmp.assign(createView(p.native().data(), &PP.RawEntry.back()));
- error_code m_ec;
file_status st = __status(tmp, &m_ec);
if (!status_known(st)) {
return err.report(m_ec);
} else if (exists(st)) {
- result = __canonical(tmp, ec);
+ result = __canonical(tmp, &m_ec);
+ if (m_ec) {
+ return err.report(m_ec);
+ }
break;
}
DNEParts.push_back(*PP);
--PP;
}
- if (PP.State == PathParser::PS_BeforeBegin)
- result = __canonical("", ec);
- if (ec)
- ec->clear();
+ if (PP.State_ == PathParser::PS_BeforeBegin) {
+ result = __canonical("", &m_ec);
+ if (m_ec) {
+ return err.report(m_ec);
+ }
+ }
if (DNEParts.empty())
return result;
for (auto It = DNEParts.rbegin(); It != DNEParts.rend(); ++It)
diff --git a/contrib/libs/cxxsupp/libcxx/src/filesystem/path.cpp b/contrib/libs/cxxsupp/libcxx/src/filesystem/path.cpp
index c89346aa510..b2019521377 100644
--- a/contrib/libs/cxxsupp/libcxx/src/filesystem/path.cpp
+++ b/contrib/libs/cxxsupp/libcxx/src/filesystem/path.cpp
@@ -45,23 +45,23 @@ path& path::replace_extension(path const& replacement) {
string_view_t path::__root_name() const {
auto PP = PathParser::CreateBegin(__pn_);
- if (PP.State == PathParser::PS_InRootName)
+ 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)
+ if (PP.State_ == PathParser::PS_InRootName)
++PP;
- if (PP.State == PathParser::PS_InRootDir)
+ 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) {
+ if (PP.State_ == PathParser::PS_InRootName) {
auto NextCh = PP.peek();
if (NextCh && isSeparator(*NextCh)) {
++PP;
@@ -69,24 +69,24 @@ string_view_t path::__root_path_raw() const {
}
return PP.RawEntry;
}
- if (PP.State == PathParser::PS_InRootDir)
+ 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)
+ while (PP->State_ <= PathParser::PS_InRootName)
++(*PP);
- return PP->State == PathParser::PS_AtEnd;
+ 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)
+ while (PP->State_ <= PathParser::PS_InRootDir)
++(*PP);
- return PP->State == PathParser::PS_AtEnd;
+ return PP->State_ == PathParser::PS_AtEnd;
}
string_view_t path::__relative_path() const {
@@ -248,7 +248,7 @@ path path::lexically_relative(const path& base) const {
auto PP = PathParser::CreateBegin(__pn_);
auto PPBase = PathParser::CreateBegin(base.__pn_);
auto CheckIterMismatchAtBase = [&]() {
- return PP.State != PPBase.State && (PP.inRootPath() || PPBase.inRootPath());
+ return PP.State_ != PPBase.State_ && (PP.inRootPath() || PPBase.inRootPath());
};
if (PP.inRootName() && PPBase.inRootName()) {
if (*PP != *PPBase)
@@ -267,7 +267,7 @@ path path::lexically_relative(const path& base) const {
// 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) {
+ while (PP && PPBase && PP.State_ == PPBase.State_ && *PP == *PPBase) {
++PP;
++PPBase;
}
@@ -380,7 +380,7 @@ 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.__state_ = static_cast<path::iterator::_ParserState>(PP.State_);
it.__entry_ = PP.RawEntry;
it.__stashed_elem_.__assign_view(*PP);
return it;
@@ -396,7 +396,7 @@ path::iterator path::end() const {
path::iterator& path::iterator::__increment() {
PathParser PP(__path_ptr_->native(), __entry_, __state_);
++PP;
- __state_ = static_cast<_ParserState>(PP.State);
+ __state_ = static_cast<_ParserState>(PP.State_);
__entry_ = PP.RawEntry;
__stashed_elem_.__assign_view(*PP);
return *this;
@@ -405,7 +405,7 @@ path::iterator& path::iterator::__increment() {
path::iterator& path::iterator::__decrement() {
PathParser PP(__path_ptr_->native(), __entry_, __state_);
--PP;
- __state_ = static_cast<_ParserState>(PP.State);
+ __state_ = static_cast<_ParserState>(PP.State_);
__entry_ = PP.RawEntry;
__stashed_elem_.__assign_view(*PP);
return *this;
diff --git a/contrib/libs/cxxsupp/libcxx/src/filesystem/path_parser.h b/contrib/libs/cxxsupp/libcxx/src/filesystem/path_parser.h
index 28a8f240e3b..06623696452 100644
--- a/contrib/libs/cxxsupp/libcxx/src/filesystem/path_parser.h
+++ b/contrib/libs/cxxsupp/libcxx/src/filesystem/path_parser.h
@@ -50,14 +50,14 @@ struct PathParser {
const string_view_t Path;
string_view_t RawEntry;
- ParserState State;
+ ParserState State_;
private:
- PathParser(string_view_t P, ParserState State) noexcept : Path(P), State(State) {}
+ 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)) {
+ : Path(P), RawEntry(E), State_(static_cast<ParserState>(S)) {
// S cannot be '0' or PS_BeforeBegin.
}
@@ -84,7 +84,7 @@ public:
if (Start == End)
return makeState(PS_AtEnd);
- switch (State) {
+ switch (State_) {
case PS_BeforeBegin: {
PosPtr TkEnd = consumeRootName(Start, End);
if (TkEnd)
@@ -125,7 +125,7 @@ public:
if (RStart == REnd) // we're decrementing the begin
return makeState(PS_BeforeBegin);
- switch (State) {
+ switch (State_) {
case PS_AtEnd: {
// Try to consume a trailing separator or root directory first.
if (PosPtr SepEnd = consumeAllSeparators(RStart, REnd)) {
@@ -169,7 +169,7 @@ public:
/// \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) {
+ switch (State_) {
case PS_BeforeBegin:
case PS_AtEnd:
return PATHSTR("");
@@ -187,7 +187,7 @@ public:
__libcpp_unreachable();
}
- explicit operator bool() const noexcept { return State != PS_BeforeBegin && State != PS_AtEnd; }
+ explicit operator bool() const noexcept { return State_ != PS_BeforeBegin && State_ != PS_AtEnd; }
PathParser& operator++() noexcept {
increment();
@@ -199,21 +199,21 @@ public:
return *this;
}
- bool atEnd() const noexcept { return State == PS_AtEnd; }
+ bool atEnd() const noexcept { return State_ == PS_AtEnd; }
- bool inRootDir() const noexcept { return State == PS_InRootDir; }
+ bool inRootDir() const noexcept { return State_ == PS_InRootDir; }
- bool inRootName() const noexcept { return State == PS_InRootName; }
+ 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;
+ State_ = NewState;
RawEntry = string_view_t(Start, End - Start);
}
void makeState(ParserState NewState) noexcept {
- State = NewState;
+ State_ = NewState;
RawEntry = {};
}
@@ -224,7 +224,7 @@ private:
/// \brief Return a pointer to the first character after the currently
/// lexed element.
PosPtr getNextTokenStartPos() const noexcept {
- switch (State) {
+ switch (State_) {
case PS_BeforeBegin:
return Path.data();
case PS_InRootName:
@@ -241,7 +241,7 @@ private:
/// \brief Return a pointer to the first character in the currently lexed
/// element.
PosPtr getCurrentTokenStartPos() const noexcept {
- switch (State) {
+ switch (State_) {
case PS_BeforeBegin:
case PS_InRootName:
return &Path.front();
diff --git a/contrib/libs/cxxsupp/libcxx/src/functional.cpp b/contrib/libs/cxxsupp/libcxx/src/functional.cpp
index 570bb78e150..ef53e3e84da 100644
--- a/contrib/libs/cxxsupp/libcxx/src/functional.cpp
+++ b/contrib/libs/cxxsupp/libcxx/src/functional.cpp
@@ -10,9 +10,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-#ifdef _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION
bad_function_call::~bad_function_call() noexcept {}
-#endif
#ifdef _LIBCPP_ABI_BAD_FUNCTION_CALL_GOOD_WHAT_MESSAGE
const char* bad_function_call::what() const noexcept { return "std::bad_function_call"; }
diff --git a/contrib/libs/cxxsupp/libcxx/src/include/overridable_function.h b/contrib/libs/cxxsupp/libcxx/src/include/overridable_function.h
index 7b0fba10f47..10e7a856c3c 100644
--- a/contrib/libs/cxxsupp/libcxx/src/include/overridable_function.h
+++ b/contrib/libs/cxxsupp/libcxx/src/include/overridable_function.h
@@ -13,6 +13,10 @@
#include <__config>
#include <cstdint>
+#if defined(__arm64e__) && __has_feature(ptrauth_calls)
+#error # include <ptrauth.h>
+#endif
+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
@@ -81,6 +85,14 @@ _LIBCPP_HIDE_FROM_ABI bool __is_function_overridden(_Ret (*__fptr)(_Args...)) no
uintptr_t __end = reinterpret_cast<uintptr_t>(&__lcxx_override_end);
uintptr_t __ptr = reinterpret_cast<uintptr_t>(__fptr);
+#if defined(__arm64e__) && __has_feature(ptrauth_calls)
+ // We must pass a void* to ptrauth_strip since it only accepts a pointer type. Also, in particular,
+ // we must NOT pass a function pointer, otherwise we will strip the function pointer, and then attempt
+ // to authenticate and re-sign it when casting it to a uintptr_t again, which will fail because we just
+ // stripped the function pointer. See rdar://122927845.
+ __ptr = reinterpret_cast<uintptr_t>(ptrauth_strip(reinterpret_cast<void*>(__ptr), ptrauth_key_function_pointer));
+#endif
+
// Finally, the function was overridden if it falls outside of the section's bounds.
return __ptr < __start || __ptr > __end;
}
diff --git a/contrib/libs/cxxsupp/libcxx/src/locale.cpp b/contrib/libs/cxxsupp/libcxx/src/locale.cpp
index 1b937dcf970..219575b2047 100644
--- a/contrib/libs/cxxsupp/libcxx/src/locale.cpp
+++ b/contrib/libs/cxxsupp/libcxx/src/locale.cpp
@@ -102,8 +102,6 @@ inline constexpr size_t countof(const T* const begin, const T* const end) {
return static_cast<size_t>(end - begin);
}
-} // namespace
-
string build_name(const string& other, const string& one, locale::category c) {
if (other == "*" || one == "*")
return "*";
@@ -115,6 +113,8 @@ string build_name(const string& other, const string& one, locale::category c) {
return "*";
}
+} // namespace
+
const locale::category locale::none;
const locale::category locale::collate;
const locale::category locale::ctype;
@@ -497,7 +497,7 @@ constinit __no_destroy<locale::__imp>
locale::__imp::classic_locale_imp_(__uninitialized_tag{}); // initialized below in classic()
const locale& locale::classic() {
- static const __no_destroy<locale> classic_locale(__private_tag{}, [] {
+ static const __no_destroy<locale> classic_locale(__private_constructor_tag{}, [] {
// executed exactly once on first initialization of `classic_locale`
locale::__imp::classic_locale_imp_.__emplace(1u);
return &locale::__imp::classic_locale_imp_.__get();
@@ -557,9 +557,9 @@ locale::locale(const locale& other, const locale& one, category c)
string locale::name() const { return __locale_->name(); }
-void locale::__install_ctor(const locale& other, facet* f, long id) {
+void locale::__install_ctor(const locale& other, facet* f, long facet_id) {
if (f)
- __locale_ = new __imp(*other.__locale_, f, id);
+ __locale_ = new __imp(*other.__locale_, f, facet_id);
else
__locale_ = other.__locale_;
__locale_->acquire();
diff --git a/contrib/libs/cxxsupp/libcxx/src/optional.cpp b/contrib/libs/cxxsupp/libcxx/src/optional.cpp
index 6ba63f2d89f..62b474a312b 100644
--- a/contrib/libs/cxxsupp/libcxx/src/optional.cpp
+++ b/contrib/libs/cxxsupp/libcxx/src/optional.cpp
@@ -6,7 +6,6 @@
//
//===----------------------------------------------------------------------===//
-#include <__availability>
#include <optional>
#include <stdexcept>
diff --git a/contrib/libs/cxxsupp/libcxx/src/ostream.cpp b/contrib/libs/cxxsupp/libcxx/src/ostream.cpp
index 443dce9a390..e1a9a4bc1de 100644
--- a/contrib/libs/cxxsupp/libcxx/src/ostream.cpp
+++ b/contrib/libs/cxxsupp/libcxx/src/ostream.cpp
@@ -6,7 +6,6 @@
//
//===----------------------------------------------------------------------===//
-#include <__availability>
#include <__config>
#ifndef _LIBCPP_HAS_NO_FILESYSTEM
# include <fstream>
diff --git a/contrib/libs/cxxsupp/libcxx/src/pstl/libdispatch.cpp b/contrib/libs/cxxsupp/libcxx/src/pstl/libdispatch.cpp
index 52d4afbcce6..3dca702341c 100644
--- a/contrib/libs/cxxsupp/libcxx/src/pstl/libdispatch.cpp
+++ b/contrib/libs/cxxsupp/libcxx/src/pstl/libdispatch.cpp
@@ -7,13 +7,12 @@
//===----------------------------------------------------------------------===//
#include <__algorithm/min.h>
-#include <__algorithm/pstl_backends/cpu_backends/libdispatch.h>
#include <__config>
+#include <__pstl/backends/libdispatch.h>
#include <dispatch/dispatch.h>
_LIBCPP_BEGIN_NAMESPACE_STD
-
-namespace __par_backend::inline __libdispatch {
+namespace __pstl::__libdispatch {
void __dispatch_apply(size_t chunk_count, void* context, void (*func)(void* context, size_t chunk)) noexcept {
::dispatch_apply_f(chunk_count, DISPATCH_APPLY_AUTO, context, func);
@@ -29,7 +28,5 @@ __chunk_partitions __partition_chunks(ptrdiff_t element_count) noexcept {
return partitions;
}
-// NOLINTNEXTLINE(llvm-namespace-comment) // This is https://llvm.org/PR56804
-} // namespace __par_backend::inline __libdispatch
-
+} // namespace __pstl::__libdispatch
_LIBCPP_END_NAMESPACE_STD
diff --git a/contrib/libs/cxxsupp/libcxx/src/random.cpp b/contrib/libs/cxxsupp/libcxx/src/random.cpp
index 93590af310e..14c6f4473d7 100644
--- a/contrib/libs/cxxsupp/libcxx/src/random.cpp
+++ b/contrib/libs/cxxsupp/libcxx/src/random.cpp
@@ -79,10 +79,8 @@ unsigned random_device::operator()() {
char* p = reinterpret_cast<char*>(&r);
while (n > 0) {
ssize_t s = read(__f_, p, n);
- _LIBCPP_SUPPRESS_DEPRECATED_PUSH
if (s == 0)
- __throw_system_error(ENODATA, "random_device got EOF"); // TODO ENODATA -> ENOMSG
- _LIBCPP_SUPPRESS_DEPRECATED_POP
+ __throw_system_error(ENOMSG, "random_device got EOF");
if (s == -1) {
if (errno != EINTR)
__throw_system_error(errno, "random_device got an unexpected error");
diff --git a/contrib/libs/cxxsupp/libcxx/src/support/win32/compiler_rt_shims.cpp b/contrib/libs/cxxsupp/libcxx/src/support/win32/compiler_rt_shims.cpp
new file mode 100644
index 00000000000..ab263224906
--- /dev/null
+++ b/contrib/libs/cxxsupp/libcxx/src/support/win32/compiler_rt_shims.cpp
@@ -0,0 +1,110 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+//
+// This file reimplements builtins that are normally provided by compiler-rt, which is
+// not provided on Windows. This should go away once compiler-rt is shipped on Windows.
+//
+
+#include <cmath>
+#include <complex>
+
+template <class T>
+static std::__complex_t<T> mul_impl(T a, T b, T c, T d) {
+ T __ac = a * c;
+ T __bd = b * d;
+ T __ad = a * d;
+ T __bc = b * c;
+ T __x = __ac - __bd;
+ T __y = __ad + __bc;
+ if (std::isnan(__x) && std::isnan(__y)) {
+ bool recalc = false;
+ if (std::isinf(a) || std::isinf(b)) {
+ a = std::copysign(std::isinf(a) ? T(1) : T(0), a);
+ b = std::copysign(std::isinf(b) ? T(1) : T(0), b);
+ if (std::isnan(c))
+ c = std::copysign(T(0), c);
+ if (std::isnan(d))
+ d = std::copysign(T(0), d);
+ recalc = true;
+ }
+ if (std::isinf(c) || std::isinf(d)) {
+ c = std::copysign(std::isinf(c) ? T(1) : T(0), c);
+ d = std::copysign(std::isinf(d) ? T(1) : T(0), d);
+ if (std::isnan(a))
+ a = std::copysign(T(0), a);
+ if (std::isnan(b))
+ b = std::copysign(T(0), b);
+ recalc = true;
+ }
+ if (!recalc && (std::isinf(__ac) || std::isinf(__bd) || std::isinf(__ad) || std::isinf(__bc))) {
+ if (std::isnan(a))
+ a = std::copysign(T(0), a);
+ if (std::isnan(b))
+ b = std::copysign(T(0), b);
+ if (std::isnan(c))
+ c = std::copysign(T(0), c);
+ if (std::isnan(d))
+ d = std::copysign(T(0), d);
+ recalc = true;
+ }
+ if (recalc) {
+ __x = T(INFINITY) * (a * c - b * d);
+ __y = T(INFINITY) * (a * d + b * c);
+ }
+ }
+ return {__x, __y};
+}
+
+extern "C" _LIBCPP_EXPORTED_FROM_ABI _Complex double __muldc3(double a, double b, double c, double d) {
+ return mul_impl(a, b, c, d);
+}
+
+extern "C" _LIBCPP_EXPORTED_FROM_ABI _Complex float __mulsc3(float a, float b, float c, float d) {
+ return mul_impl(a, b, c, d);
+}
+
+template <class T>
+std::__complex_t<T> div_impl(T a, T b, T c, T d) {
+ int ilogbw = 0;
+ T __logbw = std::logb(std::fmax(std::fabs(c), std::fabs(d)));
+ if (std::isfinite(__logbw)) {
+ ilogbw = static_cast<int>(__logbw);
+ c = std::scalbn(c, -ilogbw);
+ d = std::scalbn(d, -ilogbw);
+ }
+
+ T denom = c * c + d * d;
+ T x = std::scalbn((a * c + b * d) / denom, -ilogbw);
+ T y = std::scalbn((b * c - a * d) / denom, -ilogbw);
+ if (std::isnan(x) && std::isnan(y)) {
+ if ((denom == T(0)) && (!std::isnan(a) || !std::isnan(b))) {
+ x = std::copysign(T(INFINITY), c) * a;
+ y = std::copysign(T(INFINITY), c) * b;
+ } else if ((std::isinf(a) || std::isinf(b)) && std::isfinite(c) && std::isfinite(d)) {
+ a = std::copysign(std::isinf(a) ? T(1) : T(0), a);
+ b = std::copysign(std::isinf(b) ? T(1) : T(0), b);
+ x = T(INFINITY) * (a * c + b * d);
+ y = T(INFINITY) * (b * c - a * d);
+ } else if (std::isinf(__logbw) && __logbw > T(0) && std::isfinite(a) && std::isfinite(b)) {
+ c = std::copysign(std::isinf(c) ? T(1) : T(0), c);
+ d = std::copysign(std::isinf(d) ? T(1) : T(0), d);
+ x = T(0) * (a * c + b * d);
+ y = T(0) * (b * c - a * d);
+ }
+ }
+ return {x, y};
+}
+
+extern "C" _LIBCPP_EXPORTED_FROM_ABI _Complex double __divdc3(double a, double b, double c, double d) {
+ return div_impl(a, b, c, d);
+}
+
+extern "C" _LIBCPP_EXPORTED_FROM_ABI _Complex float __divsc3(float a, float b, float c, float d) {
+ return div_impl(a, b, c, d);
+}
diff --git a/contrib/libs/cxxsupp/libcxx/src/time_zone.cpp b/contrib/libs/cxxsupp/libcxx/src/time_zone.cpp
deleted file mode 100644
index b6bf06a116f..00000000000
--- a/contrib/libs/cxxsupp/libcxx/src/time_zone.cpp
+++ /dev/null
@@ -1,32 +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
-//
-//===----------------------------------------------------------------------===//
-
-// For information see https://libcxx.llvm.org/DesignDocs/TimeZone.html
-
-#include <chrono>
-
-#include "include/tzdb/time_zone_private.h"
-
-_LIBCPP_BEGIN_NAMESPACE_STD
-
-namespace chrono {
-
-[[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI time_zone time_zone::__create(unique_ptr<time_zone::__impl>&& __p) {
- _LIBCPP_ASSERT_NON_NULL(__p != nullptr, "initialized time_zone without a valid pimpl object");
- time_zone result;
- result.__impl_ = std::move(__p);
- return result;
-}
-
-_LIBCPP_EXPORTED_FROM_ABI time_zone::~time_zone() = default;
-
-[[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI string_view time_zone::__name() const noexcept { return __impl_->__name(); }
-
-} // namespace chrono
-
-_LIBCPP_END_NAMESPACE_STD