diff --git a/CMakeLists.txt b/CMakeLists.txt index 5064973ba73..c5663853b04 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,8 +6,8 @@ cmake_minimum_required(VERSION 3.31.0) set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) project(msvc_standard_libraries LANGUAGES CXX) -if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.44.35211") - message(FATAL_ERROR "The STL must be built with VS 2022 17.14.8 Preview 1 or later.") +if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.44.35214") + message(FATAL_ERROR "The STL must be built with VS 2022 17.14.12 Preview 1 or later.") endif() include(CheckCXXSourceCompiles) @@ -18,7 +18,7 @@ int main() {} ]=] WINDOWS_SDK_VERSION_CHECK) if(NOT WINDOWS_SDK_VERSION_CHECK) - message(FATAL_ERROR "The STL must be built with the Windows 11 SDK (10.0.26100.3916) or later. Make sure it's available by selecting it in the Individual Components tab of the VS Installer.") + message(FATAL_ERROR "The STL must be built with the Windows 11 SDK (10.0.26100.4188) or later. Make sure it's available by selecting it in the Individual Components tab of the VS Installer.") endif() if(NOT DEFINED VCLIBS_TARGET_ARCHITECTURE) @@ -92,20 +92,18 @@ set(STL_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/out/lib/${VCLIBS_I386_OR set(STL_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/out/lib/${VCLIBS_I386_OR_AMD64}") set(STL_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/out/bin/${VCLIBS_I386_OR_AMD64}") -# TRANSITION, update internal crt-common.settings.targets, atlmfc.settings.targets, and fe-components.settings.targets -# from NTDDI_WIN10_NI to NTDDI_WIN11_GE when the internal WinSDK is updated. add_compile_definitions( _ALLOW_ITERATOR_DEBUG_LEVEL_MISMATCH WIN32_LEAN_AND_MEAN STRICT _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS _WIN32_WINNT=0x0A00 NTDDI_VERSION=NTDDI_WIN11_GE) if(STL_USE_ANALYZE) - # TRANSITION, Windows SDK 10.0.26100.3916 emits + # TRANSITION, Windows SDK 10.0.26100.4188 emits # "warning C6553: The annotation for function 'LCMapStringEx' on _Param_(9) does not apply to a value type." # Reported as OS-40109504 "Windows SDK: incorrect SAL annotations on functions the STL uses". add_compile_options("$<$:/analyze:autolog-;/wd6553>") if(VCLIBS_TARGET_ARCHITECTURE STREQUAL "arm64ec") - # TRANSITION, Windows SDK 10.0.26100.3916 emits + # TRANSITION, Windows SDK 10.0.26100.4188 emits # "warning C28301: No annotations for first declaration of 'meow'" # for various intrinsics when building for ARM64EC. add_compile_options("$<$:/wd28301>") diff --git a/README.md b/README.md index d7b661218fb..ea5eb44ef28 100644 --- a/README.md +++ b/README.md @@ -141,8 +141,8 @@ Just try to follow these rules, so we can spend more time fixing bugs and implem # How To Build With The Visual Studio IDE -1. Install Visual Studio 2022 17.14.8 Preview 1 or later. - * Select "Windows 11 SDK (10.0.26100.3916)" in the VS Installer. +1. Install Visual Studio 2022 17.14.12 Preview 1 or later. + * Select "Windows 11 SDK (10.0.26100.4188)" in the VS Installer. * Select "MSVC v143 - VS 2022 C++ ARM64/ARM64EC build tools (Latest)" in the VS Installer if you would like to build the ARM64/ARM64EC target. * We recommend selecting "C++ CMake tools for Windows" in the VS Installer. @@ -158,8 +158,8 @@ Just try to follow these rules, so we can spend more time fixing bugs and implem # How To Build With A Native Tools Command Prompt -1. Install Visual Studio 2022 17.14.8 Preview 1 or later. - * Select "Windows 11 SDK (10.0.26100.3916)" in the VS Installer. +1. Install Visual Studio 2022 17.14.12 Preview 1 or later. + * Select "Windows 11 SDK (10.0.26100.4188)" in the VS Installer. * Select "MSVC v143 - VS 2022 C++ ARM64/ARM64EC build tools (Latest)" in the VS Installer if you would like to build the ARM64/ARM64EC target. * We recommend selecting "C++ CMake tools for Windows" in the VS Installer. diff --git a/azure-devops/config.yml b/azure-devops/config.yml index 7f1207a556b..d377651872b 100644 --- a/azure-devops/config.yml +++ b/azure-devops/config.yml @@ -5,7 +5,7 @@ variables: - name: poolName - value: 'StlBuild-2025-07-09T1240-Pool' + value: 'StlBuild-2025-08-12T1208-Pool' readonly: true - name: poolDemands value: 'EnableSpotVM -equals false' diff --git a/azure-devops/provision-image.ps1 b/azure-devops/provision-image.ps1 index de01c296ff3..a27553e32eb 100644 --- a/azure-devops/provision-image.ps1 +++ b/azure-devops/provision-image.ps1 @@ -42,7 +42,7 @@ foreach ($workload in $VisualStudioWorkloads) { $PowerShellUrl = 'https://github.com/PowerShell/PowerShell/releases/download/v7.5.2/PowerShell-7.5.2-win-x64.msi' $PowerShellArgs = @('/quiet', '/norestart') -$PythonUrl = 'https://www.python.org/ftp/python/3.13.5/python-3.13.5-amd64.exe' +$PythonUrl = 'https://www.python.org/ftp/python/3.13.6/python-3.13.6-amd64.exe' $PythonArgs = @('/quiet', 'InstallAllUsers=1', 'PrependPath=1', 'CompileAll=1', 'Include_doc=0') $CudaUrl = 'https://developer.download.nvidia.com/compute/cuda/12.4.0/local_installers/cuda_12.4.0_551.61_windows.exe' diff --git a/benchmarks/src/regex_search.cpp b/benchmarks/src/regex_search.cpp index bc6a3d12537..19018fc80f2 100644 --- a/benchmarks/src/regex_search.cpp +++ b/benchmarks/src/regex_search.cpp @@ -8,13 +8,14 @@ #include "lorem.hpp" using namespace std; +using namespace regex_constants; -void bm_lorem_search(benchmark::State& state, const char* pattern) { +void bm_lorem_search(benchmark::State& state, const char* pattern, syntax_option_type syntax = ECMAScript) { string repeated_lorem{lorem_ipsum}; for (long long i = 0; i < state.range(); ++i) { repeated_lorem += repeated_lorem; } - regex re{pattern}; + regex re{pattern, syntax}; for (auto _ : state) { benchmark::DoNotOptimize(repeated_lorem); @@ -33,6 +34,7 @@ void bm_lorem_search(benchmark::State& state, const char* pattern) { BENCHMARK_CAPTURE(bm_lorem_search, "^bibe", "^bibe")->Arg(2)->Arg(3)->Arg(4); BENCHMARK_CAPTURE(bm_lorem_search, "bibe", "bibe")->Arg(2)->Arg(3)->Arg(4); +BENCHMARK_CAPTURE(bm_lorem_search, "bibe".collate, "bibe", regex_constants::collate)->Arg(2)->Arg(3)->Arg(4); BENCHMARK_CAPTURE(bm_lorem_search, "(bibe)", "(bibe)")->Arg(2)->Arg(3)->Arg(4); BENCHMARK_CAPTURE(bm_lorem_search, "(bibe)+", "(bibe)+")->Arg(2)->Arg(3)->Arg(4); BENCHMARK_CAPTURE(bm_lorem_search, "(?:bibe)+", "(?:bibe)+")->Arg(2)->Arg(3)->Arg(4); diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 195166ab1f1..d8ac5859f25 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -395,6 +395,7 @@ _STD_BEGIN static_assert(_Is_ranges_bidi_iter_v<_Iter>, "This algorithm requires bidirectional iterators or stronger.") _INLINE_VAR constexpr int _ISORT_MAX = 32; // maximum size for insertion sort +// If _ISORT_MAX is ever changed from 32 == 2^5, re-analyze the implementation of stable_sort for integer overflow. template constexpr _Iter_diff_t<_It> _Isort_max{_ISORT_MAX}; @@ -2274,8 +2275,8 @@ namespace ranges { _First = _STD move(_Mid); ++_First; - using _Uty = _Make_unsigned_like_t>; - if (static_cast<_Uty>(_Skip) <= (static_cast<_Uty>(-1) >> 1)) { + constexpr auto _Half_max = (numeric_limits>::max)() / 2; + if (_Skip <= _Half_max) { _Skip <<= 1; } } @@ -9219,13 +9220,24 @@ void _Buffered_merge_sort_unchecked(const _BidIt _First, const _BidIt _Last, con auto _Chunk = _Isort_max<_BidIt>; for (;;) { // unconditionally merge elements back into the source buffer + + // _Chunk starts at 2^5 and is doubled twice in this loop. + // The first doubling (to 2^6, 2^8, 2^10, ...) doesn't check for overflow as it doesn't pose a risk. + // The second doubling (to 2^7, 2^9, 2^11, ..., 2^15, ..., 2^31, ...) defends against overflow below. _Chunk <<= 1; _STD _Chunked_merge_unchecked(_Temp_ptr, _Temp_ptr + _Count, _First, static_cast(_Chunk), static_cast(_Count), _Pred); - _Chunk <<= 1; - if (_Count <= _Chunk) { // if the input would be a single chunk, it's already sorted and we're done - return; + + // This is equivalent to doubling _Chunk followed by returning when `_Count <= _Chunk`, + // except that it doesn't risk overflowing. + // Note that returning when `_Count / 2 <= _Chunk` before doubling _Chunk + // would behave differently for odd _Count due to truncating integer division. + // Returning when `(_Count - 1) / 2 < _Chunk` correctly handles both even and odd _Count. + // We have an early return for small _Count above, so `_Count - 1` is safe to form. + if ((_Count - 1) / 2 < _Chunk) { + return; // if the input would be a single chunk, it's already sorted and we're done } + _Chunk <<= 1; // more merges necessary; merge to temporary buffer _STD _Chunked_merge_unchecked(_First, _Last, _Temp_ptr, _Chunk, _Count, _Pred); @@ -9391,12 +9403,23 @@ namespace ranges { ptrdiff_t _Chunk_size = _ISORT_MAX; for (;;) { // unconditionally merge elements back into the source buffer + + // _Chunk_size starts at 2^5 and is doubled twice in this loop. + // The first doubling (to 2^6, 2^8, 2^10, ...) doesn't check for overflow as it doesn't pose a risk. + // The second doubling (to 2^7, 2^9, 2^11, ..., 2^15, ..., 2^31, ...) defends against overflow below. _Chunk_size <<= 1; _Chunked_merge_common(_Temp_ptr, _Temp_ptr + _Count, _First, _Chunk_size, _Count, _Pred, _Proj); - _Chunk_size <<= 1; - if (_Count <= _Chunk_size) { // if the input would be a single chunk, it's already sorted and we're done - return; + + // This is equivalent to doubling _Chunk_size followed by returning when `_Count <= _Chunk_size`, + // except that it doesn't risk overflowing. + // Note that returning when `_Count / 2 <= _Chunk_size` before doubling _Chunk_size + // would behave differently for odd _Count due to truncating integer division. + // Returning when `(_Count - 1) / 2 < _Chunk_size` correctly handles both even and odd _Count. + // We have an early return for small _Count above, so `_Count - 1` is safe to form. + if ((_Count - 1) / 2 < _Chunk_size) { + return; // if the input would be a single chunk, it's already sorted and we're done } + _Chunk_size <<= 1; // more merges necessary; merge to temporary buffer _Chunked_merge_common(_First, _Last, _Temp_ptr, _Chunk_size, _Count, _Pred, _Proj); diff --git a/stl/inc/chrono b/stl/inc/chrono index dd1dec49d1a..7bbc0ea063a 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -46,7 +46,7 @@ _STD_BEGIN #if _HAS_CXX17 _NODISCARD inline int _Check_convert_result(const __std_fs_convert_result _Result) { if (_Result._Err != __std_win_error::_Success) { - _Throw_system_error_from_std_win_error(_Result._Err); + _STD _Throw_system_error_from_std_win_error(_Result._Err); } return _Result._Len; @@ -59,17 +59,17 @@ _NODISCARD basic_string _Convert_w if (!_Input.empty()) { if (!_STD _In_range(_Input.size())) { - _Throw_system_error(errc::invalid_argument); + _STD _Throw_system_error(errc::invalid_argument); } - const int _Len = _Check_convert_result( - __std_fs_convert_wide_to_narrow(_Code_page, _Input.data(), static_cast(_Input.size()), nullptr, 0)); + const int _Len = _STD _Check_convert_result( + ::__std_fs_convert_wide_to_narrow(_Code_page, _Input.data(), static_cast(_Input.size()), nullptr, 0)); _Output.resize(static_cast(_Len)); const auto _Data_as_char = reinterpret_cast(_Output.data()); - (void) _Check_convert_result(__std_fs_convert_wide_to_narrow( + (void) _STD _Check_convert_result(::__std_fs_convert_wide_to_narrow( _Code_page, _Input.data(), static_cast(_Input.size()), _Data_as_char, _Len)); } @@ -86,7 +86,7 @@ namespace chrono { static constexpr bool is_steady = false; _NODISCARD static time_point now() noexcept { // get current time - return time_point(duration(_Xtime_get_ticks())); + return time_point(duration(::_Xtime_get_ticks())); } _NODISCARD static __time64_t to_time_t(const time_point& _Time) noexcept { // convert to __time64_t @@ -157,22 +157,22 @@ namespace chrono { *--_Rnext = 's'; *--_Rnext = ']'; if (_Den != 1) { - _Rnext = _UIntegral_to_buff(_Rnext, static_cast(_Den)); + _Rnext = _STD _UIntegral_to_buff(_Rnext, static_cast(_Den)); *--_Rnext = '/'; } - _Rnext = _UIntegral_to_buff(_Rnext, static_cast(_Num)); + _Rnext = _STD _UIntegral_to_buff(_Rnext, static_cast(_Num)); *--_Rnext = '['; return _Rnext; } template void _Write_unit_suffix(basic_ostream<_CharT, _Traits>& _Os) { - constexpr auto _Suffix = _Get_literal_unit_suffix<_CharT, _Period>(); + constexpr auto _Suffix = _CHRONO _Get_literal_unit_suffix<_CharT, _Period>(); if constexpr (_Suffix == nullptr) { _CharT _Buffer[2 * (numeric_limits::digits10 + 1) + 5] = {}; // 2 numbers + "[/]s\0" const _CharT* const _Begin = - _Get_general_unit_suffix<_CharT>(_STD end(_Buffer), _Period::num, _Period::den); + _CHRONO _Get_general_unit_suffix<_CharT>(_STD end(_Buffer), _Period::num, _Period::den); _Os << _Begin; } else { _Os << _Suffix; @@ -187,7 +187,7 @@ namespace chrono { _Sstr.imbue(_Os.getloc()); _Sstr.precision(_Os.precision()); _Sstr << _Dur.count(); - _Write_unit_suffix<_Period>(_Sstr); + _CHRONO _Write_unit_suffix<_Period>(_Sstr); return _Os << _Sstr.str(); } @@ -831,7 +831,7 @@ namespace chrono { return false; } - return _Day >= _CHRONO day{1} && _Day <= _Last_day(_Year, _Month); + return _Day >= _CHRONO day{1} && _Day <= _CHRONO _Last_day(_Year, _Month); } _NODISCARD constexpr int _Calculate_weekday() const noexcept { @@ -1095,7 +1095,7 @@ namespace chrono { return _Month_day_last; } _NODISCARD constexpr day day() const noexcept { - return _Last_day(year(), month()); + return _CHRONO _Last_day(year(), month()); } _NODISCARD constexpr operator sys_days() const noexcept { @@ -1236,7 +1236,8 @@ namespace chrono { const sys_days _First_of_month = year_month_day{_Year, _Month, day{1}}; const days _First_weekday = weekday() - _CHRONO weekday{_First_of_month} + days{1}; const days _Last = _First_weekday + days{28}; - return static_cast(_Last.count()) <= static_cast(_Last_day(_Year, _Month)); + return static_cast(_Last.count()) + <= static_cast(_CHRONO _Last_day(_Year, _Month)); } private: @@ -1574,10 +1575,11 @@ namespace chrono { } template - constexpr bool - _Duration_underflows_with = !treat_as_floating_point_v - && _From::period::den / _Gcd(_From::period::den, _To::period::den) - > INTMAX_MAX / (_To::period::num / _Gcd(_From::period::num, _To::period::num)); + constexpr bool _Duration_underflows_with = !treat_as_floating_point_v + && _From::period::den / _STD _Gcd(_From::period::den, _To::period::den) + > INTMAX_MAX + / (_To::period::num + / _STD _Gcd(_From::period::num, _To::period::num)); template _NODISCARD constexpr _To _Duration_cast_underflow_to_zero(const _From& _Dur) { @@ -1627,21 +1629,23 @@ namespace chrono { return _Result > 18u ? 6u : _Result; }(); using precision = - duration, ratio<1, _Pow10(fractional_width)>>; + duration, ratio<1, _CHRONO _Pow10(fractional_width)>>; constexpr hh_mm_ss() noexcept : hh_mm_ss{_Duration::zero()} {} constexpr explicit hh_mm_ss(_Duration _Dur) : _Is_neg{_Dur < _Duration::zero()}, - _Hours{_Duration_cast_underflow_to_zero<_CHRONO hours>(_CHRONO abs(_Dur))}, - _Mins{_Duration_cast_underflow_to_zero<_CHRONO minutes>( - _Remove_duration_part<_CHRONO hours>(_CHRONO abs(_Dur)))}, - _Secs{_Duration_cast_underflow_to_zero<_CHRONO seconds>( - _Remove_duration_part<_CHRONO minutes>(_Remove_duration_part<_CHRONO hours>(_CHRONO abs(_Dur))))} { + _Hours{_CHRONO _Duration_cast_underflow_to_zero<_CHRONO hours>(_CHRONO abs(_Dur))}, + _Mins{_CHRONO _Duration_cast_underflow_to_zero<_CHRONO minutes>( + _CHRONO _Remove_duration_part<_CHRONO hours>(_CHRONO abs(_Dur)))}, + _Secs{_CHRONO _Duration_cast_underflow_to_zero<_CHRONO seconds>( + _CHRONO _Remove_duration_part<_CHRONO minutes>( + _CHRONO _Remove_duration_part<_CHRONO hours>(_CHRONO abs(_Dur))))} { if constexpr (treat_as_floating_point_v) { // no need to deal with underflow here, because floating durations allow it _Sub_secs = _CHRONO abs(_Dur) - hours() - minutes() - seconds(); } else { - _Sub_secs = _CHRONO duration_cast(_Remove_duration_part<_CHRONO seconds>(_CHRONO abs(_Dur))); + _Sub_secs = + _CHRONO duration_cast(_CHRONO _Remove_duration_part<_CHRONO seconds>(_CHRONO abs(_Dur))); } } @@ -1777,11 +1781,11 @@ namespace chrono { unique_ptr<_Tzdb_info, _Tzdb_deleter<_Tzdb_info>> _Info{_Raw_ptr}; if (_Info == nullptr) { - _Xbad_alloc(); + _STD _Xbad_alloc(); } else if (_Info->_Err == __std_tzdb_error::_Win_error) { - _XGetLastError(); + _STD _XGetLastError(); } else if (_Info->_Err == __std_tzdb_error::_Icu_error) { - _Xruntime_error("Internal error loading IANA database information"); + _STD _Xruntime_error("Internal error loading IANA database information"); } return _Info; @@ -1818,9 +1822,9 @@ namespace chrono { _NODISCARD sys_time> to_sys(const local_time<_Duration>& _Local) const { const auto _Info = get_info(_Local); if (_Info.result == local_info::nonexistent) { - _Throw_nonexistent_local_time(_Local, _Info); + _CHRONO _Throw_nonexistent_local_time(_Local, _Info); } else if (_Info.result == local_info::ambiguous) { - _Throw_ambiguous_local_time(_Local, _Info); + _CHRONO _Throw_ambiguous_local_time(_Local, _Info); } return sys_time>{_Local.time_since_epoch() - _Info.first.offset}; @@ -1862,8 +1866,8 @@ namespace chrono { const auto _Tz_len = _Name.size(); - const auto _Info = - _Make_unique_tzdb_info<__std_tzdb_get_sys_info>(_Tz_arg.c_str(), _Tz_len, _Internal_dur.count()); + const auto _Info = _CHRONO _Make_unique_tzdb_info<__std_tzdb_get_sys_info>( + _Tz_arg.c_str(), _Tz_len, _Internal_dur.count()); constexpr auto _Min_internal = _CHRONO duration_cast<_Internal_duration>(_Min_seconds.time_since_epoch()).count(); @@ -2098,7 +2102,7 @@ namespace chrono { // [time.zone.db] _NODISCARD inline string _Tzdb_generate_current_zone() { - auto _Info = _Make_unique_tzdb_info<__std_tzdb_get_current_zone>(); + auto _Info = _CHRONO _Make_unique_tzdb_info<__std_tzdb_get_current_zone>(); return _Info->_Tz_name; } @@ -2123,29 +2127,29 @@ namespace chrono { bool _All_ls_positive; _NODISCARD const time_zone* locate_zone(string_view _Tz_name) const { - auto _Tz = _Locate_zone_impl(zones, _Tz_name); + auto _Tz = _CHRONO _Locate_zone_impl(zones, _Tz_name); if (_Tz != nullptr) { return _Tz; } - const auto _Link = _Locate_zone_impl(links, _Tz_name); + const auto _Link = _CHRONO _Locate_zone_impl(links, _Tz_name); if (_Link != nullptr) { - _Tz = _Locate_zone_impl(zones, _Link->target()); + _Tz = _CHRONO _Locate_zone_impl(zones, _Link->target()); if (_Tz != nullptr) { return _Tz; } } - _Xruntime_error("unable to locate time_zone with given name"); + _STD _Xruntime_error("unable to locate time_zone with given name"); } _NODISCARD const time_zone* current_zone() const { - return locate_zone(_Tzdb_generate_current_zone()); + return locate_zone(_CHRONO _Tzdb_generate_current_zone()); } }; _NODISCARD inline tuple, vector> _Tzdb_generate_time_zones() { - auto _Info = _Make_unique_tzdb_info<__std_tzdb_get_time_zones>(); + auto _Info = _CHRONO _Make_unique_tzdb_info<__std_tzdb_get_time_zones>(); vector _Time_zones; vector _Time_zone_links; @@ -2204,12 +2208,12 @@ namespace chrono { size_t _Reg_post_2018_ls_size; // number of post-2018 LSs found in the registry unique_ptr<__std_tzdb_leap_info[], _Tzdb_deleter<__std_tzdb_leap_info[]>> _Reg_ls_data{ - __std_tzdb_get_leap_seconds(_Known_post_2018_ls_size, &_Reg_post_2018_ls_size)}; + ::__std_tzdb_get_leap_seconds(_Known_post_2018_ls_size, &_Reg_post_2018_ls_size)}; if (_Reg_post_2018_ls_size > _Known_post_2018_ls_size && !_Reg_ls_data) { - _Xbad_alloc(); // registry has new data, but failed to allocate storage + _STD _Xbad_alloc(); // registry has new data, but failed to allocate storage } else if (_Reg_post_2018_ls_size == 0 && _Reg_ls_data) { - _XGetLastError(); // allocated storage for registry data, but failed to read + _STD _XGetLastError(); // allocated storage for registry data, but failed to read } const size_t _New_size = _Pre_2018_count + _Reg_post_2018_ls_size; // total size with registry data @@ -2257,8 +2261,8 @@ namespace chrono { tzdb_list& operator=(const tzdb_list&) = delete; explicit tzdb_list(_Secret_tzdb_list_construct_tag) { - auto [_Icu_version, _Zones, _Links] = _Tzdb_generate_time_zones(); - auto [_Leap_sec, _All_ls_positive] = _Tzdb_generate_leap_seconds(0); + auto [_Icu_version, _Zones, _Links] = _CHRONO _Tzdb_generate_time_zones(); + auto [_Leap_sec, _All_ls_positive] = _CHRONO _Tzdb_generate_leap_seconds(0); auto _Version = _Icu_version + "." + _STD to_string(_Leap_sec.size()); // TRANSITION, NVCC (was DevCom-10732572), should call emplace_front with construction arguments _Tzdb_list.emplace_front(tzdb{ @@ -2301,7 +2305,8 @@ namespace chrono { const tzdb& _Reload() { _Unique_lock _Lk(_Tzdb_mutex); - auto [_Leap_sec, _All_ls_positive] = _Tzdb_generate_leap_seconds(_Tzdb_list.front().leap_seconds.size()); + auto [_Leap_sec, _All_ls_positive] = + _CHRONO _Tzdb_generate_leap_seconds(_Tzdb_list.front().leap_seconds.size()); if (!_Leap_sec.empty()) { const auto& _Tzdb = _Tzdb_list.front(); @@ -2317,7 +2322,7 @@ namespace chrono { _Links.emplace_back(_Secret_time_zone_link_construct_tag{}, _Link.name(), _Link.target()); } - auto _Version = _Tzdb_update_version(_Tzdb.version, _Leap_sec.size()); + auto _Version = _CHRONO _Tzdb_update_version(_Tzdb.version, _Leap_sec.size()); // TRANSITION, NVCC (was DevCom-10732572), should call emplace_front with construction arguments _Tzdb_list.emplace_front(tzdb{ _STD move(_Version), _STD move(_Zones), _STD move(_Links), _STD move(_Leap_sec), _All_ls_positive}); @@ -2331,14 +2336,14 @@ namespace chrono { struct _NODISCARD _Shared_lock { explicit _Shared_lock(_Smtx_t& _Mtx_) : _Mtx{&_Mtx_} { - _Smtx_lock_shared(_Mtx); + ::_Smtx_lock_shared(_Mtx); } _Shared_lock(const _Shared_lock&) = delete; _Shared_lock& operator=(const _Shared_lock&) = delete; ~_Shared_lock() { - _Smtx_unlock_shared(_Mtx); + ::_Smtx_unlock_shared(_Mtx); } _Smtx_t* _Mtx; @@ -2346,14 +2351,14 @@ namespace chrono { struct _NODISCARD _Unique_lock { explicit _Unique_lock(_Smtx_t& _Mtx_) : _Mtx{&_Mtx_} { - _Smtx_lock_exclusive(_Mtx); + ::_Smtx_lock_exclusive(_Mtx); } _Unique_lock(const _Unique_lock&) = delete; _Unique_lock& operator=(const _Unique_lock&) = delete; ~_Unique_lock() { - _Smtx_unlock_exclusive(_Mtx); + ::_Smtx_unlock_exclusive(_Mtx); } _Smtx_t* _Mtx; @@ -2368,20 +2373,20 @@ namespace chrono { return *_Tzdb_ptr; } - auto _My_tzdb = static_cast(__std_calloc_crt(1, sizeof(tzdb_list))); + auto _My_tzdb = static_cast(::__std_calloc_crt(1, sizeof(tzdb_list))); if (_My_tzdb == nullptr) { - _Xruntime_error("bad allocation"); // not bad_alloc, see N4950 [time.zone.db.access]/4 + _STD _Xruntime_error("bad allocation"); // not bad_alloc, see N4950 [time.zone.db.access]/4 } _TRY_BEGIN _STD construct_at(_My_tzdb, _Secret_tzdb_list_construct_tag{}); _CATCH(const runtime_error&) - __std_free_crt(_My_tzdb); + ::__std_free_crt(_My_tzdb); _RERAISE; _CATCH(const exception& _Except) #if _HAS_EXCEPTIONS - __std_free_crt(_My_tzdb); - _Xruntime_error(_Except.what()); + ::__std_free_crt(_My_tzdb); + _STD _Xruntime_error(_Except.what()); #endif // _HAS_EXCEPTIONS _CATCH_END @@ -2389,7 +2394,7 @@ namespace chrono { _Tzdb_ptr = _My_tzdb; } else { _STD destroy_at(_My_tzdb); - __std_free_crt(_My_tzdb); + ::__std_free_crt(_My_tzdb); } return *_Tzdb_ptr; @@ -2414,7 +2419,7 @@ namespace chrono { _RERAISE; _CATCH(const exception& _Except) #if _HAS_EXCEPTIONS - _Xruntime_error(_Except.what()); + _STD _Xruntime_error(_Except.what()); #endif // _HAS_EXCEPTIONS _CATCH_END } @@ -2422,8 +2427,8 @@ namespace chrono { _EXPORT_STD _NODISCARD inline string remote_version() { const auto& _Tzdb = _CHRONO get_tzdb(); const auto& _Version = _Tzdb.version; - const auto [_Leap_sec, _Ignored] = _Tzdb_generate_leap_seconds(_Tzdb.leap_seconds.size()); - return _Leap_sec.empty() ? _Version : _Tzdb_update_version(_Version, _Leap_sec.size()); + const auto [_Leap_sec, _Ignored] = _CHRONO _Tzdb_generate_leap_seconds(_Tzdb.leap_seconds.size()); + return _Leap_sec.empty() ? _Version : _CHRONO _Tzdb_update_version(_Version, _Leap_sec.size()); } // [time.zone.zonedtraits] @@ -2837,7 +2842,7 @@ namespace filesystem { static constexpr bool is_steady = false; _NODISCARD static time_point now() noexcept { // get current time; undo epoch adjustment - return time_point(duration(_Xtime_get_ticks() + __std_fs_file_time_epoch_adjustment)); // TRANSITION, ABI + return time_point(duration(::_Xtime_get_ticks() + __std_fs_file_time_epoch_adjustment)); // TRANSITION, ABI } #if _HAS_CXX20 @@ -3061,7 +3066,7 @@ namespace chrono { } template - constexpr auto _Clock_cast_choice = _Choose_clock_cast<_DestClock, _SourceClock, _Duration>(); + constexpr auto _Clock_cast_choice = _CHRONO _Choose_clock_cast<_DestClock, _SourceClock, _Duration>(); _EXPORT_STD template requires (_Clock_cast_choice<_DestClock, _SourceClock, _Duration> != _Clock_cast_strategy::_None) @@ -3665,7 +3670,7 @@ namespace chrono { } } - const auto _Offset = _It == _Ls_vector.begin() ? seconds{0} : _Prev_iter(_It)->_Elapsed(); + const auto _Offset = _It == _Ls_vector.begin() ? seconds{0} : _STD _Prev_iter(_It)->_Elapsed(); _Dur += _CHRONO duration_cast<_DurationType>(_Offset); if (_Original_leap == _Leap_second_rep::_File_time) { @@ -4787,7 +4792,7 @@ public: // same as _Specs_setter constexpr void _On_fill(basic_string_view<_CharT> _Sv) { if (_Sv.size() > _STD size(_Specs._Fill)) { - _Throw_format_error("Invalid fill (too long)."); + _STD _Throw_format_error("Invalid fill (too long)."); } const auto _Pos = _STD _Copy_unchecked(_Sv._Unchecked_begin(), _Sv._Unchecked_end(), _Specs._Fill); @@ -4833,11 +4838,11 @@ public: constexpr void _On_conversion_spec(char _Modifier, _CharT _Type) { if (_Modifier != '\0' && _Modifier != 'E' && _Modifier != 'O') { - _Throw_format_error("Invalid modifier specification."); + _STD _Throw_format_error("Invalid modifier specification."); } if (_Type < 0 || _Type > (numeric_limits::max)()) { - _Throw_format_error("Invalid type specification."); + _STD _Throw_format_error("Invalid type specification."); } _Chrono_spec<_CharT> _Conv_spec{._Modifier = _Modifier, ._Type = static_cast(_Type)}; @@ -4855,7 +4860,7 @@ private: _NODISCARD static constexpr int _Verify_dynamic_arg_index_in_range(const size_t _Idx) { if (!_STD in_range(_Idx)) { - _Throw_format_error("Dynamic width or precision index too large."); + _STD _Throw_format_error("Dynamic width or precision index too large."); } return static_cast(_Idx); @@ -4867,7 +4872,7 @@ template _Callbacks_type> _NODISCARD constexpr const _CharT* _Parse_conversion_specs( const _CharT* _Begin, const _CharT* _End, _Callbacks_type&& _Callbacks) { if (_Begin == _End || *_Begin == '}') { - _Throw_format_error("Invalid format string."); + _STD _Throw_format_error("Invalid format string."); } char _Mod = '\0'; @@ -4877,7 +4882,7 @@ _NODISCARD constexpr const _CharT* _Parse_conversion_specs( _Mod = static_cast(_Ch); ++_Begin; if (_Begin == _End || *_Begin == '}') { - _Throw_format_error("Invalid format string - missing type after modifier."); + _STD _Throw_format_error("Invalid format string - missing type after modifier."); } } @@ -4894,18 +4899,18 @@ _NODISCARD constexpr const _CharT* _Parse_chrono_format_specs( return _Begin; } - _Begin = _Parse_align(_Begin, _End, _Callbacks); + _Begin = _STD _Parse_align(_Begin, _End, _Callbacks); if (_Begin == _End) { return _Begin; } - _Begin = _Parse_width(_Begin, _End, _Callbacks); + _Begin = _STD _Parse_width(_Begin, _End, _Callbacks); if (_Begin == _End) { return _Begin; } if (*_Begin == '.') { - _Begin = _Parse_precision(_Begin, _End, _Callbacks); + _Begin = _STD _Parse_precision(_Begin, _End, _Callbacks); if (_Begin == _End) { return _Begin; } @@ -4920,7 +4925,7 @@ _NODISCARD constexpr const _CharT* _Parse_chrono_format_specs( } if (*_Begin != '}' && *_Begin != '%') { - _Throw_format_error("Invalid format string - chrono-specs must begin with conversion-spec"); + _STD _Throw_format_error("Invalid format string - chrono-specs must begin with conversion-spec"); } // chrono-spec @@ -4929,7 +4934,7 @@ _NODISCARD constexpr const _CharT* _Parse_chrono_format_specs( // because '%' isn't used as a non-lead-byte in any supported multibyte encoding. if (*_Begin == '%') { // conversion-spec if (++_Begin == _End) { - _Throw_format_error("Invalid format string - missing type after %"); + _STD _Throw_format_error("Invalid format string - missing type after %"); } switch (*_Begin) { @@ -4946,7 +4951,7 @@ _NODISCARD constexpr const _CharT* _Parse_chrono_format_specs( ++_Begin; break; default: // some other type - _Begin = _Parse_conversion_specs(_Begin, _End, _Callbacks); + _Begin = _STD _Parse_conversion_specs(_Begin, _End, _Callbacks); break; } } else { // literal-char @@ -5003,7 +5008,8 @@ namespace chrono { template void _Write_seconds(basic_ostream<_CharT, _Traits>& _Os, const hh_mm_ss<_Duration>& _Val) { - _Write_fractional_seconds::fractional_width>(_Os, _Val.seconds(), _Val.subseconds()); + _CHRONO _Write_fractional_seconds::fractional_width>( + _Os, _Val.seconds(), _Val.subseconds()); } template @@ -5015,34 +5021,35 @@ namespace chrono { const hh_mm_ss _Hms{_Val - _Dp}; constexpr auto _Fractional_width = decltype(_Hms)::fractional_width; if (_Lsi.is_leap_second) { - _Write_fractional_seconds<_Fractional_width>(_Os, _Hms.seconds() + seconds{60}, _Hms.subseconds()); + _CHRONO _Write_fractional_seconds<_Fractional_width>( + _Os, _Hms.seconds() + seconds{60}, _Hms.subseconds()); } else { - _Write_fractional_seconds<_Fractional_width>(_Os, _Hms.seconds(), _Hms.subseconds()); + _CHRONO _Write_fractional_seconds<_Fractional_width>(_Os, _Hms.seconds(), _Hms.subseconds()); } } else { const auto _Dp = _CHRONO floor(_Val); - _Write_seconds(_Os, hh_mm_ss{_Val - _Dp}); + _CHRONO _Write_seconds(_Os, hh_mm_ss{_Val - _Dp}); } } template void _Write_seconds(basic_ostream<_CharT, _Traits>& _Os, const _Local_time_format_t<_Duration>& _Val) { - _Write_seconds(_Os, _Val._Time); + _CHRONO _Write_seconds(_Os, _Val._Time); } template void _Write_seconds(basic_ostream<_CharT, _Traits>& _Os, const duration<_Rep, _Period>& _Val) { - _Write_seconds(_Os, hh_mm_ss{_Val}); + _CHRONO _Write_seconds(_Os, hh_mm_ss{_Val}); } template _NODISCARD tm _Fill_tm(const _Ty& _Val) { if constexpr (_Is_specialization_v<_Ty, duration>) { - return _Fill_tm(hh_mm_ss{_Val}); + return _CHRONO _Fill_tm(hh_mm_ss{_Val}); } else if constexpr (_Is_specialization_v<_Ty, _Local_time_format_t>) { - return _Fill_tm(_Val._Time); + return _CHRONO _Fill_tm(_Val._Time); } else if constexpr (_Is_any_of_v<_Ty, year_month_weekday, year_month_weekday_last>) { - auto _Tm = _Fill_tm(year_month_day{_Val}); + auto _Tm = _CHRONO _Fill_tm(year_month_day{_Val}); _Tm.tm_wday = static_cast(_Val.weekday().c_encoding()); return _Tm; } else if constexpr (_Is_any_of_v<_Ty, sys_info, local_info>) { @@ -5051,8 +5058,8 @@ namespace chrono { const auto _Dp = _CHRONO floor(_Val); const year_month_day _Ymd{_Dp}; const hh_mm_ss _Time{_Val - _Dp}; - const auto _Hms = _Fill_tm(_Time); - auto _Tm = _Fill_tm(_Ymd); + const auto _Hms = _CHRONO _Fill_tm(_Time); + auto _Tm = _CHRONO _Fill_tm(_Ymd); _Tm.tm_sec = _Hms.tm_sec; _Tm.tm_min = _Hms.tm_min; _Tm.tm_hour = _Hms.tm_hour; @@ -5115,16 +5122,17 @@ namespace chrono { _Seconds = static_cast(_Val.seconds().count()); } - tm _Time; - _Time.tm_sec = _Seconds; - _Time.tm_min = _Minutes; - _Time.tm_hour = _Hours; - _Time.tm_mday = static_cast(_Day); - _Time.tm_mon = static_cast(_Month) - 1; - _Time.tm_year = _Year - 1900; - _Time.tm_yday = _Yearday; - _Time.tm_wday = _Weekday; - return _Time; + return { + .tm_sec = _Seconds, + .tm_min = _Minutes, + .tm_hour = _Hours, + .tm_mday = static_cast(_Day), + .tm_mon = static_cast(_Month) - 1, + .tm_year = _Year - 1900, + .tm_wday = _Weekday, + .tm_yday = _Yearday, + .tm_isdst{}, + }; } } @@ -5241,7 +5249,7 @@ namespace chrono { basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& _Os, const sys_info& _Val) { return _Os << _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "begin: {}, end: {}, offset: {}, save: {}, abbrev: {}"), // - _Val.begin, _Val.end, _Val.offset, _Val.save, _Widen_string<_CharT>(_Val.abbrev)); + _Val.begin, _Val.end, _Val.offset, _Val.save, _CHRONO _Widen_string<_CharT>(_Val.abbrev)); } _EXPORT_STD template @@ -5332,30 +5340,30 @@ namespace chrono { _NODISCARD constexpr auto _Parse(basic_format_parse_context<_CharT>& _Parse_ctx) { _Chrono_specs_setter<_CharT, basic_format_parse_context<_CharT>> _Callback{_Specs, _Parse_ctx}; const auto _It = - _Parse_chrono_format_specs(_Parse_ctx._Unchecked_begin(), _Parse_ctx._Unchecked_end(), _Callback); + _STD _Parse_chrono_format_specs(_Parse_ctx._Unchecked_begin(), _Parse_ctx._Unchecked_end(), _Callback); const auto _Res_iter = _Parse_ctx.begin() + (_It - _Parse_ctx._Unchecked_begin()); if (_It != _Parse_ctx._Unchecked_end() && *_It != '}') { - _Throw_format_error("Missing '}' in format string."); + _STD _Throw_format_error("Missing '}' in format string."); } if constexpr (_Is_specialization_v<_Ty, duration>) { if constexpr (!treat_as_floating_point_v) { if (_Specs._Precision != -1) { - _Throw_format_error("Precision specification invalid for chrono::duration type with " - "integral representation type, see N4950 [time.format]/1."); + _STD _Throw_format_error("Precision specification invalid for chrono::duration type with " + "integral representation type, see N4950 [time.format]/1."); } } } else { if (_Specs._Precision != -1) { - _Throw_format_error("Precision specification invalid for non-chrono::duration type, " - "see N4950 [time.format]/1."); + _STD _Throw_format_error("Precision specification invalid for non-chrono::duration type, " + "see N4950 [time.format]/1."); } } for (const auto& _Spec : _Specs._Chrono_specs_list) { if (_Spec._Type != '\0' && !_Is_valid_type<_Ty>(_Spec._Type)) { - _Throw_format_error("Invalid type."); + _STD _Throw_format_error("Invalid type."); } _Check_modifier(_Spec._Type, _Spec._Modifier); } @@ -5411,7 +5419,7 @@ namespace chrono { } } - _Throw_format_error("Incompatible modifier for type"); + _STD _Throw_format_error("Incompatible modifier for type"); } template @@ -5497,9 +5505,9 @@ namespace chrono { wchar_t _Fmt_str[4]; _Chrono_spec _Wspec{._Modifier = _Spec._Modifier, ._Type = _Spec._Type}; - _Wstream << _STD put_time(&_Time, _Fmt_string(_Wspec, _Fmt_str)); + _Wstream << _STD put_time(&_Time, _CHRONO _Fmt_string(_Wspec, _Fmt_str)); - _Stream << _Convert_wide_to_narrow>( + _Stream << _STD _Convert_wide_to_narrow>( __std_code_page::_Utf8, _Wstream.view(), allocator{}); continue; @@ -5508,21 +5516,21 @@ namespace chrono { #endif // ^^^ no workaround ^^^ _CharT _Fmt_str[4]; - _Stream << _STD put_time<_CharT>(&_Time, _Fmt_string(_Spec, _Fmt_str)); + _Stream << _STD put_time<_CharT>(&_Time, _CHRONO _Fmt_string(_Spec, _Fmt_str)); } } int _Estimated_width = -1; - (void) _Measure_string_prefix(_Stream.view(), _Estimated_width); + (void) _STD _Measure_string_prefix(_Stream.view(), _Estimated_width); auto _Format_specs = _Specs; if (_Specs._Dynamic_width_index >= 0) { - _Format_specs._Width = _Get_dynamic_specs<_Width_checker>( + _Format_specs._Width = _STD _Get_dynamic_specs<_Width_checker>( _FormatCtx.arg(static_cast(_Specs._Dynamic_width_index))); } - return _Write_aligned(_STD move(_FormatCtx.out()), _Estimated_width, _Format_specs, _Fmt_align::_Left, - [&](auto _Out) { return _Fmt_write(_STD move(_Out), _Stream.view()); }); + return _STD _Write_aligned(_STD move(_FormatCtx.out()), _Estimated_width, _Format_specs, _Fmt_align::_Left, + [&](auto _Out) { return _STD _Fmt_write(_STD move(_Out), _Stream.view()); }); } // This echoes the functionality of put_time, but is able to handle invalid dates (when !ok()) since the @@ -5534,7 +5542,7 @@ namespace chrono { basic_ostream<_CharT>& _Os, const _Chrono_spec<_CharT>& _Spec, const tm& _Time, const _Ty& _Val) const { if constexpr (is_same_v<_Ty, local_info>) { if (_Val.result != local_info::unique) { - _Throw_format_error("Cannot print non-unique local_info"); + _STD _Throw_format_error("Cannot print non-unique local_info"); } } @@ -5547,7 +5555,7 @@ namespace chrono { // Most months have a proper last day, but February depends on the year. if constexpr (is_same_v<_Ty, month_day_last>) { if (_Val.month() == February) { - _Throw_format_error("Cannot print the last day of February without a year"); + _STD _Throw_format_error("Cannot print the last day of February without a year"); } if (!_Val.ok()) { @@ -5568,17 +5576,18 @@ namespace chrono { case 'G': if constexpr (is_same_v<_Ty, year_month>) { if (_Val.month() == January || _Val.month() == December) { - _Throw_format_error( + _STD _Throw_format_error( "The ISO week-based year for a year_month of January or December is ambiguous."); } if (!_Val.ok()) { - _Throw_format_error("The ISO week-based year for an out-of-bounds year_month is ambiguous."); + _STD _Throw_format_error( + "The ISO week-based year for an out-of-bounds year_month is ambiguous."); } const char _Gregorian_type = _Spec._Type == 'g' ? 'y' : 'Y'; _CharT _Fmt_str[4]; - _Os << _STD put_time(&_Time, _Fmt_string({._Type = _Gregorian_type}, _Fmt_str)); + _Os << _STD put_time(&_Time, _CHRONO _Fmt_string({._Type = _Gregorian_type}, _Fmt_str)); return true; } else { return false; @@ -5598,14 +5607,14 @@ namespace chrono { return false; case 'j': if constexpr (_Is_specialization_v<_Ty, duration>) { - _Os << _STD abs(_Duration_cast_underflow_to_zero(_Val).count()); + _Os << _STD abs(_CHRONO _Duration_cast_underflow_to_zero(_Val).count()); return true; } else { return false; } case 'q': if constexpr (_Is_specialization_v<_Ty, duration>) { - _Write_unit_suffix(_Os); + _CHRONO _Write_unit_suffix(_Os); } else { _STL_INTERNAL_CHECK(false); } @@ -5681,18 +5690,18 @@ namespace chrono { if (_Has_modifier) { return false; } - _Write_seconds(_Os, _Val); + _CHRONO _Write_seconds(_Os, _Val); return true; case 'Z': if constexpr (is_same_v<_Ty, sys_info>) { - _Os << _Widen_string<_CharT>(_Val.abbrev); + _Os << _CHRONO _Widen_string<_CharT>(_Val.abbrev); } else if constexpr (is_same_v<_Ty, local_info>) { - _Os << _Widen_string<_CharT>(_Val.first.abbrev); + _Os << _CHRONO _Widen_string<_CharT>(_Val.first.abbrev); } else if constexpr (_Is_specialization_v<_Ty, _Local_time_format_t>) { if (_Val._Abbrev == nullptr) { - _Throw_format_error("Cannot print local-time-format-t with null abbrev."); + _STD _Throw_format_error("Cannot print local-time-format-t with null abbrev."); } - _Os << _Widen_string<_CharT>(*_Val._Abbrev); + _Os << _CHRONO _Widen_string<_CharT>(*_Val._Abbrev); } else { _Os << _Time_zone_abbreviation; } @@ -5707,7 +5716,7 @@ namespace chrono { _Offset = hh_mm_ss{_Val.first.offset}; } else if constexpr (_Is_specialization_v<_Ty, _Local_time_format_t>) { if (_Val._Offset_sec == nullptr) { - _Throw_format_error("Cannot print local-time-format-t with null offset_sec."); + _STD _Throw_format_error("Cannot print local-time-format-t with null offset_sec."); } _Offset = hh_mm_ss{*_Val._Offset_sec}; } else { @@ -5802,12 +5811,12 @@ namespace chrono { case 'j': if constexpr (is_same_v<_Ty, month_day>) { if (_Val.month() > February) { - _Throw_format_error("The day of year for a month_day past February is ambiguous."); + _STD _Throw_format_error("The day of year for a month_day past February is ambiguous."); } return true; } else if constexpr (is_same_v<_Ty, month_day_last>) { if (_Val.month() >= February) { - _Throw_format_error( + _STD _Throw_format_error( "The day of year for a month_day_last other than January is ambiguous"); } return true; @@ -5836,7 +5845,7 @@ namespace chrono { return false; }; if (!_Validate()) { - _Throw_format_error("Cannot localize out-of-bounds time point."); + _STD _Throw_format_error("Cannot localize out-of-bounds time point."); } } } @@ -5854,7 +5863,7 @@ struct _Fill_tm_formatter { template auto format(const _Ty& _Val, _FormatContext& _FormatCtx) const { - return _Impl._Write(_FormatCtx, _Val, _Fill_tm(_Val)); + return _Impl._Write(_FormatCtx, _Val, _CHRONO _Fill_tm(_Val)); } private: @@ -6028,7 +6037,7 @@ struct formatter<_CHRONO sys_time<_Duration>, _CharT> { template auto format(const _CHRONO sys_time<_Duration>& _Val, _FormatContext& _FormatCtx) const { - return _Impl._Write(_FormatCtx, _Val, _Fill_tm(_Val)); + return _Impl._Write(_FormatCtx, _Val, _CHRONO _Fill_tm(_Val)); } private: @@ -6049,7 +6058,7 @@ struct formatter<_CHRONO utc_time<_Duration>, _CharT> { template auto format(const _CHRONO utc_time<_Duration>& _Val, _FormatContext& _FormatCtx) const { const auto _Sys = _CHRONO utc_clock::to_sys(_Val); - return _Impl._Write(_FormatCtx, _Val, _Fill_tm(_Sys)); + return _Impl._Write(_FormatCtx, _Val, _CHRONO _Fill_tm(_Sys)); } private: @@ -6073,7 +6082,7 @@ struct formatter<_CHRONO tai_time<_Duration>, _CharT> { using _Common = common_type_t<_Duration, days>; // slightly optimize by performing conversion at compile time constexpr _Common _Offset{sys_days{year{1970} / January / 1} - sys_days{year{1958} / January / 1}}; const auto _Sys = sys_time<_Duration>{_Val.time_since_epoch()} - _Offset; - return _Impl._Write(_FormatCtx, _Val, _Fill_tm(_Sys)); + return _Impl._Write(_FormatCtx, _Val, _CHRONO _Fill_tm(_Sys)); } private: @@ -6097,7 +6106,7 @@ struct formatter<_CHRONO gps_time<_Duration>, _CharT> { using _Common = common_type_t<_Duration, days>; // slightly optimize by performing conversion at compile time constexpr _Common _Offset{sys_days{year{1980} / January / Sunday[1]} - sys_days{year{1970} / January / 1}}; const auto _Sys = sys_time<_Duration>{_Val.time_since_epoch()} + _Offset; - return _Impl._Write(_FormatCtx, _Val, _Fill_tm(_Sys)); + return _Impl._Write(_FormatCtx, _Val, _CHRONO _Fill_tm(_Sys)); } private: @@ -6119,7 +6128,7 @@ struct formatter<_CHRONO file_time<_Duration>, _CharT> { auto format(const _CHRONO file_time<_Duration>& _Val, _FormatContext& _FormatCtx) const { const auto _Utc = _CHRONO file_clock::to_utc(_Val); const auto _Sys = _CHRONO utc_clock::to_sys(_Utc); - return _Impl._Write(_FormatCtx, _Utc, _Fill_tm(_Sys)); + return _Impl._Write(_FormatCtx, _Utc, _CHRONO _Fill_tm(_Sys)); } private: diff --git a/stl/inc/execution b/stl/inc/execution index 5f5134f768f..3e890f8aed6 100644 --- a/stl/inc/execution +++ b/stl/inc/execution @@ -73,23 +73,27 @@ namespace execution { _EXPORT_STD class sequenced_policy { // indicates support for only sequential execution, and requests termination on exceptions public: + explicit sequenced_policy() = default; // per LWG-4273 + using _Standard_execution_policy = int; static constexpr bool _Parallelize = false; static constexpr bool _Ivdep = false; }; - _EXPORT_STD inline constexpr sequenced_policy seq{/* unspecified */}; + _EXPORT_STD inline constexpr sequenced_policy seq{}; _EXPORT_STD class parallel_policy { // indicates support by element access functions for parallel execution with parallel forward progress // guarantees, and requests termination on exceptions public: + explicit parallel_policy() = default; // per LWG-4273 + using _Standard_execution_policy = int; static constexpr bool _Parallelize = true; static constexpr bool _Ivdep = true; }; - _EXPORT_STD inline constexpr parallel_policy par{/* unspecified */}; + _EXPORT_STD inline constexpr parallel_policy par{}; _EXPORT_STD class parallel_unsequenced_policy { // indicates support by element access functions for parallel execution with weakly parallel forward progress @@ -97,12 +101,14 @@ namespace execution { // // (at this time, equivalent to parallel_policy) public: + explicit parallel_unsequenced_policy() = default; // per LWG-4273 + using _Standard_execution_policy = int; static constexpr bool _Parallelize = true; static constexpr bool _Ivdep = true; }; - _EXPORT_STD inline constexpr parallel_unsequenced_policy par_unseq{/* unspecified */}; + _EXPORT_STD inline constexpr parallel_unsequenced_policy par_unseq{}; #if _HAS_CXX20 _EXPORT_STD class unsequenced_policy { @@ -112,12 +118,14 @@ namespace execution { // (at this time, equivalent to sequenced_policy except for for_each(_n), destroy(_n), // uninitialized_default_construct(_n), and uninitialized_value_construct(_n)) public: + explicit unsequenced_policy() = default; // per LWG-4273 + using _Standard_execution_policy = int; static constexpr bool _Parallelize = false; static constexpr bool _Ivdep = true; }; - _EXPORT_STD inline constexpr unsequenced_policy unseq{/* unspecified */}; + _EXPORT_STD inline constexpr unsequenced_policy unseq{}; #endif // _HAS_CXX20 } // namespace execution diff --git a/stl/inc/expected b/stl/inc/expected index 4080ad8b5ef..92f5590c529 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -306,19 +306,13 @@ public: template > requires (!is_same_v, in_place_t> && !is_same_v, expected> + && !is_same_v, unexpect_t> && !_Is_specialization_v, unexpected> - && (!is_same_v, bool> -#if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-10655311 - || !_Is_specialization_v, expected> -#else // ^^^ no workaround / workaround vvv - || !_Is_specialization_v, _STD expected> -#endif // ^^^ workaround ^^^ - ) + && (!is_same_v, bool> || !_Is_specialization_v, expected>) && is_constructible_v<_Ty, _Uty>) constexpr explicit(!is_convertible_v<_Uty, _Ty>) expected(_Uty&& _Other) noexcept(is_nothrow_constructible_v<_Ty, _Uty>) // strengthened - : _Value(_STD forward<_Uty>(_Other)), _Has_value(true) { - } + : _Value(_STD forward<_Uty>(_Other)), _Has_value(true) {} template requires is_constructible_v<_Err, const _UErr&> diff --git a/stl/inc/istream b/stl/inc/istream index 7e820b16e0b..9a931500047 100644 --- a/stl/inc/istream +++ b/stl/inc/istream @@ -528,6 +528,11 @@ public: return *this; } + template , int> = 0> + basic_istream& ignore(const streamsize _Count, const _Elem _Delim) { + return ignore(_Count, _Traits::to_int_type(_Delim)); + } + basic_istream& __CLR_OR_THIS_CALL read(_Elem* _Str, streamsize _Count) { // read up to _Count characters into buffer ios_base::iostate _State = ios_base::goodbit; _Chcount = 0; diff --git a/stl/inc/regex b/stl/inc/regex index 1e912b60033..817a8db8709 100644 --- a/stl/inc/regex +++ b/stl/inc/regex @@ -266,7 +266,7 @@ struct _Cmp_collate { // functor to compare for equality following collating tra template struct _Cmp_icase_translateleft { - // functor to compare for equality following collating translation of the left character + // functor to compare for equality following case-insensitive translation of the left character using _Elem = typename _RxTraits::char_type; explicit _Cmp_icase_translateleft(const _RxTraits& _Tr) noexcept : _Traits(_Tr) {} @@ -327,7 +327,6 @@ inline size_t _Regex_transform_primary(_Out_writes_(_Last1 - _First1) _Post_read template class _Regex_traits : public _Regex_traits_base { // base class for regular expression traits public: - using _Uelem = make_unsigned_t<_Elem>; using char_type = _Elem; using size_type = size_t; using string_type = basic_string<_Elem>; @@ -638,11 +637,9 @@ inline bool _Is_word(char _Ch) { template bool _Is_word(_Elem _Ch) { - // assumes 'x' == L'x' for the ASCII range - using _UElem = make_unsigned_t<_Elem>; - - const auto _UCh = static_cast<_UElem>(_Ch); - return _UCh <= static_cast<_UElem>('z') && _Is_word(static_cast(_UCh)); + // assumes that ASCII characters are represented at ASCII code points + const auto _Uchar = static_cast(_Ch); + return static_cast<_Elem>(_Uchar) == _Ch && _Uchar <= 'z' && _Is_word(_Uchar); } _EXPORT_STD template @@ -1640,7 +1637,7 @@ private: static void _Insert_node(_Node_base*, _Node_base*); _Node_base* _New_node(_Node_type _Kind); void _Add_str_node(); - void _Add_char_to_bitmap(_Elem _Ch); + void _Add_char_to_bitmap(unsigned char _Ch); void _Add_char_to_array(_Elem _Ch); void _Add_elts(_Node_class<_Elem, _RxTraits>*, typename _RxTraits::char_class_type, bool); void _Char_to_elts(const _Elem*, const _Elem*, _Sequence<_Elem>**); @@ -1888,6 +1885,7 @@ private: _Meta_type _Mchar; _Lex_mode _Mode = _Lex_mode::_Default; _Elem _Char; + _Elem _Unescaped_char; }; enum _Lang_flags2 : unsigned long long { // describe language properties @@ -2973,14 +2971,14 @@ void _Builder2<_FwdIt, _Elem, _RxTraits>::_Add_class() { // add bracket expressi } template -void _Builder2<_FwdIt, _Elem, _RxTraits>::_Add_char_to_bitmap(_Elem _Ch) { // add character to accelerator table +void _Builder2<_FwdIt, _Elem, _RxTraits>::_Add_char_to_bitmap(unsigned char _Ch) { // add character to accelerator table _Node_class<_Elem, _RxTraits>* _Node = static_cast<_Node_class<_Elem, _RxTraits>*>(_Current); if (!_Node->_Small) { _Node->_Small = new _Bitmap; } - _Node->_Small->_Mark(static_cast(_Ch)); + _Node->_Small->_Mark(_Ch); } template @@ -3001,37 +2999,37 @@ void _Builder2<_FwdIt, _Elem, _RxTraits>::_Add_char_to_class(_Elem _Ch) { // add _Ch = _Traits.translate(_Ch); } - if (static_cast(_Ch) < _Bmp_max) { - _Add_char_to_bitmap(_Ch); + auto _Uchar = static_cast(_Ch); + if (static_cast<_Elem>(_Uchar) == _Ch) { + _Add_char_to_bitmap(_Uchar); } else { _Add_char_to_array(_Ch); } } template -void _Builder2<_FwdIt, _Elem, _RxTraits>::_Add_range(const _Elem _Arg0, const _Elem _Arg1) { +void _Builder2<_FwdIt, _Elem, _RxTraits>::_Add_range(_Elem _Arg0, const _Elem _Arg1) { // add character range to set - using string_type = typename _RxTraits::string_type; - unsigned int _Ex0 = static_cast(_Arg0); - const unsigned int _Ex1 = static_cast(_Arg1); + using _String_type = typename _RxTraits::string_type; + using _Char_traits_type = typename _String_type::traits_type; _Node_class<_Elem, _RxTraits>* _Node = static_cast<_Node_class<_Elem, _RxTraits>*>(_Current); // set bits and check that the range is non-empty if (_Flags & regex_constants::collate) { _Elem _Ch; - const auto _Ch_ptr = _STD addressof(_Ch); - const auto _Arg0_ptr = _STD addressof(_Arg0); - const auto _Arg1_ptr = _STD addressof(_Arg1); - const string_type _Arg0_key = _Traits.transform(_Arg0_ptr, _Arg0_ptr + 1); - const string_type _Arg1_key = _Traits.transform(_Arg1_ptr, _Arg1_ptr + 1); + const auto _Ch_ptr = _STD addressof(_Ch); + const auto _Arg0_ptr = _STD addressof(_Arg0); + const auto _Arg1_ptr = _STD addressof(_Arg1); + const _String_type _Arg0_key = _Traits.transform(_Arg0_ptr, _Arg0_ptr + 1); + const _String_type _Arg1_key = _Traits.transform(_Arg1_ptr, _Arg1_ptr + 1); if (_Arg0_key > _Arg1_key) { _Xregex_error(regex_constants::error_range); } for (unsigned int _UCh = 0; _UCh < _Bmp_max; ++_UCh) { - _Ch = static_cast<_Elem>(_UCh); - const string_type _Ch_key = _Traits.transform(_Ch_ptr, _Ch_ptr + 1); + _Ch = static_cast<_Elem>(_UCh); + const _String_type _Ch_key = _Traits.transform(_Ch_ptr, _Ch_ptr + 1); if (_Arg0_key <= _Ch_key && _Ch_key <= _Arg1_key) { if (!_Node->_Small) { _Node->_Small = new _Bitmap; @@ -3039,32 +3037,68 @@ void _Builder2<_FwdIt, _Elem, _RxTraits>::_Add_range(const _Elem _Arg0, const _E _Node->_Small->_Mark(_UCh); } } - } else if (_Ex0 > _Ex1) { + } else if (_Char_traits_type::lt(_Arg1, _Arg0)) { _Xregex_error(regex_constants::error_range); } else { - if (!_Node->_Small && _Ex0 < _Bmp_max) { - _Node->_Small = new _Bitmap; - } + unsigned int _Ex0 = static_cast(_Arg0); + if (static_cast<_Elem>(_Ex0) == _Arg0) { + if (!_Node->_Small) { + _Node->_Small = new _Bitmap; + } - for (; _Ex0 <= _Ex1 && _Ex0 < _Bmp_max; ++_Ex0) { - _Node->_Small->_Mark(_Ex0); - } + unsigned int _Ex1 = static_cast(_Arg1); + bool _Extends_beyond_bitmap = static_cast<_Elem>(_Ex1) != _Arg1; + if (_Extends_beyond_bitmap) { + _Ex1 = _Bmp_max - 1; + } - if (_Ex1 - _Ex0 < _ARRAY_THRESHOLD) { for (; _Ex0 <= _Ex1; ++_Ex0) { - _Add_char_to_array(static_cast<_Elem>(_Ex0)); + _Node->_Small->_Mark(_Ex0); + } + + if (!_Extends_beyond_bitmap) { + return; } + + _Arg0 = static_cast<_Elem>(_Ex0); } - } - if ((_Flags & regex_constants::collate) || _Ex1 >= _Ex0) { // store remaining range as pair - if (!_Node->_Ranges) { - _Node->_Ranges = new _Buf<_Elem>; + if constexpr (sizeof(_Elem) > 1U) { + if constexpr (is_integral_v<_Elem> || is_enum_v<_Elem>) { + using _Uelem = make_unsigned_t<_Elem>; + auto _First = static_cast<_Uelem>(_Arg0); + auto _Last = static_cast<_Uelem>(_Arg1); + auto _Count = static_cast<_Uelem>(_Last - _First); + ++_Count; + if (_Count <= _ARRAY_THRESHOLD) { + for (; _Count > 0; ++_First, --_Count) { + _Add_char_to_array(static_cast<_Elem>(_First)); + } + return; + } + } else { + auto _Last = static_cast(_Arg1); + if (static_cast<_Elem>(_Last) == _Arg1) { + auto _First = static_cast(_Arg0); + auto _Count = _Last - _First + 1U; + if (_Count <= _ARRAY_THRESHOLD) { + for (; _Count > 0; ++_First, --_Count) { + _Add_char_to_array(static_cast<_Elem>(_First)); + } + return; + } + } + } } + } - _Node->_Ranges->_Insert2(static_cast<_Elem>(_Ex0)); - _Node->_Ranges->_Insert2(_Arg1); + // store remaining range as pair + if (!_Node->_Ranges) { + _Node->_Ranges = new _Buf<_Elem>; } + + _Node->_Ranges->_Insert2(_Arg0); + _Node->_Ranges->_Insert2(_Arg1); } template @@ -3090,7 +3124,7 @@ void _Builder2<_FwdIt, _Elem, _RxTraits>::_Add_named_class( using _Char_class_type = typename _RxTraits::char_class_type; _Node_class<_Elem, _RxTraits>* _Node = static_cast<_Node_class<_Elem, _RxTraits>*>(_Current); _Add_elts(_Node, _Cl, _Kind != _Rx_char_class_kind::_Positive); - if (_Bmp_max <= _STD _Max_limit()) { + if constexpr (sizeof(_Elem) > 1U) { if (_Kind == _Rx_char_class_kind::_Positive) { auto _Cl_all_bits_set = static_cast<_Char_class_type>(-1); if ((_Node->_Classes != _Cl_all_bits_set && _Cl != _Cl_all_bits_set) @@ -3146,7 +3180,8 @@ void _Builder2<_FwdIt, _Elem, _RxTraits>::_Add_equiv(const _Elem* const _First, _Node->_Small->_Mark(_Ch); } } - if (_Bmp_max < static_cast(_STD _Max_limit<_Elem>())) { // map range + + if constexpr (sizeof(_Elem) > 1U) { // map range _Sequence<_Elem>** _Cur = _STD addressof(_Node->_Equiv); _Char_to_elts(_First, _Last, _Cur); } @@ -3655,6 +3690,8 @@ _BidIt1 _Compare_translate_both(_BidIt1 _Begin1, _BidIt1 _End1, _BidIt2 _Begin2, // compare character ranges, translating characters in both ranges according to syntax options if (_Sflags & regex_constants::icase) { return _STD _Cmp_chrange(_Begin1, _End1, _Begin2, _End2, _Cmp_icase<_RxTraits>{_Traits}); + } else if constexpr (_Is_any_of_v<_RxTraits, regex_traits, regex_traits>) { + return _STD _Cmp_chrange(_Begin1, _End1, _Begin2, _End2, equal_to{}); } else if (_Sflags & regex_constants::collate) { return _STD _Cmp_chrange(_Begin1, _End1, _Begin2, _End2, _Cmp_collate<_RxTraits>{_Traits}); } else { @@ -3668,6 +3705,8 @@ _BidIt1 _Compare_translate_left(_BidIt1 _Begin1, _BidIt1 _End1, _BidIt2 _Begin2, // compare character ranges, translating characters in the left range according to syntax options if (_Sflags & regex_constants::icase) { return _STD _Cmp_chrange(_Begin1, _End1, _Begin2, _End2, _Cmp_icase_translateleft<_RxTraits>{_Traits}); + } else if constexpr (_Is_any_of_v<_RxTraits, regex_traits, regex_traits>) { + return _STD _Cmp_chrange(_Begin1, _End1, _Begin2, _End2, equal_to{}); } else if (_Sflags & regex_constants::collate) { return _STD _Cmp_chrange(_Begin1, _End1, _Begin2, _End2, _Cmp_collate_translateleft<_RxTraits>{_Traits}); } else { @@ -3675,11 +3714,39 @@ _BidIt1 _Compare_translate_left(_BidIt1 _Begin1, _BidIt1 _End1, _BidIt2 _Begin2, } } -template -bool _Lookup_range(unsigned int _Ch, const _Buf<_Elem>* _Bufptr) { // check whether _Ch is in _Buf - using _Uelem = make_unsigned_t<_Elem>; +template +_BidIt1 _Search_translate_left(_BidIt1 _Begin1, _BidIt1 _End1, _BidIt2 _Begin2, _BidIt2 _End2, const _RxTraits& _Traits, + regex_constants::syntax_option_type _Sflags) { + // searching the right character sequence in the left sequence, + // after translating characters in the left sequence according to syntax options + if (_Sflags & regex_constants::icase) { + return _STD search(_Begin1, _End1, _Begin2, _End2, _Cmp_icase_translateleft<_RxTraits>{_Traits}); + } else if constexpr (_Is_any_of_v<_RxTraits, regex_traits, regex_traits>) { + return _STD search(_Begin1, _End1, _Begin2, _End2, equal_to{}); + } else if (_Sflags & regex_constants::collate) { + return _STD search(_Begin1, _End1, _Begin2, _End2, _Cmp_collate_translateleft<_RxTraits>{_Traits}); + } else { + return _STD search(_Begin1, _End1, _Begin2, _End2, equal_to{}); + } +} + +template +bool _Lookup_range(const _Elem _Ch, const _Buf<_Elem>* const _Bufptr) { // check whether _Ch is in _Buf for (unsigned int _Ix = 0; _Ix < _Bufptr->_Size(); _Ix += 2) { // check current position - if (static_cast<_Uelem>(_Bufptr->_At(_Ix)) <= _Ch && _Ch <= static_cast<_Uelem>(_Bufptr->_At(_Ix + 1))) { + const _Elem _Left = _Bufptr->_At(_Ix); + const _Elem _Right = _Bufptr->_At(_Ix + 1); + + bool _Within_range; + if constexpr (is_same_v<_Char_traits, char_traits>) { + const auto _Uchar = static_cast(_Ch); + _Within_range = static_cast(_Left) <= _Uchar && _Uchar <= static_cast(_Right); + } else if constexpr (is_same_v<_Char_traits, char_traits>) { + _Within_range = _Left <= _Ch && _Ch <= _Right; + } else { + _Within_range = !_Char_traits::lt(_Ch, _Left) && !_Char_traits::lt(_Right, _Ch); + } + + if (_Within_range) { return true; } } @@ -3777,7 +3844,7 @@ _It _Matcher2<_BidIt, _Elem, _RxTraits, _It, _Alloc>::_Do_class(_Node_base* _Nx, } else if (_Sflags & regex_constants::collate) { _Ch = _Traits.translate(_Ch); } - const auto _UCh = static_cast(_Ch); + const auto _Uchar = static_cast(_Ch); _It _Res0 = _First; ++_Res0; @@ -3789,11 +3856,12 @@ _It _Matcher2<_BidIt, _Elem, _RxTraits, _It, _Alloc>::_Do_class(_Node_base* _Nx, _Res0 = _Resx; _Found = true; } else if (_Node->_Ranges - && (_Sflags & regex_constants::collate ? _STD _Lookup_collating_range(_Ch, _Node->_Ranges, _Traits) - : _STD _Lookup_range(_UCh, _Node->_Ranges))) { + && (_Sflags & regex_constants::collate + ? _STD _Lookup_collating_range(_Ch, _Node->_Ranges, _Traits) + : _STD _Lookup_range(_Ch, _Node->_Ranges))) { _Found = true; - } else if (_UCh < _Bmp_max) { - _Found = _Node->_Small && _Node->_Small->_Find(_UCh); + } else if (static_cast<_Elem>(_Uchar) == _Ch) { + _Found = _Node->_Small && _Node->_Small->_Find(_Uchar); } else if (_Node->_Large && _STD find(_Node->_Large->_Str(), _Node->_Large->_Str() + _Node->_Large->_Size(), _Ch) != _Node->_Large->_Str() + _Node->_Large->_Size()) { @@ -3861,15 +3929,15 @@ bool _Matcher2<_BidIt, _Elem, _RxTraits, _It, _Alloc>::_Is_wbound() const { if ((_Mflags & regex_constants::match_prev_avail) || _Tgt_state._Cur != _Begin) { // if --_Cur is valid, check for preceding word character if (_Tgt_state._Cur == _End) { - return (_Mflags & regex_constants::match_not_eow) == 0 && _Is_word(*_Prev_iter(_Tgt_state._Cur)); + return (_Mflags & regex_constants::match_not_eow) == 0 && _STD _Is_word(*_Prev_iter(_Tgt_state._Cur)); } else { - return _Is_word(*_Prev_iter(_Tgt_state._Cur)) != _Is_word(*_Tgt_state._Cur); + return _STD _Is_word(*_Prev_iter(_Tgt_state._Cur)) != _STD _Is_word(*_Tgt_state._Cur); } } else { // --_Cur is not valid if (_Tgt_state._Cur == _End) { return false; } else { - return (_Mflags & regex_constants::match_not_bow) == 0 && _Is_word(*_Tgt_state._Cur); + return (_Mflags & regex_constants::match_not_bow) == 0 && _STD _Is_word(*_Tgt_state._Cur); } } } @@ -3884,7 +3952,15 @@ typename _RxTraits::char_class_type _Matcher2<_BidIt, _Elem, _RxTraits, _It, _Al template bool _Is_ecmascript_line_terminator(_Elem _Ch) { - return _Ch == _Meta_nl || _Ch == _Meta_cr || _Ch == _Meta_ls || _Ch == _Meta_ps; + if constexpr (is_same_v<_Elem, char>) { + return _Ch == _Meta_nl || _Ch == _Meta_cr; + } else if constexpr (is_same_v<_Elem, wchar_t>) { + return _Ch == _Meta_nl || _Ch == _Meta_cr || _Ch == _Meta_ls || _Ch == _Meta_ps; + } else { + auto _UCh = static_cast(_Ch); + return static_cast<_Elem>(_UCh) == _Ch + && (_UCh == _Meta_nl || _UCh == _Meta_cr || _UCh == _Meta_ls || _UCh == _Meta_ps); + } } template @@ -4165,15 +4241,9 @@ _BidIt _Matcher2<_BidIt, _Elem, _RxTraits, _It, _Alloc>::_Skip( case _N_str: { // check for string match _Node_str<_Elem>* _Node = static_cast<_Node_str<_Elem>*>(_Nx); - for (; _First_arg != _Last; ++_First_arg) { // look for starting match - _BidIt _Next = _First_arg; - if (_STD _Compare_translate_left( - _First_arg, ++_Next, _Node->_Data._Str(), _Node->_Data._Str() + 1, _Traits, _Sflags) - != _First_arg) { - break; - } - } - return _First_arg; + auto _Str = _Node->_Data._Str(); + return _STD _Search_translate_left( + _First_arg, _Last, _Str, _Str + _Node->_Data._Size(), _Traits, _Sflags); } case _N_class: @@ -4296,8 +4366,10 @@ template template bool _Parser2<_FwdIt, _Elem, _RxTraits>::_Is_esc(_FwdIt _Ch0) const { // assumes _Ch0 != _End return _Mode == _Lex_mode::_Default && ++_Ch0 != _End - && ((!(_L_flags & _L_nex_grp) && (*_Ch0 == _Meta_lpar || *_Ch0 == _Meta_rpar)) - || (!(_L_flags & _L_nex_rep) && (*_Ch0 == _Meta_lbr || *_Ch0 == _Meta_rbr))); + && ((!(_L_flags & _L_nex_grp) + && (*_Ch0 == static_cast(_Meta_lpar) || *_Ch0 == static_cast(_Meta_rpar))) + || (!(_L_flags & _L_nex_rep) + && (*_Ch0 == static_cast(_Meta_lbr) || *_Ch0 == static_cast(_Meta_rbr)))); } template @@ -4308,16 +4380,23 @@ void _Parser2<_FwdIt, _Elem, _RxTraits>::_Trans() { // map character to meta-cha if (_Pat == _End) { _Mchar = _Meta_eos; - _Char = static_cast<_Elem>(_Meta_eos); + _Char = _Elem{}; } else { // map current character - _Char = *_Pat; - _Mchar = _CSTD strchr(_Meta_map, _Char) ? static_cast<_Meta_type>(_Char) : _Meta_chr; + _Char = *_Pat; + auto _Uchar = static_cast(_Char); + if (static_cast<_Elem>(_Uchar) == _Char && _CSTD strchr(_Meta_map, static_cast(_Uchar))) { + _Mchar = static_cast<_Meta_type>(_Uchar); + } else { + _Mchar = _Meta_chr; + } } - switch (_Char) { // handle special cases + + switch (int{_Mchar}) { // handle special cases case _Meta_esc: if (_Is_esc(_Pat)) { // replace escape sequence _FwdIt _Ch0 = _Pat; - _Mchar = static_cast<_Meta_type>(_Char = *++_Ch0); + _Char = *++_Ch0; + _Mchar = static_cast<_Meta_type>(static_cast(_Char)); } break; @@ -4361,7 +4440,7 @@ void _Parser2<_FwdIt, _Elem, _RxTraits>::_Trans() { // map character to meta-cha { // check if $ is special _FwdIt _Next = _Pat; if ((_L_flags & _L_anch_rstr) && ++_Next != _End) { - const bool _Escaped = *_Next == _Meta_esc && _Is_esc(_Next); + const bool _Escaped = *_Next == static_cast(_Meta_esc) && _Is_esc(_Next); if (_Escaped) { ++_Next; } @@ -4373,9 +4452,9 @@ void _Parser2<_FwdIt, _Elem, _RxTraits>::_Trans() { // map character to meta-cha const _Elem _Ch = *_Next; const bool _Is_end_of_alternative = - ((_L_flags & _L_alt_nl) && _Ch == _Meta_nl + ((_L_flags & _L_alt_nl) && _Ch == static_cast(_Meta_nl) && _Disj_count == 0) // dollar followed by newline '\n' for alternation - || (_Escaped && _Ch == _Meta_rpar + || (_Escaped && _Ch == static_cast(_Meta_rpar) && _Disj_count != 0); // dollar followed by (escaped) right parenthesis ')' closing a group if (!_Is_end_of_alternative) { @@ -4409,7 +4488,7 @@ void _Parser2<_FwdIt, _Elem, _RxTraits>::_Trans() { // map character to meta-cha template void _Parser2<_FwdIt, _Elem, _RxTraits>::_Next() { // advance to next input character if (_Pat != _End) { // advance - if (*_Pat == _Meta_esc && _Is_esc(_Pat)) { + if (*_Pat == static_cast(_Meta_esc) && _Is_esc(_Pat)) { ++_Pat; } @@ -4505,7 +4584,7 @@ _Prs_ret _Parser2<_FwdIt, _Elem, _RxTraits>::_Do_ex_class( if (_Size == 1 && _End_arg == _Meta_dot) { // process single-element collating elements like individual characters - _Val = *_Coll_elem_first; + _Unescaped_char = *_Coll_elem_first; return _Prs_chr; } @@ -4563,9 +4642,9 @@ bool _Parser2<_FwdIt, _Elem, _RxTraits>::_CharacterClassEscape(bool _Addit) { // template _Prs_ret _Parser2<_FwdIt, _Elem, _RxTraits>::_ClassEscape() { // check for class escape - if ((_L_flags & _L_esc_bsp) && _Char == _Esc_ctrl_b) { // handle backspace escape + if ((_L_flags & _L_esc_bsp) && _Char == static_cast(_Esc_ctrl_b)) { // handle backspace escape _Next(); - _Val = _Meta_bsp; + _Unescaped_char = static_cast<_Elem>(static_cast(_Meta_bsp)); return _Prs_chr; } else if ((_L_flags & (_L_bzr_chr | _L_bckr)) && (_Val = _Traits.value(_Char, 10)) != -1) { // handle \0 and reject other escaped decimal literals @@ -4574,6 +4653,7 @@ _Prs_ret _Parser2<_FwdIt, _Elem, _RxTraits>::_ClassEscape() { // check for class _Error(regex_constants::error_escape); } + _Unescaped_char = _Elem{}; return _Prs_chr; } else if (_CharacterEscape(true)) { return _Prs_chr; @@ -4590,13 +4670,14 @@ _Prs_ret _Parser2<_FwdIt, _Elem, _RxTraits>::_ClassAtom(const bool _Initial) { / _Next(); return _ClassEscape(); } else if (_Mchar == _Meta_lsq) { // check for valid delimited expression + _Elem _Lsq = _Char; _Next(); if (_Mchar == _Meta_colon || _Mchar == _Meta_equal || _Mchar == _Meta_dot) { // handle delimited expression _Meta_type _St = _Mchar; _Next(); return _Do_ex_class(_St); } else { // handle ordinary [ - _Val = _Meta_lsq; + _Unescaped_char = _Lsq; return _Prs_chr; } } else if ((_Mchar == _Meta_rsq @@ -4605,7 +4686,7 @@ _Prs_ret _Parser2<_FwdIt, _Elem, _RxTraits>::_ClassAtom(const bool _Initial) { / || _Mchar == _Meta_eos) { return _Prs_none; } else { // handle ordinary character - _Val = _Char; + _Unescaped_char = _Char; _Next(); return _Prs_chr; } @@ -4622,19 +4703,20 @@ void _Parser2<_FwdIt, _Elem, _RxTraits>::_ClassRanges() { // check for valid cla } _Initial = false; - if (_Ret == _Prs_chr && _Val == 0 && !(_L_flags & _L_bzr_chr)) { + if (_Ret == _Prs_chr && !(_L_flags & _L_bzr_chr) && _Unescaped_char == _Elem{}) { _Error(regex_constants::error_escape); } if (_Mchar == _Meta_dash) { // check for valid range + _Elem _Chr1 = _Unescaped_char; + _Elem _Dash = _Char; _Next(); - _Elem _Chr1 = static_cast<_Elem>(_Val); const bool _Set_preceding = _Ret == _Prs_set; if ((_Ret = _ClassAtom(false)) == _Prs_none) { // treat - as ordinary character if (!_Set_preceding) { _Nfa._Add_char_to_class(_Chr1); } - _Nfa._Add_char_to_class(_Meta_dash); + _Nfa._Add_char_to_class(_Dash); return; } @@ -4642,7 +4724,7 @@ void _Parser2<_FwdIt, _Elem, _RxTraits>::_ClassRanges() { // check for valid cla _Error(regex_constants::error_range); // set precedes or follows dash } - _Elem _Chr2 = static_cast<_Elem>(_Val); + _Elem _Chr2 = _Unescaped_char; // translate ends of range if (_Flags & regex_constants::icase) { @@ -4655,7 +4737,7 @@ void _Parser2<_FwdIt, _Elem, _RxTraits>::_ClassRanges() { // check for valid cla _Nfa._Add_range(_Chr1, _Chr2); } else if (_Ret == _Prs_chr) { - _Nfa._Add_char_to_class(static_cast<_Elem>(_Val)); + _Nfa._Add_char_to_class(_Unescaped_char); } } } @@ -4739,10 +4821,15 @@ bool _Parser2<_FwdIt, _Elem, _RxTraits>::_Wrapped_disjunction() { // add disjunc template bool _Parser2<_FwdIt, _Elem, _RxTraits>::_IsIdentityEscape(bool _In_character_class) const { // check for valid identity escape + auto _Uchar = static_cast(_Char); if (_L_flags & _L_ident_ECMA) { // ECMAScript identity escape characters - switch (_Char) { + if (static_cast<_Elem>(_Uchar) != _Char) { + return true; + } + + switch (_Uchar) { case 'c': // ASCII control character case 'd': // digit case 'D': @@ -4756,7 +4843,11 @@ bool _Parser2<_FwdIt, _Elem, _RxTraits>::_IsIdentityEscape(bool _In_character_cl } } - switch (_Char) { + if (static_cast<_Elem>(_Uchar) != _Char) { + return false; + } + + switch (_Uchar) { case _Meta_esc: // BRE, ERE, awk identity escape characters (anywhere in awk) return true; @@ -4790,7 +4881,7 @@ template bool _Parser2<_FwdIt, _Elem, _RxTraits>::_IdentityEscape(bool _In_character_class) { // check whether an escape is valid, and process it if so if (_IsIdentityEscape(_In_character_class)) { - _Val = _Char; + _Unescaped_char = _Char; _Next(); return true; } else { @@ -4800,15 +4891,15 @@ bool _Parser2<_FwdIt, _Elem, _RxTraits>::_IdentityEscape(bool _In_character_clas template bool _Parser2<_FwdIt, _Elem, _RxTraits>::_Do_ffn(_Elem _Ch) { // check for limited file format escape characters - if (_Ch == _Esc_ctrl_f) { + if (_Ch == static_cast(_Esc_ctrl_f)) { _Val = '\f'; - } else if (_Ch == _Esc_ctrl_n) { + } else if (_Ch == static_cast(_Esc_ctrl_n)) { _Val = '\n'; - } else if (_Ch == _Esc_ctrl_r) { + } else if (_Ch == static_cast(_Esc_ctrl_r)) { _Val = '\r'; - } else if (_Ch == _Esc_ctrl_t) { + } else if (_Ch == static_cast(_Esc_ctrl_t)) { _Val = '\t'; - } else if (_Ch == _Esc_ctrl_v) { + } else if (_Ch == static_cast(_Esc_ctrl_v)) { _Val = '\v'; } else { return false; @@ -4819,9 +4910,9 @@ bool _Parser2<_FwdIt, _Elem, _RxTraits>::_Do_ffn(_Elem _Ch) { // check for limit template bool _Parser2<_FwdIt, _Elem, _RxTraits>::_Do_ffnx(_Elem _Ch) { // check for the remaining file format escape characters - if (_Ch == _Esc_ctrl_a) { + if (_Ch == static_cast(_Esc_ctrl_a)) { _Val = '\a'; - } else if (_Ch == _Esc_ctrl_b) { + } else if (_Ch == static_cast(_Esc_ctrl_b)) { _Val = '\b'; } else { return false; @@ -4839,22 +4930,23 @@ bool _Parser2<_FwdIt, _Elem, _RxTraits>::_CharacterEscape(bool _In_character_cla if ((_L_flags & _L_esc_ffn && _Do_ffn(_Char)) || (_L_flags & _L_esc_ffnx && _Do_ffnx(_Char))) { _Next(); - } else if (_Char == _Esc_ctrl && (_L_flags & _L_esc_ctrl)) { // handle control escape sequence + } else if (_Char == static_cast(_Esc_ctrl) && (_L_flags & _L_esc_ctrl)) { // handle control escape sequence _Next(); - using _Uelem = typename _RxTraits::_Uelem; - _Uelem _UCh = static_cast<_Uelem>(_Char); - if (!((static_cast<_Uelem>('a') <= _UCh && _UCh <= static_cast<_Uelem>('z')) - || (static_cast<_Uelem>('A') <= _UCh && _UCh <= static_cast<_Uelem>('Z')))) { + using _Char_traits_type = typename _RxTraits::string_type::traits_type; + if ((_Char_traits_type::lt(_Char, static_cast<_Elem>('a')) + || _Char_traits_type::lt(static_cast<_Elem>('z'), _Char)) + && (_Char_traits_type::lt(_Char, static_cast<_Elem>('A')) + || _Char_traits_type::lt(static_cast<_Elem>('Z'), _Char))) { _Error(regex_constants::error_escape); } - _Val = static_cast(_Char % 32); + _Val = static_cast(_Char) % 32; _Next(); - } else if (_Char == _Esc_hex && (_L_flags & _L_esc_hex)) { // handle hexadecimal escape sequence + } else if (_Char == static_cast(_Esc_hex) && (_L_flags & _L_esc_hex)) { // handle hexadecimal escape sequence _Next(); _HexDigits(2); - } else if (_Char == _Esc_uni && (_L_flags & _L_esc_uni)) { // handle Unicode escape sequence + } else if (_Char == static_cast(_Esc_uni) && (_L_flags & _L_esc_uni)) { // handle Unicode escape sequence _Next(); _HexDigits(4); } else if ((_L_flags & _L_esc_oct) && _OctalDigits()) { // handle octal escape sequence @@ -4865,11 +4957,18 @@ bool _Parser2<_FwdIt, _Elem, _RxTraits>::_CharacterEscape(bool _In_character_cla return _IdentityEscape(_In_character_class); } - if (_STD _Max_limit() < static_cast(_Val)) { + _Unescaped_char = static_cast<_Elem>(static_cast(_Val)); + int _Cast_val; + if constexpr (is_integral_v<_Elem> || is_enum_v<_Elem>) { + _Cast_val = static_cast(static_cast>(_Unescaped_char)); + } else { + _Cast_val = static_cast(static_cast(_Unescaped_char)); + } + + if (_Cast_val != _Val) { _Error(regex_constants::error_escape); } - _Val = static_cast<_Elem>(_Val); return true; } @@ -4897,7 +4996,7 @@ void _Parser2<_FwdIt, _Elem, _RxTraits>::_AtomEscape() { // check for valid atom } } } else if (_CharacterEscape(false)) { - _Nfa._Add_char(static_cast<_Elem>(_Val)); + _Nfa._Add_char(_Unescaped_char); } else if (!(_L_flags & _L_esc_wsd) || !_CharacterClassEscape(true)) { _Error(regex_constants::error_escape); } @@ -4963,11 +5062,11 @@ bool _Parser2<_FwdIt, _Elem, _RxTraits>::_Alternative() { // check for valid alt _Next(); } else if (_Mchar == _Meta_esc) { // check for valid escape sequence _Next(); - if ((_L_flags & _L_asrt_wrd) && _Char == _Esc_word) { // add word assert + if ((_L_flags & _L_asrt_wrd) && _Char == static_cast(_Esc_word)) { // add word assert _Nfa._Add_wbound(); _Next(); _Quant = false; - } else if ((_L_flags & _L_asrt_wrd) && _Char == _Esc_not_word) { // add not-word assert + } else if ((_L_flags & _L_asrt_wrd) && _Char == static_cast(_Esc_not_word)) { // add not-word assert _Nfa._Add_wbound(); _Nfa._Negate(); _Next(); diff --git a/stl/inc/xlocale b/stl/inc/xlocale index b6c77fd7faa..ab5eda706e6 100644 --- a/stl/inc/xlocale +++ b/stl/inc/xlocale @@ -1505,7 +1505,7 @@ protected: } const char8_t* _Peek = _First1; - char32_t _Code_point = _Lead_byte; + char32_t _Code_point = static_cast(_Lead_byte); do { const char8_t _By = *++_Peek; if ((_By & 0b1100'0000u) != 0b1000'0000u) { // out-of-sequence lead byte @@ -1551,7 +1551,7 @@ protected: return partial; } - char32_t _Code_point = *_First1; + char32_t _Code_point = static_cast(*_First1); if (_Code_point < 0x80u) { // encode 1-byte sequence *_First2 = static_cast(_Code_point); continue; @@ -1613,7 +1613,7 @@ protected: const auto _Old_first1 = _First1; for (; _First1 != _Last1 && _Count > 0u; ++_First1, --_Count) { - char32_t _Code_point = *_First1; + char32_t _Code_point = static_cast(*_First1); if (_Code_point < 0b1000'0000u) { // single-byte sequence continue; } @@ -1755,7 +1755,7 @@ protected: char8_t _Lead_byte = *_First1; if (_Lead_byte < 0b1000'0000u) { // single-byte sequence - *_First2 = _Lead_byte; + *_First2 = static_cast(_Lead_byte); continue; } @@ -1782,7 +1782,7 @@ protected: } const char8_t* _Peek = _First1; - char32_t _Code_point = _Lead_byte; + char32_t _Code_point = static_cast(_Lead_byte); do { const char8_t _By = *++_Peek; if ((_By & 0b1100'0000u) != 0b1000'0000u) { // out-of-sequence lead byte @@ -1868,7 +1868,7 @@ protected: const auto _Old_first1 = _First1; for (; _First1 != _Last1 && _Count > 0u; ++_First1, --_Count) { - char32_t _Code_point = *_First1; + char32_t _Code_point = static_cast(*_First1); if (_Code_point < 0b1000'0000u) { // single-byte sequence continue; } diff --git a/stl/inc/xstring b/stl/inc/xstring index 8aa23749431..7a12198996f 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -580,6 +580,11 @@ concept _Contiguous_range_of = (_RANGES contiguous_range<_Rng>) && same_as>, _Ty>; #endif // _HAS_CXX23 +#pragma warning(push) +// Invalid annotation: 'NullTerminated' property may only be used on buffers whose elements are of integral or pointer +// type +#pragma warning(disable : 6510) + _EXPORT_STD template , class _Alloc = allocator<_Elem>> class basic_string { // null-terminated transparent array of elements private: @@ -3195,6 +3200,8 @@ private: _Compressed_pair<_Alty, _Scary_val> _Mypair; }; +#pragma warning(pop) + #if _HAS_CXX17 template >, enable_if_t, _Is_allocator<_Alloc>>, int> = 0> diff --git a/stl/inc/xutility b/stl/inc/xutility index a80fd1bdd92..d502fb227c4 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -866,8 +866,36 @@ namespace ranges { template concept _Can_deref = requires(_Ty&& __t) { *static_cast<_Ty&&>(__t); }; + struct _Must_have_ADL_found_iter_move_or_be_dereferenceable {}; + class _Cpo { private: + template + _NODISCARD static auto _Choose_return_type() { + if constexpr (_Has_ADL<_Ty>) { + return type_identity()))>{}; // intentional ADL + } else if constexpr (_Can_deref<_Ty>) { + using _Ref = decltype(*_STD declval<_Ty>()); +#if !defined(__clang__) && !defined(__EDG__) // TRANSITION, VSO-1008447, VSO-2066340 + if constexpr (is_function_v>) { + return type_identity<_Ref&>{}; + } else +#endif // ^^^ workaround ^^^ + { + if constexpr (is_lvalue_reference_v<_Ref>) { + return type_identity&&>{}; + } else { + return type_identity<_Ref>{}; + } + } + } else { + return _Must_have_ADL_found_iter_move_or_be_dereferenceable{}; + } + } + + template + using _Return_type = decltype(_Choose_return_type<_Ty>())::type; + enum class _St { _None, _Custom, _Fallback }; template @@ -886,8 +914,7 @@ namespace ranges { public: template - requires (_Choice<_Ty>._Strategy != _St::_None) - _NODISCARD _STATIC_CALL_OPERATOR constexpr decltype(auto) operator()(_Ty&& _Val) _CONST_CALL_OPERATOR + _NODISCARD _STATIC_CALL_OPERATOR constexpr _Return_type<_Ty> operator()(_Ty&& _Val) _CONST_CALL_OPERATOR noexcept(_Choice<_Ty>._No_throw) { constexpr _St _Strat = _Choice<_Ty>._Strategy; @@ -1121,8 +1148,8 @@ struct _Projected_impl { using value_type = remove_cvref_t>; [[noreturn]] indirect_result_t<_Proj&, _It> operator*() const { - _STL_REPORT_ERROR("std::projected::operator*() can't be called (N5008 [projected]/1)"); - _STL_UNREACHABLE; // no return value available for "continue on error" + static_assert( + false, "std::projected::operator*() can't be instantiated (N5008 [projected] as modified by LWG-4270)"); } }; }; @@ -3571,29 +3598,34 @@ namespace ranges { _EXPORT_STD inline constexpr _Advance_fn advance; + template + using _Distance_iterator_t = // per LWG-4303 + conditional_t>, decay_t<_Ty>, remove_const_t>>; + class _Distance_fn { public: template _Se> requires (!sized_sentinel_for<_Se, _It>) _NODISCARD _STATIC_CALL_OPERATOR constexpr iter_difference_t<_It> operator()( - _It _First, _Se _Last) _CONST_CALL_OPERATOR - noexcept(noexcept(_Distance_unchecked( - _STD _Get_unwrapped(_STD move(_First)), _STD _Get_unwrapped(_STD move(_Last))))) /* strengthened */ { + _It _First, _Se _Last) _CONST_CALL_OPERATOR noexcept(_Calculate_noexcept<_It, _Se>()) /* strengthened */ { _STD _Adl_verify_range(_First, _Last); return _Distance_unchecked( _RANGES _Unwrap_iter<_Se>(_STD move(_First)), _RANGES _Unwrap_sent<_It>(_STD move(_Last))); } - template > _Se> - _NODISCARD _STATIC_CALL_OPERATOR constexpr iter_difference_t> operator()( - _It&& _First, const _Se _Last) _CONST_CALL_OPERATOR - noexcept(noexcept(_Last - static_cast&>(_First))) /* strengthened */ { - return _Last - static_cast&>(_First); + template > _Se> + _NODISCARD _STATIC_CALL_OPERATOR constexpr iter_difference_t<_Distance_iterator_t<_It>> operator()(_It&& _First, + const _Se _Last) _CONST_CALL_OPERATOR noexcept(_Calculate_noexcept<_It, _Se>()) /* strengthened */ { + if constexpr (!is_array_v>) { + return _Last - _First; + } else { + return _Last - static_cast>(_First); + } } template _NODISCARD _STATIC_CALL_OPERATOR constexpr range_difference_t<_Rng> operator()( - _Rng&& _Range) _CONST_CALL_OPERATOR noexcept(_Nothrow_size<_Rng>) /* strengthened */ { + _Rng&& _Range) _CONST_CALL_OPERATOR noexcept(_Calculate_noexcept<_Rng>()) /* strengthened */ { if constexpr (sized_range<_Rng>) { return static_cast>(_RANGES size(_Range)); } else { @@ -3615,12 +3647,30 @@ namespace ranges { return _Count; } - template - static constexpr bool _Nothrow_size = - noexcept(_Distance_unchecked(_Ubegin(_STD declval<_Rng&>()), _Uend(_STD declval<_Rng&>()))); + template + _NODISCARD static consteval bool _Calculate_noexcept() noexcept { + if constexpr (sized_sentinel_for<_Se, _Distance_iterator_t<_It>>) { + if constexpr (!is_array_v>) { + return noexcept(_STD declval() - _STD declval<_It&>()); + } else { + return noexcept(_STD declval() - _STD declval>()); + } + } else if constexpr (sentinel_for<_Se, _It> && !sized_sentinel_for<_Se, _It>) { + return noexcept(_Distance_unchecked( + _STD _Get_unwrapped(_STD declval<_It>()), _STD _Get_unwrapped(_STD declval<_Se>()))); + } else { + return false; + } + } - template - static constexpr bool _Nothrow_size<_Rng> = noexcept(_RANGES size(_STD declval<_Rng&>())); + template + _NODISCARD static consteval bool _Calculate_noexcept() noexcept { + if constexpr (sized_range<_Rng>) { + return noexcept(_RANGES size(_STD declval<_Rng&>())); + } else { + return noexcept(_Distance_unchecked(_Ubegin(_STD declval<_Rng&>()), _Uend(_STD declval<_Rng&>()))); + } + } }; _EXPORT_STD inline constexpr _Distance_fn distance; diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 04ce668ad74..8db408fd683 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -80,6 +80,7 @@ // (__cpp_lib_freestanding_algorithm and __cpp_lib_freestanding_array only) // P2937R0 Freestanding Library: Remove strtok // P2968R2 Make std::ignore A First-Class Object +// P3223R2 Making istream::ignore() Less Surprising // P3323R1 Forbid atomic, Specify atomic_ref // (for atomic) @@ -912,7 +913,7 @@ #define _CPPLIB_VER 650 #define _MSVC_STL_VERSION 145 -#define _MSVC_STL_UPDATE 202507L +#define _MSVC_STL_UPDATE 202508L #ifndef _ALLOW_COMPILER_AND_STL_VERSION_MISMATCH #if defined(__CUDACC__) && defined(__CUDACC_VER_MAJOR__) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 3b512d1ff53..12ff729635f 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -959,12 +959,6 @@ std/containers/sequences/vector.bool/vector_bool.pass.cpp FAIL # Not analyzed. Inspecting shift operators for quoted(). std/input.output/iostream.format/quoted.manip/quoted_traits.compile.pass.cpp FAIL -# Not analyzed. -# MSVC warning C5046: 'test_undefined_internal::A::operator *': Symbol involving type with internal linkage not defined -# Clang error: function 'test_undefined_internal()::A::operator*' has internal linkage but is not defined [-Werror,-Wundefined-internal] -std/iterators/iterator.requirements/iterator.cust/iterator.cust.move/iter_rvalue_reference_t.compile.pass.cpp FAIL -std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.comp/op_spaceship.pass.cpp FAIL - # Not analyzed. Failing assert(arr[0].moves() == 1 && arr[1].moves() == 3). std/iterators/iterator.requirements/iterator.cust/iterator.cust.swap/iter_swap.pass.cpp FAIL @@ -1313,9 +1307,6 @@ std/algorithms/alg.sorting/alg.set.operations/set.intersection/set_intersection_ # Clang assertion: std::hermite(n, +inf) == inf std/numerics/c.math/hermite.pass.cpp FAIL -# Not analyzed. Test coverage for LLVM-104496 uses span. -std/containers/views/views.span/span.cons/copy.pass.cpp FAIL - # Not analyzed. These tests disable or limit allocations, which interferes with our proxy objects. std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp FAIL std/containers/sequences/vector/vector.capacity/shrink_to_fit_exceptions.pass.cpp FAIL diff --git a/tests/std/test.lst b/tests/std/test.lst index e0d87d8b8ec..d41f903c1ca 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -182,6 +182,7 @@ tests\GH_000935_complex_numerical_accuracy tests\GH_000940_missing_valarray_copy tests\GH_000952_bind_constraints tests\GH_000990_any_link_without_exceptions +tests\GH_000995_regex_custom_char_types tests\GH_001001_random_rejection_rounding tests\GH_001010_filesystem_error_encoding tests\GH_001017_discrete_distribution_out_of_range @@ -268,6 +269,7 @@ tests\GH_005421_vector_algorithms_integer_class_type_iterator tests\GH_005472_do_not_overlap tests\GH_005553_regex_character_translation tests\LWG2381_num_get_floating_point +tests\LWG2510_tag_classes tests\LWG2597_complex_branch_cut tests\LWG3018_shared_ptr_function tests\LWG3121_constrained_tuple_forwarding_ctor diff --git a/tests/std/tests/Dev11_0000000_null_forward_iterators/test.cpp b/tests/std/tests/Dev11_0000000_null_forward_iterators/test.cpp index 94008bd066a..b548e3d443d 100644 --- a/tests/std/tests/Dev11_0000000_null_forward_iterators/test.cpp +++ b/tests/std/tests/Dev11_0000000_null_forward_iterators/test.cpp @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#define _SILENCE_CXX23_ALIGNED_UNION_DEPRECATION_WARNING #define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING #define _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING @@ -10,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -18,13 +16,21 @@ #include #include #include -#include #include #include #include #include #include +#if _HAS_CXX17 +#include +#include +#endif // _HAS_CXX17 + +#if _HAS_CXX20 +#include +#endif // _HAS_CXX20 + using namespace std; // N3797 24.2.5 [forward.iterators]/2: @@ -91,14 +97,14 @@ void test_iterator() { } { - aligned_union_t<0, FwdIt> au3; - aligned_union_t<0, FwdIt> au4; + alignas(FwdIt) unsigned char buf3[sizeof(FwdIt)]; + alignas(FwdIt) unsigned char buf4[sizeof(FwdIt)]; - FwdIt* p3 = reinterpret_cast(&au3); - FwdIt* p4 = reinterpret_cast(&au4); + memset(buf3, 0xCC, sizeof(FwdIt)); + memset(buf4, 0xDD, sizeof(FwdIt)); - memset(p3, 0xCC, sizeof(FwdIt)); - memset(p4, 0xDD, sizeof(FwdIt)); + FwdIt* p3 = reinterpret_cast(buf3); + FwdIt* p4 = reinterpret_cast(buf4); new (p3) FwdIt{}; new (p4) FwdIt{}; diff --git a/tests/std/tests/GH_000995_regex_custom_char_types/env.lst b/tests/std/tests/GH_000995_regex_custom_char_types/env.lst new file mode 100644 index 00000000000..19f025bd0e6 --- /dev/null +++ b/tests/std/tests/GH_000995_regex_custom_char_types/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_matrix.lst diff --git a/tests/std/tests/GH_000995_regex_custom_char_types/test.cpp b/tests/std/tests/GH_000995_regex_custom_char_types/test.cpp new file mode 100644 index 00000000000..c3a19ec46c3 --- /dev/null +++ b/tests/std/tests/GH_000995_regex_custom_char_types/test.cpp @@ -0,0 +1,500 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +namespace signed_wchar_ns { + enum class signed_wchar_enum : short {}; + + bool operator==(const signed_wchar_enum swe, const char ch) { + return static_cast(swe) == static_cast(ch); + } + +#if !_HAS_CXX20 + bool operator!=(const signed_wchar_enum swe, const char ch) { + return !(swe == ch); + } + + bool operator==(const char ch, const signed_wchar_enum swe) { + return swe == ch; + } + + bool operator!=(const char ch, const signed_wchar_enum swe) { + return !(swe == ch); + } +#endif // !_HAS_CXX20 +} // namespace signed_wchar_ns + +using signed_wchar_ns::signed_wchar_enum; + +namespace ullong_ns { + enum class ullong_enum : unsigned long long {}; + + bool operator==(const ullong_enum ull, const char ch) { + return static_cast(ull) == static_cast(ch); + } + +#if !_HAS_CXX20 + bool operator!=(const ullong_enum ull, const char ch) { + return !(ull == ch); + } + + bool operator==(const char ch, const ullong_enum ull) { + return ull == ch; + } + + bool operator!=(const char ch, const ullong_enum ull) { + return !(ull == ch); + } +#endif // !_HAS_CXX20 +} // namespace ullong_ns + +using ullong_ns::ullong_enum; + +template +T convert_to(const signed_wchar_enum& char_enum) { + return static_cast(char_enum); +} + +template +T convert_to(const ullong_enum& char_enum) { + return static_cast(char_enum); +} + +template +class wrapped_character { +public: + wrapped_character() = default; + explicit wrapped_character(char ch) : character(static_cast(ch)) {} + explicit wrapped_character(unsigned char ch) : character(ch) {} + explicit wrapped_character(Elem w) : character(w) {} + template , int> = 0> + explicit wrapped_character(wchar_t w) : character(w) {} + explicit wrapped_character(int w) = delete; + explicit wrapped_character(unsigned int w) : character(static_cast(w)) {} + + operator unsigned char() const { + return static_cast(character); + } + + operator unsigned int() const { + return static_cast(character); + } + + operator char() const = delete; + operator wchar_t() const = delete; + operator int() const = delete; + operator unsigned long long() const = delete; + + friend bool operator==(const wrapped_character& lhs, const wrapped_character& rhs) { + return lhs.character == rhs.character; + } + + friend bool operator==(const wrapped_character& wc, const char ch) { + return wc.character == static_cast(ch); + } + +#if !_HAS_CXX20 + friend bool operator!=(const wrapped_character& lhs, const wrapped_character& rhs) { + return !(lhs == rhs); + } + + friend bool operator!=(const wrapped_character& wc, const char ch) { + return !(wc == ch); + } + + friend bool operator==(const char ch, const wrapped_character& wc) { + return wc == ch; + } + + friend bool operator!=(const char ch, const wrapped_character& wc) { + return !(wc == ch); + } +#endif // !_HAS_CXX20 + + template + friend T convert_to(const wrapped_character& wrapped_char) { + return static_cast(wrapped_char.character); + } + +private: + Elem character; +}; + +template +T convert_to(const wrapped_character& wrapped_char); + +using wrapped_wchar = wrapped_character; +using wrapped_ullong = wrapped_character; + +template +basic_string convert_to_underlying_string(FwdIt first, FwdIt last) { + basic_string str; + for (; first != last; ++first) { + str.push_back(convert_to(*first)); + } + return str; +} + +template +StringType convert_from_underlying_string(const basic_string& str) { + StringType result; + for (const auto& ch : str) { + result.push_back(static_cast(ch)); + } + return result; +} + +template +class test_regex_traits { +private: + using rx_traits = regex_traits; + +public: + using char_type = SourceChar; + using string_type = basic_string; + using locale_type = typename rx_traits::locale_type; + using char_class_type = typename rx_traits::char_class_type; + + test_regex_traits() = default; + + static size_t length(const SourceChar* p) { + return string_type::char_traits::length(p); + } + + SourceChar translate(const SourceChar c) const { + return c; + } + + SourceChar translate_nocase(const SourceChar c) const { + return static_cast(inner.translate_nocase(convert_to(c))); + } + + template + string_type transform(FwdIt first, FwdIt last) const { + auto str = convert_to_underlying_string(first, last); + return convert_from_underlying_string(inner.transform(str.begin(), str.end())); + } + + template + string_type transform_primary(FwdIt first, FwdIt last) const { + if (distance(first, last) == 1) { + return string_type{first, last}; + } + return string_type{}; + } + + template + string_type lookup_collatename(FwdIt first, FwdIt last) const { + auto str = convert_to_underlying_string(first, last); + return convert_from_underlying_string(inner.lookup_collatename(str.begin(), str.end())); + } + + template + char_class_type lookup_classname(FwdIt first, FwdIt last, bool icase = false) const { + auto str = convert_to_underlying_string(first, last); + return inner.lookup_classname(str.begin(), str.end(), icase); + } + + bool isctype(SourceChar c, char_class_type f) const { + return inner.isctype(convert_to(c), f); + } + + int value(SourceChar ch, int radix) const { + return inner.value(convert_to(ch), radix); + } + + locale_type imbue(locale_type l) { + return inner.imbue(l); + } + + locale_type getloc() const { + return inner.getloc(); + } + +private: + rx_traits inner; +}; + +template +struct custom_char_traits { + using char_type = Elem; + using int_type = conditional_t; + using pos_type = streampos; + using off_type = streamoff; + using state_type = mbstate_t; + + static Elem* copy(Elem* const first1, const Elem* const first2, const size_t count) noexcept { + copy_n(first2, count, first1); + return first1; + } + + static Elem* move(Elem* const result, const Elem* const first2, const size_t count) noexcept /* strengthened */ { + if (result == first2) { + // nothing to do + } else if (first2 <= result && result < first2 + count) { + copy_backward(first2, first2 + count, result + count); + } else { + copy_n(first2, count, result); + } + + return result; + } + + static int compare(const Elem* first1, const Elem* first2, size_t count) noexcept { + for (; 0 < count; --count, ++first1, ++first2) { + if (*first1 != *first2) { + return custom_char_traits::lt(*first1, *first2) ? -1 : +1; + } + } + + return 0; + } + + static size_t length(const Elem* first) { + size_t count = 0; + while (*first != Elem{}) { + ++count; + ++first; + } + + return count; + } + + static const Elem* find(const Elem* first, size_t count, const Elem& ch) noexcept /* strengthened */ { + // look for ch in [first, first + count) + for (; 0 < count; --count, ++first) { + if (*first == ch) { + return first; + } + } + + return nullptr; + } + + static Elem* assign(const Elem* const first, size_t count, const Elem ch) { + for (Elem* next = first; count > 0; --count, ++next) { + *next = ch; + } + + return first; + } + + static void assign(Elem& left, const Elem& right) noexcept { + left = right; + } + + static bool eq(const Elem left, const Elem right) noexcept { + return left == right; + } + + static bool lt(const Elem left, const Elem right) noexcept { + return convert_to(left) < convert_to(right); + } + + static Elem to_char_type(const int_type meta) noexcept { + return static_cast(meta); + } + + static int_type to_int_type(const Elem ch) noexcept { + return static_cast(static_cast(ch)); + } + + static bool eq_int_type(const int_type left, const int_type right) noexcept { + return left == right; + } + + static int_type not_eof(const int_type meta) noexcept { + return meta != eof() ? meta : !eof(); + } + + static int_type eof() noexcept { + return static_cast(-1); + } +}; + +template <> +struct char_traits : custom_char_traits {}; + +template <> +struct char_traits : custom_char_traits {}; + +template <> +struct char_traits : custom_char_traits {}; + +template <> +struct char_traits : custom_char_traits {}; + + +void test_gh_5592() { + // GH-5592: Remove non-standard _Uelem from parser + // This test checks that the parser compiles and doesn't crash + // when user-defined character types are used. + + // This regex is only intended to exert many different paths in the parser, + // but it is not designed to be meaningful. + wstring test_regex = L"^a*[\u00fe-\\u0101][\u0123-\u0146](?:abc|def){0,3}(=.gwer)" + LR"(\b.{6}\B(\.\d\f)\g\1\0\x34(?!gef)[-f[.a.][=b=]c-e-]$)"; + { + auto str = convert_from_underlying_string>(test_regex); + basic_regex> re{str}; + } + + { + auto str = convert_from_underlying_string>(test_regex); + basic_regex> re{str}; + } +} + +template +void test_regex_for_custom_char(const wstring& pattern, const wstring& input, bool should_match) { + auto converted_pattern = convert_from_underlying_string>(pattern); + auto converted_input = convert_from_underlying_string>(input); + basic_regex re{converted_pattern}; + assert(regex_match(converted_input, re) == should_match); +} + +void test_regex_on_custom_wchars(const wstring& pattern, const wstring& input, bool should_match) { + test_regex_for_custom_char>( + pattern, input, should_match); + test_regex_for_custom_char>(pattern, input, should_match); +} + +template +void test_regex_for_custom_char(const UnderlyingChar* pat_first, const UnderlyingChar* pat_last, + const UnderlyingChar* input_first, const UnderlyingChar* input_last, bool should_match) { + basic_string converted_pattern; + basic_string converted_input; + transform(pat_first, pat_last, back_inserter(converted_pattern), + [](UnderlyingChar val) { return static_cast(val); }); + transform(input_first, input_last, back_inserter(converted_input), + [](UnderlyingChar val) { return static_cast(val); }); + basic_regex re{converted_pattern}; + assert(regex_match(converted_input, re) == should_match); +} + +void test_regex_on_custom_ullongs(const unsigned long long* pat_first, const unsigned long long* pat_last, + const unsigned long long* input_first, const unsigned long long* input_last, bool should_match) { + test_regex_for_custom_char>( + pat_first, pat_last, input_first, input_last, should_match); + test_regex_for_custom_char>( + pat_first, pat_last, input_first, input_last, should_match); +} + +void test_gh_5671_single_character_patterns() { + // test patterns matching single characters + // simple smoke test + test_regex_on_custom_wchars(L"a", L"a", true); + test_regex_on_custom_wchars(L"a", L"b", false); + + // no truncation issues at 0x100 + test_regex_on_custom_wchars(L"\u0100", L"\u0100", true); // U+0100 LATIN CAPITAL LETTER A WITH MACRON + test_regex_on_custom_wchars(wstring(1, L'\0'), L"\u0100", false); // U+0100 LATIN CAPITAL LETTER A WITH MACRON + test_regex_on_custom_wchars(L"\u0100", wstring(1, L'\0'), false); // U+0100 LATIN CAPITAL LETTER A WITH MACRON + + // no issues with signed character values + test_regex_on_custom_wchars( + L"\uf000", L"\uf000", true); // U+F000 in private use area (signed for signed_wchar_enum) + + // matching for very large values + { + const unsigned long long pattern = 0xabababababULL; + + test_regex_on_custom_ullongs(&pattern, &pattern + 1, &pattern, &pattern + 1, true); + + for (const unsigned long long unmatched : {0xabULL, 0xababULL, 0xababababULL, 0xababababaaULL, 0xababababacULL, + 0x9bababababULL, 0xbbababababULL, 0xffffffababababULL}) { + test_regex_on_custom_ullongs(&pattern, &pattern + 1, &unmatched, &unmatched + 1, false); + } + } +} + +void test_gh_5671_line_terminators() { + // test line terminator handling for dot + test_regex_on_custom_wchars(L".", L"a", true); + test_regex_on_custom_wchars(L".", L"\r", false); + test_regex_on_custom_wchars(L".", L"\n", false); + test_regex_on_custom_wchars(L".", L"\u2028", false); // U+2028 LINE SEPARATOR + test_regex_on_custom_wchars(L".", L"\u2029", false); // U+2029 PARAGRAPH SEPARATOR + test_regex_on_custom_wchars(L".", L"\u2c60", true); // U+2C60 LATIN CAPITAL LETTER L WITH DOUBLE BAR + + { + const unsigned long long dot = L'.'; + + for (const unsigned long long line_terminator : {L'\r', L'\n', L'\u2028', L'\u2029'}) { + test_regex_on_custom_ullongs(&dot, &dot + 1, &line_terminator, &line_terminator + 1, false); + + const unsigned long long shifted_line_terminator = 0x100000000ULL + line_terminator; + test_regex_on_custom_ullongs(&dot, &dot + 1, &shifted_line_terminator, &shifted_line_terminator + 1, true); + } + } +} + +void test_gh_5671_word_boundaries() { + // test word boundaries + test_regex_on_custom_wchars(LR"(a\b.)", L"a\u0141", true); // U+0141 LATIN CAPITAL LETTER L WITH STROKE + test_regex_on_custom_wchars(LR"(a\B.)", L"a\u0141", false); // U+0141 LATIN CAPITAL LETTER L WITH STROKE +} + +void test_gh_5671_character_ranges() { + // test simple ranges + test_regex_on_custom_wchars(LR"([b-\u0141])", L"a", false); // U+0141 LATIN CAPITAL LETTER L WITH STROKE + test_regex_on_custom_wchars(LR"([b-\u0141])", L"b", true); + test_regex_on_custom_wchars(LR"([b-\u0141])", L"\u0141", true); + test_regex_on_custom_wchars(LR"([b-\u0141])", L"\u0142", false); // U+0142 LATIN SMALL LETTER L WITH STROKE + + // test that GH-5437 fix for small ranges near U+0100 remains in place for custom types + test_regex_on_custom_wchars(LR"([\u00ff-\u0100])", L"\u00FE", false); // U+00FE LATIN SMALL LETTER THORN + test_regex_on_custom_wchars(LR"([\u00ff-\u0100])", L"\u00FF", true); // U+00FF LATIN SMALL LETTER Y WITH DIAERESIS + test_regex_on_custom_wchars(LR"([\u00ff-\u0100])", L"\u0100", true); // U+0100 LATIN CAPITAL LETTER A WITH MACRON + test_regex_on_custom_wchars(LR"([\u00ff-\u0100])", L"\u0101", false); // U+0101 LATIN SMALL LETTER A WITH MACRON + + // test ranges with negative upper boundary when signed + test_regex_on_custom_wchars( + LR"([\u7fed-\u8123])", L"\u7fed", true); // U+7FED CJK UNIFIED IDEOGRAPH-7FED, U+8123 CJK UNIFIED IDEOGRAPH-8123 + test_regex_on_custom_wchars(LR"([\u7fed-\u8123])", L"\u8123", true); + test_regex_on_custom_wchars(LR"([\u7fed-\u8123])", L"\u8001", true); // U+8001 CJK UNIFIED IDEOGRAPH-8001 + test_regex_on_custom_wchars(LR"([\u7fed-\u8123])", L"\u7fec", false); // U+7FEC CJK UNIFIED IDEOGRAPH-7FEC + test_regex_on_custom_wchars(LR"([\u7fed-\u8123])", L"\u8124", false); // U+8124 CJK UNIFIED IDEOGRAPH-8124 + + // test ranges with boundaries exceeding UINT_MAX for small and large ranges + for (unsigned long long upper_bound : {0x100000006ULL, 0x100000036ULL}) { + const unsigned long long pattern[] = {L'[', 0x100000004ULL, L'-', upper_bound, L']'}; + for (unsigned long long matched = 0x100000004ULL; matched <= upper_bound; ++matched) { + test_regex_on_custom_ullongs(begin(pattern), end(pattern), &matched, &matched + 1, true); + } + + for (const unsigned long long unmatched : + {0x00000004ULL, upper_bound & 0xffffffffULL, 0x100000003ULL, upper_bound + 1ULL}) { + test_regex_on_custom_ullongs(begin(pattern), end(pattern), &unmatched, &unmatched + 1, false); + } + } +} + +void test_gh_5671() { + // GH-5671: Remove non-standard _Uelem from matcher + // + // The following tests check that internal narrowing conversions to integers in parser and matcher + // as well as signedness of the character type are handled appropriately + // even when using (weird) custom character types. + test_gh_5671_single_character_patterns(); + test_gh_5671_line_terminators(); + test_gh_5671_word_boundaries(); + test_gh_5671_character_ranges(); +} + +int main() { + test_gh_5592(); + test_gh_5671(); + return 0; +} diff --git a/tests/std/tests/GH_005244_regex_escape_sequences/test.cpp b/tests/std/tests/GH_005244_regex_escape_sequences/test.cpp index 7e66ca640a5..ba4b87d6d5f 100644 --- a/tests/std/tests/GH_005244_regex_escape_sequences/test.cpp +++ b/tests/std/tests/GH_005244_regex_escape_sequences/test.cpp @@ -24,9 +24,6 @@ class test_regex_traits { using locale_type = typename rx_traits::locale_type; using char_class_type = typename rx_traits::char_class_type; - // TRANSITION, GH-995 - using _Uelem = typename rx_traits::_Uelem; - test_regex_traits() = default; static size_t length(const charT* p) { diff --git a/tests/std/tests/GH_005553_regex_character_translation/test.cpp b/tests/std/tests/GH_005553_regex_character_translation/test.cpp index 33c5521ad49..5eadb05693e 100644 --- a/tests/std/tests/GH_005553_regex_character_translation/test.cpp +++ b/tests/std/tests/GH_005553_regex_character_translation/test.cpp @@ -26,9 +26,6 @@ class nonidempotent_translate_regex_traits : private regex_traits { using char_class_type = typename rx_traits::char_class_type; using uchar_type = make_unsigned_t; - // TRANSITION, GH-995 - using _Uelem = typename rx_traits::_Uelem; - nonidempotent_translate_regex_traits() = default; using rx_traits::length; diff --git a/tests/std/tests/LWG2510_tag_classes/env.lst b/tests/std/tests/LWG2510_tag_classes/env.lst new file mode 100644 index 00000000000..19f025bd0e6 --- /dev/null +++ b/tests/std/tests/LWG2510_tag_classes/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_matrix.lst diff --git a/tests/std/tests/LWG2510_tag_classes/test.compile.pass.cpp b/tests/std/tests/LWG2510_tag_classes/test.compile.pass.cpp new file mode 100644 index 00000000000..5e7efbdf073 --- /dev/null +++ b/tests/std/tests/LWG2510_tag_classes/test.compile.pass.cpp @@ -0,0 +1,207 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef _M_CEE_PURE +#include +#include +#endif // _M_CEE_PURE + +#if _HAS_CXX17 +#include +#endif // _HAS_CXX17 + +#if _HAS_CXX20 +#include +#include +#include +#include +#include +#endif // _HAS_CXX20 + +#if _HAS_CXX23 +#include +#include +#include +#include +#endif // _HAS_CXX23 + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +using namespace std; + +// LWG-2510 "Tag types should not be DefaultConstructible" + +template +void check_implicit_default_construction(const T&); // not defined + +template +constexpr bool implicitly_default_constructible = false; +template +constexpr bool implicitly_default_constructible({}))>> = true; + +STATIC_ASSERT(implicitly_default_constructible); +STATIC_ASSERT(implicitly_default_constructible); + +STATIC_ASSERT(!implicitly_default_constructible); +STATIC_ASSERT(!implicitly_default_constructible); +STATIC_ASSERT(!implicitly_default_constructible); + +template +void check_tag_class() { // COMPILE-ONLY + STATIC_ASSERT(is_default_constructible_v); + STATIC_ASSERT(!implicitly_default_constructible); + + STATIC_ASSERT(is_copy_constructible_v); + STATIC_ASSERT(is_move_constructible_v); + STATIC_ASSERT(is_constructible_v); + STATIC_ASSERT(is_constructible_v); + STATIC_ASSERT(is_convertible_v); + STATIC_ASSERT(is_convertible_v); + STATIC_ASSERT(is_convertible_v); + STATIC_ASSERT(is_convertible_v); + STATIC_ASSERT(is_copy_assignable_v); + STATIC_ASSERT(is_move_assignable_v); + STATIC_ASSERT(is_assignable_v); + STATIC_ASSERT(is_assignable_v); + + STATIC_ASSERT(is_nothrow_destructible_v); + + STATIC_ASSERT(!is_polymorphic_v); + + constexpr T constant_argument; + (void) constant_argument; + + // desired properties not yet guaranteed by the Standard + STATIC_ASSERT(is_nothrow_default_constructible_v); + STATIC_ASSERT(is_nothrow_copy_constructible_v); + STATIC_ASSERT(is_nothrow_move_constructible_v); + STATIC_ASSERT(is_nothrow_constructible_v); + STATIC_ASSERT(is_nothrow_constructible_v); +#if _HAS_CXX20 + STATIC_ASSERT(is_nothrow_convertible_v); + STATIC_ASSERT(is_nothrow_convertible_v); + STATIC_ASSERT(is_nothrow_convertible_v); + STATIC_ASSERT(is_nothrow_convertible_v); +#endif // _HAS_CXX20 + STATIC_ASSERT(is_nothrow_copy_assignable_v); + STATIC_ASSERT(is_nothrow_move_assignable_v); + STATIC_ASSERT(is_nothrow_assignable_v); + STATIC_ASSERT(is_nothrow_assignable_v); + + STATIC_ASSERT(is_trivially_default_constructible_v); + STATIC_ASSERT(is_trivially_copy_constructible_v); + STATIC_ASSERT(is_trivially_move_constructible_v); + STATIC_ASSERT(is_trivially_constructible_v); + STATIC_ASSERT(is_trivially_constructible_v); + STATIC_ASSERT(is_trivially_copy_assignable_v); + STATIC_ASSERT(is_trivially_move_assignable_v); + STATIC_ASSERT(is_trivially_assignable_v); + STATIC_ASSERT(is_trivially_assignable_v); + STATIC_ASSERT(is_trivially_destructible_v); + STATIC_ASSERT(is_trivially_copyable_v); + + STATIC_ASSERT(is_standard_layout_v); + STATIC_ASSERT(is_empty_v); // only guaranteed for allocator_arg_t and piecewise_construct_t + + // ABI-specific, seemingly agreed among mainstream implementations + STATIC_ASSERT(sizeof(T) == 1); +} + +void check_standard_tags() { // COMPILE-ONLY + check_tag_class(); + check_tag_class(); + check_tag_class(); +#ifndef _M_CEE_PURE + check_tag_class(); + check_tag_class(); + check_tag_class(); +#endif // _M_CEE_PURE + +#if _HAS_CXX17 + check_tag_class(); + check_tag_class>(); + check_tag_class>(); + check_tag_class(-1)>>(); + check_tag_class>(); + check_tag_class>>(); + check_tag_class>(); + check_tag_class>(); + + // LWG-4273 "Standard execution policy types should be conventional tag class types" + check_tag_class(); + check_tag_class(); + check_tag_class(); +#endif // _HAS_CXX17 + +#if _HAS_CXX20 + check_tag_class(); + check_tag_class(); + check_tag_class(); + + // LWG-4273 "Standard execution policy types should be conventional tag class types" + check_tag_class(); +#endif // _HAS_CXX20 + +#if _HAS_CXX23 + check_tag_class(); + check_tag_class(); + // TODO: Cover sorted_equivalent_t and sorted_unique_t once flat_meow are implemented. +#endif // _HAS_CXX23 + + // TODO: Update to cover newly introduced tag class types. +} + +// We intentionally implement internal disambiguation tag types like standard ones. +void check_implementation_details() { // COMPILE-ONLY + // TODO: Synchronize the check list with actual implementation details. + check_tag_class<_Alloc_exact_args_t>(); + check_tag_class<_Alloc_unpack_tuple_t>(); + check_tag_class<_Exact_args_t>(); + check_tag_class<_Leave_proxy_unbound>(); + check_tag_class<_Move_allocator_tag>(); + check_tag_class<_One_then_variadic_args_t>(); + check_tag_class<_String_constructor_concat_tag>(); + check_tag_class<_Secret_copyability_ignoring_tag>(); + check_tag_class<_Secret_scoped_allocator_construct_tag>(); + check_tag_class<_Unforced>(); + check_tag_class<_Unpack_tuple_t>(); + check_tag_class<_Value_init_tag>(); + check_tag_class<_Zero_then_variadic_args_t>(); +#ifndef _M_CEE_PURE + check_tag_class<_From_raw_state_tag>(); +#endif // _M_CEE_PURE + +#if _HAS_CXX17 + check_tag_class<_No_init_tag>(); + check_tag_class<_Not_fn_tag>(); +#endif // _HAS_CXX17 + +#if _HAS_CXX20 + check_tag_class<_Auto_id_tag>(); + check_tag_class<_For_overwrite_tag>(); + check_tag_class<_Variantish_empty_tag>(); + check_tag_class(); + check_tag_class(); + check_tag_class(); + check_tag_class(); +#endif // _HAS_CXX20 + +#if _HAS_CXX23 + check_tag_class<_Construct_expected_from_invoke_result_tag>(); + check_tag_class<_Construct_from_invoke_result_tag>(); + check_tag_class<_Extents_from_tuple>(); + check_tag_class<_Gen_detail::_Secret_tag>(); +#endif // _HAS_CXX23 +} diff --git a/tests/std/tests/P0220R1_string_view/test.cpp b/tests/std/tests/P0220R1_string_view/test.cpp index dac4ec93ae0..edc4236ae50 100644 --- a/tests/std/tests/P0220R1_string_view/test.cpp +++ b/tests/std/tests/P0220R1_string_view/test.cpp @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#include #include #include #include @@ -1229,14 +1230,20 @@ static_assert(!is_constructible_v); static_assert(!is_assignable_v); #endif // _HAS_CXX23 -// Also test that no C6510 warning +// Also test that basic_string_view produces no C6510 warning +// when instantiated with custom character types. +// GH-5563: Extend coverage to basic_string struct char_wrapper { char c; }; template <> struct std::char_traits { - using char_type = char_wrapper; + using char_type = char_wrapper; + using int_type = int; + using pos_type = char_traits::pos_type; + using off_type = char_traits::off_type; + using state_type = char_traits::state_type; static bool eq(char_wrapper lhs, char_wrapper rhs) { return lhs.c == rhs.c; @@ -1247,18 +1254,76 @@ struct std::char_traits { return strlen(reinterpret_cast(a)); } + static char_wrapper* copy(char_wrapper* const first1, const char_wrapper* const first2, const size_t count) { + copy_n(first2, count, first1); + return first1; + } + + static char_wrapper* move(char_wrapper* const first1, const char_wrapper* const first2, const size_t count) { + memmove(first1, first2, count * sizeof(char_wrapper)); + return first1; + } + static int compare(const char_wrapper* lhs, const char_wrapper* rhs, size_t count) { return char_traits::compare( reinterpret_cast(lhs), reinterpret_cast(rhs), count); } -}; -using WrappedSV = basic_string_view>; + static const char_wrapper* find(const char_wrapper* first, size_t count, const char_wrapper& ch) { + for (; 0 < count; --count, ++first) { + if (eq(*first, ch)) { + return first; + } + } + + return nullptr; + } + + static char_wrapper* assign(char_wrapper* const first, size_t count, const char_wrapper ch) { + for (char_wrapper* next = first; count > 0; --count, ++next) { + *next = ch; + } + + return first; + } + + static void assign(char_wrapper& left, const char_wrapper& right) { + left = right; + } + + static bool lt(const char_wrapper left, const char_wrapper right) { + return char_traits::lt(left.c, right.c); + } + + static char_wrapper to_char_type(const int_type meta) { + return {char_traits::to_char_type(meta)}; + } + + static int_type to_int_type(const char_wrapper ch) { + return char_traits::to_int_type(ch.c); + } + + static bool eq_int_type(const int_type left, const int_type right) { + return char_traits::eq_int_type(left, right); + } + + static int_type not_eof(const int_type meta) { + return char_traits::not_eof(meta); + } + + static int_type eof() { + return char_traits::eof(); + } +}; void test_C6510_warning() { // compile-only char_wrapper a[] = {{'a'}, {'b'}, {'c'}, {'\0'}}; - WrappedSV sv(a); + basic_string_view sv(a); (void) sv; + + // GH-5563: Extend test coverage to basic_string + basic_string s(a); + (void) s; } #if _HAS_CXX20 diff --git a/tests/std/tests/P0323R12_expected/test.cpp b/tests/std/tests/P0323R12_expected/test.cpp index ce2eccd161b..f9cdbdaa04f 100644 --- a/tests/std/tests/P0323R12_expected/test.cpp +++ b/tests/std/tests/P0323R12_expected/test.cpp @@ -2445,7 +2445,7 @@ void test_lwg_3886_volatile() { static_assert(copyable>); static_assert(copyable>); -// Test workaround for DevCom-10655311: Class derived from std::expected can't be constructed with bool value type +// Test DevCom-10655311: Class derived from std::expected can't be constructed with bool value type template class DerivedFromExpected : private expected { public: @@ -2509,6 +2509,21 @@ static_assert(!is_assignable_v&, ambiguating_expected_ static_assert(test_lwg_3886()); +// Test LWG-4222 "expected constructor from a single value missing a constraint" + +struct ConstructibleFromEverything { + explicit ConstructibleFromEverything(auto); +}; + +struct ConvertibleFromInt { + ConvertibleFromInt(int); +}; + +static_assert(!is_constructible_v, unexpect_t&>); +static_assert(!is_constructible_v, const unexpect_t&>); +static_assert(!is_constructible_v, unexpect_t>); +static_assert(!is_constructible_v, const unexpect_t>); + int main() { test_unexpected::test_all(); static_assert(test_unexpected::test_all()); diff --git a/tests/std/tests/P0811R3_midpoint_lerp/test.cpp b/tests/std/tests/P0811R3_midpoint_lerp/test.cpp index 130a41576fd..7534f719859 100644 --- a/tests/std/tests/P0811R3_midpoint_lerp/test.cpp +++ b/tests/std/tests/P0811R3_midpoint_lerp/test.cpp @@ -1031,6 +1031,8 @@ bool test_lerp() { return true; } +#pragma warning(push) +#pragma warning(disable : 4756) // ignore constant arithmetic overflow warning void test_gh_1917() { // GH-1917 : lerp(1e+308, 5e+307, 4.0) spuriously overflows using bit_type = unsigned long long; @@ -1110,6 +1112,7 @@ void test_gh_1917() { } #endif // _M_FP_STRICT } +#pragma warning(pop) constexpr bool test_gh_2112() { // GH-2112 : std::lerp is missing Arithmetic overloads diff --git a/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp b/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp index abc1699c201..e542dfe761c 100644 --- a/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp +++ b/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp @@ -1073,15 +1073,7 @@ namespace iterator_cust_move_test { static_assert(noexcept(ranges::iter_move(static_cast(&some_ints[2])))); static_assert(same_as, int&&>); -#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-1008447 static_assert(same_as, int (&)(int)>); -#else // ^^^ no workaround / workaround vvv -#ifdef _MSVC_INTERNAL_TESTING // TRANSITION, assertion will fire once VSO-2066340 ships. - static_assert(same_as, int (&&)(int)>); -#else // ^^^ defined(_MSVC_INTERNAL_TESTING) / !defined(_MSVC_INTERNAL_TESTING) vvv - static_assert(same_as, int (*)(int)>); -#endif // ^^^ !defined(_MSVC_INTERNAL_TESTING) -#endif // ^^^ workaround ^^^ static_assert(same_as, int&&>); static_assert(ranges::iter_move(some_ints) == 0); @@ -1090,11 +1082,7 @@ namespace iterator_cust_move_test { constexpr int f(int i) noexcept { return i + 1; } -#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-1008447 static_assert(same_as, int (&)(int)>); -#else // ^^^ no workaround / workaround vvv - static_assert(same_as, int (&&)(int)>); -#endif // ^^^ workaround ^^^ static_assert(ranges::iter_move(&f)(42) == 43); static_assert(noexcept(ranges::iter_move(&f))); @@ -2107,6 +2095,10 @@ struct std::common_type + concept can_call_ranges_difference = + requires(I&& it, S&& se) { distance(std::forward(it), std::forward(se)); }; + constexpr bool test_iter_forms() { { // Call next(i), validating that ++i is called once @@ -3098,7 +3090,6 @@ namespace iter_ops { } { -#ifndef __EDG__ // TRANSITION, VSO-1898890 // Call distance(i, s) with arrays which must be decayed to pointers. // (This behavior was regressed by LWG-3392.) int some_ints[] = {1, 2, 3}; @@ -3116,7 +3107,23 @@ namespace iter_ops { static_assert(noexcept(distance(const_ints + 1, const_ints))); assert(distance(const_ints, const_ints) == 0); static_assert(noexcept(distance(const_ints, const_ints))); -#endif // ^^^ no workaround ^^^ + } + + { // Test LWG-4242 "ranges::distance does not work with volatile iterators" + static_assert(can_call_ranges_difference); + static_assert(can_call_ranges_difference); + + // Per LWG-4303, ranges::distance should be well-constrained for non-pointer volatile iterators. + static_assert( + !can_call_ranges_difference, std::reverse_iterator>); + static_assert( + !can_call_ranges_difference&, std::reverse_iterator>); + + if (!std::is_constant_evaluated()) { + int arr[]{1, 2, 3}; + int* volatile ptr = arr; + assert(distance(ptr, arr + 3) == 3); + } } return true; diff --git a/tests/std/tests/VSO_0000000_initialize_everything/test.cpp b/tests/std/tests/VSO_0000000_initialize_everything/test.cpp index b5ed1baef83..a41e347078a 100644 --- a/tests/std/tests/VSO_0000000_initialize_everything/test.cpp +++ b/tests/std/tests/VSO_0000000_initialize_everything/test.cpp @@ -53,30 +53,26 @@ inline bool operator!=(const stateful_allocator& lhs, const stateful_allocato return lhs.state != rhs.state; } -// warning C4582: 'garbage_data>::data': constructor is not implicitly called -// warning C4583: 'garbage_data>::data': destructor is not implicitly called -#pragma warning(push) -#pragma warning(disable : 4582 4583) template -struct garbage_data { - union { - T data; - }; - +class garbage_data { +private: + alignas(T) unsigned char buf[sizeof(T)]; bool constructed; + +public: garbage_data() : constructed(false) { - memset(&data, 0xCC, sizeof(data)); + memset(buf, 0xCC, sizeof(T)); } garbage_data(const garbage_data&) = delete; garbage_data& operator=(const garbage_data&) = delete; T& get() { - return data; + return *ptr(); } T* ptr() { - return &data; + return reinterpret_cast(buf); } T* operator->() { @@ -92,11 +88,10 @@ struct garbage_data { template void construct(Args&&... args) { assert(!constructed); - ::new (static_cast(&data)) T(forward(args)...); + ::new (static_cast(buf)) T(forward(args)...); constructed = true; } }; -#pragma warning(pop) template void assert_string_invariants(basic_string, Alloc>& target, const char* const expected) { diff --git a/tests/std/tests/VSO_0000000_instantiate_iterators_misc/test.compile.pass.cpp b/tests/std/tests/VSO_0000000_instantiate_iterators_misc/test.compile.pass.cpp index 23fb0ef0f53..8352292398b 100644 --- a/tests/std/tests/VSO_0000000_instantiate_iterators_misc/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0000000_instantiate_iterators_misc/test.compile.pass.cpp @@ -17,6 +17,7 @@ #define _SILENCE_CXX20_OLD_SHARED_PTR_ATOMIC_SUPPORT_DEPRECATION_WARNING #define _SILENCE_CXX20_REL_OPS_DEPRECATION_WARNING #define _SILENCE_CXX20_U8PATH_DEPRECATION_WARNING +#define _SILENCE_CXX20_VOLATILE_DEPRECATION_WARNING #define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING #define _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING #define _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING diff --git a/tests/std/tests/VSO_0000000_more_pair_tuple_sfinae/test.cpp b/tests/std/tests/VSO_0000000_more_pair_tuple_sfinae/test.cpp index fb07af86b09..21a3bf66076 100644 --- a/tests/std/tests/VSO_0000000_more_pair_tuple_sfinae/test.cpp +++ b/tests/std/tests/VSO_0000000_more_pair_tuple_sfinae/test.cpp @@ -3,10 +3,6 @@ #include #include -#ifndef _M_CEE_PURE -#include -#endif // _M_CEE_PURE -#include #include #include #include @@ -42,39 +38,31 @@ STATIC_ASSERT(!is_constructible_v, allocator_arg_t, // LWG-2510 "Tag types should not be DefaultConstructible" -template -struct IsImplicitlyDefaultConstructible : false_type {}; +template +constexpr bool implicitly_default_constructible = false; -template -void ImplicitlyDefaultConstruct(const T&); +template +void check_implicit_default_construction(const T&); // not defined -template -struct IsImplicitlyDefaultConstructible({}))>> : true_type {}; +template +constexpr bool implicitly_default_constructible({}))>> = true; struct ExplicitDefault { explicit ExplicitDefault() = default; }; template -constexpr bool OrdinaryDC = is_default_constructible_v && IsImplicitlyDefaultConstructible::value; +constexpr bool OrdinaryDC = is_default_constructible_v && implicitly_default_constructible; template -constexpr bool ExplicitDC = is_default_constructible_v && !IsImplicitlyDefaultConstructible::value; +constexpr bool ExplicitDC = is_default_constructible_v && !implicitly_default_constructible; template -constexpr bool VerbotenDC = !is_default_constructible_v && !IsImplicitlyDefaultConstructible::value; +constexpr bool VerbotenDC = !is_default_constructible_v && !implicitly_default_constructible; STATIC_ASSERT(OrdinaryDC); STATIC_ASSERT(VerbotenDC); STATIC_ASSERT(ExplicitDC); -STATIC_ASSERT(ExplicitDC); -STATIC_ASSERT(ExplicitDC); -STATIC_ASSERT(ExplicitDC); -#ifndef _M_CEE_PURE -STATIC_ASSERT(ExplicitDC); -STATIC_ASSERT(ExplicitDC); -STATIC_ASSERT(ExplicitDC); -#endif // _M_CEE_PURE using Expl = ExplicitDefault; using NOPE = NoDefault; diff --git a/tests/std/tests/VSO_0000000_nullptr_stream_out/test.cpp b/tests/std/tests/VSO_0000000_nullptr_stream_out/test.cpp index 52e074acd43..635bce087c2 100644 --- a/tests/std/tests/VSO_0000000_nullptr_stream_out/test.cpp +++ b/tests/std/tests/VSO_0000000_nullptr_stream_out/test.cpp @@ -64,4 +64,17 @@ int main() { STATIC_ASSERT(OstreamInsertable); STATIC_ASSERT(OstreamInsertable); STATIC_ASSERT(!OstreamInsertable); + + { // Test P3223R2 "Making std::istream::ignore Less Surprising" + istringstream in{"\xF0\x9F\xA4\xA1 Clown Face"}; + decltype(auto) ret = in.ignore(100, '\xA1'); + + STATIC_ASSERT(is_same_v); + assert(&ret == &static_cast(in)); + assert(in.gcount() == 4); + + string s; + in >> s; + assert(s == "Clown"); + } } diff --git a/tests/std/tests/VSO_0000000_regex_use/test.cpp b/tests/std/tests/VSO_0000000_regex_use/test.cpp index a1e41b84421..ea6e246adb6 100644 --- a/tests/std/tests/VSO_0000000_regex_use/test.cpp +++ b/tests/std/tests/VSO_0000000_regex_use/test.cpp @@ -2103,6 +2103,32 @@ void test_gh_5576() { match_default, "AbGweEXfFlXlLLlffflEXlF"); } +void test_gh_5672() { + // GH-5672: Speed up skip optimization for default `regex_traits` in `collate` mode + // The PR added a faster branch in the skip optimization when matching in collate mode + // for default `regex_traits` and `regex_traits`. + // The following tests check that searching still works correctly when the faster branch is engaged. + { + test_regex collating_re(&g_regexTester, "g", regex_constants::collate); + + collating_re.should_search_match("abcdefghijklmnopqrstuvwxyz", "g"); + collating_re.should_search_fail("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + collating_re.should_search_match("zyxwvutsrqponmlkjihgfedcba", "g"); + collating_re.should_search_fail("ZYXWVUTSRQPONMLKJIHGFEDCBA"); + collating_re.should_search_fail("zyxwvutsrqponmlkjihedcba"); + } + + { + test_wregex collating_re(&g_regexTester, L"g", regex_constants::collate); + + collating_re.should_search_match(L"abcdefghijklmnopqrstuvwxyz", L"g"); + collating_re.should_search_fail(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + collating_re.should_search_match(L"zyxwvutsrqponmlkjihgfedcba", L"g"); + collating_re.should_search_fail(L"ZYXWVUTSRQPONMLKJIHGFEDCBA"); + collating_re.should_search_fail(L"zyxwvutsrqponmlkjihedcba"); + } +} + int main() { test_dev10_449367_case_insensitivity_should_work(); test_dev11_462743_regex_collate_should_not_disable_regex_icase(); @@ -2153,6 +2179,7 @@ int main() { test_gh_5490(); test_gh_5509(); test_gh_5576(); + test_gh_5672(); return g_regexTester.result(); } diff --git a/tests/std/tests/VSO_0180466_algorithm_overhauls/test.cpp b/tests/std/tests/VSO_0180466_algorithm_overhauls/test.cpp index 63ecb94d0c3..4a8ce66f58d 100644 --- a/tests/std/tests/VSO_0180466_algorithm_overhauls/test.cpp +++ b/tests/std/tests/VSO_0180466_algorithm_overhauls/test.cpp @@ -6,6 +6,9 @@ #pragma warning(disable : 4389) // signed/unsigned mismatch in arithmetic #ifdef __clang__ +#if __clang_major__ >= 21 // TRANSITION, unconditionally silence this warning when Clang 21 is available +#pragma clang diagnostic ignored "-Wcharacter-conversion" +#endif // __clang_major__ >= 21 #pragma clang diagnostic ignored "-Wsign-compare" #endif // __clang__ diff --git a/tests/utils/stl/test/tests.py b/tests/utils/stl/test/tests.py index b049c185fa8..f8762f1cb2d 100644 --- a/tests/utils/stl/test/tests.py +++ b/tests/utils/stl/test/tests.py @@ -258,7 +258,7 @@ def _handleEnvlst(self, litConfig): self.compileFlags.append('/arm64EC') self.linkFlags.append('/machine:arm64ec') - # TRANSITION, Windows SDK 10.0.26100.3916 emits + # TRANSITION, Windows SDK 10.0.26100.4188 emits # "warning C28301: No annotations for first declaration of 'meow'" # for various intrinsics when building for ARM64EC. self.compileFlags.append('/wd28301')