diff --git a/.github/ISSUE_TEMPLATE/cxx20-feature.md b/.github/ISSUE_TEMPLATE/cxx23-feature.md similarity index 70% rename from .github/ISSUE_TEMPLATE/cxx20-feature.md rename to .github/ISSUE_TEMPLATE/cxx23-feature.md index c7b3749aa2b..399071c4475 100644 --- a/.github/ISSUE_TEMPLATE/cxx20-feature.md +++ b/.github/ISSUE_TEMPLATE/cxx23-feature.md @@ -1,8 +1,8 @@ --- -name: cxx20 Feature +name: cxx23 Feature about: For STL maintainers only title: PAPER_NUMBER PAPER_TITLE -labels: cxx20 +labels: cxx23 assignees: '' --- @@ -22,3 +22,8 @@ the https://wg21.link redirector will start working. Feature-test macro: `#define MACRO_NAME MACRO_VALUE` + +Note: We're still working on finishing C++20. Until we're done +with that (and the compiler implements distinct `/std:c++20` and +`/std:c++latest` options), we won't be able to review PRs for +C++23 features. diff --git a/CMakeLists.txt b/CMakeLists.txt index 5029bd03aec..a96985b708d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT DEFINED CMAKE_TOOLCHAIN_FILE AND EXISTS "${CMAKE_CURRENT_LIST_DIR}/vcpkg set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_LIST_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake") endif() -cmake_minimum_required(VERSION 3.17) +cmake_minimum_required(VERSION 3.18) set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) project(msvc_standard_libraries LANGUAGES CXX) diff --git a/README.md b/README.md index 3da3ef34440..8cf9388913d 100644 --- a/README.md +++ b/README.md @@ -143,14 +143,14 @@ Just try to follow these rules, so we can spend more time fixing bugs and implem The STL uses boost-math headers to provide P0226R1 Mathematical Special Functions. We recommend using [vcpkg][] to acquire this dependency. -1. Install Visual Studio 2019 16.8 Preview 5 or later. +1. Install Visual Studio 2019 16.9 Preview 1 or later. * We recommend selecting "C++ CMake tools for Windows" in the VS Installer. This will ensure that you're using supported versions of CMake and Ninja. - * Otherwise, install [CMake][] 3.17 or later, and [Ninja][] 1.8.2 or later. + * Otherwise, install [CMake][] 3.18 or later, and [Ninja][] 1.8.2 or later. 2. Open Visual Studio, and choose the "Clone or check out code" option. Enter the URL of this repository, `https://github.com/microsoft/STL`. 3. Open a terminal in the IDE with `` Ctrl + ` `` (by default) or press on "View" in the top bar, and then "Terminal". -4. In the terminal, invoke `git submodule update --init vcpkg` +4. In the terminal, invoke `git submodule update --init --progress llvm-project vcpkg` 5. In the terminal, invoke `.\vcpkg\bootstrap-vcpkg.bat` 6. In the terminal, invoke `.\vcpkg\vcpkg.exe install boost-math:x86-windows boost-math:x64-windows` 7. Choose the architecture you wish to build in the IDE, and build as you would any other project. All necessary CMake @@ -158,15 +158,15 @@ acquire this dependency. # How To Build With A Native Tools Command Prompt -1. Install Visual Studio 2019 16.8 Preview 5 or later. +1. Install Visual Studio 2019 16.9 Preview 1 or later. * We recommend selecting "C++ CMake tools for Windows" in the VS Installer. This will ensure that you're using supported versions of CMake and Ninja. - * Otherwise, install [CMake][] 3.17 or later, and [Ninja][] 1.8.2 or later. + * Otherwise, install [CMake][] 3.18 or later, and [Ninja][] 1.8.2 or later. 2. Open a command prompt. 3. Change directories to a location where you'd like a clone of this STL repository. 4. `git clone https://github.com/microsoft/STL` 5. `cd STL` -6. `git submodule update --init vcpkg` +6. `git submodule update --init --progress llvm-project vcpkg` 7. `.\vcpkg\bootstrap-vcpkg.bat` 8. `.\vcpkg\vcpkg.exe install boost-math:x86-windows boost-math:x64-windows` @@ -234,13 +234,12 @@ C:\Users\username\Desktop>dumpbin /IMPORTS .\example.exe | findstr msvcp # How To Run The Tests With A Native Tools Command Prompt 1. Follow either [How To Build With A Native Tools Command Prompt][] or [How To Build With The Visual Studio IDE][]. -2. Invoke `git submodule update --init llvm-project` at the root of the STL source tree. -3. Acquire [Python][] 3.9 or newer and have it on the `PATH` (or run it directly using its absolute or relative path). -4. Have LLVM's `bin` directory on the `PATH` (so `clang-cl.exe` is available). +2. Acquire [Python][] 3.9 or newer and have it on the `PATH` (or run it directly using its absolute or relative path). +3. Have LLVM's `bin` directory on the `PATH` (so `clang-cl.exe` is available). * We recommend selecting "C++ Clang tools for Windows" in the VS Installer. This will automatically add LLVM to the `PATH` of the x86 and x64 Native Tools Command Prompts, and will ensure that you're using a supported version. * Otherwise, use [LLVM's installer][] and choose to add LLVM to your `PATH` during installation. -5. Follow the instructions below. +4. Follow the instructions below. ## Running All The Tests @@ -397,7 +396,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception [CMake]: https://cmake.org/download [Code of Conduct FAQ]: https://opensource.microsoft.com/codeofconduct/faq/ [Compiler Explorer]: https://godbolt.org -[Developer Community]: https://developercommunity.visualstudio.com/spaces/62/index.html +[Developer Community]: https://aka.ms/feedback/report?space=62 [Discord server]: https://discord.gg/XWanNww [How To Build With A Native Tools Command Prompt]: #how-to-build-with-a-native-tools-command-prompt [How To Build With The Visual Studio IDE]: #how-to-build-with-the-visual-studio-ide @@ -409,7 +408,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception [N4868]: https://wg21.link/n4868 [NOTICE.txt]: NOTICE.txt [Ninja]: https://ninja-build.org -[Pipelines]: https://dev.azure.com/vclibs/STL/_build/latest?definitionId=2&branchName=master +[Pipelines]: https://dev.azure.com/vclibs/STL/_build/latest?definitionId=4&branchName=master [Python]: https://www.python.org/downloads/windows/ [Roadmap]: https://github.com/microsoft/STL/wiki/Roadmap [Status Chart]: https://microsoft.github.io/STL/ diff --git a/azure-devops/create-vmss.ps1 b/azure-devops/create-vmss.ps1 index 797e00f20c0..1434ce0ac48 100644 --- a/azure-devops/create-vmss.ps1 +++ b/azure-devops/create-vmss.ps1 @@ -25,7 +25,7 @@ $LiveVMPrefix = 'BUILD' $WindowsServerSku = '2019-Datacenter' $ProgressActivity = 'Creating Scale Set' -$TotalProgress = 11 +$TotalProgress = 12 $CurrentProgress = 1 <# @@ -159,6 +159,14 @@ function Wait-Shutdown { } +#################################################################################################### +Write-Progress ` + -Activity $ProgressActivity ` + -Status 'Setting the subscription context' ` + -PercentComplete (100 / $TotalProgress * $CurrentProgress++) + +Set-AzContext -SubscriptionName CPP_STL_GitHub + #################################################################################################### Write-Progress ` -Activity $ProgressActivity ` @@ -391,6 +399,4 @@ New-AzVmss ` Write-Progress -Activity $ProgressActivity -Completed Write-Host "Location: $Location" Write-Host "Resource group name: $ResourceGroupName" -Write-Host "User name: AdminUser" -Write-Host "Using generated password: $AdminPW" Write-Host 'Finished!' diff --git a/azure-devops/provision-image.ps1 b/azure-devops/provision-image.ps1 index ea84e185ab1..d09d0e6db72 100644 --- a/azure-devops/provision-image.ps1 +++ b/azure-devops/provision-image.ps1 @@ -88,6 +88,9 @@ $Workloads = @( 'Microsoft.VisualStudio.Component.VC.CMake.Project', 'Microsoft.VisualStudio.Component.VC.CoreIde', 'Microsoft.VisualStudio.Component.VC.Llvm.Clang', + 'Microsoft.VisualStudio.Component.VC.Runtimes.ARM.Spectre', + 'Microsoft.VisualStudio.Component.VC.Runtimes.ARM64.Spectre', + 'Microsoft.VisualStudio.Component.VC.Runtimes.x86.x64.Spectre', 'Microsoft.VisualStudio.Component.VC.Tools.ARM', 'Microsoft.VisualStudio.Component.VC.Tools.ARM64', 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64', @@ -99,6 +102,9 @@ $Sku = 'Enterprise' $VisualStudioBootstrapperUrl = 'https://aka.ms/vs/16/pre/vs_enterprise.exe' $PythonUrl = 'https://www.python.org/ftp/python/3.9.0/python-3.9.0-amd64.exe' +# https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk +$WindowsDriverKitUrl = 'https://go.microsoft.com/fwlink/?linkid=2128854' + $CudaUrl = ` 'https://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda_10.1.243_426.00_win10.exe' $CudaFeatures = 'nvcc_10.1 cuobjdump_10.1 nvprune_10.1 cupti_10.1 gpu_library_advisor_10.1 memcheck_10.1 ' + ` @@ -223,6 +229,36 @@ Function InstallPython { } } +<# +.SYNOPSIS +Installs the Windows Driver Kit. + +.DESCRIPTION +InstallWindowsDriverKit installs the Windows Driver Kit from the supplied URL. + +.PARAMETER Url +The URL of the Windows Driver Kit installer. +#> +Function InstallWindowsDriverKit { + Param( + [String]$Url + ) + + Write-Host 'Downloading the Windows Driver Kit...' + [string]$installerPath = Get-TempFilePath -Extension 'exe' + curl.exe -L -o $installerPath -s -S $Url + Write-Host 'Installing the Windows Driver Kit...' + $proc = Start-Process -FilePath $installerPath -ArgumentList ` + @('/quiet', '/features', 'OptionId.WindowsDriverKitComplete') -Wait -PassThru + $exitCode = $proc.ExitCode + if ($exitCode -eq 0) { + Write-Host 'Installation successful!' + } + else { + Write-Error "Installation failed! Exited with $exitCode." + } +} + <# .SYNOPSIS Installs NVIDIA's CUDA Toolkit. @@ -300,6 +336,7 @@ Add-MpPreference -ExclusionProcess python.exe InstallPython $PythonUrl InstallVisualStudio -Workloads $Workloads -BootstrapperUrl $VisualStudioBootstrapperUrl +InstallWindowsDriverKit $WindowsDriverKitUrl InstallCuda -Url $CudaUrl -Features $CudaFeatures Write-Host 'Updating PATH...' diff --git a/azure-devops/run-build.yml b/azure-devops/run-build.yml index 2d52b453755..3d4258ec860 100644 --- a/azure-devops/run-build.yml +++ b/azure-devops/run-build.yml @@ -2,12 +2,13 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception jobs: -- job: ${{ parameters.targetPlatform }} +- job: '${{ parameters.targetPlatform }}_${{ parameters.shardNum }}' timeoutInMinutes: 360 variables: buildOutputLocation: 'D:\build\${{ parameters.targetPlatform }}' litFlags: '-j$(testParallelism);--timeout=240;--shuffle;--xunit-xml-output=$(buildOutputLocation)/test-results.xml' + shardFlags: '--num-shards=${{ parameters.numShards }};--run-shard=${{ parameters.shardNum }}' vcpkgLocation: '$(Build.SourcesDirectory)/vcpkg' steps: - script: | @@ -62,8 +63,8 @@ jobs: -host_arch=amd64 -arch=${{ parameters.vsDevCmdArch }} -no_logo cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=$(vcpkgLocation)\scripts\buildsystems\vcpkg.cmake ^ -DVCPKG_TARGET_TRIPLET=${{ parameters.targetPlatform }}-windows -DCMAKE_CXX_COMPILER=cl ^ - -DCMAKE_BUILD_TYPE=Release -DLIT_FLAGS=$(litFlags) ^ - -DCMAKE_CXX_FLAGS=/analyze ^ + -DCMAKE_BUILD_TYPE=Release -DLIT_FLAGS=$(litFlags);$(shardFlags) ^ + -DCMAKE_CXX_FLAGS=/analyze:autolog- ^ -S $(Build.SourcesDirectory) -B $(buildOutputLocation) cmake --build $(buildOutputLocation) displayName: 'Build the STL' @@ -88,4 +89,4 @@ jobs: searchFolder: $(buildOutputLocation) testResultsFormat: JUnit testResultsFiles: '**/test-results.xml' - testRunTitle: 'test-${{ parameters.targetPlatform }}' + testRunTitle: 'test-${{ parameters.targetPlatform }}-${{ parameters.shardNum }}' diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 641674e59de..8530fa6b2ef 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -6,7 +6,7 @@ variables: tmpDir: 'D:\Temp' -pool: 'StlBuild-2020-10-23' +pool: 'StlBuild-2020-11-10' stages: - stage: Code_Format @@ -63,18 +63,124 @@ stages: parameters: targetPlatform: x86 vsDevCmdArch: x86 + numShards: 8 + shardNum: 1 + + - template: azure-devops/run-build.yml + parameters: + targetPlatform: x86 + vsDevCmdArch: x86 + numShards: 8 + shardNum: 2 + + - template: azure-devops/run-build.yml + parameters: + targetPlatform: x86 + vsDevCmdArch: x86 + numShards: 8 + shardNum: 3 + + - template: azure-devops/run-build.yml + parameters: + targetPlatform: x86 + vsDevCmdArch: x86 + numShards: 8 + shardNum: 4 + + - template: azure-devops/run-build.yml + parameters: + targetPlatform: x86 + vsDevCmdArch: x86 + numShards: 8 + shardNum: 5 + + - template: azure-devops/run-build.yml + parameters: + targetPlatform: x86 + vsDevCmdArch: x86 + numShards: 8 + shardNum: 6 + + - template: azure-devops/run-build.yml + parameters: + targetPlatform: x86 + vsDevCmdArch: x86 + numShards: 8 + shardNum: 7 + + - template: azure-devops/run-build.yml + parameters: + targetPlatform: x86 + vsDevCmdArch: x86 + numShards: 8 + shardNum: 8 + + - template: azure-devops/run-build.yml + parameters: + targetPlatform: x64 + vsDevCmdArch: amd64 + numShards: 8 + shardNum: 1 + + - template: azure-devops/run-build.yml + parameters: + targetPlatform: x64 + vsDevCmdArch: amd64 + numShards: 8 + shardNum: 2 + + - template: azure-devops/run-build.yml + parameters: + targetPlatform: x64 + vsDevCmdArch: amd64 + numShards: 8 + shardNum: 3 + + - template: azure-devops/run-build.yml + parameters: + targetPlatform: x64 + vsDevCmdArch: amd64 + numShards: 8 + shardNum: 4 + + - template: azure-devops/run-build.yml + parameters: + targetPlatform: x64 + vsDevCmdArch: amd64 + numShards: 8 + shardNum: 5 + + - template: azure-devops/run-build.yml + parameters: + targetPlatform: x64 + vsDevCmdArch: amd64 + numShards: 8 + shardNum: 6 + + - template: azure-devops/run-build.yml + parameters: + targetPlatform: x64 + vsDevCmdArch: amd64 + numShards: 8 + shardNum: 7 - template: azure-devops/run-build.yml parameters: targetPlatform: x64 vsDevCmdArch: amd64 + numShards: 8 + shardNum: 8 - template: azure-devops/run-build.yml parameters: targetPlatform: arm vsDevCmdArch: arm + numShards: 1 + shardNum: 1 - template: azure-devops/run-build.yml parameters: targetPlatform: arm64 vsDevCmdArch: arm64 + numShards: 1 + shardNum: 1 diff --git a/llvm-project b/llvm-project index d66428cb995..a668ad92d5e 160000 --- a/llvm-project +++ b/llvm-project @@ -1 +1 @@ -Subproject commit d66428cb995c7a04ecb02951d5021d815fc02b2b +Subproject commit a668ad92d5e2161e07e1a435a19ea5072f52a989 diff --git a/stl/aliases/arm64ec/std_init_once_begin_initialize.obj b/stl/aliases/arm64ec/std_init_once_begin_initialize.obj index 593e6c144ab..431291f2f90 100644 Binary files a/stl/aliases/arm64ec/std_init_once_begin_initialize.obj and b/stl/aliases/arm64ec/std_init_once_begin_initialize.obj differ diff --git a/stl/aliases/arm64ec/std_init_once_complete.obj b/stl/aliases/arm64ec/std_init_once_complete.obj index 35149685437..363bfe340e5 100644 Binary files a/stl/aliases/arm64ec/std_init_once_complete.obj and b/stl/aliases/arm64ec/std_init_once_complete.obj differ diff --git a/stl/aliases/generate.cmd b/stl/aliases/generate.cmd index afad08f9bd9..12cb87b3bc2 100644 --- a/stl/aliases/generate.cmd +++ b/stl/aliases/generate.cmd @@ -44,8 +44,7 @@ mkdir arm64ec chpe\std_init_once_begin_initialize.obj ..\..\..\..\..\tools\amd64\aliasobj.exe ^ /machine:arm64ec ^ - __imp___std_init_once_begin_initialize ^ - __imp_InitOnceBeginInitialize ^ + -m std_init_once_begin_initialize-arm64ec.txt ^ arm64ec\std_init_once_begin_initialize.obj :: __std_init_once_complete @@ -72,6 +71,5 @@ mkdir arm64ec chpe\std_init_once_complete.obj ..\..\..\..\..\tools\amd64\aliasobj.exe ^ /machine:arm64ec ^ - __imp___std_init_once_complete ^ - __imp_InitOnceComplete ^ + -m std_init_once_complete-arm64ec.txt ^ arm64ec\std_init_once_complete.obj diff --git a/stl/aliases/std_init_once_begin_initialize-arm64ec.txt b/stl/aliases/std_init_once_begin_initialize-arm64ec.txt new file mode 100644 index 00000000000..3431bdf51cf --- /dev/null +++ b/stl/aliases/std_init_once_begin_initialize-arm64ec.txt @@ -0,0 +1,2 @@ +#__std_init_once_begin_initialize #InitOnceBeginInitialize +__imp___std_init_once_begin_initialize __imp_InitOnceBeginInitialize diff --git a/stl/aliases/std_init_once_complete-arm64ec.txt b/stl/aliases/std_init_once_complete-arm64ec.txt new file mode 100644 index 00000000000..4a146c7abfc --- /dev/null +++ b/stl/aliases/std_init_once_complete-arm64ec.txt @@ -0,0 +1,2 @@ +#__std_init_once_complete #InitOnceComplete +__imp___std_init_once_complete __imp_InitOnceComplete diff --git a/stl/inc/__msvc_all_public_headers.hpp b/stl/inc/__msvc_all_public_headers.hpp index 912896ed2d9..b238fdb7602 100644 --- a/stl/inc/__msvc_all_public_headers.hpp +++ b/stl/inc/__msvc_all_public_headers.hpp @@ -37,18 +37,52 @@ #define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING #define _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS +// Core STL Headers +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Core C Wrapper Headers +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef _CORE_HEADERS_ONLY + +// Non-Core STL Headers #include #include #include -#include #include #include #include #include -#include #include -#include -#include #include #include #include @@ -57,28 +91,24 @@ #include #include #include -#include #include #include #include #include #include #include -#include #include #include #include #include #include #include -#include #include #include #include #include #include #include -#include #include #include #include @@ -92,16 +122,13 @@ #include #include #include -#include #include #include #include #include -#include #include #include #include -#include #ifndef _M_CEE_PURE #include @@ -120,32 +147,15 @@ #include #endif // _M_CEE -#include +// Non-Core C Wrapper Headers #include -#include -#include -#include -#include -#include #include -#include -#include #include -#include -#include #include -#include #include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include + +// Non-Core Experimental Headers #include #include #include @@ -157,9 +167,10 @@ #include #include +#endif // _CORE_HEADERS_ONLY + #ifndef _MSVC_TESTING_NVCC #include -#include #include #include #include @@ -181,7 +192,6 @@ #include #include #include -#include #include #include #include @@ -207,6 +217,11 @@ #include #include +#ifndef _CORE_HEADERS_ONLY +#include +#include +#endif // _CORE_HEADERS_ONLY + #ifndef _M_CEE_PURE #include #endif // _M_CEE_PURE diff --git a/stl/inc/__msvc_system_error_abi.hpp b/stl/inc/__msvc_system_error_abi.hpp index d6744adf1f2..d95b458cf55 100644 --- a/stl/inc/__msvc_system_error_abi.hpp +++ b/stl/inc/__msvc_system_error_abi.hpp @@ -8,7 +8,7 @@ #define __MSVC_SYSTEM_ERROR_ABI_HPP #include #if _STL_COMPILER_PREPROCESSOR -#include +#include #pragma pack(push, _CRT_PACKING) #pragma warning(push, _STL_WARNING_LEVEL) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index d9422ad4140..29d6bcbefe4 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -490,58 +490,6 @@ template _Se, class _Pj = identity, - indirect_unary_predicate> _Pr> - _NODISCARD constexpr _It operator()(_It _First, _Se _Last, _Pr _Pred, _Pj _Proj = {}) const { - _Adl_verify_range(_First, _Last); - - auto _UResult = _Find_if_not_unchecked( - _Get_unwrapped(_STD move(_First)), _Get_unwrapped(_STD move(_Last)), _Pass_fn(_Pred), _Pass_fn(_Proj)); - - _Seek_wrapped(_First, _STD move(_UResult)); - return _First; - } - - template , _Pj>> _Pr> - _NODISCARD constexpr borrowed_iterator_t<_Rng> operator()(_Rng&& _Range, _Pr _Pred, _Pj _Proj = {}) const { - auto _First = _RANGES begin(_Range); - - auto _UResult = _Find_if_not_unchecked( - _Get_unwrapped(_STD move(_First)), _Uend(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj)); - - _Seek_wrapped(_First, _STD move(_UResult)); - return _First; - } - - private: - template - _NODISCARD static constexpr _It _Find_if_not_unchecked(_It _First, const _Se _Last, _Pr _Pred, _Pj _Proj) { - _STL_INTERNAL_STATIC_ASSERT(input_iterator<_It>); - _STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se, _It>); - _STL_INTERNAL_STATIC_ASSERT(indirect_unary_predicate<_Pr, projected<_It, _Pj>>); - - for (; _First != _Last; ++_First) { - if (!_STD invoke(_Pred, _STD invoke(_Proj, *_First))) { - break; - } - } - - return _First; - } - }; - - inline constexpr _Find_if_not_fn find_if_not{_Not_quite_object::_Construct_tag{}}; -} // namespace ranges -#endif // __cpp_lib_concepts - // FUNCTION TEMPLATE adjacent_find template _NODISCARD _CONSTEXPR20 _FwdIt adjacent_find(const _FwdIt _First, _FwdIt _Last, _Pr _Pred) { @@ -3929,16 +3877,19 @@ namespace ranges { _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_STD move(_First)); const auto _ULast = _Get_unwrapped(_STD move(_Last)); - if constexpr (_Fill_memset_is_safe) { -#ifdef __cpp_lib_is_constant_evaluated - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_is_constant_evaluated - { + if (!_STD is_constant_evaluated()) { + if constexpr (_Fill_memset_is_safe) { const auto _Distance = static_cast(_ULast - _UFirst); _Fill_memset(_UFirst, _Value, _Distance); - _UFirst += _Distance; - _Seek_wrapped(_First, _UFirst); + _Seek_wrapped(_First, _UFirst + _Distance); return _First; + } else if constexpr (_Fill_zero_memset_is_safe) { + if (_Is_all_bits_zero(_Value)) { + const auto _Distance = static_cast(_ULast - _UFirst); + _Fill_zero_memset(_UFirst, _Distance); + _Seek_wrapped(_First, _UFirst + _Distance); + return _First; + } } } @@ -3969,15 +3920,17 @@ namespace ranges { constexpr _It operator()(_It _First, iter_difference_t<_It> _Count, const _Ty& _Value) const { if (_Count > 0) { auto _UFirst = _Get_unwrapped_n(_STD move(_First), _Count); - if constexpr (_Fill_memset_is_safe) { -#ifdef __cpp_lib_is_constant_evaluated - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_is_constant_evaluated - { + if (!_STD is_constant_evaluated()) { + if constexpr (_Fill_memset_is_safe) { _Fill_memset(_UFirst, _Value, static_cast(_Count)); - _UFirst += _Count; - _Seek_wrapped(_First, _UFirst); // no need to move since _UFirst is a pointer + _Seek_wrapped(_First, _UFirst + _Count); // no need to move since _UFirst is a pointer return _First; + } else if constexpr (_Fill_zero_memset_is_safe) { + if (_Is_all_bits_zero(_Value)) { + _Fill_zero_memset(_UFirst, static_cast(_Count)); + _Seek_wrapped(_First, _UFirst + _Count); // no need to move since _UFirst is a pointer + return _First; + } } } diff --git a/stl/inc/atomic b/stl/inc/atomic index 78820eb37b3..8dfadf62917 100644 --- a/stl/inc/atomic +++ b/stl/inc/atomic @@ -13,9 +13,9 @@ #error is not supported when compiling with /clr:pure. #endif // _M_CEE_PURE -#include // for size_t -#include -#include +#include +#include +#include #include #if _HAS_CXX20 #include @@ -2465,25 +2465,6 @@ _NODISCARD bool atomic_is_lock_free(const atomic<_Ty>* _Mem) noexcept { return _Mem->is_lock_free(); } -template -_CXX20_DEPRECATE_ATOMIC_INIT void atomic_init( - atomic<_Ty>* const _Mem, const typename atomic<_Ty>::value_type _Value) noexcept { -#if 1 // TRANSITION, ABI - _CSTD memcpy(_STD addressof(_Mem->_Storage), _STD addressof(_Value), sizeof(_Ty)); -#else // ^^^ don't break ABI / break ABI vvv - _CSTD memcpy(_Mem, _STD addressof(_Value), sizeof(_Ty)); -#endif // TRANSITION, ABI - _CSTD memset(reinterpret_cast(_Mem) + sizeof(_Ty), 0, sizeof(atomic<_Ty>) - sizeof(_Ty)); -} - -template -_CXX20_DEPRECATE_ATOMIC_INIT void atomic_init( - volatile atomic<_Ty>* const _Mem, const typename atomic<_Ty>::value_type _Value) noexcept { - // NB: respecting volatility here appears unimplementable - static_assert(_Deprecate_non_lock_free_volatile<_Ty>, "Never fails"); - _STD atomic_init(const_cast*>(_Mem), _Value); -} - template void atomic_store(volatile atomic<_Ty>* const _Mem, const _Identity_t<_Ty> _Value) noexcept { static_assert(_Deprecate_non_lock_free_volatile<_Ty>, "Never fails"); @@ -2507,6 +2488,19 @@ void atomic_store_explicit(atomic<_Ty>* const _Mem, const _Identity_t<_Ty> _Valu _Mem->store(_Value, _Order); } +template +_CXX20_DEPRECATE_ATOMIC_INIT void atomic_init( + volatile atomic<_Ty>* const _Mem, const typename atomic<_Ty>::value_type _Value) noexcept { + static_assert(_Deprecate_non_lock_free_volatile<_Ty>, "Never fails"); + _STD atomic_store_explicit(_Mem, _Value, memory_order_relaxed); +} + +template +_CXX20_DEPRECATE_ATOMIC_INIT void atomic_init( + atomic<_Ty>* const _Mem, const typename atomic<_Ty>::value_type _Value) noexcept { + _STD atomic_store_explicit(_Mem, _Value, memory_order_relaxed); +} + template _NODISCARD _Ty atomic_load(const volatile atomic<_Ty>* const _Mem) noexcept { static_assert(_Deprecate_non_lock_free_volatile<_Ty>, "Never fails"); diff --git a/stl/inc/barrier b/stl/inc/barrier index 2258cfe26de..fc0eb1df2cd 100644 --- a/stl/inc/barrier +++ b/stl/inc/barrier @@ -18,7 +18,7 @@ #else // ^^^ !_HAS_CXX20 / _HAS_CXX20 vvv #include -#include +#include #include #include diff --git a/stl/inc/cassert b/stl/inc/cassert index 18b2f2b7778..cf8f3cef253 100644 --- a/stl/inc/cassert +++ b/stl/inc/cassert @@ -1,9 +1,9 @@ -// cassert standard header +// cassert standard header (core) // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // NOTE: no include guard -#include +#include #include diff --git a/stl/inc/cctype b/stl/inc/cctype index d9980f4f33d..cc6c49fe7b3 100644 --- a/stl/inc/cctype +++ b/stl/inc/cctype @@ -1,4 +1,4 @@ -// cctype standard header +// cctype standard header (core) // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception @@ -6,7 +6,7 @@ #pragma once #ifndef _CCTYPE_ #define _CCTYPE_ -#include +#include #if _STL_COMPILER_PREPROCESSOR #include diff --git a/stl/inc/cerrno b/stl/inc/cerrno index efc14b66727..1b5a470c32c 100644 --- a/stl/inc/cerrno +++ b/stl/inc/cerrno @@ -1,4 +1,4 @@ -// cerrno standard header +// cerrno standard header (core) // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception @@ -6,7 +6,7 @@ #pragma once #ifndef _CERRNO_ #define _CERRNO_ -#include +#include #if _STL_COMPILER_PREPROCESSOR #include diff --git a/stl/inc/cfenv b/stl/inc/cfenv index 778dd014a82..c78b9837248 100644 --- a/stl/inc/cfenv +++ b/stl/inc/cfenv @@ -1,4 +1,4 @@ -// cfenv standard header +// cfenv standard header (core) // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception @@ -6,7 +6,7 @@ #pragma once #ifndef _CFENV_ #define _CFENV_ -#include +#include #if _STL_COMPILER_PREPROCESSOR #include diff --git a/stl/inc/charconv b/stl/inc/charconv index ae2cbb5cac7..9994d42f528 100644 --- a/stl/inc/charconv +++ b/stl/inc/charconv @@ -12,9 +12,8 @@ #if !_HAS_CXX17 #pragma message("The contents of are available only with C++17 or later.") #else // ^^^ !_HAS_CXX17 / _HAS_CXX17 vvv -#include +#include #include -#include #include #include #include @@ -1057,60 +1056,6 @@ _NODISCARD inline uint64_t _Divide(_Big_integer_flt& _Numerator, const _Big_inte // ^^^^^^^^^^ DERIVED FROM corecrt_internal_big_integer.h ^^^^^^^^^^ -// vvvvvvvvvv DERIVED FROM corecrt_internal_fltintrn.h vvvvvvvvvv - -template -struct _Floating_type_traits; - -template <> -struct _Floating_type_traits { - static constexpr int32_t _Mantissa_bits = FLT_MANT_DIG; - static constexpr int32_t _Exponent_bits = sizeof(float) * CHAR_BIT - FLT_MANT_DIG; - - static constexpr int32_t _Maximum_binary_exponent = FLT_MAX_EXP - 1; - static constexpr int32_t _Minimum_binary_exponent = FLT_MIN_EXP - 1; - - static constexpr int32_t _Exponent_bias = 127; - - static constexpr int32_t _Sign_shift = _Exponent_bits + _Mantissa_bits - 1; - static constexpr int32_t _Exponent_shift = _Mantissa_bits - 1; - - using _Uint_type = uint32_t; - - static constexpr uint32_t _Exponent_mask = (1u << _Exponent_bits) - 1; - static constexpr uint32_t _Normal_mantissa_mask = (1u << _Mantissa_bits) - 1; - static constexpr uint32_t _Denormal_mantissa_mask = (1u << (_Mantissa_bits - 1)) - 1; - static constexpr uint32_t _Special_nan_mantissa_mask = 1u << (_Mantissa_bits - 2); - static constexpr uint32_t _Shifted_sign_mask = 1u << _Sign_shift; - static constexpr uint32_t _Shifted_exponent_mask = _Exponent_mask << _Exponent_shift; -}; - -template <> -struct _Floating_type_traits { - static constexpr int32_t _Mantissa_bits = DBL_MANT_DIG; - static constexpr int32_t _Exponent_bits = sizeof(double) * CHAR_BIT - DBL_MANT_DIG; - - static constexpr int32_t _Maximum_binary_exponent = DBL_MAX_EXP - 1; - static constexpr int32_t _Minimum_binary_exponent = DBL_MIN_EXP - 1; - - static constexpr int32_t _Exponent_bias = 1023; - - static constexpr int32_t _Sign_shift = _Exponent_bits + _Mantissa_bits - 1; - static constexpr int32_t _Exponent_shift = _Mantissa_bits - 1; - - using _Uint_type = uint64_t; - - static constexpr uint64_t _Exponent_mask = (1ULL << _Exponent_bits) - 1; - static constexpr uint64_t _Normal_mantissa_mask = (1ULL << _Mantissa_bits) - 1; - static constexpr uint64_t _Denormal_mantissa_mask = (1ULL << (_Mantissa_bits - 1)) - 1; - static constexpr uint64_t _Special_nan_mantissa_mask = 1ULL << (_Mantissa_bits - 2); - static constexpr uint64_t _Shifted_sign_mask = 1ULL << _Sign_shift; - static constexpr uint64_t _Shifted_exponent_mask = _Exponent_mask << _Exponent_shift; -}; - -// ^^^^^^^^^^ DERIVED FROM corecrt_internal_fltintrn.h ^^^^^^^^^^ - - // vvvvvvvvvv DERIVED FROM corecrt_internal_strtox.h vvvvvvvvvv // This type is used to hold a partially-parsed string representation of a floating-point number. diff --git a/stl/inc/chrono b/stl/inc/chrono index 8405b26be58..d53e2873cb6 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -8,9 +8,10 @@ #define _CHRONO_ #include #if _STL_COMPILER_PREPROCESSOR +#include #include #include -#include +#include #include #include @@ -617,6 +618,88 @@ namespace chrono { }; using high_resolution_clock = steady_clock; + +#if _HAS_CXX20 + // [time.duration.io] + +#define _IF_PERIOD_RETURN_SUFFIX_ELSE(_TYPE, _SUFFIX) \ + if constexpr (is_same_v<_Period, _TYPE>) { \ + if constexpr (is_same_v<_CharT, char>) { \ + return _SUFFIX; \ + } else { \ + return L##_SUFFIX; \ + } \ + } else + + template + _NODISCARD constexpr const _CharT* _Get_literal_unit_suffix() { + _IF_PERIOD_RETURN_SUFFIX_ELSE(atto, "as") + _IF_PERIOD_RETURN_SUFFIX_ELSE(femto, "fs") + _IF_PERIOD_RETURN_SUFFIX_ELSE(pico, "ps") + _IF_PERIOD_RETURN_SUFFIX_ELSE(nano, "ns") + _IF_PERIOD_RETURN_SUFFIX_ELSE(micro, "us") + _IF_PERIOD_RETURN_SUFFIX_ELSE(milli, "ms") + _IF_PERIOD_RETURN_SUFFIX_ELSE(centi, "cs") + _IF_PERIOD_RETURN_SUFFIX_ELSE(deci, "ds") + _IF_PERIOD_RETURN_SUFFIX_ELSE(seconds::period, "s") + _IF_PERIOD_RETURN_SUFFIX_ELSE(deca, "das") + _IF_PERIOD_RETURN_SUFFIX_ELSE(hecto, "hs") + _IF_PERIOD_RETURN_SUFFIX_ELSE(kilo, "ks") + _IF_PERIOD_RETURN_SUFFIX_ELSE(mega, "Ms") + _IF_PERIOD_RETURN_SUFFIX_ELSE(giga, "Gs") + _IF_PERIOD_RETURN_SUFFIX_ELSE(tera, "Ts") + _IF_PERIOD_RETURN_SUFFIX_ELSE(peta, "Ps") + _IF_PERIOD_RETURN_SUFFIX_ELSE(exa, "Es") + _IF_PERIOD_RETURN_SUFFIX_ELSE(minutes::period, "min") + _IF_PERIOD_RETURN_SUFFIX_ELSE(hours::period, "h") + _IF_PERIOD_RETURN_SUFFIX_ELSE(ratio<86400>, "d") + + { + return nullptr; + } + } + +#undef _IF_PERIOD_RETURN_SUFFIX_ELSE + + template + _NODISCARD _CharT* _Get_general_unit_suffix(_CharT* _Rnext, const intmax_t _Num, const intmax_t _Den) { + // Returns the head pointer of the string, built in reverse. + _STL_INTERNAL_CHECK(_Num > 0 && _Den > 0); + *--_Rnext = '\0'; + *--_Rnext = 's'; + *--_Rnext = ']'; + if (_Den != 1) { + _Rnext = _UIntegral_to_buff(_Rnext, static_cast(_Den)); + *--_Rnext = '/'; + } + + _Rnext = _UIntegral_to_buff(_Rnext, static_cast(_Num)); + *--_Rnext = '['; + return _Rnext; + } + + template + basic_ostream<_CharT, _Traits>& operator<<( + basic_ostream<_CharT, _Traits>& _Os, const duration<_Rep, _Period>& _Dur) { + basic_ostringstream<_CharT, _Traits> _Sstr; + _Sstr.flags(_Os.flags()); + _Sstr.imbue(_Os.getloc()); + _Sstr.precision(_Os.precision()); + _Sstr << _Dur.count(); + + constexpr auto _Suffix = _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); + _Sstr << _Begin; + } else { + _Sstr << _Suffix; + } + + return _Os << _Sstr.str(); + } +#endif // _HAS_CXX20 } // namespace chrono // HELPERS diff --git a/stl/inc/cinttypes b/stl/inc/cinttypes index 2b130570796..d1f07e10a51 100644 --- a/stl/inc/cinttypes +++ b/stl/inc/cinttypes @@ -1,4 +1,4 @@ -// cinttypes standard header +// cinttypes standard header (core) // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception @@ -6,7 +6,7 @@ #pragma once #ifndef _CINTTYPES_ #define _CINTTYPES_ -#include +#include #if _STL_COMPILER_PREPROCESSOR #include diff --git a/stl/inc/clocale b/stl/inc/clocale index f725ad9df67..bfc5a0aacff 100644 --- a/stl/inc/clocale +++ b/stl/inc/clocale @@ -1,4 +1,4 @@ -// clocale standard header +// clocale standard header (core) // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception @@ -6,7 +6,7 @@ #pragma once #ifndef _CLOCALE_ #define _CLOCALE_ -#include +#include #if _STL_COMPILER_PREPROCESSOR #include diff --git a/stl/inc/cmath b/stl/inc/cmath index cdc55d438d4..354587044fe 100644 --- a/stl/inc/cmath +++ b/stl/inc/cmath @@ -12,6 +12,10 @@ #include #include +#if !defined(_M_CEE) && !defined(__clang__) +#include +#endif // !defined(_M_CEE) && !defined(__clang__) + #if _HAS_CXX20 #include #endif // _HAS_CXX20 @@ -56,11 +60,23 @@ _NODISCARD _Check_return_ inline float cbrt(_In_ float _Xx) noexcept /* strength } _NODISCARD _Check_return_ inline float ceil(_In_ float _Xx) noexcept /* strengthened */ { +#ifdef _M_CEE return _CSTD ceilf(_Xx); +#elif defined(__clang__) + return __builtin_ceilf(_Xx); +#else // ^^^ __clang__ / !__clang__ vvv + return __ceilf(_Xx); +#endif // __clang__ } _NODISCARD _Check_return_ inline float copysign(_In_ float _Number, _In_ float _Sign) noexcept /* strengthened */ { +#ifdef _M_CEE return _CSTD copysignf(_Number, _Sign); +#elif defined(__clang__) + return __builtin_copysignf(_Number, _Sign); +#else // ^^^ __clang__ / !__clang__ vvv + return __copysignf(_Number, _Sign); +#endif // __clang__ } _NODISCARD _Check_return_ inline float cos(_In_ float _Xx) noexcept /* strengthened */ { @@ -100,7 +116,13 @@ _NODISCARD _Check_return_ inline float fdim(_In_ float _Xx, _In_ float _Yx) noex } _NODISCARD _Check_return_ inline float floor(_In_ float _Xx) noexcept /* strengthened */ { +#ifdef _M_CEE return _CSTD floorf(_Xx); +#elif defined(__clang__) + return __builtin_floorf(_Xx); +#else // ^^^ __clang__ / !__clang__ vvv + return __floorf(_Xx); +#endif // __clang__ } _NODISCARD _Check_return_ inline float fma(_In_ float _Xx, _In_ float _Yx, _In_ float _Zx) noexcept /* strengthened */ { @@ -208,7 +230,13 @@ _NODISCARD _Check_return_ inline float rint(_In_ float _Xx) noexcept /* strength } _NODISCARD _Check_return_ inline float round(_In_ float _Xx) noexcept /* strengthened */ { +#ifdef _M_CEE return _CSTD roundf(_Xx); +#elif defined(__clang__) + return __builtin_roundf(_Xx); +#else // ^^^ __clang__ / !__clang__ vvv + return __roundf(_Xx); +#endif // __clang__ } _NODISCARD _Check_return_ inline float scalbln(_In_ float _Xx, _In_ long _Yx) noexcept /* strengthened */ { @@ -244,7 +272,13 @@ _NODISCARD _Check_return_ inline float tgamma(_In_ float _Xx) noexcept /* streng } _NODISCARD _Check_return_ inline float trunc(_In_ float _Xx) noexcept /* strengthened */ { +#ifdef _M_CEE return _CSTD truncf(_Xx); +#elif defined(__clang__) + return __builtin_truncf(_Xx); +#else // ^^^ __clang__ / !__clang__ vvv + return __truncf(_Xx); +#endif // __clang__ } _NODISCARD _Check_return_ inline long double acos(_In_ long double _Xx) noexcept /* strengthened */ { @@ -281,12 +315,24 @@ _NODISCARD _Check_return_ inline long double cbrt(_In_ long double _Xx) noexcept } _NODISCARD _Check_return_ inline long double ceil(_In_ long double _Xx) noexcept /* strengthened */ { +#ifdef _M_CEE return _CSTD ceill(_Xx); +#elif defined(__clang__) + return __builtin_ceill(_Xx); +#else // ^^^ __clang__ / !__clang__ vvv + return __ceil(static_cast(_Xx)); +#endif // __clang__ } _NODISCARD _Check_return_ inline long double copysign(_In_ long double _Number, _In_ long double _Sign) noexcept /* strengthened */ { +#ifdef _M_CEE return _CSTD copysignl(_Number, _Sign); +#elif defined(__clang__) + return __builtin_copysignl(_Number, _Sign); +#else // ^^^ __clang__ / !__clang__ vvv + return __copysign(static_cast(_Number), static_cast(_Sign)); +#endif // __clang__ } _NODISCARD _Check_return_ inline long double cos(_In_ long double _Xx) noexcept /* strengthened */ { @@ -327,7 +373,13 @@ _NODISCARD _Check_return_ inline long double fdim(_In_ long double _Xx, _In_ lon } _NODISCARD _Check_return_ inline long double floor(_In_ long double _Xx) noexcept /* strengthened */ { +#ifdef _M_CEE return _CSTD floorl(_Xx); +#elif defined(__clang__) + return __builtin_floorl(_Xx); +#else // ^^^ __clang__ / !__clang__ vvv + return __floor(static_cast(_Xx)); +#endif // __clang__ } _NODISCARD _Check_return_ inline long double fma( @@ -444,7 +496,13 @@ _NODISCARD _Check_return_ inline long double rint(_In_ long double _Xx) noexcept } _NODISCARD _Check_return_ inline long double round(_In_ long double _Xx) noexcept /* strengthened */ { +#ifdef _M_CEE return _CSTD roundl(_Xx); +#elif defined(__clang__) + return __builtin_roundl(_Xx); +#else // ^^^ __clang__ / !__clang__ vvv + return __round(static_cast(_Xx)); +#endif // __clang__ } _NODISCARD _Check_return_ inline long double scalbln(_In_ long double _Xx, _In_ long _Yx) noexcept /* strengthened */ { @@ -480,7 +538,13 @@ _NODISCARD _Check_return_ inline long double tgamma(_In_ long double _Xx) noexce } _NODISCARD _Check_return_ inline long double trunc(_In_ long double _Xx) noexcept /* strengthened */ { +#ifdef _M_CEE return _CSTD truncl(_Xx); +#elif defined(__clang__) + return __builtin_truncl(_Xx); +#else // ^^^ __clang__ / !__clang__ vvv + return __trunc(static_cast(_Xx)); +#endif // __clang__ } @@ -561,13 +625,22 @@ _STD _Common_float_type_t<_Ty1, _Ty2> remquo(_Ty1 _Left, _Ty2 _Right, int* _Pquo #endif // _HAS_IF_CONSTEXPR } -#define _GENERIC_MATH1R(FUN, RET) \ +#define _GENERIC_MATH1_BASE(NAME, RET, FUN) \ template , int> = 0> \ - _NODISCARD RET FUN(_Ty _Left) noexcept /* strengthened */ { \ - return _CSTD FUN(static_cast(_Left)); \ + _NODISCARD RET NAME(_Ty _Left) noexcept /* strengthened */ { \ + return FUN(static_cast(_Left)); \ } -#define _GENERIC_MATH1(FUN) _GENERIC_MATH1R(FUN, double) +#define _GENERIC_MATH1R(FUN, RET) _GENERIC_MATH1_BASE(FUN, RET, _CSTD FUN) +#define _GENERIC_MATH1(FUN) _GENERIC_MATH1R(FUN, double) + +#ifdef _M_CEE +#define _GENERIC_MATH1I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH1_BASE(FUN, double, _CSTD FUN) +#elif defined(__clang__) +#define _GENERIC_MATH1I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH1_BASE(FUN, double, CLANG_INTRIN) +#else // ^^^ __clang__ / !__clang__ vvv +#define _GENERIC_MATH1I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH1_BASE(FUN, double, MSVC_INTRIN) +#endif // __clang__ #define _GENERIC_MATH1X(FUN, ARG2) \ template , int> = 0> \ @@ -575,14 +648,24 @@ _STD _Common_float_type_t<_Ty1, _Ty2> remquo(_Ty1 _Left, _Ty2 _Right, int* _Pquo return _CSTD FUN(static_cast(_Left), _Arg2); \ } -#define _GENERIC_MATH2(FUN) \ - template && _STD is_arithmetic_v<_Ty2>, int> = 0> \ - _NODISCARD _STD _Common_float_type_t<_Ty1, _Ty2> FUN(_Ty1 _Left, _Ty2 _Right) noexcept /* strengthened */ { \ - using _Common = _STD _Common_float_type_t<_Ty1, _Ty2>; \ - return _CSTD FUN(static_cast<_Common>(_Left), static_cast<_Common>(_Right)); \ +#define _GENERIC_MATH2_BASE(NAME, FUN) \ + template && _STD is_arithmetic_v<_Ty2>, int> = 0> \ + _NODISCARD _STD _Common_float_type_t<_Ty1, _Ty2> NAME(_Ty1 _Left, _Ty2 _Right) noexcept /* strengthened */ { \ + using _Common = _STD _Common_float_type_t<_Ty1, _Ty2>; \ + return FUN(static_cast<_Common>(_Left), static_cast<_Common>(_Right)); \ } +#define _GENERIC_MATH2(FUN) _GENERIC_MATH2_BASE(FUN, _CSTD FUN) + +#ifdef _M_CEE +#define _GENERIC_MATH2I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH2_BASE(FUN, _CSTD FUN) +#elif defined(__clang__) +#define _GENERIC_MATH2I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH2_BASE(FUN, CLANG_INTRIN) +#else // ^^^ __clang__ / !__clang__ vvv +#define _GENERIC_MATH2I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH2_BASE(FUN, MSVC_INTRIN) +#endif // __clang__ + // The following order matches N4820 26.8.1 [cmath.syn]. _GENERIC_MATH1(acos) _GENERIC_MATH1(asin) @@ -622,20 +705,20 @@ _GENERIC_MATH1(erf) _GENERIC_MATH1(erfc) _GENERIC_MATH1(lgamma) _GENERIC_MATH1(tgamma) -_GENERIC_MATH1(ceil) -_GENERIC_MATH1(floor) +_GENERIC_MATH1I(ceil, __builtin_ceil, __ceil) +_GENERIC_MATH1I(floor, __builtin_floor, __floor) _GENERIC_MATH1(nearbyint) _GENERIC_MATH1(rint) _GENERIC_MATH1R(lrint, long) _GENERIC_MATH1R(llrint, long long) -_GENERIC_MATH1(round) +_GENERIC_MATH1I(round, __builtin_round, __round) _GENERIC_MATH1R(lround, long) _GENERIC_MATH1R(llround, long long) -_GENERIC_MATH1(trunc) +_GENERIC_MATH1I(trunc, __builtin_trunc, __trunc) _GENERIC_MATH2(fmod) _GENERIC_MATH2(remainder) // remquo() is hand-crafted -_GENERIC_MATH2(copysign) +_GENERIC_MATH2I(copysign, __builtin_copysign, __copysign) // nan(const char*) is exempt _GENERIC_MATH2(nextafter) _GENERIC_MATH1X(nexttoward, long double) @@ -647,10 +730,14 @@ _GENERIC_MATH2(fmin) // The "classification/comparison functions" (fpclassify(), etc.) are exempt, LWG-1327 // TRANSITION, VSO-945789, Special Math shouldn't be exempt +#undef _GENERIC_MATH1_BASE #undef _GENERIC_MATH1R #undef _GENERIC_MATH1 +#undef _GENERIC_MATH1I #undef _GENERIC_MATH1X +#undef _GENERIC_MATH2_BASE #undef _GENERIC_MATH2 +#undef _GENERIC_MATH2I _STD_BEGIN diff --git a/stl/inc/compare b/stl/inc/compare index b50e3518cc2..d40440c5a1b 100644 --- a/stl/inc/compare +++ b/stl/inc/compare @@ -13,6 +13,7 @@ #pragma message("The contents of are available only with C++20 or later.") #else // ^^^ !_HAS_CXX20 / _HAS_CXX20 vvv #ifdef __cpp_lib_concepts +#include #include #else // ^^^ __cpp_lib_concepts / !__cpp_lib_concepts vvv #include @@ -340,9 +341,499 @@ struct compare_three_way { using is_transparent = int; }; // clang-format on -#endif // __cpp_lib_concepts -// Other components not yet implemented +// Note: The following CPOs are passing arguments as lvalues; see GH-1374. + +// CUSTOMIZATION POINT OBJECT strong_order +namespace _Strong_order { + void strong_order(); // Block unqualified name lookup; see GH-1374. + + template + concept _Has_ADL = requires(_Ty1& _Left, _Ty2& _Right) { + static_cast(/* ADL */ strong_order(_Left, _Right)); + }; + + template + concept _Can_compare_three_way = requires(_Ty1& _Left, _Ty2& _Right) { + static_cast(compare_three_way{}(_Left, _Right)); + }; + + class _Cpo { + private: + enum class _St { _None, _Adl, _Floating, _Three }; + + template + _NODISCARD static _CONSTEVAL _Choice_t<_St> _Choose() noexcept { + if constexpr (!same_as, decay_t<_Ty2>>) { + return {_St::_None}; + } else if constexpr (_Has_ADL<_Ty1, _Ty2>) { + return {_St::_Adl, noexcept(static_cast( + /* ADL */ strong_order(_STD declval<_Ty1&>(), _STD declval<_Ty2&>())))}; + } else if constexpr (floating_point>) { + return {_St::_Floating, true}; + } else if constexpr (_Can_compare_three_way<_Ty1, _Ty2>) { + return {_St::_Three, noexcept(static_cast( + compare_three_way{}(_STD declval<_Ty1&>(), _STD declval<_Ty2&>())))}; + } else { + return {_St::_None}; + } + } + + template + static constexpr _Choice_t<_St> _Choice = _Choose<_Ty1, _Ty2>(); + + public: + // clang-format off + template + requires (_Choice<_Ty1&, _Ty2&>._Strategy != _St::_None) + _NODISCARD constexpr strong_ordering operator()(_Ty1&& _Left, _Ty2&& _Right) const + noexcept(_Choice<_Ty1&, _Ty2&>._No_throw) { + // clang-format on + constexpr _St _Strat = _Choice<_Ty1&, _Ty2&>._Strategy; + if constexpr (_Strat == _St::_Adl) { + return static_cast(/* ADL */ strong_order(_Left, _Right)); + } else if constexpr (_Strat == _St::_Floating) { + using _Floating_type = decay_t<_Ty1>; + using _Traits = _Floating_type_traits<_Floating_type>; + using _Uint_type = typename _Traits::_Uint_type; + + auto _Left_uint = _STD bit_cast<_Uint_type>(_Left); + auto _Right_uint = _STD bit_cast<_Uint_type>(_Right); + + // 1. Ultra-fast path: equal representations are equal. + if (_Left_uint == _Right_uint) { + return strong_ordering::equal; + } + + // 2. Examine the sign bits. + const bool _Left_negative = (_Left_uint & _Traits::_Shifted_sign_mask) != 0; + const bool _Right_negative = (_Right_uint & _Traits::_Shifted_sign_mask) != 0; + + // 3. Fast path: any negative value is less than any positive value. + if (_Left_negative != _Right_negative) { + return _Left_negative ? strong_ordering::less : strong_ordering::greater; + } + + // 4. Clear the (identical) sign bits. We've already stored them for use at the end. + _Left_uint &= ~_Traits::_Shifted_sign_mask; + _Right_uint &= ~_Traits::_Shifted_sign_mask; + + // 5. Perform the final comparison, reversed for negative values. + // (For example, 1.5 is less than 2.5, but -1.5 is greater than -2.5.) + if (_Left_negative) { + return _Right_uint <=> _Left_uint; + } else { + return _Left_uint <=> _Right_uint; + } + } else if constexpr (_Strat == _St::_Three) { + return static_cast(compare_three_way{}(_Left, _Right)); + } else { + static_assert(_Always_false<_Ty1>, "should be unreachable"); + } + } + }; +} // namespace _Strong_order + +namespace _Cpos { + inline constexpr _Strong_order::_Cpo strong_order; +} +using namespace _Cpos; + +// CUSTOMIZATION POINT OBJECT weak_order +namespace _Weak_order { + void weak_order(); // Block unqualified name lookup; see GH-1374. + + template + concept _Has_ADL = requires(_Ty1& _Left, _Ty2& _Right) { + static_cast(/* ADL */ weak_order(_Left, _Right)); + }; + + template + concept _Can_compare_three_way = requires(_Ty1& _Left, _Ty2& _Right) { + static_cast(compare_three_way{}(_Left, _Right)); + }; + + // Throughput optimization: attempting to use _STD strong_order will always select ADL strong_order here. + void strong_order(); // Block unqualified name lookup; see GH-1374. + + class _Cpo { + private: + enum class _St { _None, _Adl, _Floating, _Three, _Strong }; + + template + _NODISCARD static _CONSTEVAL _Choice_t<_St> _Choose() noexcept { + if constexpr (!same_as, decay_t<_Ty2>>) { + return {_St::_None}; + } else if constexpr (_Has_ADL<_Ty1, _Ty2>) { + return {_St::_Adl, noexcept(static_cast( + /* ADL */ weak_order(_STD declval<_Ty1&>(), _STD declval<_Ty2&>())))}; + } else if constexpr (floating_point>) { + return {_St::_Floating, true}; + } else if constexpr (_Can_compare_three_way<_Ty1, _Ty2>) { + return {_St::_Three, noexcept(static_cast( + compare_three_way{}(_STD declval<_Ty1&>(), _STD declval<_Ty2&>())))}; + } else if constexpr (_Strong_order::_Has_ADL<_Ty1, _Ty2>) { + return {_St::_Strong, noexcept(static_cast(static_cast( + /* ADL, throughput optimization */ strong_order( + _STD declval<_Ty1&>(), _STD declval<_Ty2&>()))))}; + } else { + return {_St::_None}; + } + } + + template + static constexpr _Choice_t<_St> _Choice = _Choose<_Ty1, _Ty2>(); + + public: + // clang-format off + template + requires (_Choice<_Ty1&, _Ty2&>._Strategy != _St::_None) + _NODISCARD constexpr weak_ordering operator()(_Ty1&& _Left, _Ty2&& _Right) const + noexcept(_Choice<_Ty1&, _Ty2&>._No_throw) { + // clang-format on + constexpr _St _Strat = _Choice<_Ty1&, _Ty2&>._Strategy; + if constexpr (_Strat == _St::_Adl) { + return static_cast(/* ADL */ weak_order(_Left, _Right)); + } else if constexpr (_Strat == _St::_Floating) { + using _Floating_type = decay_t<_Ty1>; + using _Traits = _Floating_type_traits<_Floating_type>; + using _Uint_type = typename _Traits::_Uint_type; + + auto _Left_uint = _STD bit_cast<_Uint_type>(_Left); + auto _Right_uint = _STD bit_cast<_Uint_type>(_Right); + + // 1. Ultra-fast path: equal representations are equivalent. + if (_Left_uint == _Right_uint) { + return weak_ordering::equivalent; + } + + // 2. Fold negative zero into positive zero. + constexpr _Uint_type _Negative_zero = _Traits::_Shifted_sign_mask; + + if (_Left_uint == _Negative_zero) { + _Left_uint = 0; + } else if (_Right_uint == _Negative_zero) { // The representations are known to be non-equal here. + _Right_uint = 0; + } + + // 3. Examine the sign bits. + const bool _Left_negative = (_Left_uint & _Traits::_Shifted_sign_mask) != 0; + const bool _Right_negative = (_Right_uint & _Traits::_Shifted_sign_mask) != 0; + + // 4. Fast path: after folding negative zero, any negative value is less than any positive value. + if (_Left_negative != _Right_negative) { + return _Left_negative ? weak_ordering::less : weak_ordering::greater; + } + + // 5. Clear the (identical) sign bits. We've already stored them for use at the end. + _Left_uint &= ~_Traits::_Shifted_sign_mask; + _Right_uint &= ~_Traits::_Shifted_sign_mask; + + // 6. Fold all NaN values together. + // (The fact that _Infinity_plus_one represents a signaling NaN is irrelevant here.) + constexpr _Uint_type _Infinity_plus_one = _Traits::_Shifted_exponent_mask + 1; + + if (_Left_uint > _Infinity_plus_one) { + _Left_uint = _Infinity_plus_one; + } + + if (_Right_uint > _Infinity_plus_one) { + _Right_uint = _Infinity_plus_one; + } + + // 7. Perform the final comparison, reversed for negative values. + // (For example, 1.5 is less than 2.5, but -1.5 is greater than -2.5.) + if (_Left_negative) { + return static_cast(_Right_uint <=> _Left_uint); + } else { + return static_cast(_Left_uint <=> _Right_uint); + } + } else if constexpr (_Strat == _St::_Three) { + return static_cast(compare_three_way{}(_Left, _Right)); + } else if constexpr (_Strat == _St::_Strong) { + return static_cast( + static_cast(/* ADL, throughput optimization */ strong_order(_Left, _Right))); + } else { + static_assert(_Always_false<_Ty1>, "should be unreachable"); + } + } + }; +} // namespace _Weak_order + +namespace _Cpos { + inline constexpr _Weak_order::_Cpo weak_order; +} +using namespace _Cpos; + +// CUSTOMIZATION POINT OBJECT partial_order +namespace _Partial_order { + void partial_order(); // Block unqualified name lookup; see GH-1374. + + template + concept _Has_ADL = requires(_Ty1& _Left, _Ty2& _Right) { + static_cast(/* ADL */ partial_order(_Left, _Right)); + }; + + template + concept _Can_compare_three_way = requires(_Ty1& _Left, _Ty2& _Right) { + static_cast(compare_three_way{}(_Left, _Right)); + }; + + // Throughput optimization: attempting to use _STD weak_order + // will attempt to select ADL weak_order, followed by ADL strong_order, here. + void weak_order(); // Block unqualified name lookup; see GH-1374. + void strong_order(); // Block unqualified name lookup; see GH-1374. + + class _Cpo { + private: + enum class _St { _None, _Adl, _Three, _Weak, _Strong }; + + template + _NODISCARD static _CONSTEVAL _Choice_t<_St> _Choose() noexcept { + if constexpr (!same_as, decay_t<_Ty2>>) { + return {_St::_None}; + } else if constexpr (_Has_ADL<_Ty1, _Ty2>) { + return {_St::_Adl, noexcept(static_cast( + /* ADL */ partial_order(_STD declval<_Ty1&>(), _STD declval<_Ty2&>())))}; + } else if constexpr (_Can_compare_three_way<_Ty1, _Ty2>) { + return {_St::_Three, noexcept(static_cast( + compare_three_way{}(_STD declval<_Ty1&>(), _STD declval<_Ty2&>())))}; + } else if constexpr (_Weak_order::_Has_ADL<_Ty1, _Ty2>) { + return {_St::_Weak, + noexcept(static_cast(static_cast( + /* ADL, throughput optimization */ weak_order(_STD declval<_Ty1&>(), _STD declval<_Ty2&>()))))}; + } else if constexpr (_Strong_order::_Has_ADL<_Ty1, _Ty2>) { + return {_St::_Strong, noexcept(static_cast(static_cast( + /* ADL, throughput optimization */ strong_order( + _STD declval<_Ty1&>(), _STD declval<_Ty2&>()))))}; + } else { + return {_St::_None}; + } + } + + template + static constexpr _Choice_t<_St> _Choice = _Choose<_Ty1, _Ty2>(); + + public: + // clang-format off + template + requires (_Choice<_Ty1&, _Ty2&>._Strategy != _St::_None) + _NODISCARD constexpr partial_ordering operator()(_Ty1&& _Left, _Ty2&& _Right) const + noexcept(_Choice<_Ty1&, _Ty2&>._No_throw) { + // clang-format on + constexpr _St _Strat = _Choice<_Ty1&, _Ty2&>._Strategy; + if constexpr (_Strat == _St::_Adl) { + return static_cast(/* ADL */ partial_order(_Left, _Right)); + } else if constexpr (_Strat == _St::_Three) { + return static_cast(compare_three_way{}(_Left, _Right)); + } else if constexpr (_Strat == _St::_Weak) { + return static_cast( + static_cast(/* ADL, throughput optimization */ weak_order(_Left, _Right))); + } else if constexpr (_Strat == _St::_Strong) { + return static_cast( + static_cast(/* ADL, throughput optimization */ strong_order(_Left, _Right))); + } else { + static_assert(_Always_false<_Ty1>, "should be unreachable"); + } + } + }; +} // namespace _Partial_order + +namespace _Cpos { + inline constexpr _Partial_order::_Cpo partial_order; +} +using namespace _Cpos; + +// clang-format off +template +concept _Can_fallback_eq_lt = requires(_Ty1& _Left, _Ty2& _Right) { + { _Left == _Right } -> _Implicitly_convertible_to; + { _Left < _Right } -> _Implicitly_convertible_to; +}; +// clang-format on + +// CUSTOMIZATION POINT OBJECT compare_strong_order_fallback +namespace _Compare_strong_order_fallback { + template + concept _Can_strong_order = requires(_Ty1& _Left, _Ty2& _Right) { + _STD strong_order(_Left, _Right); + }; + + class _Cpo { + private: + enum class _St { _None, _Strong, _Fallback }; + + template + _NODISCARD static _CONSTEVAL _Choice_t<_St> _Choose() noexcept { + if constexpr (!same_as, decay_t<_Ty2>>) { + return {_St::_None}; + } else if constexpr (_Can_strong_order<_Ty1, _Ty2>) { + return {_St::_Strong, noexcept(_STD strong_order(_STD declval<_Ty1&>(), _STD declval<_Ty2&>()))}; + } else if constexpr (_Can_fallback_eq_lt<_Ty1, _Ty2>) { + return {_St::_Fallback, + noexcept(_STD declval<_Ty1&>() == _STD declval<_Ty2&>() + ? strong_ordering::equal + : _STD declval<_Ty1&>() < _STD declval<_Ty2&>() ? strong_ordering::less + : strong_ordering::greater)}; + } else { + return {_St::_None}; + } + } + + template + static constexpr _Choice_t<_St> _Choice = _Choose<_Ty1, _Ty2>(); + + public: + // clang-format off + template + requires (_Choice<_Ty1&, _Ty2&>._Strategy != _St::_None) + _NODISCARD constexpr strong_ordering operator()(_Ty1&& _Left, _Ty2&& _Right) const + noexcept(_Choice<_Ty1&, _Ty2&>._No_throw) { + // clang-format on + constexpr _St _Strat = _Choice<_Ty1&, _Ty2&>._Strategy; + if constexpr (_Strat == _St::_Strong) { + return _STD strong_order(_Left, _Right); + } else if constexpr (_Strat == _St::_Fallback) { + return _Left == _Right ? strong_ordering::equal + : _Left < _Right ? strong_ordering::less : strong_ordering::greater; + } else { + static_assert(_Always_false<_Ty1>, "should be unreachable"); + } + } + }; +} // namespace _Compare_strong_order_fallback + +namespace _Cpos { + inline constexpr _Compare_strong_order_fallback::_Cpo compare_strong_order_fallback; +} +using namespace _Cpos; + +// CUSTOMIZATION POINT OBJECT compare_weak_order_fallback +namespace _Compare_weak_order_fallback { + template + concept _Can_weak_order = requires(_Ty1& _Left, _Ty2& _Right) { + _STD weak_order(_Left, _Right); + }; + + class _Cpo { + private: + enum class _St { _None, _Weak, _Fallback }; + + template + _NODISCARD static _CONSTEVAL _Choice_t<_St> _Choose() noexcept { + if constexpr (!same_as, decay_t<_Ty2>>) { + return {_St::_None}; + } else if constexpr (_Can_weak_order<_Ty1, _Ty2>) { + return {_St::_Weak, noexcept(_STD weak_order(_STD declval<_Ty1&>(), _STD declval<_Ty2&>()))}; + } else if constexpr (_Can_fallback_eq_lt<_Ty1, _Ty2>) { + return {_St::_Fallback, + noexcept(_STD declval<_Ty1&>() == _STD declval<_Ty2&>() + ? weak_ordering::equivalent + : _STD declval<_Ty1&>() < _STD declval<_Ty2&>() ? weak_ordering::less + : weak_ordering::greater)}; + } else { + return {_St::_None}; + } + } + + template + static constexpr _Choice_t<_St> _Choice = _Choose<_Ty1, _Ty2>(); + + public: + // clang-format off + template + requires (_Choice<_Ty1&, _Ty2&>._Strategy != _St::_None) + _NODISCARD constexpr weak_ordering operator()(_Ty1&& _Left, _Ty2&& _Right) const + noexcept(_Choice<_Ty1&, _Ty2&>._No_throw) { + // clang-format on + constexpr _St _Strat = _Choice<_Ty1&, _Ty2&>._Strategy; + if constexpr (_Strat == _St::_Weak) { + return _STD weak_order(_Left, _Right); + } else if constexpr (_Strat == _St::_Fallback) { + return _Left == _Right ? weak_ordering::equivalent + : _Left < _Right ? weak_ordering::less : weak_ordering::greater; + } else { + static_assert(_Always_false<_Ty1>, "should be unreachable"); + } + } + }; +} // namespace _Compare_weak_order_fallback + +namespace _Cpos { + inline constexpr _Compare_weak_order_fallback::_Cpo compare_weak_order_fallback; +} +using namespace _Cpos; + +// CUSTOMIZATION POINT OBJECT compare_partial_order_fallback +namespace _Compare_partial_order_fallback { + template + concept _Can_partial_order = requires(_Ty1& _Left, _Ty2& _Right) { + _STD partial_order(_Left, _Right); + }; + + // clang-format off + template + concept _Can_fallback_eq_lt_twice = requires(_Ty1& _Left, _Ty2& _Right) { + { _Left == _Right } -> _Implicitly_convertible_to; + { _Left < _Right } -> _Implicitly_convertible_to; + { _Right < _Left } -> _Implicitly_convertible_to; + }; + // clang-format on + + class _Cpo { + private: + enum class _St { _None, _Partial, _Fallback }; + + template + _NODISCARD static _CONSTEVAL _Choice_t<_St> _Choose() noexcept { + if constexpr (!same_as, decay_t<_Ty2>>) { + return {_St::_None}; + } else if constexpr (_Can_partial_order<_Ty1, _Ty2>) { + return {_St::_Partial, noexcept(_STD partial_order(_STD declval<_Ty1&>(), _STD declval<_Ty2&>()))}; + } else if constexpr (_Can_fallback_eq_lt_twice<_Ty1, _Ty2>) { + return {_St::_Fallback, + noexcept(_STD declval<_Ty1&>() == _STD declval<_Ty2&>() + ? partial_ordering::equivalent + : _STD declval<_Ty1&>() < _STD declval<_Ty2&>() + ? partial_ordering::less + : _STD declval<_Ty2&>() < _STD declval<_Ty1&>() ? partial_ordering::greater + : partial_ordering::unordered)}; + } else { + return {_St::_None}; + } + } + + template + static constexpr _Choice_t<_St> _Choice = _Choose<_Ty1, _Ty2>(); + + public: + // clang-format off + template + requires (_Choice<_Ty1&, _Ty2&>._Strategy != _St::_None) + _NODISCARD constexpr partial_ordering operator()(_Ty1&& _Left, _Ty2&& _Right) const + noexcept(_Choice<_Ty1&, _Ty2&>._No_throw) { + // clang-format on + constexpr _St _Strat = _Choice<_Ty1&, _Ty2&>._Strategy; + if constexpr (_Strat == _St::_Partial) { + return _STD partial_order(_Left, _Right); + } else if constexpr (_Strat == _St::_Fallback) { + return _Left == _Right + ? partial_ordering::equivalent + : _Left < _Right ? partial_ordering::less + : _Right < _Left ? partial_ordering::greater : partial_ordering::unordered; + } else { + static_assert(_Always_false<_Ty1>, "should be unreachable"); + } + } + }; +} // namespace _Compare_partial_order_fallback + +namespace _Cpos { + inline constexpr _Compare_partial_order_fallback::_Cpo compare_partial_order_fallback; +} +using namespace _Cpos; + +#endif // __cpp_lib_concepts _STD_END #pragma pop_macro("new") diff --git a/stl/inc/complex b/stl/inc/complex index 8a39add392f..60b017fdb92 100644 --- a/stl/inc/complex +++ b/stl/inc/complex @@ -10,9 +10,27 @@ #if _STL_COMPILER_PREPROCESSOR #include #include +#include #include +#include +#include #include +#ifdef _M_CEE_PURE +// no intrinsics for /clr:pure +#elif defined(__clang__) +// TRANSITION, not using FMA intrinsics for Clang yet +#elif defined(_M_IX86) || defined(_M_X64) +#define _FMP_USING_X86_X64_INTRINSICS +#include +#include +extern "C" int __isa_available; +extern "C" __m128d __cdecl _mm_fmsub_sd(__m128d, __m128d, __m128d); +#elif defined(_M_ARM64) +#define _FMP_USING_ARM64_INTRINSICS +#include +#endif // ^^^ defined(_M_ARM64) ^^^ + #pragma pack(push, _CRT_PACKING) #pragma warning(push, _STL_WARNING_LEVEL) #pragma warning(disable : _STL_DISABLED_WARNINGS) @@ -41,6 +59,296 @@ struct _C_ldouble_complex { #define _IM 1 _STD_BEGIN + +// implements multi-precision floating point arithmetic for numerical algorithms +#pragma float_control(precise, on, push) +namespace _Float_multi_prec { + // multi-precision floating point types + template + struct _Fmp_t; + + template + struct _Fmp_t<_Ty, 2> { + static_assert(is_floating_point_v<_Ty>, "_Ty must be floating-point"); + _Ty _Val0; // most significant numeric_limits<_Ty>::precision bits + _Ty _Val1; // least significant numeric_limits<_Ty>::precision bits + }; + + // addition + + // 1x precision + 1x precision -> 2x precision + // the result is exact when: + // 1) the result doesn't overflow + // 2) either underflow is gradual, or no internal underflow occurs + // 3) intermediate precision is either the same as _Ty, or greater than twice the precision of _Ty + // 4) parameters and local variables do not retain extra intermediate precision + // 5) rounding mode is rounding to nearest + // violation of condition 3 or 5 could lead to relative error on the order of epsilon^2 + // violation of other conditions could lead to worse results + template + _NODISCARD constexpr _Fmp_t<_Ty, 2> _Add_x2(const _Ty _Xval, const _Ty _Yval) noexcept { + const _Ty _Sum0 = _Xval + _Yval; + const _Ty _Ymod = _Sum0 - _Xval; + const _Ty _Xmod = _Sum0 - _Ymod; + const _Ty _Yerr = _Yval - _Ymod; + const _Ty _Xerr = _Xval - _Xmod; + return {_Sum0, _Xerr + _Yerr}; + } + + // 1x precision + 1x precision -> 2x precision + // requires: exponent(_Xval) + countr_zero(significand(_Xval)) >= exponent(_Yval) || _Xval == 0 + // the result is exact when: + // 0) the requirement above is satisfied + // 1) no internal overflow occurs + // 2) either underflow is gradual, or no internal underflow occurs + // 3) intermediate precision is either the same as _Ty, or greater than twice the precision of _Ty + // 4) parameters and local variables do not retain extra intermediate precision + // 5) rounding mode is rounding to nearest + // violation of condition 3 or 5 could lead to relative error on the order of epsilon^2 + // violation of other conditions could lead to worse results + template + _NODISCARD constexpr _Fmp_t<_Ty, 2> _Add_small_x2(const _Ty _Xval, const _Ty _Yval) noexcept { + const _Ty _Sum0 = _Xval + _Yval; + const _Ty _Ymod = _Sum0 - _Xval; + const _Ty _Yerr = _Yval - _Ymod; + return {_Sum0, _Yerr}; + } + + // 1x precision + 2x precision -> 2x precision + // requires: exponent(_Xval) + countr_zero(significand(_Xval)) >= exponent(_Yval._Val0) || _Xval == 0 + template + _NODISCARD constexpr _Fmp_t<_Ty, 2> _Add_small_x2(const _Ty _Xval, const _Fmp_t<_Ty, 2>& _Yval) noexcept { + const _Fmp_t<_Ty, 2> _Sum0 = _Add_small_x2(_Xval, _Yval._Val0); + return _Add_small_x2(_Sum0._Val0, _Sum0._Val1 + _Yval._Val1); + } + + // 2x precision + 2x precision -> 1x precision + template + _NODISCARD constexpr _Ty _Add_x1(const _Fmp_t<_Ty, 2>& _Xval, const _Fmp_t<_Ty, 2>& _Yval) noexcept { + const _Fmp_t<_Ty, 2> _Sum00 = _Add_x2(_Xval._Val0, _Yval._Val0); + return _Sum00._Val0 + (_Sum00._Val1 + (_Xval._Val1 + _Yval._Val1)); + } + + // multiplication + + // round to 26 significant bits, ties toward zero + _NODISCARD _CONSTEXPR_BIT_CAST double _High_half(const double _Val) noexcept { + const auto _Bits = _Bit_cast(_Val); + const auto _High_half_bits = (_Bits + 0x3ff'ffffULL) & 0xffff'ffff'f800'0000ULL; + return _Bit_cast(_High_half_bits); + } + + // _Xval * _Xval - _Prod0 + // the result is exact when: + // 1) _Prod0 is _Xval^2 faithfully rounded + // 2) no internal overflow or underflow occurs + // violation of condition 1 could lead to relative error on the order of epsilon + _NODISCARD _CONSTEXPR_BIT_CAST double _Sqr_error_fallback(const double _Xval, const double _Prod0) noexcept { + const double _Xhigh = _High_half(_Xval); + const double _Xlow = _Xval - _Xhigh; + return ((_Xhigh * _Xhigh - _Prod0) + 2.0 * _Xhigh * _Xlow) + _Xlow * _Xlow; + } + +#ifdef _FMP_USING_X86_X64_INTRINSICS + _NODISCARD inline double _Sqr_error_x86_x64_fma(const double _Xval, const double _Prod0) noexcept { + const __m128d _Mx = _mm_set_sd(_Xval); + const __m128d _Mprod0 = _mm_set_sd(_Prod0); + const __m128d _Mresult = _mm_fmsub_sd(_Mx, _Mx, _Mprod0); + double _Result; + _mm_store_sd(&_Result, _Mresult); + return _Result; + } +#endif // _FMP_USING_X86_X64_INTRINSICS + +#ifdef _FMP_USING_ARM64_INTRINSICS + _NODISCARD inline double _Sqr_error_arm64_neon(const double _Xval, const double _Prod0) noexcept { + const float64x1_t _Mx = vld1_f64(&_Xval); + const float64x1_t _Mprod0 = vld1_f64(&_Prod0); + const float64x1_t _Mresult = vfma_f64(vneg_f64(_Mprod0), _Mx, _Mx); + double _Result; + vst1_f64(&_Result, _Mresult); + return _Result; + } +#endif // _FMP_USING_ARM64_INTRINSICS + + // square(1x precision) -> 2x precision + // the result is exact when no internal overflow or underflow occurs + _NODISCARD inline _Fmp_t _Sqr_x2(const double _Xval) noexcept { + const double _Prod0 = _Xval * _Xval; + +#if defined(_FMP_USING_X86_X64_INTRINSICS) + +#ifdef __AVX2__ + return {_Prod0, _Sqr_error_x86_x64_fma(_Xval, _Prod0)}; +#else // ^^^ defined(__AVX2__) / !defined(__AVX2__) vvv + const bool _Definitely_have_fma = __isa_available >= __ISA_AVAILABLE_AVX2; + if (_Definitely_have_fma) { + return {_Prod0, _Sqr_error_x86_x64_fma(_Xval, _Prod0)}; + } else { + return {_Prod0, _Sqr_error_fallback(_Xval, _Prod0)}; + } +#endif // ^^^ !defined(__AVX2__) ^^^ + +#elif defined(_FMP_USING_ARM64_INTRINSICS) + // https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=vs-2019#base-requirements + // Both floating-point and NEON support are presumed to be present in hardware. + return {_Prod0, _Sqr_error_arm64_neon(_Xval, _Prod0)}; +#else // ^^^ defined(_FMP_USING_ARM64_INTRINSICS) / not using intrinsics vvv + return {_Prod0, _Sqr_error_fallback(_Xval, _Prod0)}; +#endif // ^^^ not using intrinsics ^^^ + } +} // namespace _Float_multi_prec +#pragma float_control(pop) + +#undef _FMP_USING_X86_X64_INTRINSICS +#undef _FMP_USING_ARM64_INTRINSICS + +#define _FMP ::std::_Float_multi_prec:: + +// implements numerical algorithms for +namespace _Math_algorithms { + // TRANSITION: sqrt() isn't constexpr + // _Hypot_leg_huge = _Ty{0.5} * _STD sqrt((_STD numeric_limits<_Ty>::max)()); + // _Hypot_leg_tiny = _STD sqrt(_Ty{2.0} * (_STD numeric_limits<_Ty>::min)() / _STD numeric_limits<_Ty>::epsilon()); + template + struct _Hypot_leg_huge_helper { + static constexpr _Ty value{6.703903964971298e+153}; + }; + template <> + struct _Hypot_leg_huge_helper { + static constexpr float value{9.2233715e+18f}; + }; + template + _INLINE_VAR constexpr _Ty _Hypot_leg_huge = _Hypot_leg_huge_helper<_Ty>::value; + + template + struct _Hypot_leg_tiny_helper { + static constexpr _Ty value{1.4156865331029228e-146}; + }; + template <> + struct _Hypot_leg_tiny_helper { + static constexpr float value{4.440892e-16f}; + }; + template + _INLINE_VAR constexpr _Ty _Hypot_leg_tiny = _Hypot_leg_tiny_helper<_Ty>::value; + + template + _NODISCARD _Ty _Norm_minus_one(const _Ty _Xval, const _Ty _Yval) noexcept { + // requires |_Xval| >= |_Yval| and 0.5 <= |_Xval| < 2^12 + // returns _Xval * _Xval + _Yval * _Yval - 1 + const _FMP _Fmp_t<_Ty, 2> _Xsqr = _FMP _Sqr_x2(_Xval); + const _FMP _Fmp_t<_Ty, 2> _Ysqr = _FMP _Sqr_x2(_Yval); + const _FMP _Fmp_t<_Ty, 2> _Xsqr_m1 = _FMP _Add_small_x2(_Ty{-1.0}, _Xsqr); + return _Add_x1(_Xsqr_m1, _Ysqr); + } + + _NODISCARD inline float _Norm_minus_one(const float _Xval, const float _Yval) noexcept { + const auto _Dx = static_cast(_Xval); + const auto _Dy = static_cast(_Yval); + return static_cast((_Dx * _Dx - 1.0) + _Dy * _Dy); + } + + // TRANSITION: CRT log1p can be inaccurate for tiny inputs under directed rounding modes + template + _NODISCARD _Ty _Logp1(const _Ty _Xval) { // returns log(1 + _Xval) + static_assert(is_floating_point_v<_Ty>, "_Ty must be floating-point"); + + if (_Is_nan(_Xval)) { // NaN + return _Xval + _Xval; // raise FE_INVALID if _Xval is a signaling NaN + } + + if (_Xval <= _Ty{-0.5} || _Ty{2.0} <= _Xval) { // naive formula is moderately accurate + if (_Xval == (numeric_limits<_Ty>::max)()) { // avoid overflow + return _STD log(_Xval); + } + + return _STD log(_Ty{1.0} + _Xval); + } + + const _Ty _Xabs = _Float_abs(_Xval); + if (_Xabs < numeric_limits<_Ty>::epsilon()) { // zero or tiny + if (_Xval == _Ty{0.0}) { + return _Xval; + } + + // honor rounding mode, raise FE_INEXACT + return _Xval - _Ty{0.5} * _Xval * _Xval; + } + + // compute log(1 + _Xval) with fixup for small _Xval + const _FMP _Fmp_t<_Ty, 2> _Xp1 = _FMP _Add_small_x2(_Ty{1.0}, _Xval); + return _STD log(_Xp1._Val0) + _Xp1._Val1 / _Xp1._Val0; + } + + template + _NODISCARD _Ty _Log_hypot(const _Ty _Xval, const _Ty _Yval) noexcept { // returns log(hypot(_Xval, _Yval)) + static_assert(is_floating_point_v<_Ty>, "_Ty must be floating-point"); + + if (!_Is_finite(_Xval) || !_Is_finite(_Yval)) { // Inf or NaN + // raise FE_INVALID and return NaN if at least one of them is a signaling NaN + if (_Is_signaling_nan(_Xval) || _Is_signaling_nan(_Yval)) { + return _Xval + _Yval; + } + + // return +Inf if at least one of them is an infinity, even when the other is a quiet NaN + if (_Is_inf(_Xval)) { + return _Float_abs(_Xval); + } + + if (_Is_inf(_Yval)) { + return _Float_abs(_Yval); + } + + // at least one of them is a quiet NaN, and the other is not an infinity + return _Xval + _Yval; + } + + _Ty _Av = _Float_abs(_Xval); + _Ty _Bv = _Float_abs(_Yval); + + if (_Av < _Bv) { // ensure that _Bv <= _Av + _STD swap(_Av, _Bv); + } + + if (_Bv == 0) { + return _STD log(_Av); + } + + if (_Hypot_leg_tiny<_Ty> < _Av && _Av < _Hypot_leg_huge<_Ty>) { // no overflow or harmful underflow + constexpr _Ty _Norm_small = _Ty{0.5}; + constexpr _Ty _Norm_big = _Ty{3.0}; + + const _Ty _Bv_sqr = _Bv * _Bv; + + if (_Av == _Ty{1.0}) { // correctly return +0 when _Av == 1 and _Bv * _Bv underflows + // _Norm_minus_one(_Av, _Bv) could return -0 under FE_DOWNWARD rounding mode + return _Logp1(_Bv_sqr) * _Ty{0.5}; + } + + const _Ty _Norm = _Av * _Av + _Bv_sqr; + + if (_Norm_small < _Norm && _Norm < _Norm_big) { // avoid catastrophic cancellation + return _Logp1(_Norm_minus_one(_Av, _Bv)) * _Ty{0.5}; + } else { + return _STD log(_Norm) * _Ty{0.5}; + } + } else { // use 1 1/2 precision to preserve bits + constexpr _Ty _Cm = _Ty{22713.0L / 32768.0L}; + constexpr _Ty _Cl = _Ty{1.4286068203094172321214581765680755e-6L}; + + const int _Exponent = _STD ilogb(_Av); + const _Ty _Av_scaled = _STD scalbn(_Av, -_Exponent); + const _Ty _Bv_scaled = _STD scalbn(_Bv, -_Exponent); + const _Ty _Bv_scaled_sqr = _Bv_scaled * _Bv_scaled; + const _Ty _Norm_scaled = _Av_scaled * _Av_scaled + _Bv_scaled_sqr; + const _Ty _Real_shifted = _STD log(_Norm_scaled) * _Ty{0.5}; + return (_Real_shifted + _Exponent * _Cl) + _Exponent * _Cm; + } + } +} // namespace _Math_algorithms + +#undef _FMP + using _Dcomplex_value = _CSTD _C_double_complex; using _Fcomplex_value = _CSTD _C_float_complex; using _Lcomplex_value = _CSTD _C_ldouble_complex; @@ -66,8 +374,12 @@ public: return (numeric_limits<_Ty>::max)(); } + static constexpr _Ty _Flt_norm_min() { + return (numeric_limits<_Ty>::min)() > 0 ? (numeric_limits<_Ty>::min)() : 0; + } + static _Ty _Abs(_Ty _Left) { - return static_cast<_Ty>(_Left < 0 ? -_Left : _Left); + return static_cast<_Ty>(_Signbit(_Left) ? -_Left : _Left); } static _Ty _Cosh(_Ty _Left, _Ty _Right) { // return cosh(_Left) * _Right @@ -75,7 +387,7 @@ public: } static _Ty _Copysign(_Ty _Magnitude, _Ty _Sign) { - return static_cast<_Ty>(_Sign < 0 ? -_Abs(_Magnitude) : _Abs(_Magnitude)); + return static_cast<_Ty>(_Signbit(_Sign) ? -_Abs(_Magnitude) : _Abs(_Magnitude)); } static short _Exp(_Ty* _Pleft, _Ty _Right, short _Exponent) { // compute exp(*_Pleft) * _Right * 2 ^ _Exponent @@ -106,7 +418,7 @@ public: } static bool _Signbit(_Ty _Left) { - return _Left < 0; + return (_STD signbit)(static_cast(_Left)); } static _Ty _Sinh(_Ty _Left, _Ty _Right) { // return sinh(_Left) * _Right @@ -200,6 +512,10 @@ public: return (numeric_limits::max)(); } + static constexpr _Ty _Flt_norm_min() { + return (numeric_limits::min)(); + } + static _Ty _Abs(_Ty _Left) { // testing _Left < 0 would be incorrect when _Left is -0.0 return _CSTD fabsl(_Left); @@ -340,6 +656,10 @@ public: return (numeric_limits::max)(); } + static constexpr _Ty _Flt_norm_min() { + return (numeric_limits::min)(); + } + static _Ty _Abs(_Ty _Left) { // testing _Left < 0 would be incorrect when _Left is -0.0 return _CSTD fabs(_Left); @@ -475,6 +795,10 @@ public: return (numeric_limits::max)(); } + static constexpr _Ty _Flt_norm_min() { + return (numeric_limits::min)(); + } + static _Ty _Abs(_Ty _Left) { // testing _Left < 0 would be incorrect when _Left is -0.0 return _CSTD fabsf(_Left); @@ -1524,10 +1848,13 @@ _NODISCARD complex<_Ty> exp(const complex<_Ty>& _Left) { // FUNCTION TEMPLATE _Fabs template -_Ty _Fabs(const complex<_Ty>& _Left, int* _Pexp) { // return magnitude and scale factor +_Ty _Fabs(const complex<_Ty>& _Left, int* _Pexp) { // Used by sqrt(), return magnitude and scale factor. + // Returns a non-zero even integer in *_Pexp when _Left is finite + // and non-zero. + // Returns 0 in *_Pexp when _Left is zero, infinity, or NaN. *_Pexp = 0; - _Ty _Av = real(_Left); - _Ty _Bv = imag(_Left); + _Ty _Av = _Ctraits<_Ty>::_Abs(_STD real(_Left)); + _Ty _Bv = _Ctraits<_Ty>::_Abs(_STD imag(_Left)); if (_Ctraits<_Ty>::_Isinf(_Av) || _Ctraits<_Ty>::_Isinf(_Bv)) { return _Ctraits<_Ty>::_Infv(); // at least one component is INF @@ -1536,13 +1863,8 @@ _Ty _Fabs(const complex<_Ty>& _Left, int* _Pexp) { // return magnitude and scale } else if (_Ctraits<_Ty>::_Isnan(_Bv)) { return _Bv; // imaginary component is NaN } else { // neither component is NaN or INF - _Av = _Ctraits<_Ty>::_Abs(_Av); - _Bv = _Ctraits<_Ty>::_Abs(_Bv); - if (_Av < _Bv) { // ensure that |_Bv| <= |_Av| - _Ty _Tmp = _Av; - _Av = _Bv; - _Bv = _Tmp; + _STD swap(_Av, _Bv); } if (_Av == 0) { @@ -1550,16 +1872,28 @@ _Ty _Fabs(const complex<_Ty>& _Left, int* _Pexp) { // return magnitude and scale } if (1 <= _Av) { - *_Pexp = 2; - _Av = _Av * static_cast<_Ty>(0.25); - _Bv = _Bv * static_cast<_Ty>(0.25); + *_Pexp = 4; + _Av = _Av * static_cast<_Ty>(0.0625); + _Bv = _Bv * static_cast<_Ty>(0.0625); } else { - *_Pexp = -2; - _Av = _Av * 4; - _Bv = _Bv * 4; + constexpr _Ty _Flt_eps = _Ctraits<_Ty>::_Flt_eps(); + // TRANSITION, workaround for non floating point _Ty + constexpr _Ty _Leg_tiny = _Flt_eps == 0 ? _Ty{0} : 2 * _Ctraits<_Ty>::_Flt_norm_min() / _Flt_eps; + + if (_Av < _Leg_tiny) { + constexpr int _Exponent = -2 * numeric_limits<_Ty>::digits; + + *_Pexp = _Exponent; + _Av = _Ctraits<_Ty>::ldexp(_Av, -_Exponent); + _Bv = _Ctraits<_Ty>::ldexp(_Bv, -_Exponent); + } else { + *_Pexp = -2; + _Av = _Av * 4; + _Bv = _Bv * 4; + } } - _Ty _Tmp = _Av - _Bv; + const _Ty _Tmp = _Av - _Bv; if (_Tmp == _Av) { return _Av; // _Bv unimportant } else if (_Bv < _Tmp) { // use simple approximation @@ -1580,32 +1914,20 @@ _Ty _Fabs(const complex<_Ty>& _Left, int* _Pexp) { // return magnitude and scale // FUNCTION TEMPLATE log template -_NODISCARD complex<_Ty> log(const complex<_Ty>& _Left) { - _Ty _Theta = _Ctraits<_Ty>::atan2(imag(_Left), real(_Left)); // get phase - - if (_Ctraits<_Ty>::_Isnan(_Theta)) { - return complex<_Ty>(_Theta, _Theta); // real or imag is NaN - } else { // use 1 1/2 precision to preserve bits - constexpr _Ty _Cm = static_cast<_Ty>(22713.0L / 32768.0L); - constexpr _Ty _Cl = static_cast<_Ty>(1.4286068203094172321214581765680755e-6L); - int _Leftexp; - _Ty _Rho = _Fabs(_Left, &_Leftexp); // get magnitude and scale factor - - _Ty _Leftn = static_cast<_Ty>(_Leftexp); +_NODISCARD _Ty _Log_abs(const complex<_Ty>& _Left) noexcept { // for double, long double, and non floating point types + return static_cast<_Ty>( + _Math_algorithms::_Log_hypot(static_cast(_STD real(_Left)), static_cast(_STD imag(_Left)))); +} - _Ty _Real; - if (_Rho == 0) { - _Real = -_Ctraits<_Ty>::_Infv(); // log(0) == -INF - } else if (_Ctraits<_Ty>::_Isinf(_Rho)) { - _Real = _Rho; // log(INF) == INF - } else { - _Real = static_cast<_Ty>(_Ctraits<_Ty>::log(_Rho)); // These casts are TRANSITION, DevCom-1093507 - _Real += static_cast<_Ty>(_Leftn * _Cl); - _Real += static_cast<_Ty>(_Leftn * _Cm); - } +_NODISCARD inline float _Log_abs(const complex& _Left) noexcept { + return _Math_algorithms::_Log_hypot(_STD real(_Left), _STD imag(_Left)); +} - return complex<_Ty>(_Real, _Theta); - } +template +_NODISCARD complex<_Ty> log(const complex<_Ty>& _Left) { + const _Ty _Log_abs_v = _STD _Log_abs(_Left); // get logarithm of magnitude + const _Ty _Theta = _Ctraits<_Ty>::atan2(_STD imag(_Left), _STD real(_Left)); // get phase + return complex<_Ty>(_Log_abs_v, _Theta); } // FUNCTION TEMPLATE pow @@ -1678,7 +2000,7 @@ _NODISCARD complex<_Ty> sqrt(const complex<_Ty>& _Left) { return complex<_Ty>(_Ctraits<_Ty>::_Infv(), _Im); // (any, +/-Inf) } else if (_Ctraits<_Ty>::_Isnan(_Im)) { if (_Re < 0) { - return complex<_Ty>(_Im, _Re); // (-Inf, NaN) + return complex<_Ty>(_Ctraits<_Ty>::_Abs(_Im), _Ctraits<_Ty>::_Copysign(_Re, _Im)); // (-Inf, NaN) } else { return _Left; // (+Inf, NaN) } diff --git a/stl/inc/concepts b/stl/inc/concepts index fad9a75caa8..0f311a9dbd6 100644 --- a/stl/inc/concepts +++ b/stl/inc/concepts @@ -48,6 +48,10 @@ concept convertible_to = __is_convertible_to(_From, _To) static_cast<_To>(_Fn()); }; +// CONCEPT _Implicitly_convertible_to +template +concept _Implicitly_convertible_to = is_convertible_v<_From, _To>; + // CONCEPT common_reference_with template concept common_reference_with = @@ -305,6 +309,14 @@ template concept strict_weak_order = relation<_FTy, _Ty1, _Ty2>; // clang-format on + +// STRUCT TEMPLATE _Choice_t +template +struct _Choice_t { + _Ty _Strategy = _Ty{}; + bool _No_throw = false; +}; + _STD_END #pragma pop_macro("new") diff --git a/stl/inc/coroutine b/stl/inc/coroutine index c041e17463b..59ceb440fcb 100644 --- a/stl/inc/coroutine +++ b/stl/inc/coroutine @@ -135,7 +135,7 @@ _NODISCARD constexpr strong_ordering operator<=>( template struct hash> { - _NODISCARD size_t operator()(const coroutine_handle<_Promise>& _Coro) noexcept { + _NODISCARD size_t operator()(const coroutine_handle<_Promise>& _Coro) const noexcept { return _Hash_representation(_Coro.address()); } }; diff --git a/stl/inc/csetjmp b/stl/inc/csetjmp index 3c25d009937..802ff156e63 100644 --- a/stl/inc/csetjmp +++ b/stl/inc/csetjmp @@ -1,4 +1,4 @@ -// csetjmp standard header +// csetjmp standard header (core) // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception @@ -6,7 +6,7 @@ #pragma once #ifndef _CSETJMP_ #define _CSETJMP_ -#include +#include #if _STL_COMPILER_PREPROCESSOR #include diff --git a/stl/inc/csignal b/stl/inc/csignal index 077056161ee..fc88191d7dc 100644 --- a/stl/inc/csignal +++ b/stl/inc/csignal @@ -1,4 +1,4 @@ -// csignal standard header +// csignal standard header (core) // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception @@ -6,7 +6,7 @@ #pragma once #ifndef _CSIGNAL_ #define _CSIGNAL_ -#include +#include #if _STL_COMPILER_PREPROCESSOR #include diff --git a/stl/inc/cstdarg b/stl/inc/cstdarg index af09a4fa7d2..f9897bcb17a 100644 --- a/stl/inc/cstdarg +++ b/stl/inc/cstdarg @@ -1,4 +1,4 @@ -// cstdarg standard header +// cstdarg standard header (core) // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception @@ -6,7 +6,7 @@ #pragma once #ifndef _CSTDARG_ #define _CSTDARG_ -#include +#include #if _STL_COMPILER_PREPROCESSOR #include diff --git a/stl/inc/cstdint b/stl/inc/cstdint index f543b38f3da..c61aed7d7b5 100644 --- a/stl/inc/cstdint +++ b/stl/inc/cstdint @@ -1,4 +1,4 @@ -// cstdint standard header +// cstdint standard header (core) // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception @@ -6,7 +6,7 @@ #pragma once #ifndef _CSTDINT_ #define _CSTDINT_ -#include +#include #if _STL_COMPILER_PREPROCESSOR #include diff --git a/stl/inc/cstring b/stl/inc/cstring index 8c714e9db08..a0140aa307c 100644 --- a/stl/inc/cstring +++ b/stl/inc/cstring @@ -1,4 +1,4 @@ -// cstring standard header +// cstring standard header (core) // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception @@ -6,7 +6,7 @@ #pragma once #ifndef _CSTRING_ #define _CSTRING_ -#include +#include #if _STL_COMPILER_PREPROCESSOR #include diff --git a/stl/inc/ctime b/stl/inc/ctime index a6f3ddc01a9..94ed91c49c8 100644 --- a/stl/inc/ctime +++ b/stl/inc/ctime @@ -1,4 +1,4 @@ -// ctime standard header +// ctime standard header (core) // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception @@ -6,7 +6,7 @@ #pragma once #ifndef _CTIME_ #define _CTIME_ -#include +#include #if _STL_COMPILER_PREPROCESSOR #include diff --git a/stl/inc/cuchar b/stl/inc/cuchar index 86119e20f87..fc8feb0be82 100644 --- a/stl/inc/cuchar +++ b/stl/inc/cuchar @@ -1,4 +1,4 @@ -// cuchar standard header +// cuchar standard header (core) // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception @@ -6,7 +6,7 @@ #pragma once #ifndef _CUCHAR_ #define _CUCHAR_ -#include +#include #if _STL_COMPILER_PREPROCESSOR #include diff --git a/stl/inc/cwctype b/stl/inc/cwctype index 567d6642ae7..cfcbe9040ef 100644 --- a/stl/inc/cwctype +++ b/stl/inc/cwctype @@ -1,4 +1,4 @@ -// cwctype standard header +// cwctype standard header (core) // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception @@ -6,7 +6,7 @@ #pragma once #ifndef _CWCTYPE_ #define _CWCTYPE_ -#include +#include #if _STL_COMPILER_PREPROCESSOR #include diff --git a/stl/inc/experimental/coroutine b/stl/inc/experimental/coroutine index c6ed2a2a292..062973090ba 100644 --- a/stl/inc/experimental/coroutine +++ b/stl/inc/experimental/coroutine @@ -16,7 +16,7 @@ #if _HAS_EXCEPTIONS #include #endif -#include +#include #include #pragma pack(push, _CRT_PACKING) diff --git a/stl/inc/experimental/resumable b/stl/inc/experimental/resumable index 7f308dd3ecf..0991c7c20d4 100644 --- a/stl/inc/experimental/resumable +++ b/stl/inc/experimental/resumable @@ -15,8 +15,8 @@ #if _HAS_EXCEPTIONS #include #endif +#include #include -#include #include #pragma pack(push, _CRT_PACKING) diff --git a/stl/inc/filesystem b/stl/inc/filesystem index 948ac146e73..52e41e51fec 100644 --- a/stl/inc/filesystem +++ b/stl/inc/filesystem @@ -622,7 +622,6 @@ namespace filesystem { _NODISCARD inline bool _Is_drive_prefix_with_slash_slash_question(const wstring_view _Text) { // test if _Text starts with a \\?\X: prefix - using namespace _STD string_view_literals; // TRANSITION, VSO-571749 return _Text.size() >= 6 && _Text._Starts_with(LR"(\\?\)"sv) && _Is_drive_prefix(_Text.data() + 4); } @@ -1250,8 +1249,6 @@ namespace filesystem { } _NODISCARD path lexically_normal() const { - using namespace _STD string_view_literals; // TRANSITION, VSO-571749 - constexpr wstring_view _Dot = L"."sv; constexpr wstring_view _Dot_dot = L".."sv; @@ -1686,8 +1683,6 @@ namespace filesystem { } _NODISCARD inline path path::lexically_relative(const path& _Base) const { - using namespace _STD string_view_literals; // TRANSITION, VSO-571749 - constexpr wstring_view _Dot = L"."sv; constexpr wstring_view _Dot_dot = L".."sv; @@ -1810,7 +1805,6 @@ namespace filesystem { private: static string _Pretty_message(const string_view _Op, const path& _Path1, const path& _Path2 = {}) { - using namespace _STD string_view_literals; // TRANSITION, VSO-571749 string _Result; // Convert the paths to narrow encoding in a way that gracefully handles non-encodable characters const auto _Code_page = __std_fs_code_page(); @@ -2550,7 +2544,6 @@ namespace filesystem { _NODISCARD static __std_win_error _Open_dir( path& _Path, const directory_options _Options_arg, _Find_file_handle& _Dir, __std_fs_find_data& _Data) { - using namespace _STD string_view_literals; // TRANSITION, VSO-571749 const size_t _Null_term_len = _CSTD wcslen(_Path.c_str()); if (_Null_term_len == 0 || _Null_term_len != _Path.native().size()) { return __std_win_error::_File_not_found; @@ -3021,7 +3014,6 @@ namespace filesystem { // FUNCTION canonical _NODISCARD inline __std_win_error _Canonical(path& _Result, const wstring& _Text) { // pre: _Result.empty() - using namespace _STD string_view_literals; // TRANSITION, VSO-571749 if (_Text.empty()) { return __std_win_error::_Success; } diff --git a/stl/inc/iterator b/stl/inc/iterator index 42b7bd52160..39452a5bd75 100644 --- a/stl/inc/iterator +++ b/stl/inc/iterator @@ -602,7 +602,7 @@ public: #endif // TRANSITION, VSO-1225825 _Variantish(const _Variantish& _That) noexcept( - noexcept(is_nothrow_copy_constructible_v<_It>&& is_nothrow_copy_constructible_v<_Se>)) + is_nothrow_copy_constructible_v<_It>&& is_nothrow_copy_constructible_v<_Se>) : _Contains{_That._Contains} { switch (_Contains) { case _Variantish_state::_Holds_iter: @@ -1105,7 +1105,6 @@ public: // [counted.iter.elem] _NODISCARD constexpr decltype(auto) operator*() noexcept(noexcept(*_Current)) /* strengthened */ { #if _ITERATOR_DEBUG_LEVEL != 0 - // Per proposed resolution of LWG-3472 _STL_VERIFY(_Length > 0, "counted_iterator dereference beyond end of range"); #endif // _ITERATOR_DEBUG_LEVEL != 0 return *_Current; @@ -1114,7 +1113,6 @@ public: _NODISCARD constexpr decltype(auto) operator*() const noexcept(noexcept(*_Current)) /* strengthened */ requires _Dereferenceable { #if _ITERATOR_DEBUG_LEVEL != 0 - // Per proposed resolution of LWG-3472 _STL_VERIFY(_Length > 0, "counted_iterator dereference beyond end of range"); #endif // _ITERATOR_DEBUG_LEVEL != 0 return *_Current; diff --git a/stl/inc/latch b/stl/inc/latch index 3743af76484..16eea8b0fed 100644 --- a/stl/inc/latch +++ b/stl/inc/latch @@ -18,7 +18,7 @@ #else // ^^^ !_HAS_CXX20 / _HAS_CXX20 vvv #include -#include +#include #pragma pack(push, _CRT_PACKING) #pragma warning(push, _STL_WARNING_LEVEL) diff --git a/stl/inc/memory b/stl/inc/memory index d168f49e698..006c97a1342 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -428,10 +428,17 @@ namespace ranges { if constexpr (_Fill_memset_is_safe<_It, _Ty>) { const auto _OFinal = _RANGES next(_OFirst, _STD move(_OLast)); - const auto _Diff = static_cast(_OFinal - _OFirst); - _Fill_memset(_OFirst, _Val, _Diff); + _Fill_memset(_OFirst, _Val, static_cast(_OFinal - _OFirst)); return _OFinal; } else { + if constexpr (_Fill_zero_memset_is_safe<_It, _Ty>) { + if (_Is_all_bits_zero(_Val)) { + const auto _OFinal = _RANGES next(_OFirst, _STD move(_OLast)); + _Fill_zero_memset(_OFirst, static_cast(_OFinal - _OFirst)); + return _OFinal; + } + } + _Uninitialized_backout _Backout{_STD move(_OFirst)}; while (_Backout._Last != _OLast) { @@ -458,11 +465,19 @@ _NoThrowFwdIt uninitialized_fill_n(_NoThrowFwdIt _First, const _Diff _Count_raw, } auto _UFirst = _Get_unwrapped_n(_First, _Count); - if constexpr (_Fill_memset_is_safe<_Unwrapped_n_t, _Tval>) { + if constexpr (_Fill_memset_is_safe) { _Fill_memset(_UFirst, _Val, static_cast(_Count)); _UFirst += _Count; } else { - _Uninitialized_backout<_Unwrapped_n_t> _Backout{_UFirst}; + if constexpr (_Fill_zero_memset_is_safe) { + if (_Is_all_bits_zero(_Val)) { + _Fill_zero_memset(_UFirst, static_cast(_Count)); + _Seek_wrapped(_First, _UFirst + _Count); + return _First; + } + } + + _Uninitialized_backout _Backout{_UFirst}; for (; _Count > 0; --_Count) { _Backout._Emplace_back(_Val); @@ -527,10 +542,18 @@ namespace ranges { } auto _UFirst = _Get_unwrapped_n(_STD move(_First), _Count); - if constexpr (_Fill_memset_is_safe<_It, _Ty>) { + if constexpr (_Fill_memset_is_safe) { _Fill_memset(_UFirst, _Val, static_cast(_Count)); _Seek_wrapped(_First, _UFirst + _Count); } else { + if constexpr (_Fill_zero_memset_is_safe) { + if (_Is_all_bits_zero(_Val)) { + _Fill_zero_memset(_UFirst, static_cast(_Count)); + _Seek_wrapped(_First, _UFirst + _Count); + return _First; + } + } + _Uninitialized_backout _Backout{_STD move(_UFirst)}; for (; _Count > 0; --_Count) { @@ -2386,6 +2409,12 @@ void _Uninitialized_fill_multidimensional_n(_Ty* const _Out, const size_t _Size, } else if constexpr (_Fill_memset_is_safe<_Ty*, _Ty>) { _Fill_memset(_Out, _Val, _Size); } else { + if constexpr (_Fill_zero_memset_is_safe<_Ty*, _Ty>) { + if (_Is_all_bits_zero(_Val)) { + _Fill_zero_memset(_Out, _Size); + return; + } + } _Uninitialized_rev_destroying_backout _Backout{_Out}; for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _Backout._Emplace_back(_Val); @@ -2730,6 +2759,13 @@ void _Uninitialized_fill_multidimensional_n_al(_Ty* const _Out, const size_t _Si } else if constexpr (_Fill_memset_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, const _Ty&>::value) { _Fill_memset(_Out, _Val, _Size); } else { + if constexpr (_Fill_zero_memset_is_safe<_Ty*, + _Ty> && _Uses_default_construct<_Alloc, _Ty*, const _Ty&>::value) { + if (_Is_all_bits_zero(_Val)) { + _Fill_zero_memset(_Out, _Size); + return; + } + } _Uninitialized_rev_destroying_backout_al _Backout{_Out, _Al}; for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _Backout._Emplace_back(_Val); diff --git a/stl/inc/memory_resource b/stl/inc/memory_resource index 3aebab8a602..bb47641ee87 100644 --- a/stl/inc/memory_resource +++ b/stl/inc/memory_resource @@ -661,7 +661,7 @@ namespace pmr { } protected: - virtual void* do_allocate(size_t _Bytes, size_t _Align) override { // TRANSITION, DevCom-1159869 + virtual void* do_allocate(const size_t _Bytes, const size_t _Align) override { // allocate from the current buffer or a new larger buffer from upstream if (!_STD align(_Align, _Bytes, _Current_buffer, _Space_available)) { _Increase_capacity(_Bytes, _Align); diff --git a/stl/inc/mutex b/stl/inc/mutex index 501fa02c01f..5d781ceff82 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -14,7 +14,7 @@ #endif // _M_CEE_PURE #include -#include +#include #include #include #include diff --git a/stl/inc/random b/stl/inc/random index 1854b1f234d..8ce829c3b37 100644 --- a/stl/inc/random +++ b/stl/inc/random @@ -11,8 +11,8 @@ #if _STL_COMPILER_PREPROCESSOR #include #include +#include #include -#include #include #include #include @@ -1824,12 +1824,12 @@ private: result_type _Eval(_Engine& _Eng, _Ty _Min, _Ty _Max) const { // compute next value in range [_Min, _Max] _Rng_from_urng<_Uty, _Engine> _Generator(_Eng); - const _Uty _Umin = _Adjust(_Uty(_Min)); - const _Uty _Umax = _Adjust(_Uty(_Max)); + const _Uty _Umin = _Adjust(static_cast<_Uty>(_Min)); + const _Uty _Umax = _Adjust(static_cast<_Uty>(_Max)); _Uty _Uret; - if (_Umax - _Umin == _Uty(-1)) { + if (_Umax - _Umin == static_cast<_Uty>(-1)) { _Uret = static_cast<_Uty>(_Generator._Get_all_bits()); } else { _Uret = static_cast<_Uty>(_Generator(static_cast<_Uty>(_Umax - _Umin + 1))); @@ -1839,23 +1839,19 @@ private: } static _Uty _Adjust(_Uty _Uval) { // convert signed ranges to unsigned ranges and vice versa - return _Adjust(_Uval, is_signed<_Ty>{}); - } - - static _Uty _Adjust(_Uty _Uval, true_type) { // convert signed ranges to unsigned ranges and vice versa - const _Uty _Adjuster = (_Uty(-1) >> 1) + 1; // 2^(N-1) + if _CONSTEXPR_IF (is_signed_v<_Ty>) { + const _Uty _Adjuster = (static_cast<_Uty>(-1) >> 1) + 1; // 2^(N-1) - if (_Uval < _Adjuster) { - return static_cast<_Uty>(_Uval + _Adjuster); - } else { - return static_cast<_Uty>(_Uval - _Adjuster); + if (_Uval < _Adjuster) { + return static_cast<_Uty>(_Uval + _Adjuster); + } else { + return static_cast<_Uty>(_Uval - _Adjuster); + } + } else { // _Ty is already unsigned, do nothing + return _Uval; } } - static _Uty _Adjust(_Uty _Uval, false_type) { // _Ty is already unsigned, do nothing - return _Uval; - } - param_type _Par; }; diff --git a/stl/inc/ranges b/stl/inc/ranges index 776e1310efe..577cdd0d323 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -11,6 +11,7 @@ #ifndef __cpp_lib_concepts #pragma message("The contents of are available only with C++20 concepts support.") #else // ^^^ !defined(__cpp_lib_concepts) / defined(__cpp_lib_concepts) vvv +#include #include #include #include @@ -583,7 +584,7 @@ namespace ranges { // clang-format off template requires constructible_from<_Ty, _Types...> - constexpr explicit single_view(in_place_t, _Types&&... _Args) noexcept( // explicit per LWG-3428 + constexpr explicit single_view(in_place_t, _Types&&... _Args) noexcept( is_nothrow_constructible_v<_Ty, _Types...>) // strengthened // clang-format on : _Val{in_place, _STD forward<_Types>(_Args)...} {} @@ -634,6 +635,99 @@ namespace ranges { inline constexpr _Single_fn single; } // namespace views + // CLASS TEMPLATE ranges::istream_view + template + concept _Stream_extractable = requires(basic_istream<_Elem, _Traits>& __is, _Ty& __t) { + __is >> __t; + }; + + // clang-format off + template > + requires default_initializable<_Ty> && _Stream_extractable<_Ty, _Elem, _Traits> + class basic_istream_view : public view_interface> { + // clang-format on + private: + class _Iterator { + private: + basic_istream_view* _Parent = nullptr; + + public: + using iterator_concept = input_iterator_tag; + using difference_type = ptrdiff_t; + using value_type = _Ty; + + _Iterator() = default; + constexpr explicit _Iterator(basic_istream_view& _Parent_) noexcept : _Parent{_STD addressof(_Parent_)} {} + + _Iterator(const _Iterator&) = delete; + _Iterator(_Iterator&&) = default; + + _Iterator& operator=(const _Iterator&) = delete; + _Iterator& operator=(_Iterator&&) = default; + + _Iterator& operator++() { +#if _ITERATOR_DEBUG_LEVEL != 0 + // Per LWG-3489 + _STL_VERIFY(_Parent != nullptr, "cannot increment default-initialized istream_view iterator"); + _STL_VERIFY( + _Parent->_Stream != nullptr, "cannot increment istream_view iterator with uninitialized stream"); + _STL_VERIFY(!_Parent->_Stream_at_end(), "cannot increment istream_view iterator at end of stream"); +#endif // _ITERATOR_DEBUG_LEVEL != 0 + *_Parent->_Stream >> _Parent->_Val; + return *this; + } + + void operator++(int) { + ++*this; + } + + _NODISCARD _Ty& operator*() const noexcept /* strengthened */ { +#if _ITERATOR_DEBUG_LEVEL != 0 + // Per LWG-3489 + _STL_VERIFY(_Parent != nullptr, "cannot dereference default-initialized istream_view iterator"); + _STL_VERIFY( + _Parent->_Stream != nullptr, "cannot dereference istream_view iterator with uninitialized stream"); + _STL_VERIFY(!_Parent->_Stream_at_end(), "cannot dereference istream_view iterator at end of stream"); +#endif // _ITERATOR_DEBUG_LEVEL != 0 + return _Parent->_Val; + } + + _NODISCARD friend bool operator==(const _Iterator& _Left, default_sentinel_t) noexcept /* strengthened */ { + return _Left._Parent == nullptr || _Left._Parent->_Stream_at_end(); + } + }; + + basic_istream<_Elem, _Traits>* _Stream = nullptr; + _Ty _Val = _Ty{}; + + public: + basic_istream_view() = default; + constexpr explicit basic_istream_view(basic_istream<_Elem, _Traits>& _Stream_) noexcept( + is_nothrow_default_constructible_v<_Ty>) // strengthened + : _Stream{_STD addressof(_Stream_)} {} + + _NODISCARD constexpr auto begin() { + if (_Stream) { + *_Stream >> _Val; + } + return _Iterator{*this}; + } + + _NODISCARD constexpr default_sentinel_t end() const noexcept { + return default_sentinel; + } + + _NODISCARD constexpr bool _Stream_at_end() const noexcept { + return !*_Stream; + } + }; + + template + _NODISCARD basic_istream_view<_Ty, _Elem, _Traits> istream_view(basic_istream<_Elem, _Traits>& _Stream) noexcept( + is_nothrow_default_constructible_v<_Ty>) /* strengthened */ { + return basic_istream_view<_Ty, _Elem, _Traits>{_Stream}; + } + // CLASS TEMPLATE ranges::ref_view // clang-format off template @@ -733,11 +827,13 @@ namespace ranges { requires (_Choice<_Rng>._Strategy != _St::_None) _NODISCARD constexpr auto operator()(_Rng&& _Range) const noexcept(_Choice<_Rng>._No_throw) { // clang-format on - if constexpr (_Choice<_Rng>._Strategy == _St::_View) { + constexpr _St _Strat = _Choice<_Rng>._Strategy; + + if constexpr (_Strat == _St::_View) { return _STD forward<_Rng>(_Range); - } else if constexpr (_Choice<_Rng>._Strategy == _St::_Ref) { + } else if constexpr (_Strat == _St::_Ref) { return ref_view{_STD forward<_Rng>(_Range)}; - } else if constexpr (_Choice<_Rng>._Strategy == _St::_Subrange) { + } else if constexpr (_Strat == _St::_Subrange) { return subrange{_STD forward<_Rng>(_Range)}; } else { static_assert(_Always_false<_Rng>, "Should be unreachable"); @@ -763,11 +859,10 @@ namespace ranges { /* [[no_unique_address]] */ _Semiregular_box<_Pr> _Pred{}; template // TRANSITION, LWG-3289 - struct _Iterator_base {}; + struct _Category_base {}; // clang-format off - template - requires _Has_member_iterator_category<_Traits> - struct _Iterator_base<_Traits> { + template <_Has_member_iterator_category _Traits> + struct _Category_base<_Traits> { // clang-format on using iterator_category = conditional_t, @@ -776,7 +871,7 @@ namespace ranges { forward_iterator_tag, input_iterator_tag>>; }; - class _Iterator : public _Iterator_base>> { + class _Iterator : public _Category_base>> { private: /* [[no_unique_address]] */ iterator_t<_Vw> _Current{}; filter_view* _Parent{}; @@ -987,14 +1082,18 @@ namespace ranges { /* [[no_unique_address]] */ _Semiregular_box<_Pr> _Pred; template - _NODISCARD constexpr auto operator()(_Rng&& _Range) const - noexcept(noexcept(filter_view{_STD forward<_Rng>(_Range), _STD move(*_Pred)})) requires requires { - filter_view{static_cast<_Rng&&>(_Range), _STD move(*_Pred)}; + _NODISCARD constexpr auto operator()(_Rng&& _Range) const& noexcept( + noexcept(filter_view{_STD forward<_Rng>(_Range), *_Pred})) requires requires { + filter_view{static_cast<_Rng&&>(_Range), *_Pred}; } - { - // clang-format on - return filter_view{_STD forward<_Rng>(_Range), _STD move(*_Pred)}; + { return filter_view{_STD forward<_Rng>(_Range), *_Pred}; } + + template + _NODISCARD constexpr auto operator()(_Rng&& _Range) && noexcept( + noexcept(filter_view{_STD forward<_Rng>(_Range), _STD move(*_Pred)})) requires requires { + filter_view{static_cast<_Rng&&>(_Range), _STD move(*_Pred)}; } + { return filter_view{_STD forward<_Rng>(_Range), _STD move(*_Pred)}; } }; public: @@ -1043,11 +1142,10 @@ namespace ranges { class _Sentinel; template // TRANSITION, LWG-3289 - struct _Iterator_base {}; + struct _Category_base {}; // clang-format off - template - requires _Has_member_iterator_category<_Traits> - struct _Iterator_base<_Traits, _Base> { + template <_Has_member_iterator_category _Traits, class _Base> + struct _Category_base<_Traits, _Base> { // clang-format on using iterator_category = conditional_t>>, @@ -1057,7 +1155,7 @@ namespace ranges { }; template - class _Iterator : public _Iterator_base>, _Maybe_const<_Const, _Vw>> { + class _Iterator : public _Category_base>, _Maybe_const<_Const, _Vw>> { private: template friend class _Iterator; @@ -1093,7 +1191,7 @@ namespace ranges { _Iterator() = default; constexpr _Iterator(_Parent_t& _Parent_, iterator_t<_Base> _Current_) noexcept( - noexcept(is_nothrow_move_constructible_v>)) // strengthened + is_nothrow_move_constructible_v>) // strengthened : _Current{_STD move(_Current_)}, _Parent{_STD addressof(_Parent_)} { #if _ITERATOR_DEBUG_LEVEL != 0 _Adl_verify_range(_Current, _RANGES end(_Parent_._Range)); @@ -1295,8 +1393,7 @@ namespace ranges { _NODISCARD friend constexpr difference_type operator-(const _Iterator& _Left, const _Iterator& _Right) noexcept(noexcept(_Left._Current - _Right._Current)) /* strengthened */ - requires sized_sentinel_for, iterator_t<_Base>> { // constraints per LWG issue - // unnumbered as of 2020-09-03 + requires sized_sentinel_for, iterator_t<_Base>> { #if _ITERATOR_DEBUG_LEVEL != 0 _Left._Same_range(_Right); #endif // _ITERATOR_DEBUG_LEVEL != 0 @@ -1470,15 +1567,19 @@ namespace ranges { struct _Partial : _Pipe::_Base<_Partial<_Fn>> { /* [[no_unique_address]] */ _Semiregular_box<_Fn> _Fun; - // clang-format off template - _NODISCARD constexpr auto operator()(_Rng&& _Range) const noexcept(noexcept( - transform_view{_STD forward<_Rng>(_Range), _STD move(*_Fun)})) requires requires { + _NODISCARD constexpr auto operator()(_Rng&& _Range) const& noexcept( + noexcept(transform_view{_STD forward<_Rng>(_Range), *_Fun})) requires requires { + transform_view{static_cast<_Rng&&>(_Range), *_Fun}; + } + { return transform_view{_STD forward<_Rng>(_Range), *_Fun}; } + + template + _NODISCARD constexpr auto operator()(_Rng&& _Range) && noexcept( + noexcept(transform_view{_STD forward<_Rng>(_Range), _STD move(*_Fun)})) requires requires { transform_view{static_cast<_Rng&&>(_Range), _STD move(*_Fun)}; - } { - // clang-format on - return transform_view{_STD forward<_Rng>(_Range), _STD move(*_Fun)}; } + { return transform_view{_STD forward<_Rng>(_Range), _STD move(*_Fun)}; } }; public: @@ -1647,8 +1748,8 @@ namespace ranges { } }; - template // Per P/R of LWG-3447 - take_view(_Rng&&, range_difference_t<_Rng>)->take_view>; + template + take_view(_Rng&&, range_difference_t<_Rng>) -> take_view>; namespace views { // VARIABLE views::take @@ -1712,15 +1813,17 @@ namespace ranges { _NODISCARD constexpr auto operator()(_Rng&& _Range, range_difference_t<_Rng> _Count) const noexcept( _Choice<_Rng>._No_throw) { // clang-format on - if constexpr (_Choice<_Rng>._Strategy == _St::_Empty) { + constexpr _St _Strat = _Choice<_Rng>._Strategy; + + if constexpr (_Strat == _St::_Empty) { // it's an empty_view: return another empty view return remove_cvref_t<_Rng>{}; - } else if constexpr (_Choice<_Rng>._Strategy == _St::_Preserve) { + } else if constexpr (_Strat == _St::_Preserve) { // it's a "reconstructible range"; return the same kind of range with a restricted extent _Count = (_STD min)(_RANGES distance(_Range), _Count); const auto _First = _RANGES begin(_Range); return remove_cvref_t<_Rng>{_First, _First + _Count}; - } else if constexpr (_Choice<_Rng>._Strategy == _St::_Take_view) { + } else if constexpr (_Strat == _St::_Take_view) { return take_view{_STD forward<_Rng>(_Range), _Count}; } } @@ -1734,6 +1837,191 @@ namespace ranges { inline constexpr _Take_fn take; } // namespace views + // CLASS TEMPLATE ranges::take_while_view + // clang-format off + template + requires input_range<_Vw> && is_object_v<_Pr> && indirect_unary_predicate> + class take_while_view : public view_interface> { + // clang-format on + private: + /* [[no_unique_address]] */ _Vw _Range{}; + /* [[no_unique_address]] */ _Semiregular_box<_Pr> _Pred{}; + + template + class _Sentinel { + private: + template + friend class _Sentinel; + + using _Base_Ty = _Maybe_const<_Const, _Vw>; + using _Base_iterator = _Maybe_wrapped<_Wrapped, iterator_t<_Base_Ty>>; + using _Base_sentinel = _Maybe_wrapped<_Wrapped, sentinel_t<_Base_Ty>>; + + template + using _Maybe_const_iter = _Maybe_wrapped<_Wrapped, iterator_t<_Maybe_const<_OtherConst, _Vw>>>; + + /* [[no_unique_address]] */ _Base_sentinel _Last{}; + const _Pr* _Pred = nullptr; + + public: + _Sentinel() = default; + + constexpr explicit _Sentinel(_Base_sentinel _Last_, const _Pr* const _Pred_) noexcept( + is_nothrow_move_constructible_v<_Base_sentinel>) // strengthened + : _Last(_STD move(_Last_)), _Pred(_Pred_) {} + + // clang-format off + constexpr _Sentinel(_Sentinel _That) noexcept( + is_nothrow_constructible_v<_Base_sentinel, _Maybe_wrapped<_Wrapped, sentinel_t<_Vw>>>) // strengthened + requires _Const && convertible_to<_Maybe_wrapped<_Wrapped, sentinel_t<_Vw>>, _Base_sentinel> + : _Last(_STD move(_That._Last)), _Pred(_That._Pred) {} + // clang-format on + + _NODISCARD constexpr _Base_sentinel base() const + noexcept(is_nothrow_copy_constructible_v<_Base_sentinel>) /* strengthened */ { + return _Last; + } + + _NODISCARD friend constexpr bool operator==(const _Base_iterator& _Left, const _Sentinel& _Right) { + return _Right._Last == _Left || !_STD invoke(*_Right._Pred, *_Left); + } + + // clang-format off + template + requires sentinel_for<_Base_sentinel, _Maybe_const_iter<_OtherConst>> + _NODISCARD friend constexpr bool operator==( + const _Maybe_const_iter<_OtherConst>& _Left, const _Sentinel& _Right) { + // clang-format on + return _Right._Last == _Left || !_STD invoke(*_Right._Pred, *_Left); + } + + using _Prevent_inheriting_unwrap = _Sentinel; + + // clang-format off + _NODISCARD constexpr auto _Unwrapped() const& + requires _Wrapped && _Unwrappable_v&> { + // clang-format on + return _Sentinel<_Const, false>{_Get_unwrapped(_Last), _Pred}; + } + // clang-format off + _NODISCARD constexpr auto _Unwrapped() && requires _Wrapped && _Unwrappable_v> { + // clang-format on + return _Sentinel<_Const, false>{_Get_unwrapped(_STD move(_Last)), _Pred}; + } + + static constexpr bool _Unwrap_when_unverified = _Do_unwrap_when_unverified_v>; + + constexpr void _Seek_to(const _Sentinel<_Const, false>& _That) requires _Wrapped { + _Seek_wrapped(_Last, _That._Last); + } + constexpr void _Seek_to(_Sentinel<_Const, false>&& _That) requires _Wrapped { + _Seek_wrapped(_Last, _STD move(_That._Last)); + } + }; + + public: + take_while_view() = default; + + constexpr take_while_view(_Vw _Range_, _Pr _Pred_) noexcept( + is_nothrow_move_constructible_v<_Vw>&& is_nothrow_move_constructible_v<_Pr>) // strengthened + : _Range(_STD move(_Range_)), _Pred{in_place, _STD move(_Pred_)} {} + + _NODISCARD constexpr _Vw base() const& noexcept( + is_nothrow_copy_constructible_v<_Vw>) /* strengthened */ requires copy_constructible<_Vw> { + return _Range; + } + _NODISCARD constexpr _Vw base() && noexcept(is_nothrow_move_constructible_v<_Vw>) /* strengthened */ { + return _STD move(_Range); + } + + _NODISCARD constexpr const _Pr& pred() const noexcept /* strengthened */ { +#if _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_Pred, "value-initialized take_while_view has no predicate"); +#endif // _CONTAINER_DEBUG_LEVEL > 0 + return *_Pred; + } + + // clang-format off + _NODISCARD constexpr auto begin() noexcept( + noexcept(_RANGES begin(_Range))) /* strengthened */ requires (!_Simple_view<_Vw>) { + // clang-format on + return _RANGES begin(_Range); + } + + // clang-format off + _NODISCARD constexpr auto begin() const noexcept( + noexcept(_RANGES begin(_Range))) /* strengthened */ requires range + && indirect_unary_predicate> { + // clang-format on + return _RANGES begin(_Range); + } + + // clang-format off + _NODISCARD constexpr auto end() noexcept( + noexcept(_RANGES end(_Range)) && is_nothrow_move_constructible_v<_Sentinel>) /* strengthened */ + requires (!_Simple_view<_Vw>) { + // clang-format on +#if _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_Pred, "value-initialized take_while_view cannot call end"); +#endif // _CONTAINER_DEBUG_LEVEL > 0 + return _Sentinel{_RANGES end(_Range), _STD addressof(*_Pred)}; + } + + // clang-format off + _NODISCARD constexpr auto end() const noexcept( + noexcept(_RANGES end(_Range)) && is_nothrow_move_constructible_v<_Sentinel>) /* strengthened */ + requires range && indirect_unary_predicate> { + // clang-format on +#if _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_Pred, "value-initialized take_while_view cannot call end"); +#endif // _CONTAINER_DEBUG_LEVEL > 0 + return _Sentinel{_RANGES end(_Range), _STD addressof(*_Pred)}; + } + }; + + template + take_while_view(_Rng&&, _Pr) -> take_while_view, _Pr>; + + namespace views { + // VARIABLE views::take_while + class _Take_while_fn { + private: + template + struct _Partial : _Pipe::_Base<_Partial<_Pr>> { + /* [[no_unique_address]] */ _Semiregular_box<_Pr> _Pred; + + template + _NODISCARD constexpr auto operator()(_Rng&& _Range) const& noexcept( + noexcept(take_while_view{_STD forward<_Rng>(_Range), *_Pred})) requires requires { + take_while_view{static_cast<_Rng&&>(_Range), *_Pred}; + } + { return take_while_view{_STD forward<_Rng>(_Range), *_Pred}; } + + template + _NODISCARD constexpr auto operator()(_Rng&& _Range) && noexcept( + noexcept(take_while_view{_STD forward<_Rng>(_Range), _STD move(*_Pred)})) requires requires { + take_while_view{static_cast<_Rng&&>(_Range), _STD move(*_Pred)}; + } + { return take_while_view{_STD forward<_Rng>(_Range), _STD move(*_Pred)}; } + }; + + public: + template + _NODISCARD constexpr auto operator()(_Rng&& _Range, _Pr _Pred) const + noexcept(noexcept(take_while_view{_STD forward<_Rng>(_Range), _STD move(_Pred)})) requires requires { + take_while_view{static_cast<_Rng&&>(_Range), _STD move(_Pred)}; + } + { return take_while_view{_STD forward<_Rng>(_Range), _STD move(_Pred)}; } + + template <_Copy_constructible_object _Pr> + _NODISCARD constexpr auto operator()(_Pr _Pred) const noexcept(is_nothrow_move_constructible_v<_Pr>) { + return _Partial<_Pr>{._Pred = {in_place, _STD move(_Pred)}}; + } + }; + + inline constexpr _Take_while_fn take_while; + } // namespace views + // CLASS TEMPLATE ranges::drop_view template class drop_view : public _Cached_position_t && !(random_access_range<_Vw> && sized_range<_Vw>), @@ -1762,7 +2050,7 @@ namespace ranges { } // clang-format off - _NODISCARD constexpr auto begin() // constraints per proposed resolution of LWG-3482 + _NODISCARD constexpr auto begin() requires (!(_Simple_view<_Vw> && random_access_range && sized_range)) { // clang-format on if constexpr (sized_range<_Vw> && random_access_range<_Vw>) { @@ -1808,7 +2096,7 @@ namespace ranges { } // clang-format off - _NODISCARD constexpr auto begin() const // constraints per proposed resolution of LWG-3482 + _NODISCARD constexpr auto begin() const requires random_access_range && sized_range { // clang-format on const auto _Offset = (_STD min)(_RANGES distance(_Range), _Count); @@ -1894,14 +2182,16 @@ namespace ranges { _NODISCARD constexpr auto operator()(_Rng&& _Range, range_difference_t<_Rng> _Count) const noexcept( _Choice<_Rng>._No_throw) { // clang-format on - if constexpr (_Choice<_Rng>._Strategy == _St::_Empty) { + constexpr _St _Strat = _Choice<_Rng>._Strategy; + + if constexpr (_Strat == _St::_Empty) { // it's an empty_view: return another empty view return remove_cvref_t<_Rng>{}; - } else if constexpr (_Choice<_Rng>._Strategy == _St::_Preserve) { + } else if constexpr (_Strat == _St::_Preserve) { // it's a "reconstructible range"; return the same kind of range with a restricted extent _Count = (_STD min)(_RANGES distance(_Range), _Count); return remove_cvref_t<_Rng>{_RANGES begin(_Range) + _Count, _RANGES end(_Range)}; - } else if constexpr (_Choice<_Rng>._Strategy == _St::_Drop_view) { + } else if constexpr (_Strat == _St::_Drop_view) { return drop_view{_STD forward<_Rng>(_Range), _Count}; } } @@ -1913,24 +2203,69 @@ namespace ranges { }; inline constexpr _Drop_fn drop; + + // VARIABLE views::counted + class _Counted_fn { + private: + enum class _St { _Span, _Subrange, _Subrange_counted }; + + template + _NODISCARD static _CONSTEVAL _Choice_t<_St> _Choose() noexcept { + _STL_INTERNAL_STATIC_ASSERT(input_or_output_iterator<_It>); + if constexpr (contiguous_iterator<_It>) { + return {_St::_Span, noexcept(span{_STD to_address(_STD declval<_It>()), iter_difference_t<_It>{}})}; + } else if constexpr (random_access_iterator<_It>) { + return {_St::_Subrange, + noexcept(subrange{_STD declval<_It>(), _STD declval<_It>() + iter_difference_t<_It>{}})}; + } else { + return {_St::_Subrange_counted, + noexcept(subrange{ + counted_iterator{_STD declval<_It>(), iter_difference_t<_It>{}}, default_sentinel})}; + } + } + + template + static constexpr _Choice_t<_St> _Choice = _Choose<_It>(); + + public: + // clang-format off + template + requires input_or_output_iterator> + _NODISCARD constexpr auto operator()(_It&& _First, const iter_difference_t> _Count) const + noexcept(_Choice>._No_throw) { + // clang-format on + _STL_ASSERT(_Count >= 0, "The size passed to views::counted must be non-negative"); + constexpr _St _Strat = _Choice>._Strategy; + + if constexpr (_Strat == _St::_Span) { + return span{_STD to_address(_STD forward<_It>(_First)), static_cast(_Count)}; + } else if constexpr (_Strat == _St::_Subrange) { + return subrange{_First, _First + _Count}; + } else if constexpr (_Strat == _St::_Subrange_counted) { + return subrange{counted_iterator{_STD forward<_It>(_First), _Count}, default_sentinel}; + } + } + }; + + inline constexpr _Counted_fn counted; } // namespace views - // CLASS TEMPLATE ranges::reverse_view + // CLASS TEMPLATE ranges::drop_while_view // clang-format off - template - requires bidirectional_range<_Vw> - class reverse_view : public _Cached_position_t, _Vw, reverse_view<_Vw>> { + template + requires input_range<_Vw> && is_object_v<_Pr> && indirect_unary_predicate> + class drop_while_view : public _Cached_position_t, _Vw, drop_while_view<_Vw, _Pr>> { // clang-format on private: /* [[no_unique_address]] */ _Vw _Range{}; - - template - using _Rev_iter = reverse_iterator>; + /* [[no_unique_address]] */ _Semiregular_box<_Pr> _Pred{}; public: - reverse_view() = default; - constexpr explicit reverse_view(_Vw _Range_) noexcept(is_nothrow_move_constructible_v<_Vw>) // strengthened - : _Range(_STD move(_Range_)) {} + drop_while_view() = default; + + constexpr drop_while_view(_Vw _Range_, _Pr _Pred_) noexcept( + is_nothrow_move_constructible_v<_Vw>&& is_nothrow_move_constructible_v<_Pr>) // strengthened + : _Range(_STD move(_Range_)), _Pred{in_place, _STD move(_Pred_)} {} _NODISCARD constexpr _Vw base() const& noexcept( is_nothrow_copy_constructible_v<_Vw>) /* strengthened */ requires copy_constructible<_Vw> { @@ -1940,42 +2275,251 @@ namespace ranges { return _STD move(_Range); } - _NODISCARD constexpr _Rev_iter<_Vw> begin() { - if constexpr (common_range<_Vw>) { - return _Rev_iter<_Vw>{_RANGES end(_Range)}; - } else { + _NODISCARD constexpr const _Pr& pred() const noexcept /* strengthened */ { +#if _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_Pred, "value-initialized drop_while_view has no predicate"); +#endif // _CONTAINER_DEBUG_LEVEL > 0 + return *_Pred; + } + + _NODISCARD constexpr auto begin() { +#if _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_Pred, "LWG-3490 forbids calling begin on a drop_while_view with no predicate"); +#endif // _CONTAINER_DEBUG_LEVEL > 0 + if constexpr (forward_range<_Vw>) { if (this->_Has_cache()) { - return _Rev_iter<_Vw>{this->_Get_cache(_Range)}; + return this->_Get_cache(_Range); } + } - iterator_t<_Vw> _First; - if constexpr (sized_range<_Vw>) { - _First = _RANGES next(_RANGES begin(_Range), _RANGES distance(_Range)); - } else { - _First = _RANGES next(_RANGES begin(_Range), _RANGES end(_Range)); - } + auto _First = _RANGES find_if_not(_Range, _STD cref(*_Pred)); + if constexpr (forward_range<_Vw>) { this->_Set_cache(_Range, _First); - return _Rev_iter<_Vw>{_STD move(_First)}; } - } - _NODISCARD constexpr auto begin() const noexcept( - noexcept(_Rev_iter{_RANGES end(_Range)})) /* strengthened */ requires common_range { - return _Rev_iter{_RANGES end(_Range)}; + return _First; } - _NODISCARD constexpr _Rev_iter<_Vw> end() noexcept( - noexcept(_Rev_iter<_Vw>{_RANGES begin(_Range)})) /* strengthened */ { - return _Rev_iter<_Vw>{_RANGES begin(_Range)}; - } - _NODISCARD constexpr auto end() const noexcept( - noexcept(_Rev_iter{_RANGES begin(_Range)})) /* strengthened */ requires common_range { - return _Rev_iter{_RANGES begin(_Range)}; + _NODISCARD constexpr auto end() noexcept(noexcept(_RANGES end(_Range))) /* strengthened */ { + return _RANGES end(_Range); } + }; - _NODISCARD constexpr auto size() noexcept( - noexcept(_RANGES size(_Range))) /* strengthened */ requires sized_range<_Vw> { - return _RANGES size(_Range); + template + drop_while_view(_Rng&&, _Pr) -> drop_while_view, _Pr>; + + namespace views { + // VARIABLE views::drop_while + class _Drop_while_fn { + private: + template + struct _Partial : _Pipe::_Base<_Partial<_Pr>> { + /* [[no_unique_address]] */ _Semiregular_box<_Pr> _Pred; + + template + _NODISCARD constexpr auto operator()(_Rng&& _Range) const& noexcept( + noexcept(drop_while_view{_STD forward<_Rng>(_Range), *_Pred})) requires requires { + drop_while_view{static_cast<_Rng&&>(_Range), *_Pred}; + } + { return drop_while_view{_STD forward<_Rng>(_Range), *_Pred}; } + + template + _NODISCARD constexpr auto operator()(_Rng&& _Range) && noexcept( + noexcept(drop_while_view{_STD forward<_Rng>(_Range), _STD move(*_Pred)})) requires requires { + drop_while_view{static_cast<_Rng&&>(_Range), _STD move(*_Pred)}; + } + { return drop_while_view{_STD forward<_Rng>(_Range), _STD move(*_Pred)}; } + }; + + public: + template + _NODISCARD constexpr auto operator()(_Rng&& _Range, _Pr _Pred) const + noexcept(noexcept(drop_while_view{_STD forward<_Rng>(_Range), _STD move(_Pred)})) requires requires { + drop_while_view{static_cast<_Rng&&>(_Range), _STD move(_Pred)}; + } + { return drop_while_view{_STD forward<_Rng>(_Range), _STD move(_Pred)}; } + + template <_Copy_constructible_object _Pr> + _NODISCARD constexpr auto operator()(_Pr _Pred) const noexcept(is_nothrow_move_constructible_v<_Pr>) { + return _Partial<_Pr>{._Pred = {in_place, _STD move(_Pred)}}; + } + }; + + inline constexpr _Drop_while_fn drop_while; + } // namespace views + + // CLASS TEMPLATE ranges::common_view + // clang-format off + template + requires (!common_range<_Vw> && copyable>) + class common_view : public view_interface> { + // clang-format on + private: + /* [[no_unique_address]] */ _Vw _Base{}; + + public: + common_view() = default; + constexpr explicit common_view(_Vw _Base_) noexcept(is_nothrow_move_constructible_v<_Vw>) // strengthened + : _Base(_STD move(_Base_)) {} + + _NODISCARD constexpr _Vw base() const& noexcept( + is_nothrow_copy_constructible_v<_Vw>) /* strengthened */ requires copy_constructible<_Vw> { + return _Base; + } + _NODISCARD constexpr _Vw base() && noexcept(is_nothrow_move_constructible_v<_Vw>) /* strengthened */ { + return _STD move(_Base); + } + + _NODISCARD constexpr auto begin() noexcept( + noexcept(_RANGES begin(_Base)) && is_nothrow_move_constructible_v>) /* strengthened */ { + if constexpr (random_access_range<_Vw> && sized_range<_Vw>) { + return _RANGES begin(_Base); + } else { + return common_iterator, sentinel_t<_Vw>>{_RANGES begin(_Base)}; + } + } + + _NODISCARD constexpr auto begin() const noexcept( + noexcept(_RANGES begin(_Base)) + && is_nothrow_move_constructible_v>) /* strengthened */ requires range { + if constexpr (random_access_range && sized_range) { + return _RANGES begin(_Base); + } else { + return common_iterator, sentinel_t>{_RANGES begin(_Base)}; + } + } + + _NODISCARD constexpr auto end() { + if constexpr (random_access_range<_Vw> && sized_range<_Vw>) { + return _RANGES begin(_Base) + _RANGES size(_Base); + } else { + return common_iterator, sentinel_t<_Vw>>{_RANGES end(_Base)}; + } + } + + _NODISCARD constexpr auto end() const requires range { + if constexpr (random_access_range && sized_range) { + return _RANGES begin(_Base) + _RANGES size(_Base); + } else { + return common_iterator, sentinel_t>{_RANGES end(_Base)}; + } + } + + _NODISCARD constexpr auto size() noexcept( + noexcept(_RANGES size(_Base))) /* strengthened */ requires sized_range<_Vw> { + return _RANGES size(_Base); + } + _NODISCARD constexpr auto size() const + noexcept(noexcept(_RANGES size(_Base))) /* strengthened */ requires sized_range { + return _RANGES size(_Base); + } + }; + + template + common_view(_Rng &&) -> common_view>; + + namespace views { + // VARIABLE views::common + class _Common_fn : public _Pipe::_Base<_Common_fn> { + private: + enum class _St { _None, _All, _Common }; + + template + _NODISCARD static _CONSTEVAL _Choice_t<_St> _Choose() noexcept { + if constexpr (common_range<_Rng>) { + return {_St::_All, noexcept(views::all(_STD declval<_Rng>()))}; + } else if constexpr (copyable>) { + return {_St::_Common, noexcept(common_view{_STD declval<_Rng>()})}; + } else { + return {_St::_None}; + } + } + + template + static constexpr _Choice_t<_St> _Choice = _Choose<_Rng>(); + + public: + // clang-format off + template + requires (_Choice<_Rng>._Strategy != _St::_None) + _NODISCARD constexpr auto operator()(_Rng&& _Range) const noexcept(_Choice<_Rng>._No_throw) { + // clang-format on + constexpr _St _Strat = _Choice<_Rng>._Strategy; + + if constexpr (_Strat == _St::_All) { + return views::all(_STD forward<_Rng>(_Range)); + } else if constexpr (_Strat == _St::_Common) { + return common_view{_STD forward<_Rng>(_Range)}; + } else { + static_assert(_Always_false<_Rng>, "Should be unreachable"); + } + } + }; + + inline constexpr _Common_fn common; + } // namespace views + + // CLASS TEMPLATE ranges::reverse_view + // clang-format off + template + requires bidirectional_range<_Vw> + class reverse_view : public _Cached_position_t, _Vw, reverse_view<_Vw>> { + // clang-format on + private: + /* [[no_unique_address]] */ _Vw _Range{}; + + template + using _Rev_iter = reverse_iterator>; + + public: + reverse_view() = default; + constexpr explicit reverse_view(_Vw _Range_) noexcept(is_nothrow_move_constructible_v<_Vw>) // strengthened + : _Range(_STD move(_Range_)) {} + + _NODISCARD constexpr _Vw base() const& noexcept( + is_nothrow_copy_constructible_v<_Vw>) /* strengthened */ requires copy_constructible<_Vw> { + return _Range; + } + _NODISCARD constexpr _Vw base() && noexcept(is_nothrow_move_constructible_v<_Vw>) /* strengthened */ { + return _STD move(_Range); + } + + _NODISCARD constexpr _Rev_iter<_Vw> begin() { + if constexpr (common_range<_Vw>) { + return _Rev_iter<_Vw>{_RANGES end(_Range)}; + } else { + if (this->_Has_cache()) { + return _Rev_iter<_Vw>{this->_Get_cache(_Range)}; + } + + iterator_t<_Vw> _First; + if constexpr (sized_range<_Vw>) { + _First = _RANGES next(_RANGES begin(_Range), _RANGES distance(_Range)); + } else { + _First = _RANGES next(_RANGES begin(_Range), _RANGES end(_Range)); + } + this->_Set_cache(_Range, _First); + return _Rev_iter<_Vw>{_STD move(_First)}; + } + } + + _NODISCARD constexpr auto begin() const noexcept( + noexcept(_Rev_iter{_RANGES end(_Range)})) /* strengthened */ requires common_range { + return _Rev_iter{_RANGES end(_Range)}; + } + + _NODISCARD constexpr _Rev_iter<_Vw> end() noexcept( + noexcept(_Rev_iter<_Vw>{_RANGES begin(_Range)})) /* strengthened */ { + return _Rev_iter<_Vw>{_RANGES begin(_Range)}; + } + _NODISCARD constexpr auto end() const noexcept( + noexcept(_Rev_iter{_RANGES begin(_Range)})) /* strengthened */ requires common_range { + return _Rev_iter{_RANGES begin(_Range)}; + } + + _NODISCARD constexpr auto size() noexcept( + noexcept(_RANGES size(_Range))) /* strengthened */ requires sized_range<_Vw> { + return _RANGES size(_Range); } _NODISCARD constexpr auto size() const noexcept(noexcept(_RANGES size(_Range))) /* strengthened */ requires sized_range { @@ -2043,13 +2587,15 @@ namespace ranges { requires (_Choice<_Rng>._Strategy != _St::_None) _NODISCARD constexpr auto operator()(_Rng&& _Range) const noexcept(_Choice<_Rng>._No_throw) { // clang-format on - if constexpr (_Choice<_Rng>._Strategy == _St::_Base) { + constexpr _St _Strat = _Choice<_Rng>._Strategy; + + if constexpr (_Strat == _St::_Base) { return _STD forward<_Rng>(_Range).base(); - } else if constexpr (_Choice<_Rng>._Strategy == _St::_Subrange_unsized) { + } else if constexpr (_Strat == _St::_Subrange_unsized) { return subrange{_Range.end().base(), _Range.begin().base()}; - } else if constexpr (_Choice<_Rng>._Strategy == _St::_Subrange_sized) { + } else if constexpr (_Strat == _St::_Subrange_sized) { return subrange{_Range.end().base(), _Range.begin().base(), _Range.size()}; - } else if constexpr (_Choice<_Rng>._Strategy == _St::_Reverse) { + } else if constexpr (_Strat == _St::_Reverse) { return reverse_view{_STD forward<_Rng>(_Range)}; } else { static_assert(_Always_false<_Rng>, "Should be unreachable"); @@ -2059,6 +2605,381 @@ namespace ranges { inline constexpr _Reverse_fn reverse; } // namespace views + + // CLASS TEMPLATE ranges::elements_view + template + concept _Has_tuple_element = requires(_Tuple __t) { + typename tuple_size<_Tuple>::type; + requires _Index < tuple_size_v<_Tuple>; + typename tuple_element_t<_Index, _Tuple>; + // clang-format off + { _STD get<_Index>(__t) } -> convertible_to&>; + // clang-format on + }; + + // clang-format off + template + requires view<_Vw> && _Has_tuple_element, _Index> + && _Has_tuple_element>, _Index> + class elements_view : public view_interface> { + // clang-format on + private: + /* [[no_unique_address]] */ _Vw _Range{}; + + template + class _Sentinel; + + template // TRANSITION, LWG-3289 + struct _Category_base {}; + + // clang-format off + template <_Has_member_iterator_category _Traits> + struct _Category_base<_Traits> { + // clang-format on + using iterator_category = typename _Traits::iterator_category; + }; + + template + class _Iterator : public _Category_base>> { + private: + template + friend class _Iterator; + template + friend class _Sentinel; + + using _Base = _Maybe_const<_Const, _Vw>; + + iterator_t<_Base> _Current{}; + + public: + using iterator_concept = conditional_t, random_access_iterator_tag, + conditional_t, bidirectional_iterator_tag, + conditional_t, forward_iterator_tag, input_iterator_tag>>>; + using value_type = remove_cvref_t>>; + using difference_type = range_difference_t<_Base>; + + _Iterator() = default; + + constexpr explicit _Iterator(iterator_t<_Base> _Current_) noexcept( + is_nothrow_move_constructible_v>) // strengthened + : _Current{_STD move(_Current_)} {} + + // clang-format off + constexpr _Iterator(_Iterator _It) noexcept( + is_nothrow_constructible_v, iterator_t<_Vw>>) // strengthened + requires _Const && convertible_to, iterator_t<_Base>> + : _Current{_STD move(_It._Current)} {} + // clang-format on + + _NODISCARD constexpr iterator_t<_Base> base() const& noexcept( + is_nothrow_copy_constructible_v>) /* strengthened */ + requires copyable> { + return _Current; + } + + _NODISCARD constexpr iterator_t<_Base> base() && noexcept( + is_nothrow_move_constructible_v>) /* strengthened */ { + return _STD move(_Current); + } + + _NODISCARD constexpr decltype(auto) operator*() const + noexcept(noexcept(_STD get<_Index>(*_Current))) /* strengthened */ { + return _STD get<_Index>(*_Current); + } + + constexpr _Iterator& operator++() noexcept(noexcept(++_Current)) /* strengthened */ { + ++_Current; + return *this; + } + + constexpr void operator++(int) noexcept(noexcept(++_Current)) /* strengthened */ { + // Constraint removed per LWG-3492 + ++_Current; + } + + constexpr _Iterator operator++(int) noexcept( + noexcept(++_Current) && is_nothrow_copy_constructible_v>) /* strengthened */ + requires forward_range<_Base> { + auto _Tmp = *this; + ++_Current; + return _Tmp; + } + + constexpr _Iterator& operator--() noexcept(noexcept(--_Current)) /* strengthened */ + requires bidirectional_range<_Base> { + --_Current; + return *this; + } + + constexpr _Iterator operator--(int) noexcept( + noexcept(--_Current) && is_nothrow_copy_constructible_v>) /* strengthened */ + requires bidirectional_range<_Base> { + auto _Tmp = *this; + --_Current; + return _Tmp; + } + + constexpr void _Verify_offset(const difference_type _Off) const requires random_access_range<_Base> { +#if _ITERATOR_DEBUG_LEVEL != 0 + (void) _Off; +#else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 / _ITERATOR_DEBUG_LEVEL != 0 vvv + if constexpr (_Offset_verifiable_v>) { + _Current._Verify_offset(_Off); + } +#endif // _ITERATOR_DEBUG_LEVEL == 0 + } + + constexpr _Iterator& operator+=(const difference_type _Off) noexcept( + noexcept(_Current += _Off)) /* strengthened */ requires random_access_range<_Base> { +#if _ITERATOR_DEBUG_LEVEL != 0 + _Verify_offset(_Off); +#endif // _ITERATOR_DEBUG_LEVEL != 0 + _Current += _Off; + return *this; + } + constexpr _Iterator& operator-=(const difference_type _Off) noexcept( + noexcept(_Current -= _Off)) /* strengthened */ requires random_access_range<_Base> { +#if _ITERATOR_DEBUG_LEVEL != 0 + _Verify_offset(-_Off); +#endif // _ITERATOR_DEBUG_LEVEL != 0 + _Current -= _Off; + return *this; + } + + _NODISCARD constexpr decltype(auto) operator[](const difference_type _Idx) const + noexcept(noexcept(_STD get<_Index>(*(_Current + _Idx)))) /* strengthened */ + requires random_access_range<_Base> { +#if _ITERATOR_DEBUG_LEVEL != 0 + _Verify_offset(_Idx); +#endif // _ITERATOR_DEBUG_LEVEL != 0 + return _STD get<_Index>(*(_Current + _Idx)); + } + + _NODISCARD friend constexpr bool operator==(const _Iterator& _Left, const _Iterator& _Right) noexcept( + noexcept(_Left._Current == _Right._Current)) /* strengthened */ + requires equality_comparable> { + return _Left._Current == _Right._Current; + } + + _NODISCARD friend constexpr bool operator<(const _Iterator& _Left, const _Iterator& _Right) noexcept( + noexcept(_Left._Current < _Right._Current)) /* strengthened */ requires random_access_range<_Base> { + return _Left._Current < _Right._Current; + } + _NODISCARD friend constexpr bool operator>(const _Iterator& _Left, const _Iterator& _Right) noexcept( + noexcept(_Left._Current < _Right._Current)) /* strengthened */ requires random_access_range<_Base> { + return _Right < _Left; + } + _NODISCARD friend constexpr bool operator<=(const _Iterator& _Left, const _Iterator& _Right) noexcept( + noexcept(_Left._Current < _Right._Current)) /* strengthened */ requires random_access_range<_Base> { + return !(_Right < _Left); + } + _NODISCARD friend constexpr bool operator>=(const _Iterator& _Left, const _Iterator& _Right) noexcept( + noexcept(_Left._Current < _Right._Current)) /* strengthened */ requires random_access_range<_Base> { + return !(_Left < _Right); + } + + // clang-format off + _NODISCARD friend constexpr auto operator<=>(const _Iterator& _Left, const _Iterator& _Right) noexcept( + noexcept(_Left._Current <=> _Right._Current)) /* strengthened */ + requires random_access_range<_Base> && three_way_comparable> { + // clang-format on + return _Left._Current <=> _Right._Current; + } + + _NODISCARD friend constexpr _Iterator operator+(const _Iterator& _It, const difference_type _Off) noexcept( + noexcept(_STD declval&>() += _Off) + && is_nothrow_copy_constructible_v>) /* strengthened */ + requires random_access_range<_Base> { +#if _ITERATOR_DEBUG_LEVEL != 0 + _It._Verify_offset(_Off); +#endif // _ITERATOR_DEBUG_LEVEL != 0 + auto _Copy = _It; + _Copy._Current += _Off; + return _Copy; + } + + _NODISCARD friend constexpr _Iterator operator+(const difference_type _Off, const _Iterator& _It) noexcept( + noexcept(_STD declval&>() += _Off) + && is_nothrow_copy_constructible_v>) /* strengthened */ + requires random_access_range<_Base> { +#if _ITERATOR_DEBUG_LEVEL != 0 + _It._Verify_offset(_Off); +#endif // _ITERATOR_DEBUG_LEVEL != 0 + auto _Copy = _It; + _Copy._Current += _Off; + return _Copy; + } + + _NODISCARD friend constexpr _Iterator operator-(const _Iterator& _It, const difference_type _Off) noexcept( + noexcept(_STD declval&>() -= _Off) + && is_nothrow_copy_constructible_v>) /* strengthened */ + requires random_access_range<_Base> { +#if _ITERATOR_DEBUG_LEVEL != 0 + _It._Verify_offset(-_Off); +#endif // _ITERATOR_DEBUG_LEVEL != 0 + auto _Copy = _It; + _Copy._Current -= _Off; + return _Copy; + } + + _NODISCARD friend constexpr difference_type operator-(const _Iterator& _Left, + const _Iterator& _Right) noexcept(noexcept(_Left._Current - _Right._Current)) /* strengthened */ + requires sized_sentinel_for, iterator_t<_Base>> { + return _Left._Current - _Right._Current; + } + }; + + template + class _Sentinel { + private: + template + friend class _Sentinel; + + using _Base = _Maybe_const<_Const, _Vw>; + + sentinel_t<_Base> _Last{}; + + template + _NODISCARD static constexpr const iterator_t<_Maybe_const<_OtherConst, _Vw>>& _Get_current( + const _Iterator<_OtherConst>& _It) noexcept { + return _It._Current; + } + + public: + _Sentinel() = default; + constexpr explicit _Sentinel(sentinel_t<_Base> _Last_) noexcept( + is_nothrow_move_constructible_v>) // strengthened + : _Last(_STD move(_Last_)) {} + + // clang-format off + constexpr _Sentinel(_Sentinel _Se) + noexcept(is_nothrow_constructible_v, sentinel_t<_Vw>>) // strengthened + requires _Const && convertible_to, sentinel_t<_Base>> + : _Last(_STD move(_Se._Last)) {} + // clang-format on + + _NODISCARD constexpr sentinel_t<_Base> base() const + noexcept(is_nothrow_copy_constructible_v>) /* strengthened */ { + return _Last; + } + + // clang-format off + template + requires sentinel_for, iterator_t<_Maybe_const<_OtherConst, _Vw>>> + _NODISCARD friend constexpr bool operator==(const _Iterator<_OtherConst>& _Left, + const _Sentinel& _Right) noexcept(noexcept(_Get_current(_Left) == _Right._Last)) /* strengthened */ { + // clang-format on + return _Get_current(_Left) == _Right._Last; + } + + // clang-format off + template + requires sized_sentinel_for, iterator_t<_Maybe_const<_OtherConst, _Vw>>> + _NODISCARD friend constexpr range_difference_t<_Maybe_const<_OtherConst, _Vw>> operator-( + const _Iterator<_OtherConst>& _Left, const _Sentinel& _Right) noexcept( + noexcept(_Get_current(_Left) - _Right._Last)) /* strengthened */ { + // clang-format on + return _Get_current(_Left) - _Right._Last; + } + + // clang-format off + template + requires sized_sentinel_for, iterator_t<_Maybe_const<_OtherConst, _Vw>>> + _NODISCARD friend constexpr range_difference_t<_Maybe_const<_OtherConst, _Vw>> operator-( + const _Sentinel& _Left, const _Iterator<_OtherConst>& _Right) noexcept( + noexcept(_Left._Last - _Get_current(_Right))) /* strengthened */ { + // clang-format on + return _Left._Last - _Get_current(_Right); + } + }; + + public: + elements_view() = default; + + constexpr explicit elements_view(_Vw _Range_) noexcept(is_nothrow_move_constructible_v<_Vw>) // strengthened + : _Range(_STD move(_Range_)) {} + + _NODISCARD constexpr _Vw base() const& noexcept(is_nothrow_copy_constructible_v<_Vw>) /* strengthened */ + requires copy_constructible<_Vw> { + return _Range; + } + + _NODISCARD constexpr _Vw base() && noexcept(is_nothrow_move_constructible_v<_Vw>) /* strengthened */ { + return _STD move(_Range); + } + + // clang-format off + _NODISCARD constexpr _Iterator begin() noexcept( + noexcept(_RANGES begin(_Range)) && is_nothrow_move_constructible_v>) /* strengthened */ + requires (!_Simple_view<_Vw>) { + // clang-format on + return _Iterator{_RANGES begin(_Range)}; + } + + _NODISCARD constexpr _Iterator begin() const + noexcept(noexcept(_RANGES begin(_Range)) + && is_nothrow_move_constructible_v>) /* strengthened */ + requires range { + return _Iterator{_RANGES begin(_Range)}; + } + + // clang-format off + _NODISCARD constexpr auto end() noexcept(noexcept( + _RANGES end(_Range)) && is_nothrow_move_constructible_v>) /* strengthened */ + requires (!_Simple_view<_Vw>) { + // clang-format on + if constexpr (common_range<_Vw>) { + return _Iterator{_RANGES end(_Range)}; + } else { + return _Sentinel{_RANGES end(_Range)}; + } + } + + // clang-format off + _NODISCARD constexpr auto end() const noexcept(noexcept( + _RANGES end(_Range)) && is_nothrow_move_constructible_v>) /* strengthened */ + requires range { + // clang-format on + if constexpr (common_range) { + return _Iterator{_RANGES end(_Range)}; + } else { + return _Sentinel{_RANGES end(_Range)}; + } + } + + _NODISCARD constexpr auto size() noexcept(noexcept(_RANGES size(_Range))) /* strengthened */ + requires sized_range<_Vw> { + return _RANGES size(_Range); + } + _NODISCARD constexpr auto size() const noexcept(noexcept(_RANGES size(_Range))) /* strengthened */ + requires sized_range { + return _RANGES size(_Range); + } + }; + + template + using keys_view = elements_view, 0>; + template + using values_view = elements_view, 1>; + + namespace views { + // VARIABLE views::elements + template + class _Elements_fn : public _Pipe::_Base<_Elements_fn<_Index>> { + public: + template + _NODISCARD constexpr auto operator()(_Rng&& _Range) const noexcept( + noexcept(elements_view, _Index>{_STD forward<_Rng>(_Range)})) requires requires { + elements_view, _Index>{static_cast<_Rng&&>(_Range)}; + } + { return elements_view, _Index>{_STD forward<_Rng>(_Range)}; } + }; + + template + inline constexpr _Elements_fn<_Index> elements; + inline constexpr auto keys = elements<0>; + inline constexpr auto values = elements<1>; + } // namespace views } // namespace ranges namespace views = ranges::views; diff --git a/stl/inc/ratio b/stl/inc/ratio index d290147f24a..0a1b09f7619 100644 --- a/stl/inc/ratio +++ b/stl/inc/ratio @@ -8,7 +8,7 @@ #define _RATIO_ #include #if _STL_COMPILER_PREPROCESSOR -#include +#include #include #pragma pack(push, _CRT_PACKING) diff --git a/stl/inc/semaphore b/stl/inc/semaphore index 0845bdf00f3..79d2760603b 100644 --- a/stl/inc/semaphore +++ b/stl/inc/semaphore @@ -19,7 +19,7 @@ #include #include -#include +#include #pragma pack(push, _CRT_PACKING) #pragma warning(push, _STL_WARNING_LEVEL) diff --git a/stl/inc/string b/stl/inc/string index 09802c114e1..72d3cebb2d8 100644 --- a/stl/inc/string +++ b/stl/inc/string @@ -448,7 +448,7 @@ inline long double stold(const wstring& _Str, size_t* _Idx = nullptr) { // conve return _Ans; } -// HELPERS FOR to_string AND to_wstring +// HELPERS FOR to_string AND to_wstring AND operator<<(duration) template _Elem* _UIntegral_to_buff(_Elem* _RNext, _UTy _UVal) { // format _UVal into buffer *ending at* _RNext static_assert(is_unsigned_v<_UTy>, "_UTy must be unsigned"); diff --git a/stl/inc/tuple b/stl/inc/tuple index ee6f40fb1e2..bdb3aaed54d 100644 --- a/stl/inc/tuple +++ b/stl/inc/tuple @@ -8,7 +8,6 @@ #define _TUPLE_ #include #if _STL_COMPILER_PREPROCESSOR -#include #include #include @@ -685,6 +684,9 @@ public: template friend constexpr const tuple_element_t<_Index, tuple<_Types...>>&& get(const tuple<_Types...>&& _Tuple) noexcept; + template + friend constexpr auto&& _Tuple_get(tuple<_Types...>&& _Tuple) noexcept; + template friend constexpr _Ty& get(tuple<_Types...>& _Tuple) noexcept; @@ -797,6 +799,14 @@ _NODISCARD constexpr const tuple_element_t<_Index, tuple<_Types...>>&& get(const return static_cast(static_cast(_Tuple)._Myfirst._Val); } +template +_NODISCARD constexpr auto&& _Tuple_get(tuple<_Types...>&& _Tuple) noexcept { + // used by pair's piecewise constructor + using _Ty = tuple_element_t<_Index, tuple<_Types...>>; + using _Ttype = typename tuple_element<_Index, tuple<_Types...>>::_Ttype; + return static_cast<_Ty&&>(static_cast<_Ttype&>(_Tuple)._Myfirst._Val); +} + // FUNCTION TEMPLATE get (by type) template _NODISCARD constexpr _Ty& get(tuple<_Types...>& _Tuple) noexcept { @@ -972,19 +982,6 @@ _NODISCARD constexpr _Ty make_from_tuple(_Tuple&& _Tpl) { // construct _Ty from } #endif // _HAS_CXX17 -// TEMPLATE CONSTRUCTOR pair::pair(tuple, tuple, sequence, sequence) -template -template -constexpr pair<_Ty1, _Ty2>::pair( - _Tuple1& _Val1, _Tuple2& _Val2, index_sequence<_Indexes1...>, index_sequence<_Indexes2...>) - : first(_STD get<_Indexes1>(_STD move(_Val1))...), second(_STD get<_Indexes2>(_STD move(_Val2))...) {} - -// TEMPLATE CONSTRUCTOR pair::pair(piecewise_construct_t, tuple, tuple) -template -template -_CONSTEXPR20 pair<_Ty1, _Ty2>::pair(piecewise_construct_t, tuple<_Types1...> _Val1, tuple<_Types2...> _Val2) - : pair(_Val1, _Val2, index_sequence_for<_Types1...>{}, index_sequence_for<_Types2...>{}) {} - // STRUCT TEMPLATE uses_allocator template struct uses_allocator, _Alloc> : true_type {}; // true_type if container allocator enabled diff --git a/stl/inc/type_traits b/stl/inc/type_traits index cae9e1b0baf..e978fe15e20 100644 --- a/stl/inc/type_traits +++ b/stl/inc/type_traits @@ -8,6 +8,7 @@ #define _TYPE_TRAITS_ #include #if _STL_COMPILER_PREPROCESSOR +#include #include #pragma pack(push, _CRT_PACKING) @@ -2272,6 +2273,56 @@ template struct _Is_nothrow_hashable<_Kty, void_t{}(_STD declval()))>> : bool_constant{}(_STD declval()))> {}; +// vvvvvvvvvv DERIVED FROM corecrt_internal_fltintrn.h vvvvvvvvvv + +template +struct _Floating_type_traits; + +template <> +struct _Floating_type_traits { + static constexpr int32_t _Mantissa_bits = 24; // FLT_MANT_DIG + static constexpr int32_t _Exponent_bits = 8; // sizeof(float) * CHAR_BIT - FLT_MANT_DIG + static constexpr int32_t _Maximum_binary_exponent = 127; // FLT_MAX_EXP - 1 + static constexpr int32_t _Minimum_binary_exponent = -126; // FLT_MIN_EXP - 1 + static constexpr int32_t _Exponent_bias = 127; + static constexpr int32_t _Sign_shift = 31; // _Exponent_bits + _Mantissa_bits - 1 + static constexpr int32_t _Exponent_shift = 23; // _Mantissa_bits - 1 + + using _Uint_type = uint32_t; + + static constexpr uint32_t _Exponent_mask = 0x000000FFu; // (1u << _Exponent_bits) - 1 + static constexpr uint32_t _Normal_mantissa_mask = 0x00FFFFFFu; // (1u << _Mantissa_bits) - 1 + static constexpr uint32_t _Denormal_mantissa_mask = 0x007FFFFFu; // (1u << (_Mantissa_bits - 1)) - 1 + static constexpr uint32_t _Special_nan_mantissa_mask = 0x00400000u; // 1u << (_Mantissa_bits - 2) + static constexpr uint32_t _Shifted_sign_mask = 0x80000000u; // 1u << _Sign_shift + static constexpr uint32_t _Shifted_exponent_mask = 0x7F800000u; // _Exponent_mask << _Exponent_shift +}; + +template <> +struct _Floating_type_traits { + static constexpr int32_t _Mantissa_bits = 53; // DBL_MANT_DIG + static constexpr int32_t _Exponent_bits = 11; // sizeof(double) * CHAR_BIT - DBL_MANT_DIG + static constexpr int32_t _Maximum_binary_exponent = 1023; // DBL_MAX_EXP - 1 + static constexpr int32_t _Minimum_binary_exponent = -1022; // DBL_MIN_EXP - 1 + static constexpr int32_t _Exponent_bias = 1023; + static constexpr int32_t _Sign_shift = 63; // _Exponent_bits + _Mantissa_bits - 1 + static constexpr int32_t _Exponent_shift = 52; // _Mantissa_bits - 1 + + using _Uint_type = uint64_t; + + static constexpr uint64_t _Exponent_mask = 0x00000000000007FFu; // (1ULL << _Exponent_bits) - 1 + static constexpr uint64_t _Normal_mantissa_mask = 0x001FFFFFFFFFFFFFu; // (1ULL << _Mantissa_bits) - 1 + static constexpr uint64_t _Denormal_mantissa_mask = 0x000FFFFFFFFFFFFFu; // (1ULL << (_Mantissa_bits - 1)) - 1 + static constexpr uint64_t _Special_nan_mantissa_mask = 0x0008000000000000u; // 1ULL << (_Mantissa_bits - 2) + static constexpr uint64_t _Shifted_sign_mask = 0x8000000000000000u; // 1ULL << _Sign_shift + static constexpr uint64_t _Shifted_exponent_mask = 0x7FF0000000000000u; // _Exponent_mask << _Exponent_shift +}; + +template <> +struct _Floating_type_traits : _Floating_type_traits {}; + +// ^^^^^^^^^^ DERIVED FROM corecrt_internal_fltintrn.h ^^^^^^^^^^ + #if _HAS_TR1_NAMESPACE _STL_DISABLE_DEPRECATED_WARNING namespace _DEPRECATE_TR1_NAMESPACE tr1 { diff --git a/stl/inc/utility b/stl/inc/utility index 53e38b608af..cc191b85356 100644 --- a/stl/inc/utility +++ b/stl/inc/utility @@ -123,6 +123,9 @@ _INLINE_VAR constexpr piecewise_construct_t piecewise_construct{}; template class tuple; +template +_NODISCARD constexpr auto&& _Tuple_get(tuple<_Types...>&& _Tuple) noexcept; + template struct pair { // store a pair of values using first_type = _Ty1; @@ -263,10 +266,12 @@ struct pair { // store a pair of values #endif // ^^^ !_HAS_CONDITIONAL_EXPLICIT ^^^ template - constexpr pair(_Tuple1& _Val1, _Tuple2& _Val2, index_sequence<_Indexes1...>, index_sequence<_Indexes2...>); + constexpr pair(_Tuple1& _Val1, _Tuple2& _Val2, index_sequence<_Indexes1...>, index_sequence<_Indexes2...>) + : first(_Tuple_get<_Indexes1>(_STD move(_Val1))...), second(_Tuple_get<_Indexes2>(_STD move(_Val2))...) {} template - _CONSTEXPR20 pair(piecewise_construct_t, tuple<_Types1...> _Val1, tuple<_Types2...> _Val2); + _CONSTEXPR20 pair(piecewise_construct_t, tuple<_Types1...> _Val1, tuple<_Types2...> _Val2) + : pair(_Val1, _Val2, index_sequence_for<_Types1...>{}, index_sequence_for<_Types2...>{}) {} pair& operator=(const volatile pair&) = delete; diff --git a/stl/inc/xatomic.h b/stl/inc/xatomic.h index 3298d828ae8..af41c5af67a 100644 --- a/stl/inc/xatomic.h +++ b/stl/inc/xatomic.h @@ -11,9 +11,6 @@ #include #include -#if defined(_WIN64) && (_MSC_FULL_VER <= 192829213) // TRANSITION -#include // Visual Studio 2019 to define 128-bit CAS in -#endif // defined(_WIN64) && (_MSC_FULL_VER <= 192829213), TRANSITION #pragma pack(push, _CRT_PACKING) #pragma warning(push, _STL_WARNING_LEVEL) diff --git a/stl/inc/xatomic_wait.h b/stl/inc/xatomic_wait.h index caeb3fdaf9d..42378ea39d3 100644 --- a/stl/inc/xatomic_wait.h +++ b/stl/inc/xatomic_wait.h @@ -9,7 +9,7 @@ #include #if _STL_COMPILER_PREPROCESSOR -#include +#include #include #pragma pack(push, _CRT_PACKING) diff --git a/stl/inc/xcharconv.h b/stl/inc/xcharconv.h index 9305de5505d..ecd69b6d02e 100644 --- a/stl/inc/xcharconv.h +++ b/stl/inc/xcharconv.h @@ -9,7 +9,7 @@ #include #if _STL_COMPILER_PREPROCESSOR -#include +#include #include #include diff --git a/stl/inc/xcharconv_ryu.h b/stl/inc/xcharconv_ryu.h index def634d2273..1b2b95a8e05 100644 --- a/stl/inc/xcharconv_ryu.h +++ b/stl/inc/xcharconv_ryu.h @@ -38,7 +38,7 @@ #include #if _STL_COMPILER_PREPROCESSOR -#include +#include #include #include diff --git a/stl/inc/xcharconv_ryu_tables.h b/stl/inc/xcharconv_ryu_tables.h index cea6fd2b5a8..508d3479fdf 100644 --- a/stl/inc/xcharconv_ryu_tables.h +++ b/stl/inc/xcharconv_ryu_tables.h @@ -38,7 +38,7 @@ #include #if _STL_COMPILER_PREPROCESSOR -#include +#include #if !_HAS_CXX17 #error The contents of are only available with C++17. (Also, you should not include this internal header.) diff --git a/stl/inc/xfilesystem_abi.h b/stl/inc/xfilesystem_abi.h index 7991c1d522e..52f8c8f7404 100644 --- a/stl/inc/xfilesystem_abi.h +++ b/stl/inc/xfilesystem_abi.h @@ -9,7 +9,7 @@ #include #if _STL_COMPILER_PREPROCESSOR -#include +#include #include #pragma pack(push, _CRT_PACKING) diff --git a/stl/inc/xiosbase b/stl/inc/xiosbase index e56578a265b..bf5bf3a072e 100644 --- a/stl/inc/xiosbase +++ b/stl/inc/xiosbase @@ -454,7 +454,7 @@ public: static void __CLRCALL_PURE_OR_CDECL _Addstd(ios_base*); // add standard stream - size_t _Stdstr; // if > 0 index of standard stream to suppress destruction + size_t _Stdstr{0}; // if > 0 index of standard stream to suppress destruction protected: __CLR_OR_THIS_CALL ios_base() {} @@ -547,9 +547,9 @@ private: fmtflags _Fmtfl; // format flags streamsize _Prec; // field precision streamsize _Wide; // field width - _Iosarray* _Arr; // pointer to first node of long/pointer array - _Fnarray* _Calls; // pointer to first node of call list - locale* _Ploc; // pointer to locale + _Iosarray* _Arr{nullptr}; // pointer to first node of long/pointer array + _Fnarray* _Calls{nullptr}; // pointer to first node of call list + locale* _Ploc{nullptr}; // pointer to locale __PURE_APPDOMAIN_GLOBAL static int _Index; __PURE_APPDOMAIN_GLOBAL static bool _Sync; diff --git a/stl/inc/xlocinfo.h b/stl/inc/xlocinfo.h index 9891775d16a..f3e36738c9c 100644 --- a/stl/inc/xlocinfo.h +++ b/stl/inc/xlocinfo.h @@ -9,10 +9,10 @@ #include #if _STL_COMPILER_PREPROCESSOR -#include -#include -#include // TRANSITION, VSO-661721 -#include +#include +#include +#include // TRANSITION, VSO-661721 +#include #pragma pack(push, _CRT_PACKING) #pragma warning(push, _STL_WARNING_LEVEL) diff --git a/stl/inc/xloctime b/stl/inc/xloctime index 1dbf298843e..55cb9f0df2d 100644 --- a/stl/inc/xloctime +++ b/stl/inc/xloctime @@ -539,6 +539,8 @@ protected: private: ios_base::iostate __CLRCALL_OR_CDECL _Getint(_InIt& _First, _InIt& _Last, int _Lo, int _Hi, int& _Val, const _Ctype& _Ctype_fac) const { // get integer in range [_Lo, _Hi] from [_First, _Last) + _STL_INTERNAL_CHECK(0 <= _Hi && _Hi <= 9999); + const int _Hi_digits = (_Hi <= 9 ? 1 : _Hi <= 99 ? 2 : _Hi <= 999 ? 3 : 4); char _Ac[_MAX_INT_DIG]; char* _Ep; char* _Ptr = _Ac; @@ -554,26 +556,26 @@ private: } } - bool _Seendigit = false; + int _Digits_seen = 0; for (; _First != _Last && _Ctype_fac.narrow(*_First) == '0'; ++_First) { // strip leading zeros - _Seendigit = true; + ++_Digits_seen; } - if (_Seendigit) { + if (_Digits_seen > 0) { *_Ptr++ = '0'; // replace one or more with single zero } for (char* const _Pe = &_Ac[_MAX_INT_DIG - 1]; - _First != _Last && '0' <= (_Ch = _Ctype_fac.narrow(*_First)) && _Ch <= '9'; - _Seendigit = true, (void) ++_First) { // copy digits + _First != _Last && '0' <= (_Ch = _Ctype_fac.narrow(*_First)) && _Ch <= '9' && _Digits_seen < _Hi_digits; + ++_Digits_seen, (void) ++_First) { // copy digits *_Ptr = _Ch; if (_Ptr < _Pe) { ++_Ptr; // drop trailing digits if already too large } } - if (!_Seendigit) { + if (_Digits_seen == 0) { _Ptr = _Ac; } diff --git a/stl/inc/xmemory b/stl/inc/xmemory index 61482e6f834..0d9926f45d4 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -397,7 +397,7 @@ struct _Get_propagate_on_container_swap<_Ty, void_t struct _Get_is_always_equal { - using type = typename is_empty<_Ty>::type; + using type = bool_constant>; }; template @@ -1737,6 +1737,12 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_fill_n( _Fill_memset(_Unfancy(_First), _Val, static_cast(_Count)); return _First + _Count; } else { + if constexpr (_Fill_zero_memset_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value) { + if (_Is_all_bits_zero(_Val)) { + _Fill_zero_memset(_Unfancy(_First), static_cast(_Count)); + return _First + _Count; + } + } _Uninitialized_backout_al<_Alloc> _Backout{_First, _Al}; for (; 0 < _Count; --_Count) { _Backout._Emplace_back(_Val); @@ -1787,6 +1793,12 @@ void uninitialized_fill(const _NoThrowFwdIt _First, const _NoThrowFwdIt _Last, c if constexpr (_Fill_memset_is_safe<_Unwrapped_t, _Tval>) { _Fill_memset(_UFirst, _Val, static_cast(_ULast - _UFirst)); } else { + if constexpr (_Fill_zero_memset_is_safe<_Unwrapped_t, _Tval>) { + if (_Is_all_bits_zero(_Val)) { + _Fill_zero_memset(_UFirst, static_cast(_ULast - _UFirst)); + return; + } + } _Uninitialized_backout<_Unwrapped_t> _Backout{_UFirst}; while (_Backout._Last != _ULast) { _Backout._Emplace_back(_Val); diff --git a/stl/inc/xthreads.h b/stl/inc/xthreads.h index f2d95ff63d4..c8c88800575 100644 --- a/stl/inc/xthreads.h +++ b/stl/inc/xthreads.h @@ -8,7 +8,7 @@ #define _THR_XTHREADS_H #include #if _STL_COMPILER_PREPROCESSOR -#include +#include #include #pragma pack(push, _CRT_PACKING) diff --git a/stl/inc/xtimec.h b/stl/inc/xtimec.h index 67b75522d16..64741469db9 100644 --- a/stl/inc/xtimec.h +++ b/stl/inc/xtimec.h @@ -9,7 +9,7 @@ #include #if _STL_COMPILER_PREPROCESSOR -#include +#include #pragma pack(push, _CRT_PACKING) #pragma warning(push, _STL_WARNING_LEVEL) diff --git a/stl/inc/xtree b/stl/inc/xtree index 1dd2fffbe58..1b22fb347dc 100644 --- a/stl/inc/xtree +++ b/stl/inc/xtree @@ -905,10 +905,10 @@ public: } _Tree(_Tree&& _Right) - : _Mypair( - _One_then_variadic_args_t{}, _Right.key_comp(), _One_then_variadic_args_t{}, _STD move(_Right._Getal())) { + : _Mypair(_One_then_variadic_args_t{}, _Right.key_comp(), // intentionally copy comparator, see LWG-2227 + _One_then_variadic_args_t{}, _STD move(_Right._Getal())) { _Alloc_sentinel_and_proxy(); - _Swap_val(_Right); + _Swap_val_excluding_comp(_Right); } private: @@ -925,7 +925,8 @@ private: public: _Tree(_Tree&& _Right, const allocator_type& _Al) - : _Mypair(_One_then_variadic_args_t{}, _Right.key_comp(), _One_then_variadic_args_t{}, _Al) { + : _Mypair(_One_then_variadic_args_t{}, _Right.key_comp(), // intentionally copy comparator, see LWG-2227 + _One_then_variadic_args_t{}, _Al) { if _CONSTEXPR_IF (!_Alnode_traits::is_always_equal::value) { if (_Getal() != _Right._Getal()) { _Different_allocator_move_construct(_STD move(_Right)); @@ -934,15 +935,15 @@ public: } _Alloc_sentinel_and_proxy(); - _Swap_val(_Right); + _Swap_val_excluding_comp(_Right); } private: void _Move_assign(_Tree& _Right, _Equal_allocators) noexcept(is_nothrow_move_assignable_v) { clear(); - _Getcomp() = _Right._Getcomp(); + _Getcomp() = _Right._Getcomp(); // intentionally copy comparator, see LWG-2227 _Pocma(_Getal(), _Right._Getal()); - _Swap_val(_Right); + _Swap_val_excluding_comp(_Right); } void _Move_assign(_Tree& _Right, _Propagate_allocators) { @@ -950,14 +951,14 @@ private: _Move_assign(_Right, _Equal_allocators{}); } else { clear(); - _Getcomp() = _Right._Getcomp(); + _Getcomp() = _Right._Getcomp(); // intentionally copy comparator, see LWG-2227 auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alnode, _Getal()); auto&& _Right_alproxy = _GET_PROXY_ALLOCATOR(_Alnode, _Right._Getal()); _Container_proxy_ptr<_Alty> _Proxy(_Right_alproxy, _Leave_proxy_unbound{}); - const auto _Scary = _Get_scary(); - auto _Right_scary = _Right._Get_scary(); - const auto _Newhead = _STD exchange(_Right_scary->_Myhead, _Node::_Buyheadnode(_Right._Getal())); - const auto _Newsize = _STD exchange(_Right_scary->_Mysize, size_type{0}); + const auto _Scary = _Get_scary(); + const auto _Right_scary = _Right._Get_scary(); + const auto _Newhead = _STD exchange(_Right_scary->_Myhead, _Node::_Buyheadnode(_Right._Getal())); + const auto _Newsize = _STD exchange(_Right_scary->_Mysize, size_type{0}); _Scary->_Erase_head(_Getal()); _Pocma(_Getal(), _Right._Getal()); _Scary->_Myhead = _Newhead; @@ -972,7 +973,7 @@ private: _Move_assign(_Right, _Equal_allocators{}); } else { clear(); - _Getcomp() = _Right._Getcomp(); + _Getcomp() = _Right._Getcomp(); // intentionally copy comparator, see LWG-2227 _Copy(_Right, _Move_tag{}); } } @@ -987,11 +988,10 @@ public: } private: - void _Swap_val(_Tree& _Right) { // swap contents with _Right, equal allocators - const auto _Scary = _Get_scary(); - auto _Right_scary = _Right._Get_scary(); + void _Swap_val_excluding_comp(_Tree& _Right) { // swap contents (except comparator) with _Right, equal allocators + const auto _Scary = _Get_scary(); + const auto _Right_scary = _Right._Get_scary(); _Scary->_Swap_proxy_and_iterators(*_Right_scary); - _Swap_adl(_Getcomp(), _Right._Getcomp()); _Swap_adl(_Scary->_Myhead, _Right_scary->_Myhead); _STD swap(_Scary->_Mysize, _Right_scary->_Mysize); } @@ -1575,7 +1575,8 @@ public: void swap(_Tree& _Right) noexcept(_Is_nothrow_swappable::value) /* strengthened */ { if (this != _STD addressof(_Right)) { _Pocs(_Getal(), _Right._Getal()); - _Swap_val(_Right); + _Swap_val_excluding_comp(_Right); + _Swap_adl(_Getcomp(), _Right._Getcomp()); } } @@ -1758,7 +1759,7 @@ protected: _Nodeptr _Newroot = _Scary->_Myhead; // point at nil node if (!_Rootnode->_Isnil) { // copy or move a node, then any subtrees - typename is_same::type _Is_set; + bool_constant> _Is_set; _Nodeptr _Pnode = _Copy_or_move(_Rootnode->_Myval, _Movefl, _Is_set); _Pnode->_Parent = _Wherenode; _Pnode->_Color = _Rootnode->_Color; diff --git a/stl/inc/xutility b/stl/inc/xutility index fa244555d08..acdfe28d346 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -413,7 +413,7 @@ template <_Has_member_element_type _Ty> struct indirectly_readable_traits<_Ty> : _Cond_value_type {}; // clang-format off -template <_Has_member_value_type _Ty> // Per LWG-3446 +template <_Has_member_value_type _Ty> requires _Has_member_element_type<_Ty> && same_as, remove_cv_t> struct indirectly_readable_traits<_Ty> : _Cond_value_type {}; @@ -473,7 +473,7 @@ struct _Iter_traits_difference { // clang-format off template -concept _Cpp17_iterator = // per LWG-3420 +concept _Cpp17_iterator = requires(_It __i) { { *__i } -> _Can_reference; { ++__i } -> same_as<_It&>; @@ -662,13 +662,6 @@ struct iterator_traits<_Ty*> { // CUSTOMIZATION POINT OBJECT ranges::iter_move namespace ranges { - // STRUCT TEMPLATE _Choice_t - template - struct _Choice_t { - _Ty _Strategy = _Ty{}; - bool _No_throw = false; - }; - namespace _Iter_move { void iter_move(); // Block unqualified name lookup @@ -705,9 +698,11 @@ namespace ranges { template requires (_Choice<_Ty>._Strategy != _St::_None) _NODISCARD constexpr decltype(auto) operator()(_Ty&& _Val) const noexcept(_Choice<_Ty>._No_throw) { - if constexpr (_Choice<_Ty>._Strategy == _St::_Custom) { + constexpr _St _Strat = _Choice<_Ty>._Strategy; + + if constexpr (_Strat == _St::_Custom) { return iter_move(static_cast<_Ty&&>(_Val)); - } else if constexpr (_Choice<_Ty>._Strategy == _St::_Fallback) { + } else if constexpr (_Strat == _St::_Fallback) { using _Ref = decltype(*static_cast<_Ty&&>(_Val)); if constexpr (is_lvalue_reference_v<_Ref>) { return _STD move(*static_cast<_Ty&&>(_Val)); @@ -770,7 +765,7 @@ concept indirectly_writable = requires(_It&& __i, _Ty&& __t) { // CONCEPT _Integer_like // clang-format off template -concept _Integer_like = _Is_nonbool_integral<_Ty>; // per the proposed resolution of LWG-3467 +concept _Integer_like = _Is_nonbool_integral<_Ty>; // CONCEPT _Signed_integer_like template @@ -783,7 +778,7 @@ using _Make_unsigned_like_t = make_unsigned_t<_Ty>; // ALIAS TEMPLATE _Make_signed_like_t template -using _Make_signed_like_t = make_signed_t<_Ty>; // per the proposed resolution of LWG-3403 +using _Make_signed_like_t = make_signed_t<_Ty>; // CONCEPT weakly_incrementable // clang-format off @@ -1092,11 +1087,13 @@ namespace ranges { template requires (_Choice<_Ty1, _Ty2>._Strategy != _St::_None) constexpr void operator()(_Ty1&& _Val1, _Ty2&& _Val2) const noexcept(_Choice<_Ty1, _Ty2>._No_throw) { - if constexpr (_Choice<_Ty1, _Ty2>._Strategy == _St::_Custom) { + constexpr _St _Strat = _Choice<_Ty1, _Ty2>._Strategy; + + if constexpr (_Strat == _St::_Custom) { iter_swap(static_cast<_Ty1&&>(_Val1), static_cast<_Ty2&&>(_Val2)); - } else if constexpr (_Choice<_Ty1, _Ty2>._Strategy == _St::_Swap) { + } else if constexpr (_Strat == _St::_Swap) { _RANGES swap(*static_cast<_Ty1&&>(_Val1), *static_cast<_Ty2&&>(_Val2)); - } else if constexpr (_Choice<_Ty1, _Ty2>._Strategy == _St::_Exchange) { + } else if constexpr (_Strat == _St::_Exchange) { *static_cast<_Ty1&&>(_Val1) = _Iter_exchange_move(static_cast<_Ty2&&>(_Val2), static_cast<_Ty1&&>(_Val1)); } else { @@ -1485,10 +1482,6 @@ _NODISCARD constexpr _Ty* _Get_unwrapped_n(_Ty* const _Src, _Diff) { } #endif // _HAS_IF_CONSTEXPR -template -using _Unwrapped_n_t = - _Remove_cvref_t(), _Iter_diff_t<_Remove_cvref_t<_Iter>>{}))>; - // FUNCTION TEMPLATE _Seek_wrapped template _INLINE_VAR constexpr bool _Wrapped_seekable_v = false; @@ -1919,7 +1912,6 @@ public: // clang-format off template #ifdef __cpp_lib_concepts - // Per LWG-3435 requires (!is_same_v<_Other, _BidIt>) && convertible_to #endif // __cpp_lib_concepts _CONSTEXPR17 reverse_iterator(const reverse_iterator<_Other>& _Right) noexcept( @@ -1928,7 +1920,6 @@ public: template #ifdef __cpp_lib_concepts - // Per LWG-3435 requires (!is_same_v<_Other, _BidIt>) && convertible_to && assignable_from<_BidIt&, const _Other&> #endif // __cpp_lib_concepts @@ -2073,11 +2064,6 @@ protected: _BidIt current{}; }; -#ifdef __cpp_lib_concepts -template -concept _Implicitly_convertible_to = is_convertible_v<_From, _To>; -#endif // __cpp_lib_concepts - template _NODISCARD _CONSTEXPR17 bool operator==(const reverse_iterator<_BidIt1>& _Left, const reverse_iterator<_BidIt2>& _Right) #ifdef __cpp_lib_concepts @@ -2415,11 +2401,13 @@ namespace ranges { template <_Should_range_access _Ty> requires (_Choice<_Ty&>._Strategy != _St::_None) _NODISCARD constexpr auto operator()(_Ty&& _Val) const noexcept(_Choice<_Ty&>._No_throw) { - if constexpr (_Choice<_Ty&>._Strategy == _St::_Array) { + constexpr _St _Strat = _Choice<_Ty&>._Strategy; + + if constexpr (_Strat == _St::_Array) { return _Val; - } else if constexpr (_Choice<_Ty&>._Strategy == _St::_Member) { + } else if constexpr (_Strat == _St::_Member) { return _Val.begin(); - } else if constexpr (_Choice<_Ty&>._Strategy == _St::_Non_member) { + } else if constexpr (_Strat == _St::_Non_member) { return begin(_Val); } else { static_assert(_Always_false<_Ty>, "Should be unreachable"); @@ -2478,9 +2466,11 @@ namespace ranges { template <_Should_range_access _Ty> requires (_Choice<_Ty&>._Strategy != _St::_None) _NODISCARD constexpr auto operator()(_Ty&& _Val) const noexcept(_Choice<_Ty&>._No_throw) { - if constexpr (_Choice<_Ty&>._Strategy == _St::_Member) { + constexpr _St _Strat = _Choice<_Ty&>._Strategy; + + if constexpr (_Strat == _St::_Member) { return _Val._Unchecked_begin(); - } else if constexpr (_Choice<_Ty&>._Strategy == _St::_Unwrap) { + } else if constexpr (_Strat == _St::_Unwrap) { return _Get_unwrapped(_RANGES begin(_Val)); } else { static_assert(_Always_false<_Ty>, "Should be unreachable"); @@ -2550,12 +2540,14 @@ namespace ranges { template <_Should_range_access _Ty> requires (_Choice<_Ty&>._Strategy != _St::_None) _NODISCARD constexpr auto operator()(_Ty&& _Val) const noexcept(_Choice<_Ty&>._No_throw) { - if constexpr (_Choice<_Ty&>._Strategy == _St::_Array) { + constexpr _St _Strat = _Choice<_Ty&>._Strategy; + + if constexpr (_Strat == _St::_Array) { // extent_v> reuses specializations from _Choose return _Val + extent_v>; - } else if constexpr (_Choice<_Ty&>._Strategy == _St::_Member) { + } else if constexpr (_Strat == _St::_Member) { return _Val.end(); - } else if constexpr (_Choice<_Ty&>._Strategy == _St::_Non_member) { + } else if constexpr (_Strat == _St::_Non_member) { return end(_Val); } else { static_assert(_Always_false<_Ty>, "should be unreachable"); @@ -2611,9 +2603,11 @@ namespace ranges { template <_Should_range_access _Ty> requires (_Choice<_Ty&>._Strategy != _St::_None) _NODISCARD constexpr auto operator()(_Ty&& _Val) const noexcept(_Choice<_Ty&>._No_throw) { - if constexpr (_Choice<_Ty&>._Strategy == _St::_Member) { + constexpr _St _Strat = _Choice<_Ty&>._Strategy; + + if constexpr (_Strat == _St::_Member) { return _Val._Unchecked_end(); - } else if constexpr (_Choice<_Ty&>._Strategy == _St::_Unwrap) { + } else if constexpr (_Strat == _St::_Unwrap) { return _Get_unwrapped(_RANGES end(_Val)); } else { static_assert(_Always_false<_Ty>, "Should be unreachable"); @@ -2746,11 +2740,13 @@ namespace ranges { template <_Should_range_access _Ty> requires (_Choice<_Ty&>._Strategy != _St::_None) _NODISCARD constexpr auto operator()(_Ty&& _Val) const noexcept(_Choice<_Ty&>._No_throw) { - if constexpr (_Choice<_Ty&>._Strategy == _St::_Member) { + constexpr _St _Strat = _Choice<_Ty&>._Strategy; + + if constexpr (_Strat == _St::_Member) { return _Val.rbegin(); - } else if constexpr (_Choice<_Ty&>._Strategy == _St::_Non_member) { + } else if constexpr (_Strat == _St::_Non_member) { return rbegin(_Val); - } else if constexpr (_Choice<_Ty&>._Strategy == _St::_Make_reverse) { + } else if constexpr (_Strat == _St::_Make_reverse) { return _STD make_reverse_iterator(_RANGES end(_Val)); } else { static_assert(_Always_false<_Ty>, "should be unreachable"); @@ -2817,11 +2813,13 @@ namespace ranges { template <_Should_range_access _Ty> requires (_Choice<_Ty&>._Strategy != _St::_None) _NODISCARD constexpr auto operator()(_Ty&& _Val) const noexcept(_Choice<_Ty&>._No_throw) { - if constexpr (_Choice<_Ty&>._Strategy == _St::_Member) { + constexpr _St _Strat = _Choice<_Ty&>._Strategy; + + if constexpr (_Strat == _St::_Member) { return _Val.rend(); - } else if constexpr (_Choice<_Ty&>._Strategy == _St::_Non_member) { + } else if constexpr (_Strat == _St::_Non_member) { return rend(_Val); - } else if constexpr (_Choice<_Ty&>._Strategy == _St::_Make_reverse) { + } else if constexpr (_Strat == _St::_Make_reverse) { return _STD make_reverse_iterator(_RANGES begin(_Val)); } else { static_assert(_Always_false<_Ty>, "should be unreachable"); @@ -2934,14 +2932,16 @@ namespace ranges { template requires (_Choice<_Ty&>._Strategy != _St::_None) _NODISCARD constexpr auto operator()(_Ty&& _Val) const noexcept(_Choice<_Ty&>._No_throw) { - if constexpr (_Choice<_Ty&>._Strategy == _St::_Array) { + constexpr _St _Strat = _Choice<_Ty&>._Strategy; + + if constexpr (_Strat == _St::_Array) { // extent_v> reuses specializations from _Choose return extent_v>; - } else if constexpr (_Choice<_Ty&>._Strategy == _St::_Member) { + } else if constexpr (_Strat == _St::_Member) { return _Val.size(); - } else if constexpr (_Choice<_Ty&>._Strategy == _St::_Non_member) { + } else if constexpr (_Strat == _St::_Non_member) { return size(_Val); - } else if constexpr (_Choice<_Ty&>._Strategy == _St::_Subtract) { + } else if constexpr (_Strat == _St::_Subtract) { const auto _Delta = _RANGES end(_Val) - _RANGES begin(_Val); return static_cast<_Make_unsigned_like_t>>(_Delta); } else { @@ -3007,11 +3007,13 @@ namespace ranges { template requires (_Choice<_Ty&>._Strategy != _St::_None) _NODISCARD constexpr bool operator()(_Ty&& _Val) const noexcept(_Choice<_Ty&>._No_throw) { - if constexpr (_Choice<_Ty&>._Strategy == _St::_Member) { + constexpr _St _Strat = _Choice<_Ty&>._Strategy; + + if constexpr (_Strat == _St::_Member) { return static_cast(_Val.empty()); - } else if constexpr (_Choice<_Ty&>._Strategy == _St::_Size) { + } else if constexpr (_Strat == _St::_Size) { return _RANGES size(_Val) == 0; - } else if constexpr (_Choice<_Ty&>._Strategy == _St::_Compare) { + } else if constexpr (_Strat == _St::_Compare) { return static_cast(_RANGES begin(_Val) == _RANGES end(_Val)); } else { static_assert(_Always_false<_Ty>, "should be unreachable"); @@ -3067,9 +3069,11 @@ namespace ranges { template <_Should_range_access _Ty> requires (_Choice<_Ty&>._Strategy != _St::_None) _NODISCARD constexpr auto operator()(_Ty&& _Val) const noexcept(_Choice<_Ty&>._No_throw) { - if constexpr (_Choice<_Ty&>._Strategy == _St::_Member) { + constexpr _St _Strat = _Choice<_Ty&>._Strategy; + + if constexpr (_Strat == _St::_Member) { return _Val.data(); - } else if constexpr (_Choice<_Ty&>._Strategy == _St::_Address) { + } else if constexpr (_Strat == _St::_Address) { return _STD to_address(_RANGES begin(_Val)); } else { static_assert(_Always_false<_Ty>, "should be unreachable"); @@ -3327,7 +3331,7 @@ namespace ranges { inline constexpr _Distance_fn distance{_Not_quite_object::_Construct_tag{}}; // VARIABLE ranges::ssize - class _Ssize_fn { // Per the proposed resolution of LWG-3403 + class _Ssize_fn { public: // clang-format off template @@ -4000,7 +4004,6 @@ public: // clang-format off template #ifdef __cpp_lib_concepts - // per LWG-3435 requires (!is_same_v<_Other, _Iter>) && convertible_to #endif // __cpp_lib_concepts _CONSTEXPR17 move_iterator(const move_iterator<_Other>& _Right) noexcept( @@ -4009,7 +4012,6 @@ public: template #ifdef __cpp_lib_concepts - // per LWG-3435 requires (!is_same_v<_Other, _Iter>) && convertible_to && assignable_from<_Iter&, const _Other&> #endif // __cpp_lib_concepts @@ -4813,12 +4815,33 @@ _INLINE_VAR constexpr bool _Fill_memset_is_safe = conjunction_v, template _INLINE_VAR constexpr bool _Fill_memset_is_safe<_FwdIt, _Ty, false> = false; +template > +_INLINE_VAR constexpr bool _Fill_zero_memset_is_safe = + conjunction_v, is_scalar<_Iter_value_t<_FwdIt>>, negation>>, + negation>>>, is_assignable<_Iter_ref_t<_FwdIt>, const _Ty&>>; + +template +_INLINE_VAR constexpr bool _Fill_zero_memset_is_safe<_FwdIt, _Ty, false> = false; + template void _Fill_memset(_DestTy* const _Dest, const _Ty _Val, const size_t _Count) { _DestTy _Dest_val = _Val; // implicitly convert (a cast would suppress warnings); also handles _DestTy being bool _CSTD memset(_Dest, static_cast(_Dest_val), _Count); } +template +void _Fill_zero_memset(_DestTy* const _Dest, const size_t _Count) { + _CSTD memset(_Dest, 0, _Count * sizeof(_DestTy)); +} + +template +_NODISCARD bool _Is_all_bits_zero(const _Ty& _Val) { + // checks if scalar type has all bits set to zero + _STL_INTERNAL_STATIC_ASSERT(is_scalar_v<_Ty> && !is_member_pointer_v<_Ty>); + constexpr _Ty _Zero{}; + return _CSTD memcmp(&_Val, &_Zero, sizeof(_Ty)) == 0; +} + #if _HAS_IF_CONSTEXPR template _CONSTEXPR20 void fill(const _FwdIt _First, const _FwdIt _Last, const _Ty& _Val) { @@ -4829,13 +4852,18 @@ _CONSTEXPR20 void fill(const _FwdIt _First, const _FwdIt _Last, const _Ty& _Val) } else { auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); - if constexpr (_Fill_memset_is_safe) { #ifdef __cpp_lib_is_constant_evaluated - if (!_STD is_constant_evaluated()) + if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated - { + { + if constexpr (_Fill_memset_is_safe) { _Fill_memset(_UFirst, _Val, static_cast(_ULast - _UFirst)); return; + } else if constexpr (_Fill_zero_memset_is_safe) { + if (_Is_all_bits_zero(_Val)) { + _Fill_zero_memset(_UFirst, static_cast(_ULast - _UFirst)); + return; + } } } @@ -4890,15 +4918,20 @@ _CONSTEXPR20 _OutIt fill_n(_OutIt _Dest, const _Diff _Count_raw, const _Ty& _Val return _Last; } else { auto _UDest = _Get_unwrapped_n(_Dest, _Count); - if constexpr (_Fill_memset_is_safe) { #ifdef __cpp_lib_is_constant_evaluated - if (!_STD is_constant_evaluated()) + if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated - { + { + if constexpr (_Fill_memset_is_safe) { _Fill_memset(_UDest, _Val, static_cast(_Count)); - _UDest += _Count; - _Seek_wrapped(_Dest, _UDest); + _Seek_wrapped(_Dest, _UDest + _Count); return _Dest; + } else if constexpr (_Fill_zero_memset_is_safe) { + if (_Is_all_bits_zero(_Val)) { + _Fill_zero_memset(_UDest, static_cast(_Count)); + _Seek_wrapped(_Dest, _UDest + _Count); + return _Dest; + } } } @@ -5451,7 +5484,8 @@ _NODISCARD constexpr bool _Within_limits(const _Ty& _Val, false_type, false_type template _NODISCARD constexpr bool _Within_limits(_InIt, const _Ty& _Val) { // check whether _Val is within the limits of _Elem using _Elem = remove_pointer_t<_InIt>; - return _Within_limits(_Val, is_signed<_Elem>{}, is_signed<_Ty>{}, bool_constant<-1 == static_cast<_Ty>(-1)>{}); + return _Within_limits(_Val, bool_constant>{}, bool_constant>{}, + bool_constant<-1 == static_cast<_Ty>(-1)>{}); } template @@ -5867,6 +5901,54 @@ namespace ranges { }; inline constexpr _Find_if_fn find_if{_Not_quite_object::_Construct_tag{}}; + + // VARIABLE ranges::find_if_not + class _Find_if_not_fn : private _Not_quite_object { + public: + using _Not_quite_object::_Not_quite_object; + + template _Se, class _Pj = identity, + indirect_unary_predicate> _Pr> + _NODISCARD constexpr _It operator()(_It _First, _Se _Last, _Pr _Pred, _Pj _Proj = {}) const { + _Adl_verify_range(_First, _Last); + + auto _UResult = _Find_if_not_unchecked( + _Get_unwrapped(_STD move(_First)), _Get_unwrapped(_STD move(_Last)), _Pass_fn(_Pred), _Pass_fn(_Proj)); + + _Seek_wrapped(_First, _STD move(_UResult)); + return _First; + } + + template , _Pj>> _Pr> + _NODISCARD constexpr borrowed_iterator_t<_Rng> operator()(_Rng&& _Range, _Pr _Pred, _Pj _Proj = {}) const { + auto _First = _RANGES begin(_Range); + + auto _UResult = _Find_if_not_unchecked( + _Get_unwrapped(_STD move(_First)), _Uend(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj)); + + _Seek_wrapped(_First, _STD move(_UResult)); + return _First; + } + + private: + template + _NODISCARD static constexpr _It _Find_if_not_unchecked(_It _First, const _Se _Last, _Pr _Pred, _Pj _Proj) { + _STL_INTERNAL_STATIC_ASSERT(input_iterator<_It>); + _STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se, _It>); + _STL_INTERNAL_STATIC_ASSERT(indirect_unary_predicate<_Pr, projected<_It, _Pj>>); + + for (; _First != _Last; ++_First) { + if (!_STD invoke(_Pred, _STD invoke(_Proj, *_First))) { + break; + } + } + + return _First; + } + }; + + inline constexpr _Find_if_not_fn find_if_not{_Not_quite_object::_Construct_tag{}}; } // namespace ranges #endif // __cpp_lib_concepts @@ -6045,16 +6127,20 @@ struct _Float_traits { // traits for double and long double: using type = unsigned long long; + static constexpr type _Sign_mask = 0x8000'0000'0000'0000ULL; static constexpr type _Magnitude_mask = 0x7fff'ffff'ffff'ffffULL; static constexpr type _Exponent_mask = 0x7ff0'0000'0000'0000ULL; + static constexpr type _Quiet_nan_mask = 0x0008'0000'0000'0000ULL; }; template <> struct _Float_traits { using type = unsigned int; + static constexpr type _Sign_mask = 0x8000'0000U; static constexpr type _Magnitude_mask = 0x7fff'ffffU; static constexpr type _Exponent_mask = 0x7f80'0000U; + static constexpr type _Quiet_nan_mask = 0x0040'0000U; }; // FUNCTION TEMPLATE _Float_abs_bits @@ -6070,12 +6156,36 @@ _NODISCARD _CONSTEXPR_BIT_CAST _Ty _Float_abs(const _Ty _Xx) { // constexpr floa return _Bit_cast<_Ty>(_Float_abs_bits(_Xx)); } +// FUNCTION TEMPLATE _Float_copysign +template , int> = 0> +_NODISCARD _CONSTEXPR_BIT_CAST _Ty _Float_copysign(const _Ty _Magnitude, const _Ty _Sign) { // constexpr copysign() + const auto _Signbit = _Bit_cast::type>(_Sign) & _Float_traits<_Ty>::_Sign_mask; + return _Bit_cast<_Ty>(_Float_abs_bits(_Magnitude) | _Signbit); +} + // FUNCTION TEMPLATE _Is_nan template , int> = 0> _NODISCARD _CONSTEXPR_BIT_CAST bool _Is_nan(const _Ty _Xx) { // constexpr isnan() return _Float_abs_bits(_Xx) > _Float_traits<_Ty>::_Exponent_mask; } +// FUNCTION TEMPLATE _Is_signaling_nan +// TRANSITION, workaround x86 ABI +// On x86 ABI, floating point by-value arguments and return values are passed in 80-bit x87 registers. +// When the value is a 32-bit or 64-bit signaling NaN, the conversion to/from 80-bit raises FE_INVALID +// and turns it into a quiet NaN. This behavior is undesirable if we want to test for signaling NaNs. +template , int> = 0> +_NODISCARD _CONSTEXPR_BIT_CAST bool _Is_signaling_nan(const _Ty& _Xx) { // returns true if input is a signaling NaN + const auto _Abs_bits = _Float_abs_bits(_Xx); + return _Abs_bits > _Float_traits<_Ty>::_Exponent_mask && ((_Abs_bits & _Float_traits<_Ty>::_Quiet_nan_mask) == 0); +} + +// FUNCTION TEMPLATE _Is_inf +template , int> = 0> +_NODISCARD _CONSTEXPR_BIT_CAST bool _Is_inf(const _Ty _Xx) { // constexpr isinf() + return _Float_abs_bits(_Xx) == _Float_traits<_Ty>::_Exponent_mask; +} + // FUNCTION TEMPLATE _Is_finite template , int> = 0> _NODISCARD _CONSTEXPR_BIT_CAST bool _Is_finite(const _Ty _Xx) { // constexpr isfinite() @@ -6091,7 +6201,6 @@ struct _Nontrivial_dummy_type { _STL_INTERNAL_STATIC_ASSERT(!is_trivially_default_constructible_v<_Nontrivial_dummy_type>); _STD_END -#undef _CONSTEXPR_BIT_CAST #pragma pop_macro("new") _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index afb1523b28f..ae2642680f7 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -165,7 +165,6 @@ // P0718R2 atomic>, atomic> // P0758R1 is_nothrow_convertible // P0768R1 Library Support For The Spaceship Comparison Operator <=> -// (partially implemented) // P0769R2 shift_left(), shift_right() // P0811R3 midpoint(), lerp() // P0879R0 constexpr For Swapping Functions @@ -503,7 +502,7 @@ #define _CPPLIB_VER 650 #define _MSVC_STL_VERSION 142 -#define _MSVC_STL_UPDATE 202010L +#define _MSVC_STL_UPDATE 202011L #ifndef _ALLOW_COMPILER_AND_STL_VERSION_MISMATCH #ifdef __EDG__ @@ -1185,12 +1184,8 @@ #define __cpp_lib_constexpr_tuple 201811L #define __cpp_lib_constexpr_utility 201811L -#ifdef __cpp_impl_coroutine // TRANSITION, Clang and EDG coroutine support -#if __cpp_impl_coroutine >= 201902L +#ifdef __cpp_impl_coroutine // TRANSITION, Clang coroutine support #define __cpp_lib_coroutine 201902L -#else // ^^^ __cpp_impl_coroutine >= 201902L ^^^ / vvv __cpp_impl_coroutine < 201902L vvv -#define __cpp_lib_coroutine 197000L // TRANSITION, VS 2019 16.8 Preview 4 -#endif // ^^^ __cpp_impl_coroutine < 201902L ^^^ #endif // __cpp_impl_coroutine #define __cpp_lib_destroying_delete 201806L @@ -1214,10 +1209,15 @@ #define __cpp_lib_span 202002L #define __cpp_lib_ssize 201902L #define __cpp_lib_starts_ends_with 201711L -#define __cpp_lib_to_address 201711L -#define __cpp_lib_to_array 201907L -#define __cpp_lib_type_identity 201806L -#define __cpp_lib_unwrap_ref 201811L + +#ifdef __cpp_lib_concepts // TRANSITION, GH-395 +#define __cpp_lib_three_way_comparison 201711L +#endif // __cpp_lib_concepts + +#define __cpp_lib_to_address 201711L +#define __cpp_lib_to_array 201907L +#define __cpp_lib_type_identity 201806L +#define __cpp_lib_unwrap_ref 201811L #endif // _HAS_CXX20 #ifndef _M_CEE diff --git a/stl/msbuild/stl_1/stl_1.files.settings.targets b/stl/msbuild/stl_1/stl_1.files.settings.targets index 7c36449ea49..8c423bd34ec 100644 --- a/stl/msbuild/stl_1/stl_1.files.settings.targets +++ b/stl/msbuild/stl_1/stl_1.files.settings.targets @@ -11,7 +11,6 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception "> nativecpp - diff --git a/stl/msbuild/stl_2/msvcp_2.settings.targets b/stl/msbuild/stl_2/msvcp_2.settings.targets index afcc4c12419..79540664211 100644 --- a/stl/msbuild/stl_2/msvcp_2.settings.targets +++ b/stl/msbuild/stl_2/msvcp_2.settings.targets @@ -36,8 +36,6 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception $(CrtBuildDir)\msvcprt_2$(BuildSuffix).$(MsvcpFlavor).import_only.lib $(LibOutputFileName).$(MsvcpFlavor) $(IntermediateOutputDirectory)\$(DllDefName).def - $(IntermediateOutputDirectoryEC)\$(DllDefName).def - $(IntermediateOutputDirectory)\$(DllDefName).def true $(OutputPath)\$(OutputName)$(_PDB_VER_NAME_)$(DllPdbFlavorSuffix) diff --git a/stl/msbuild/stl_2/stl_2.files.settings.targets b/stl/msbuild/stl_2/stl_2.files.settings.targets index 0b5a57a2c3d..4f28e08a72d 100644 --- a/stl/msbuild/stl_2/stl_2.files.settings.targets +++ b/stl/msbuild/stl_2/stl_2.files.settings.targets @@ -11,7 +11,6 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception "> nativecpp - diff --git a/stl/msbuild/stl_atomic_wait/stl_atomic_wait.files.settings.targets b/stl/msbuild/stl_atomic_wait/stl_atomic_wait.files.settings.targets index 05ac026443d..e7cc52c398d 100644 --- a/stl/msbuild/stl_atomic_wait/stl_atomic_wait.files.settings.targets +++ b/stl/msbuild/stl_atomic_wait/stl_atomic_wait.files.settings.targets @@ -17,21 +17,4 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception nativecpp - - - - - $(IntermediateOutputDirectoryEC)\atomic_wait.obj; - $(IntermediateOutputDirectoryEC)\parallel_algorithms.obj; - - - - - - - - - diff --git a/stl/msbuild/stl_base/libcp.settings.targets b/stl/msbuild/stl_base/libcp.settings.targets index 336c34ac84c..d9cbf1677a9 100644 --- a/stl/msbuild/stl_base/libcp.settings.targets +++ b/stl/msbuild/stl_base/libcp.settings.targets @@ -32,10 +32,6 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - - - - diff --git a/stl/msbuild/stl_base/msvcp.settings.targets b/stl/msbuild/stl_base/msvcp.settings.targets index 1155276faab..3dec66549c7 100644 --- a/stl/msbuild/stl_base/msvcp.settings.targets +++ b/stl/msbuild/stl_base/msvcp.settings.targets @@ -39,8 +39,6 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception $(CrtBuildDir)\msvcprt_base$(BuildSuffix).$(MsvcpFlavor).import_only.lib $(LibOutputFileName).$(MsvcpFlavor) $(IntermediateOutputDirectory)\$(DllDefName).def - $(IntermediateOutputDirectoryEC)\$(DllDefName).def - $(IntermediateOutputDirectory)\$(DllDefName).def $(ClDefines);_STL_CONCRT_SUPPORT true @@ -89,292 +87,6 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - - - - $(IntermediateOutputDirectoryEC)\_tolower.obj; - $(IntermediateOutputDirectoryEC)\_toupper.obj; - $(IntermediateOutputDirectoryEC)\atomic.obj; - $(IntermediateOutputDirectoryEC)\cthread.obj; - $(IntermediateOutputDirectoryEC)\xnotify.obj; - $(IntermediateOutputDirectoryEC)\xtime.obj; - $(IntermediateOutputDirectoryEC)\xcosh.obj; - $(IntermediateOutputDirectoryEC)\xdint.obj; - $(IntermediateOutputDirectoryEC)\xdnorm.obj; - $(IntermediateOutputDirectoryEC)\xdscale.obj; - $(IntermediateOutputDirectoryEC)\xdtento.obj; - $(IntermediateOutputDirectoryEC)\xdtest.obj; - $(IntermediateOutputDirectoryEC)\xdunscal.obj; - $(IntermediateOutputDirectoryEC)\xexp.obj; - $(IntermediateOutputDirectoryEC)\xfcosh.obj; - $(IntermediateOutputDirectoryEC)\xfdint.obj; - $(IntermediateOutputDirectoryEC)\xfdnorm.obj; - $(IntermediateOutputDirectoryEC)\xfdscale.obj; - $(IntermediateOutputDirectoryEC)\xfdtento.obj; - $(IntermediateOutputDirectoryEC)\xfdtest.obj; - $(IntermediateOutputDirectoryEC)\xfdunsca.obj; - $(IntermediateOutputDirectoryEC)\xferaise.obj; - $(IntermediateOutputDirectoryEC)\xfexp.obj; - $(IntermediateOutputDirectoryEC)\xfprec.obj; - $(IntermediateOutputDirectoryEC)\xfsinh.obj; - $(IntermediateOutputDirectoryEC)\xfvalues.obj; - $(IntermediateOutputDirectoryEC)\xgetwctype.obj; - $(IntermediateOutputDirectoryEC)\xlcosh.obj; - $(IntermediateOutputDirectoryEC)\xldint.obj; - $(IntermediateOutputDirectoryEC)\xldscale.obj; - $(IntermediateOutputDirectoryEC)\xldtento.obj; - $(IntermediateOutputDirectoryEC)\xldtest.obj; - $(IntermediateOutputDirectoryEC)\xldunsca.obj; - $(IntermediateOutputDirectoryEC)\xlexp.obj; - $(IntermediateOutputDirectoryEC)\xlpoly.obj; - $(IntermediateOutputDirectoryEC)\xlprec.obj; - $(IntermediateOutputDirectoryEC)\xlsinh.obj; - $(IntermediateOutputDirectoryEC)\xlvalues.obj; - $(IntermediateOutputDirectoryEC)\xmbtowc.obj; - $(IntermediateOutputDirectoryEC)\xmtx.obj; - $(IntermediateOutputDirectoryEC)\xpoly.obj; - $(IntermediateOutputDirectoryEC)\xprec.obj; - $(IntermediateOutputDirectoryEC)\xsinh.obj; - $(IntermediateOutputDirectoryEC)\xstod.obj; - $(IntermediateOutputDirectoryEC)\xstof.obj; - $(IntermediateOutputDirectoryEC)\xstoflt.obj; - $(IntermediateOutputDirectoryEC)\xstol.obj; - $(IntermediateOutputDirectoryEC)\xstold.obj; - $(IntermediateOutputDirectoryEC)\xstoll.obj; - $(IntermediateOutputDirectoryEC)\xstopfx.obj; - $(IntermediateOutputDirectoryEC)\xstoul.obj; - $(IntermediateOutputDirectoryEC)\xstoull.obj; - $(IntermediateOutputDirectoryEC)\xstoxflt.obj; - $(IntermediateOutputDirectoryEC)\xstrcoll.obj; - $(IntermediateOutputDirectoryEC)\xstrxfrm.obj; - $(IntermediateOutputDirectoryEC)\xtowlower.obj; - $(IntermediateOutputDirectoryEC)\xtowupper.obj; - $(IntermediateOutputDirectoryEC)\xvalues.obj; - $(IntermediateOutputDirectoryEC)\xwcscoll.obj; - $(IntermediateOutputDirectoryEC)\xwcsxfrm.obj; - $(IntermediateOutputDirectoryEC)\xwctomb.obj; - $(IntermediateOutputDirectoryEC)\xwstod.obj; - $(IntermediateOutputDirectoryEC)\xwstof.obj; - $(IntermediateOutputDirectoryEC)\xwstoflt.obj; - $(IntermediateOutputDirectoryEC)\xwstold.obj; - $(IntermediateOutputDirectoryEC)\xwstopfx.obj; - $(IntermediateOutputDirectoryEC)\xwstoxfl.obj; - $(IntermediateOutputDirectoryEC)\excptptr.obj; - $(IntermediateOutputDirectoryEC)\StlCompareStringA.obj; - $(IntermediateOutputDirectoryEC)\StlCompareStringW.obj; - $(IntermediateOutputDirectoryEC)\StlLCMapStringA.obj; - $(IntermediateOutputDirectoryEC)\StlLCMapStringW.obj; - $(IntermediateOutputDirectoryEC)\winapinls.obj; - $(IntermediateOutputDirectoryEC)\cerr.obj; - $(IntermediateOutputDirectoryEC)\cin.obj; - $(IntermediateOutputDirectoryEC)\clog.obj; - $(IntermediateOutputDirectoryEC)\cout.obj; - $(IntermediateOutputDirectoryEC)\filesys.obj; - $(IntermediateOutputDirectoryEC)\fiopen.obj; - $(IntermediateOutputDirectoryEC)\future.obj; - $(IntermediateOutputDirectoryEC)\iomanip.obj; - $(IntermediateOutputDirectoryEC)\ios.obj; - $(IntermediateOutputDirectoryEC)\iosptrs.obj; - $(IntermediateOutputDirectoryEC)\iostream.obj; - $(IntermediateOutputDirectoryEC)\locale.obj; - $(IntermediateOutputDirectoryEC)\locale0.obj; - $(IntermediateOutputDirectoryEC)\multprec.obj; - $(IntermediateOutputDirectoryEC)\raisehan.obj; - $(IntermediateOutputDirectoryEC)\stdhndlr.obj; - $(IntermediateOutputDirectoryEC)\stdthrow.obj; - $(IntermediateOutputDirectoryEC)\syserror.obj; - $(IntermediateOutputDirectoryEC)\cond.obj; - $(IntermediateOutputDirectoryEC)\mutex.obj; - $(IntermediateOutputDirectoryEC)\pplerror.obj; - $(IntermediateOutputDirectoryEC)\ppltasks.obj; - $(IntermediateOutputDirectoryEC)\taskscheduler.obj; - $(IntermediateOutputDirectoryEC)\thread0.obj; - $(IntermediateOutputDirectoryEC)\uncaught_exception.obj; - $(IntermediateOutputDirectoryEC)\uncaught_exceptions.obj; - $(IntermediateOutputDirectoryEC)\ushcerr.obj; - $(IntermediateOutputDirectoryEC)\ushcin.obj; - $(IntermediateOutputDirectoryEC)\ushclog.obj; - $(IntermediateOutputDirectoryEC)\ushcout.obj; - $(IntermediateOutputDirectoryEC)\ushiostr.obj; - $(IntermediateOutputDirectoryEC)\wcerr.obj; - $(IntermediateOutputDirectoryEC)\wcin.obj; - $(IntermediateOutputDirectoryEC)\wclog.obj; - $(IntermediateOutputDirectoryEC)\wcout.obj; - $(IntermediateOutputDirectoryEC)\wiostrea.obj; - $(IntermediateOutputDirectoryEC)\wlocale.obj; - $(IntermediateOutputDirectoryEC)\xalloc.obj; - $(IntermediateOutputDirectoryEC)\xdateord.obj; - $(IntermediateOutputDirectoryEC)\xlgamma.obj; - $(IntermediateOutputDirectoryEC)\xlocale.obj; - $(IntermediateOutputDirectoryEC)\xlock.obj; - $(IntermediateOutputDirectoryEC)\xonce.obj; - $(IntermediateOutputDirectoryEC)\xrngabort.obj; - $(IntermediateOutputDirectoryEC)\xrngdev.obj; - $(IntermediateOutputDirectoryEC)\xthrow.obj; - $(IntermediateOutputDirectoryEC)\winapisupp.obj; - $(IntermediateOutputDirectoryEC)\dllmain.obj; - $(IntermediateOutputDirectoryEC)\instances.obj; - - - - - $(IntermediateOutputDirectoryEC)\filesystem.obj; - $(IntermediateOutputDirectoryEC)\locale0_implib.obj; - $(IntermediateOutputDirectoryEC)\nothrow.obj; - $(IntermediateOutputDirectoryEC)\parallel_algorithms.obj; - $(IntermediateOutputDirectoryEC)\sharedmutex.obj; - $(IntermediateOutputDirectoryEC)\vector_algorithms.obj; - - - - - - - - - - false - true - - - - - - - - - - diff --git a/stl/msbuild/stl_codecvt_ids/msvcp_codecvt_ids.settings.targets b/stl/msbuild/stl_codecvt_ids/msvcp_codecvt_ids.settings.targets index 3df5ef40e29..2116ad9a688 100644 --- a/stl/msbuild/stl_codecvt_ids/msvcp_codecvt_ids.settings.targets +++ b/stl/msbuild/stl_codecvt_ids/msvcp_codecvt_ids.settings.targets @@ -50,11 +50,6 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception true - - $(IntermediateOutputDirectoryEC)\$(DllDefName).def - $(IntermediateOutputDirectory)\$(DllDefName).def - - LIBRARYNAME=$(OutputName.ToUpper());$(DllCppDefines) @@ -75,11 +70,6 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - - - - - - - - - - + + false + + + false + + + false + + + false + + + false + diff --git a/stl/src/filesystem.cpp b/stl/src/filesystem.cpp index a8493ec49ae..15d42a2ed7d 100644 --- a/stl/src/filesystem.cpp +++ b/stl/src/filesystem.cpp @@ -253,8 +253,7 @@ void __stdcall __std_fs_directory_iterator_close(_In_ const __std_fs_dir_handle if (_Code_page == __std_code_page{CP_UTF8} || _Code_page == __std_code_page{54936}) { // For UTF-8 or GB18030, attempt to use WC_ERR_INVALID_CHARS. (These codepages can't use WC_NO_BEST_FIT_CHARS - // below, and other codepages can't use WC_ERR_INVALID_CHARS.) WC_ERR_INVALID_CHARS is Windows Vista+. - // Windows XP will activate the ERROR_INVALID_FLAGS fallback below. + // below, and other codepages can't use WC_ERR_INVALID_CHARS.) _Result._Len = WideCharToMultiByte(static_cast(_Code_page), WC_ERR_INVALID_CHARS, _Input_str, _Input_len, _Output_str, _Output_len, nullptr, nullptr); } else { // For other codepages, attempt to use WC_NO_BEST_FIT_CHARS. diff --git a/stl/src/ios.cpp b/stl/src/ios.cpp index 8640a63169b..487ddadc21a 100644 --- a/stl/src/ios.cpp +++ b/stl/src/ios.cpp @@ -31,6 +31,7 @@ void __CLRCALL_PURE_OR_CDECL ios_base::_Ios_base_dtor(ios_base* _This) { // dest } _This->_Tidy(); + delete _This->_Ploc; } diff --git a/stl/src/syserror.cpp b/stl/src/syserror.cpp index 39aad443048..47c8b7e9ce6 100644 --- a/stl/src/syserror.cpp +++ b/stl/src/syserror.cpp @@ -14,94 +14,186 @@ #include "syserror_import_lib.cpp" #endif +namespace { + using _STD errc; + + struct _Win_errtab_t { // maps Windows error to Posix error + int _Windows; + errc _Posix; + }; + + constexpr _Win_errtab_t _Win_errtab[] = { + // table of Windows/Posix pairs + {ERROR_ACCESS_DENIED, errc::permission_denied}, + {ERROR_ALREADY_EXISTS, errc::file_exists}, + {ERROR_BAD_NETPATH, errc::no_such_file_or_directory}, + {ERROR_BAD_UNIT, errc::no_such_device}, + {ERROR_BROKEN_PIPE, errc::broken_pipe}, + {ERROR_BUFFER_OVERFLOW, errc::filename_too_long}, + {ERROR_BUSY, errc::device_or_resource_busy}, + {ERROR_BUSY_DRIVE, errc::device_or_resource_busy}, + {ERROR_CANNOT_MAKE, errc::permission_denied}, + {ERROR_CANTOPEN, errc::io_error}, + {ERROR_CANTREAD, errc::io_error}, + {ERROR_CANTWRITE, errc::io_error}, + {ERROR_CURRENT_DIRECTORY, errc::permission_denied}, + {ERROR_DEV_NOT_EXIST, errc::no_such_device}, + {ERROR_DEVICE_IN_USE, errc::device_or_resource_busy}, + {ERROR_DIR_NOT_EMPTY, errc::directory_not_empty}, + {ERROR_DIRECTORY, errc::invalid_argument}, + {ERROR_DISK_FULL, errc::no_space_on_device}, + {ERROR_FILE_EXISTS, errc::file_exists}, + {ERROR_FILE_NOT_FOUND, errc::no_such_file_or_directory}, + {ERROR_HANDLE_DISK_FULL, errc::no_space_on_device}, + {ERROR_INVALID_ACCESS, errc::permission_denied}, + {ERROR_INVALID_DRIVE, errc::no_such_device}, + {ERROR_INVALID_FUNCTION, errc::function_not_supported}, + {ERROR_INVALID_HANDLE, errc::invalid_argument}, + {ERROR_INVALID_NAME, errc::no_such_file_or_directory}, + {ERROR_INVALID_PARAMETER, errc::invalid_argument}, + {ERROR_LOCK_VIOLATION, errc::no_lock_available}, + {ERROR_LOCKED, errc::no_lock_available}, + {ERROR_NEGATIVE_SEEK, errc::invalid_argument}, + {ERROR_NOACCESS, errc::permission_denied}, + {ERROR_NOT_ENOUGH_MEMORY, errc::not_enough_memory}, + {ERROR_NOT_READY, errc::resource_unavailable_try_again}, + {ERROR_NOT_SAME_DEVICE, errc::cross_device_link}, + {ERROR_NOT_SUPPORTED, errc::not_supported}, + {ERROR_OPEN_FAILED, errc::io_error}, + {ERROR_OPEN_FILES, errc::device_or_resource_busy}, + {ERROR_OPERATION_ABORTED, errc::operation_canceled}, + {ERROR_OUTOFMEMORY, errc::not_enough_memory}, + {ERROR_PATH_NOT_FOUND, errc::no_such_file_or_directory}, + {ERROR_READ_FAULT, errc::io_error}, + {ERROR_REPARSE_TAG_INVALID, errc::invalid_argument}, + {ERROR_RETRY, errc::resource_unavailable_try_again}, + {ERROR_SEEK, errc::io_error}, + {ERROR_SHARING_VIOLATION, errc::permission_denied}, + {ERROR_TOO_MANY_OPEN_FILES, errc::too_many_files_open}, + {ERROR_WRITE_FAULT, errc::io_error}, + {ERROR_WRITE_PROTECT, errc::permission_denied}, + {WSAEACCES, errc::permission_denied}, + {WSAEADDRINUSE, errc::address_in_use}, + {WSAEADDRNOTAVAIL, errc::address_not_available}, + {WSAEAFNOSUPPORT, errc::address_family_not_supported}, + {WSAEALREADY, errc::connection_already_in_progress}, + {WSAEBADF, errc::bad_file_descriptor}, + {WSAECONNABORTED, errc::connection_aborted}, + {WSAECONNREFUSED, errc::connection_refused}, + {WSAECONNRESET, errc::connection_reset}, + {WSAEDESTADDRREQ, errc::destination_address_required}, + {WSAEFAULT, errc::bad_address}, + {WSAEHOSTUNREACH, errc::host_unreachable}, + {WSAEINPROGRESS, errc::operation_in_progress}, + {WSAEINTR, errc::interrupted}, + {WSAEINVAL, errc::invalid_argument}, + {WSAEISCONN, errc::already_connected}, + {WSAEMFILE, errc::too_many_files_open}, + {WSAEMSGSIZE, errc::message_size}, + {WSAENAMETOOLONG, errc::filename_too_long}, + {WSAENETDOWN, errc::network_down}, + {WSAENETRESET, errc::network_reset}, + {WSAENETUNREACH, errc::network_unreachable}, + {WSAENOBUFS, errc::no_buffer_space}, + {WSAENOPROTOOPT, errc::no_protocol_option}, + {WSAENOTCONN, errc::not_connected}, + {WSAENOTSOCK, errc::not_a_socket}, + {WSAEOPNOTSUPP, errc::operation_not_supported}, + {WSAEPROTONOSUPPORT, errc::protocol_not_supported}, + {WSAEPROTOTYPE, errc::wrong_protocol_type}, + {WSAETIMEDOUT, errc::timed_out}, + {WSAEWOULDBLOCK, errc::operation_would_block}, + }; + + struct _Sys_errtab_t { // maps error_code to NTBS + errc _Errcode; + const char* _Name; + }; + + constexpr _Sys_errtab_t _Sys_errtab[] = { + // table of Posix code/name pairs + {errc::address_family_not_supported, "address family not supported"}, + {errc::address_in_use, "address in use"}, + {errc::address_not_available, "address not available"}, + {errc::already_connected, "already connected"}, + {errc::argument_list_too_long, "argument list too long"}, + {errc::argument_out_of_domain, "argument out of domain"}, + {errc::bad_address, "bad address"}, + {errc::bad_file_descriptor, "bad file descriptor"}, + {errc::bad_message, "bad message"}, + {errc::broken_pipe, "broken pipe"}, + {errc::connection_aborted, "connection aborted"}, + {errc::connection_already_in_progress, "connection already in progress"}, + {errc::connection_refused, "connection refused"}, + {errc::connection_reset, "connection reset"}, + {errc::cross_device_link, "cross device link"}, + {errc::destination_address_required, "destination address required"}, + {errc::device_or_resource_busy, "device or resource busy"}, + {errc::directory_not_empty, "directory not empty"}, + {errc::executable_format_error, "executable format error"}, + {errc::file_exists, "file exists"}, + {errc::file_too_large, "file too large"}, + {errc::filename_too_long, "filename too long"}, + {errc::function_not_supported, "function not supported"}, + {errc::host_unreachable, "host unreachable"}, + {errc::identifier_removed, "identifier removed"}, + {errc::illegal_byte_sequence, "illegal byte sequence"}, + {errc::inappropriate_io_control_operation, "inappropriate io control operation"}, + {errc::interrupted, "interrupted"}, + {errc::invalid_argument, "invalid argument"}, + {errc::invalid_seek, "invalid seek"}, + {errc::io_error, "io error"}, + {errc::is_a_directory, "is a directory"}, + {errc::message_size, "message size"}, + {errc::network_down, "network down"}, + {errc::network_reset, "network reset"}, + {errc::network_unreachable, "network unreachable"}, + {errc::no_buffer_space, "no buffer space"}, + {errc::no_child_process, "no child process"}, + {errc::no_link, "no link"}, + {errc::no_lock_available, "no lock available"}, + {errc::no_message_available, "no message available"}, + {errc::no_message, "no message"}, + {errc::no_protocol_option, "no protocol option"}, + {errc::no_space_on_device, "no space on device"}, + {errc::no_stream_resources, "no stream resources"}, + {errc::no_such_device_or_address, "no such device or address"}, + {errc::no_such_device, "no such device"}, + {errc::no_such_file_or_directory, "no such file or directory"}, + {errc::no_such_process, "no such process"}, + {errc::not_a_directory, "not a directory"}, + {errc::not_a_socket, "not a socket"}, + {errc::not_a_stream, "not a stream"}, + {errc::not_connected, "not connected"}, + {errc::not_enough_memory, "not enough memory"}, + {errc::not_supported, "not supported"}, + {errc::operation_canceled, "operation canceled"}, + {errc::operation_in_progress, "operation in progress"}, + {errc::operation_not_permitted, "operation not permitted"}, + {errc::operation_not_supported, "operation not supported"}, + {errc::operation_would_block, "operation would block"}, + {errc::owner_dead, "owner dead"}, + {errc::permission_denied, "permission denied"}, + {errc::protocol_error, "protocol error"}, + {errc::protocol_not_supported, "protocol not supported"}, + {errc::read_only_file_system, "read only file system"}, + {errc::resource_deadlock_would_occur, "resource deadlock would occur"}, + {errc::resource_unavailable_try_again, "resource unavailable try again"}, + {errc::result_out_of_range, "result out of range"}, + {errc::state_not_recoverable, "state not recoverable"}, + {errc::stream_timeout, "stream timeout"}, + {errc::text_file_busy, "text file busy"}, + {errc::timed_out, "timed out"}, + {errc::too_many_files_open_in_system, "too many files open in system"}, + {errc::too_many_files_open, "too many files open"}, + {errc::too_many_links, "too many links"}, + {errc::too_many_symbolic_link_levels, "too many symbolic link levels"}, + {errc::value_too_large, "value too large"}, + {errc::wrong_protocol_type, "wrong protocol type"}, + }; +} // unnamed namespace + _STD_BEGIN -struct _Win_errtab_t { // maps Windows error to Posix error - int _Windows; - errc _Posix; -}; - -static constexpr _Win_errtab_t _Win_errtab[] = { - // table of Windows/Posix pairs - {ERROR_ACCESS_DENIED, errc::permission_denied}, - {ERROR_ALREADY_EXISTS, errc::file_exists}, - {ERROR_BAD_NETPATH, errc::no_such_file_or_directory}, - {ERROR_BAD_UNIT, errc::no_such_device}, - {ERROR_BROKEN_PIPE, errc::broken_pipe}, - {ERROR_BUFFER_OVERFLOW, errc::filename_too_long}, - {ERROR_BUSY, errc::device_or_resource_busy}, - {ERROR_BUSY_DRIVE, errc::device_or_resource_busy}, - {ERROR_CANNOT_MAKE, errc::permission_denied}, - {ERROR_CANTOPEN, errc::io_error}, - {ERROR_CANTREAD, errc::io_error}, - {ERROR_CANTWRITE, errc::io_error}, - {ERROR_CURRENT_DIRECTORY, errc::permission_denied}, - {ERROR_DEV_NOT_EXIST, errc::no_such_device}, - {ERROR_DEVICE_IN_USE, errc::device_or_resource_busy}, - {ERROR_DIR_NOT_EMPTY, errc::directory_not_empty}, - {ERROR_DIRECTORY, errc::invalid_argument}, - {ERROR_DISK_FULL, errc::no_space_on_device}, - {ERROR_FILE_EXISTS, errc::file_exists}, - {ERROR_FILE_NOT_FOUND, errc::no_such_file_or_directory}, - {ERROR_HANDLE_DISK_FULL, errc::no_space_on_device}, - {ERROR_INVALID_ACCESS, errc::permission_denied}, - {ERROR_INVALID_DRIVE, errc::no_such_device}, - {ERROR_INVALID_FUNCTION, errc::function_not_supported}, - {ERROR_INVALID_HANDLE, errc::invalid_argument}, - {ERROR_INVALID_NAME, errc::no_such_file_or_directory}, - {ERROR_INVALID_PARAMETER, errc::invalid_argument}, - {ERROR_LOCK_VIOLATION, errc::no_lock_available}, - {ERROR_LOCKED, errc::no_lock_available}, - {ERROR_NEGATIVE_SEEK, errc::invalid_argument}, - {ERROR_NOACCESS, errc::permission_denied}, - {ERROR_NOT_ENOUGH_MEMORY, errc::not_enough_memory}, - {ERROR_NOT_READY, errc::resource_unavailable_try_again}, - {ERROR_NOT_SAME_DEVICE, errc::cross_device_link}, - {ERROR_NOT_SUPPORTED, errc::not_supported}, - {ERROR_OPEN_FAILED, errc::io_error}, - {ERROR_OPEN_FILES, errc::device_or_resource_busy}, - {ERROR_OPERATION_ABORTED, errc::operation_canceled}, - {ERROR_OUTOFMEMORY, errc::not_enough_memory}, - {ERROR_PATH_NOT_FOUND, errc::no_such_file_or_directory}, - {ERROR_READ_FAULT, errc::io_error}, - {ERROR_REPARSE_TAG_INVALID, errc::invalid_argument}, - {ERROR_RETRY, errc::resource_unavailable_try_again}, - {ERROR_SEEK, errc::io_error}, - {ERROR_SHARING_VIOLATION, errc::permission_denied}, - {ERROR_TOO_MANY_OPEN_FILES, errc::too_many_files_open}, - {ERROR_WRITE_FAULT, errc::io_error}, - {ERROR_WRITE_PROTECT, errc::permission_denied}, - {WSAEACCES, errc::permission_denied}, - {WSAEADDRINUSE, errc::address_in_use}, - {WSAEADDRNOTAVAIL, errc::address_not_available}, - {WSAEAFNOSUPPORT, errc::address_family_not_supported}, - {WSAEALREADY, errc::connection_already_in_progress}, - {WSAEBADF, errc::bad_file_descriptor}, - {WSAECONNABORTED, errc::connection_aborted}, - {WSAECONNREFUSED, errc::connection_refused}, - {WSAECONNRESET, errc::connection_reset}, - {WSAEDESTADDRREQ, errc::destination_address_required}, - {WSAEFAULT, errc::bad_address}, - {WSAEHOSTUNREACH, errc::host_unreachable}, - {WSAEINPROGRESS, errc::operation_in_progress}, - {WSAEINTR, errc::interrupted}, - {WSAEINVAL, errc::invalid_argument}, - {WSAEISCONN, errc::already_connected}, - {WSAEMFILE, errc::too_many_files_open}, - {WSAEMSGSIZE, errc::message_size}, - {WSAENAMETOOLONG, errc::filename_too_long}, - {WSAENETDOWN, errc::network_down}, - {WSAENETRESET, errc::network_reset}, - {WSAENETUNREACH, errc::network_unreachable}, - {WSAENOBUFS, errc::no_buffer_space}, - {WSAENOPROTOOPT, errc::no_protocol_option}, - {WSAENOTCONN, errc::not_connected}, - {WSAENOTSOCK, errc::not_a_socket}, - {WSAEOPNOTSUPP, errc::operation_not_supported}, - {WSAEPROTONOSUPPORT, errc::protocol_not_supported}, - {WSAEPROTOTYPE, errc::wrong_protocol_type}, - {WSAETIMEDOUT, errc::timed_out}, - {WSAEWOULDBLOCK, errc::operation_would_block}, -}; _CRTIMP2_PURE int __CLRCALL_PURE_OR_CDECL _Winerror_map(int _Errcode) { // convert Windows error to Posix error if possible, otherwise 0 @@ -125,93 +217,6 @@ _CRTIMP2_PURE unsigned long __CLRCALL_PURE_OR_CDECL _Winerror_message( return static_cast(_CSTD __std_get_string_size_without_trailing_whitespace(_Narrow, _Chars)); } -struct _Sys_errtab_t { // maps error_code to NTBS - errc _Errcode; - const char* _Name; -}; - -static constexpr _Sys_errtab_t _Sys_errtab[] = { - // table of Posix code/name pairs - {errc::address_family_not_supported, "address family not supported"}, - {errc::address_in_use, "address in use"}, - {errc::address_not_available, "address not available"}, - {errc::already_connected, "already connected"}, - {errc::argument_list_too_long, "argument list too long"}, - {errc::argument_out_of_domain, "argument out of domain"}, - {errc::bad_address, "bad address"}, - {errc::bad_file_descriptor, "bad file descriptor"}, - {errc::bad_message, "bad message"}, - {errc::broken_pipe, "broken pipe"}, - {errc::connection_aborted, "connection aborted"}, - {errc::connection_already_in_progress, "connection already in progress"}, - {errc::connection_refused, "connection refused"}, - {errc::connection_reset, "connection reset"}, - {errc::cross_device_link, "cross device link"}, - {errc::destination_address_required, "destination address required"}, - {errc::device_or_resource_busy, "device or resource busy"}, - {errc::directory_not_empty, "directory not empty"}, - {errc::executable_format_error, "executable format error"}, - {errc::file_exists, "file exists"}, - {errc::file_too_large, "file too large"}, - {errc::filename_too_long, "filename too long"}, - {errc::function_not_supported, "function not supported"}, - {errc::host_unreachable, "host unreachable"}, - {errc::identifier_removed, "identifier removed"}, - {errc::illegal_byte_sequence, "illegal byte sequence"}, - {errc::inappropriate_io_control_operation, "inappropriate io control operation"}, - {errc::interrupted, "interrupted"}, - {errc::invalid_argument, "invalid argument"}, - {errc::invalid_seek, "invalid seek"}, - {errc::io_error, "io error"}, - {errc::is_a_directory, "is a directory"}, - {errc::message_size, "message size"}, - {errc::network_down, "network down"}, - {errc::network_reset, "network reset"}, - {errc::network_unreachable, "network unreachable"}, - {errc::no_buffer_space, "no buffer space"}, - {errc::no_child_process, "no child process"}, - {errc::no_link, "no link"}, - {errc::no_lock_available, "no lock available"}, - {errc::no_message_available, "no message available"}, - {errc::no_message, "no message"}, - {errc::no_protocol_option, "no protocol option"}, - {errc::no_space_on_device, "no space on device"}, - {errc::no_stream_resources, "no stream resources"}, - {errc::no_such_device_or_address, "no such device or address"}, - {errc::no_such_device, "no such device"}, - {errc::no_such_file_or_directory, "no such file or directory"}, - {errc::no_such_process, "no such process"}, - {errc::not_a_directory, "not a directory"}, - {errc::not_a_socket, "not a socket"}, - {errc::not_a_stream, "not a stream"}, - {errc::not_connected, "not connected"}, - {errc::not_enough_memory, "not enough memory"}, - {errc::not_supported, "not supported"}, - {errc::operation_canceled, "operation canceled"}, - {errc::operation_in_progress, "operation in progress"}, - {errc::operation_not_permitted, "operation not permitted"}, - {errc::operation_not_supported, "operation not supported"}, - {errc::operation_would_block, "operation would block"}, - {errc::owner_dead, "owner dead"}, - {errc::permission_denied, "permission denied"}, - {errc::protocol_error, "protocol error"}, - {errc::protocol_not_supported, "protocol not supported"}, - {errc::read_only_file_system, "read only file system"}, - {errc::resource_deadlock_would_occur, "resource deadlock would occur"}, - {errc::resource_unavailable_try_again, "resource unavailable try again"}, - {errc::result_out_of_range, "result out of range"}, - {errc::state_not_recoverable, "state not recoverable"}, - {errc::stream_timeout, "stream timeout"}, - {errc::text_file_busy, "text file busy"}, - {errc::timed_out, "timed out"}, - {errc::too_many_files_open_in_system, "too many files open in system"}, - {errc::too_many_files_open, "too many files open"}, - {errc::too_many_links, "too many links"}, - {errc::too_many_symbolic_link_levels, "too many symbolic link levels"}, - {errc::value_too_large, "value too large"}, - {errc::wrong_protocol_type, "wrong protocol type"}, -}; - _CRTIMP2_PURE const char* __CLRCALL_PURE_OR_CDECL _Syserror_map(int _Errcode) { // convert to name of generic error for (const auto& _Entry : _Sys_errtab) { if (static_cast(_Entry._Errcode) == _Errcode) { diff --git a/stl/src/winapinls.cpp b/stl/src/winapinls.cpp index 44f792e55a4..38e2b0c63f8 100644 --- a/stl/src/winapinls.cpp +++ b/stl/src/winapinls.cpp @@ -1,625 +1,11 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#include "awint.hpp" - -#if _STL_WIN32_WINNT < _WIN32_WINNT_VISTA - -#include -#include -#include // for _countof -#include - -namespace { - struct LCIDTOLOCALENAME { - LCID lcid; - const wchar_t* localeName; - }; - - struct LOCALENAMEINDEX { - const wchar_t* name; - int index; - }; - - // Map of LCID to locale name for Windows XP. - // Data in this table has been obtained from National Language Support (NLS) API Reference. - // The table is sorted to improve search performance. - // clang-format off - constexpr LCIDTOLOCALENAME LcidToLocaleNameTable[] = { - { 0x0001, L"ar" }, - { 0x0002, L"bg" }, - { 0x0003, L"ca" }, - { 0x0004, L"zh-CHS" }, - { 0x0005, L"cs" }, - { 0x0006, L"da" }, - { 0x0007, L"de" }, - { 0x0008, L"el" }, - { 0x0009, L"en" }, - { 0x000A, L"es" }, - { 0x000B, L"fi" }, - { 0x000C, L"fr" }, - { 0x000D, L"he" }, - { 0x000E, L"hu" }, - { 0x000F, L"is" }, - { 0x0010, L"it" }, - { 0x0011, L"ja" }, - { 0x0012, L"ko" }, - { 0x0013, L"nl" }, - { 0x0014, L"no" }, - { 0x0015, L"pl" }, - { 0x0016, L"pt" }, - { 0x0018, L"ro" }, - { 0x0019, L"ru" }, - { 0x001A, L"hr" }, - { 0x001B, L"sk" }, - { 0x001C, L"sq" }, - { 0x001D, L"sv" }, - { 0x001E, L"th" }, - { 0x001F, L"tr" }, - { 0x0020, L"ur" }, - { 0x0021, L"id" }, - { 0x0022, L"uk" }, - { 0x0023, L"be" }, - { 0x0024, L"sl" }, - { 0x0025, L"et" }, - { 0x0026, L"lv" }, - { 0x0027, L"lt" }, - { 0x0029, L"fa" }, - { 0x002A, L"vi" }, - { 0x002B, L"hy" }, - { 0x002C, L"az" }, - { 0x002D, L"eu" }, - { 0x002F, L"mk" }, - { 0x0036, L"af" }, - { 0x0037, L"ka" }, - { 0x0038, L"fo" }, - { 0x0039, L"hi" }, - { 0x003E, L"ms" }, - { 0x003F, L"kk" }, - { 0x0040, L"ky" }, - { 0x0041, L"sw" }, - { 0x0043, L"uz" }, - { 0x0044, L"tt" }, - { 0x0046, L"pa" }, - { 0x0047, L"gu" }, - { 0x0049, L"ta" }, - { 0x004A, L"te" }, - { 0x004B, L"kn" }, - { 0x004E, L"mr" }, - { 0x004F, L"sa" }, - { 0x0050, L"mn" }, - { 0x0056, L"gl" }, - { 0x0057, L"kok" }, - { 0x005A, L"syr" }, - { 0x0065, L"div" }, - { 0x007f, L"" }, - { 0x0401, L"ar-SA" }, - { 0x0402, L"bg-BG" }, - { 0x0403, L"ca-ES" }, - { 0x0404, L"zh-TW" }, - { 0x0405, L"cs-CZ" }, - { 0x0406, L"da-DK" }, - { 0x0407, L"de-DE" }, - { 0x0408, L"el-GR" }, - { 0x0409, L"en-US" }, - { 0x040B, L"fi-FI" }, - { 0x040C, L"fr-FR" }, - { 0x040D, L"he-IL" }, - { 0x040E, L"hu-HU" }, - { 0x040F, L"is-IS" }, - { 0x0410, L"it-IT" }, - { 0x0411, L"ja-JP" }, - { 0x0412, L"ko-KR" }, - { 0x0413, L"nl-NL" }, - { 0x0414, L"nb-NO" }, - { 0x0415, L"pl-PL" }, - { 0x0416, L"pt-BR" }, - { 0x0418, L"ro-RO" }, - { 0x0419, L"ru-RU" }, - { 0x041A, L"hr-HR" }, - { 0x041B, L"sk-SK" }, - { 0x041C, L"sq-AL" }, - { 0x041D, L"sv-SE" }, - { 0x041E, L"th-TH" }, - { 0x041F, L"tr-TR" }, - { 0x0420, L"ur-PK" }, - { 0x0421, L"id-ID" }, - { 0x0422, L"uk-UA" }, - { 0x0423, L"be-BY" }, - { 0x0424, L"sl-SI" }, - { 0x0425, L"et-EE" }, - { 0x0426, L"lv-LV" }, - { 0x0427, L"lt-LT" }, - { 0x0429, L"fa-IR" }, - { 0x042A, L"vi-VN" }, - { 0x042B, L"hy-AM" }, - { 0x042C, L"az-AZ-Latn" }, - { 0x042D, L"eu-ES" }, - { 0x042F, L"mk-MK" }, - { 0x0432, L"tn-ZA" }, - { 0x0434, L"xh-ZA" }, - { 0x0435, L"zu-ZA" }, - { 0x0436, L"af-ZA" }, - { 0x0437, L"ka-GE" }, - { 0x0438, L"fo-FO" }, - { 0x0439, L"hi-IN" }, - { 0x043A, L"mt-MT" }, - { 0x043B, L"se-NO" }, - { 0x043E, L"ms-MY" }, - { 0x043F, L"kk-KZ" }, - { 0x0440, L"ky-KG" }, - { 0x0441, L"sw-KE" }, - { 0x0443, L"uz-UZ-Latn" }, - { 0x0444, L"tt-RU" }, - { 0x0445, L"bn-IN" }, - { 0x0446, L"pa-IN" }, - { 0x0447, L"gu-IN" }, - { 0x0449, L"ta-IN" }, - { 0x044A, L"te-IN" }, - { 0x044B, L"kn-IN" }, - { 0x044C, L"ml-IN" }, - { 0x044E, L"mr-IN" }, - { 0x044F, L"sa-IN" }, - { 0x0450, L"mn-MN" }, - { 0x0452, L"cy-GB" }, - { 0x0456, L"gl-ES" }, - { 0x0457, L"kok-IN" }, - { 0x045A, L"syr-SY" }, - { 0x0465, L"div-MV" }, - { 0x046B, L"quz-BO" }, - { 0x046C, L"ns-ZA" }, - { 0x0481, L"mi-NZ" }, - { 0x0801, L"ar-IQ" }, - { 0x0804, L"zh-CN" }, - { 0x0807, L"de-CH" }, - { 0x0809, L"en-GB" }, - { 0x080A, L"es-MX" }, - { 0x080C, L"fr-BE" }, - { 0x0810, L"it-CH" }, - { 0x0813, L"nl-BE" }, - { 0x0814, L"nn-NO" }, - { 0x0816, L"pt-PT" }, - { 0x081A, L"sr-SP-Latn" }, - { 0x081D, L"sv-FI" }, - { 0x082C, L"az-AZ-Cyrl" }, - { 0x083B, L"se-SE" }, - { 0x083E, L"ms-BN" }, - { 0x0843, L"uz-UZ-Cyrl" }, - { 0x086B, L"quz-EC" }, - { 0x0C01, L"ar-EG" }, - { 0x0C04, L"zh-HK" }, - { 0x0C07, L"de-AT" }, - { 0x0C09, L"en-AU" }, - { 0x0C0A, L"es-ES" }, - { 0x0C0C, L"fr-CA" }, - { 0x0C1A, L"sr-SP-Cyrl" }, - { 0x0C3B, L"se-FI" }, - { 0x0C6B, L"quz-PE" }, - { 0x1001, L"ar-LY" }, - { 0x1004, L"zh-SG" }, - { 0x1007, L"de-LU" }, - { 0x1009, L"en-CA" }, - { 0x100A, L"es-GT" }, - { 0x100C, L"fr-CH" }, - { 0x101A, L"hr-BA" }, - { 0x103B, L"smj-NO" }, - { 0x1401, L"ar-DZ" }, - { 0x1404, L"zh-MO" }, - { 0x1407, L"de-LI" }, - { 0x1409, L"en-NZ" }, - { 0x140A, L"es-CR" }, - { 0x140C, L"fr-LU" }, - { 0x141A, L"bs-BA-Latn" }, - { 0x143B, L"smj-SE" }, - { 0x1801, L"ar-MA" }, - { 0x1809, L"en-IE" }, - { 0x180A, L"es-PA" }, - { 0x180C, L"fr-MC" }, - { 0x181A, L"sr-BA-Latn" }, - { 0x183B, L"sma-NO" }, - { 0x1C01, L"ar-TN" }, - { 0x1C09, L"en-ZA" }, - { 0x1C0A, L"es-DO" }, - { 0x1C1A, L"sr-BA-Cyrl" }, - { 0x1C3B, L"sma-SE" }, - { 0x2001, L"ar-OM" }, - { 0x2009, L"en-JM" }, - { 0x200A, L"es-VE" }, - { 0x203B, L"sms-FI" }, - { 0x2401, L"ar-YE" }, - { 0x2409, L"en-CB" }, - { 0x240A, L"es-CO" }, - { 0x243B, L"smn-FI" }, - { 0x2801, L"ar-SY" }, - { 0x2809, L"en-BZ" }, - { 0x280A, L"es-PE" }, - { 0x2C01, L"ar-JO" }, - { 0x2C09, L"en-TT" }, - { 0x2C0A, L"es-AR" }, - { 0x3001, L"ar-LB" }, - { 0x3009, L"en-ZW" }, - { 0x300A, L"es-EC" }, - { 0x3401, L"ar-KW" }, - { 0x3409, L"en-PH" }, - { 0x340A, L"es-CL" }, - { 0x3801, L"ar-AE" }, - { 0x380A, L"es-UY" }, - { 0x3C01, L"ar-BH" }, - { 0x3C0A, L"es-PY" }, - { 0x4001, L"ar-QA" }, - { 0x400A, L"es-BO" }, - { 0x440A, L"es-SV" }, - { 0x480A, L"es-HN" }, - { 0x4C0A, L"es-NI" }, - { 0x500A, L"es-PR" }, - { 0x7C04, L"zh-CHT" }, - { 0x7C1A, L"sr" }, - }; - // clang-format on - - static_assert(_STD is_sorted(_STD begin(LcidToLocaleNameTable), _STD end(LcidToLocaleNameTable), - [](const auto& left, const auto& right) { return left.lcid < right.lcid; })); - - // Map of locale name to an index in LcidToLocaleNameTable, for Windows XP. - // Data in this table has been obtained from National Language Support (NLS) API Reference. - // The table is sorted to improve search performance. - // clang-format off - constexpr LOCALENAMEINDEX LocaleNameToIndexTable[] = { - { L"" , 66 }, - { L"af" , 44 }, - { L"af-za" , 113 }, - { L"ar" , 0 }, - { L"ar-ae" , 216 }, - { L"ar-bh" , 218 }, - { L"ar-dz" , 177 }, - { L"ar-eg" , 160 }, - { L"ar-iq" , 143 }, - { L"ar-jo" , 207 }, - { L"ar-kw" , 213 }, - { L"ar-lb" , 210 }, - { L"ar-ly" , 169 }, - { L"ar-ma" , 185 }, - { L"ar-om" , 196 }, - { L"ar-qa" , 220 }, - { L"ar-sa" , 67 }, - { L"ar-sy" , 204 }, - { L"ar-tn" , 191 }, - { L"ar-ye" , 200 }, - { L"az" , 41 }, - { L"az-az-cyrl" , 155 }, - { L"az-az-latn" , 107 }, - { L"be" , 33 }, - { L"be-by" , 99 }, - { L"bg" , 1 }, - { L"bg-bg" , 68 }, - { L"bn-in" , 125 }, - { L"bs-ba-latn" , 183 }, - { L"ca" , 2 }, - { L"ca-es" , 69 }, - { L"cs" , 4 }, - { L"cs-cz" , 71 }, - { L"cy-gb" , 135 }, - { L"da" , 5 }, - { L"da-dk" , 72 }, - { L"de" , 6 }, - { L"de-at" , 162 }, - { L"de-ch" , 145 }, - { L"de-de" , 73 }, - { L"de-li" , 179 }, - { L"de-lu" , 171 }, - { L"div" , 65 }, - { L"div-mv" , 139 }, - { L"el" , 7 }, - { L"el-gr" , 74 }, - { L"en" , 8 }, - { L"en-au" , 163 }, - { L"en-bz" , 205 }, - { L"en-ca" , 172 }, - { L"en-cb" , 201 }, - { L"en-gb" , 146 }, - { L"en-ie" , 186 }, - { L"en-jm" , 197 }, - { L"en-nz" , 180 }, - { L"en-ph" , 214 }, - { L"en-tt" , 208 }, - { L"en-us" , 75 }, - { L"en-za" , 192 }, - { L"en-zw" , 211 }, - { L"es" , 9 }, - { L"es-ar" , 209 }, - { L"es-bo" , 221 }, - { L"es-cl" , 215 }, - { L"es-co" , 202 }, - { L"es-cr" , 181 }, - { L"es-do" , 193 }, - { L"es-ec" , 212 }, - { L"es-es" , 164 }, - { L"es-gt" , 173 }, - { L"es-hn" , 223 }, - { L"es-mx" , 147 }, - { L"es-ni" , 224 }, - { L"es-pa" , 187 }, - { L"es-pe" , 206 }, - { L"es-pr" , 225 }, - { L"es-py" , 219 }, - { L"es-sv" , 222 }, - { L"es-uy" , 217 }, - { L"es-ve" , 198 }, - { L"et" , 35 }, - { L"et-ee" , 101 }, - { L"eu" , 42 }, - { L"eu-es" , 108 }, - { L"fa" , 38 }, - { L"fa-ir" , 104 }, - { L"fi" , 10 }, - { L"fi-fi" , 76 }, - { L"fo" , 46 }, - { L"fo-fo" , 115 }, - { L"fr" , 11 }, - { L"fr-be" , 148 }, - { L"fr-ca" , 165 }, - { L"fr-ch" , 174 }, - { L"fr-fr" , 77 }, - { L"fr-lu" , 182 }, - { L"fr-mc" , 188 }, - { L"gl" , 62 }, - { L"gl-es" , 136 }, - { L"gu" , 55 }, - { L"gu-in" , 127 }, - { L"he" , 12 }, - { L"he-il" , 78 }, - { L"hi" , 47 }, - { L"hi-in" , 116 }, - { L"hr" , 24 }, - { L"hr-ba" , 175 }, - { L"hr-hr" , 90 }, - { L"hu" , 13 }, - { L"hu-hu" , 79 }, - { L"hy" , 40 }, - { L"hy-am" , 106 }, - { L"id" , 31 }, - { L"id-id" , 97 }, - { L"is" , 14 }, - { L"is-is" , 80 }, - { L"it" , 15 }, - { L"it-ch" , 149 }, - { L"it-it" , 81 }, - { L"ja" , 16 }, - { L"ja-jp" , 82 }, - { L"ka" , 45 }, - { L"ka-ge" , 114 }, - { L"kk" , 49 }, - { L"kk-kz" , 120 }, - { L"kn" , 58 }, - { L"kn-in" , 130 }, - { L"ko" , 17 }, - { L"ko-kr" , 83 }, - { L"kok" , 63 }, - { L"kok-in" , 137 }, - { L"ky" , 50 }, - { L"ky-kg" , 121 }, - { L"lt" , 37 }, - { L"lt-lt" , 103 }, - { L"lv" , 36 }, - { L"lv-lv" , 102 }, - { L"mi-nz" , 142 }, - { L"mk" , 43 }, - { L"mk-mk" , 109 }, - { L"ml-in" , 131 }, - { L"mn" , 61 }, - { L"mn-mn" , 134 }, - { L"mr" , 59 }, - { L"mr-in" , 132 }, - { L"ms" , 48 }, - { L"ms-bn" , 157 }, - { L"ms-my" , 119 }, - { L"mt-mt" , 117 }, - { L"nb-no" , 85 }, - { L"nl" , 18 }, - { L"nl-be" , 150 }, - { L"nl-nl" , 84 }, - { L"nn-no" , 151 }, - { L"no" , 19 }, - { L"ns-za" , 141 }, - { L"pa" , 54 }, - { L"pa-in" , 126 }, - { L"pl" , 20 }, - { L"pl-pl" , 86 }, - { L"pt" , 21 }, - { L"pt-br" , 87 }, - { L"pt-pt" , 152 }, - { L"quz-bo" , 140 }, - { L"quz-ec" , 159 }, - { L"quz-pe" , 168 }, - { L"ro" , 22 }, - { L"ro-ro" , 88 }, - { L"ru" , 23 }, - { L"ru-ru" , 89 }, - { L"sa" , 60 }, - { L"sa-in" , 133 }, - { L"se-fi" , 167 }, - { L"se-no" , 118 }, - { L"se-se" , 156 }, - { L"sk" , 25 }, - { L"sk-sk" , 91 }, - { L"sl" , 34 }, - { L"sl-si" , 100 }, - { L"sma-no" , 190 }, - { L"sma-se" , 195 }, - { L"smj-no" , 176 }, - { L"smj-se" , 184 }, - { L"smn-fi" , 203 }, - { L"sms-fi" , 199 }, - { L"sq" , 26 }, - { L"sq-al" , 92 }, - { L"sr" , 227 }, - { L"sr-ba-cyrl" , 194 }, - { L"sr-ba-latn" , 189 }, - { L"sr-sp-cyrl" , 166 }, - { L"sr-sp-latn" , 153 }, - { L"sv" , 27 }, - { L"sv-fi" , 154 }, - { L"sv-se" , 93 }, - { L"sw" , 51 }, - { L"sw-ke" , 122 }, - { L"syr" , 64 }, - { L"syr-sy" , 138 }, - { L"ta" , 56 }, - { L"ta-in" , 128 }, - { L"te" , 57 }, - { L"te-in" , 129 }, - { L"th" , 28 }, - { L"th-th" , 94 }, - { L"tn-za" , 110 }, - { L"tr" , 29 }, - { L"tr-tr" , 95 }, - { L"tt" , 53 }, - { L"tt-ru" , 124 }, - { L"uk" , 32 }, - { L"uk-ua" , 98 }, - { L"ur" , 30 }, - { L"ur-pk" , 96 }, - { L"uz" , 52 }, - { L"uz-uz-cyrl" , 158 }, - { L"uz-uz-latn" , 123 }, - { L"vi" , 39 }, - { L"vi-vn" , 105 }, - { L"xh-za" , 111 }, - { L"zh-chs" , 3 }, - { L"zh-cht" , 226 }, - { L"zh-cn" , 144 }, - { L"zh-hk" , 161 }, - { L"zh-mo" , 178 }, - { L"zh-sg" , 170 }, - { L"zh-tw" , 70 }, - { L"zu-za" , 112 }, - }; - // clang-format on - - // This static_assert is case-sensitive, which is more than sufficient for the case-insensitive runtime lookups. - static_assert(_STD is_sorted( - _STD begin(LocaleNameToIndexTable), _STD end(LocaleNameToIndexTable), [](const auto& left, const auto& right) { - return _STD wstring_view{left.name} < _STD wstring_view{right.name}; - })); - -} // unnamed namespace - -// __wcsnicmp_ascii -// Implements wcsnicmp for ASCII chars only. -// We can't use wcsncmp in this context because we may end up trying to modify -// locale data structs or even calling the same function in NLS code. -extern "C" int __wcsnicmp_ascii(__in const wchar_t* string1, __in const wchar_t* string2, __in size_t count) { - wchar_t f; - wchar_t l; - int result = 0; - - if (count) { - // validation section - do { - f = static_cast(__ascii_towlower(*string1)); - l = static_cast(__ascii_towlower(*string2)); - ++string1; - ++string2; - } while (--count && f && f == l); - result = static_cast(f - l); - } - - return result; -} - -// Maps input locale name to the index on LcidToLocaleNameTable -extern "C" int GetTableIndexFromLocaleName(__in const wchar_t* localeName) { - const LOCALENAMEINDEX* localeNamesIndex = LocaleNameToIndexTable; - int bottom = 0; - int top = _countof(LocaleNameToIndexTable) - 1; - - while (bottom <= top) { - int middle = (bottom + top) / 2; - int testIndex = __wcsnicmp_ascii(localeName, localeNamesIndex[middle].name, LOCALE_NAME_MAX_LENGTH); - - if (testIndex == 0) { - return localeNamesIndex[middle].index; - } - - if (testIndex < 0) { - top = middle - 1; - } else { - bottom = middle + 1; - } - } - - return -1; -} +#include -// Maps input LCID to an index in LcidToLocaleNameTable -extern "C" int GetTableIndexFromLcid(__in LCID lcid) { - int bottom = 0; - int top = _countof(LcidToLocaleNameTable) - 1; +#if _STL_WIN32_WINNT < _STL_WIN32_WINNT_VISTA - while (bottom <= top) { - int middle = (bottom + top) / 2; - int testIndex = lcid - LcidToLocaleNameTable[middle].lcid; - - if (testIndex == 0) { - return middle; - } - - if (testIndex < 0) { - top = middle - 1; - } else { - bottom = middle + 1; - } - } - - return -1; -} - -// __crtDownlevelLocaleNameToLCID() - Maps the locale name to LCID on Windows XP. -extern "C" LCID __cdecl __crtDownlevelLocaleNameToLCID(LPCWSTR localeName) { - int index; - - if (localeName == nullptr) { - return 0; - } - - index = GetTableIndexFromLocaleName(localeName); - - if (index < 0 || index >= _countof(LcidToLocaleNameTable)) { - return 0; - } - - return LcidToLocaleNameTable[index].lcid; -} - -// __crtDownlevelLCIDToLocaleName() - Maps the LCID to locale name on Windows XP. -extern "C" int __cdecl __crtDownlevelLCIDToLocaleName(LCID lcid, LPWSTR outLocaleName, int cchLocaleName) { - if (lcid == 0 || lcid == LOCALE_USER_DEFAULT || lcid == LOCALE_SYSTEM_DEFAULT) { - return 0; - } - - if ((outLocaleName == nullptr && cchLocaleName > 0) || cchLocaleName < 0) { - return 0; - } - - const int index = GetTableIndexFromLcid(lcid); - if (index < 0) { - return 0; - } - - const wchar_t* const buffer = LcidToLocaleNameTable[index].localeName; - // the following cast is safe because LOCALE_NAME_MAX_LENGTH fits in int: - const int count = static_cast(wcsnlen(buffer, LOCALE_NAME_MAX_LENGTH)); - - if (cchLocaleName > 0) { - if (count >= cchLocaleName) { - return 0; - } - - wcscpy_s(outLocaleName, cchLocaleName, buffer); - } - - return count + 1; -} +#include "awint.hpp" // TRANSITION, ABI: preserved for binary compatibility extern "C" _CRTIMP2 int __cdecl __crtCompareStringEx(_In_opt_ LPCWSTR lpLocaleName, _In_ DWORD dwCmpFlags, @@ -641,4 +27,4 @@ extern "C" _CRTIMP2 int __cdecl __crtGetLocaleInfoEx(_In_opt_ LPCWSTR const lpLo return GetLocaleInfoEx(lpLocaleName, LCType, lpLCData, cchData); } -#endif // _STL_WIN32_WINNT < _WIN32_WINNT_VISTA +#endif // _STL_WIN32_WINNT < _STL_WIN32_WINNT_VISTA diff --git a/stl/src/xonce.cpp b/stl/src/xonce.cpp index b36f0a53b41..b145b118d3b 100644 --- a/stl/src/xonce.cpp +++ b/stl/src/xonce.cpp @@ -7,12 +7,14 @@ #include "awint.hpp" -_STD_BEGIN +namespace { + struct _Xfg_trampoline_parameter { + void* _Pv; + _STD _Execute_once_fp_t _Callback; + }; +} // unnamed namespace -struct _Xfg_trampoline_parameter { - void* _Pv; - _Execute_once_fp_t _Callback; -}; +_STD_BEGIN // TRANSITION, ABI _CRTIMP2_PURE int __CLRCALL_PURE_OR_CDECL _Execute_once( diff --git a/stl/src/xstol.cpp b/stl/src/xstol.cpp index 3cd73becd64..0e5f94ba008 100644 --- a/stl/src/xstol.cpp +++ b/stl/src/xstol.cpp @@ -10,8 +10,6 @@ #include #include -#include "xmath.hpp" - _EXTERN_C_UNLESS_PURE _CRTIMP2_PURE unsigned long __CLRCALL_PURE_OR_CDECL _Stoulx(const char*, char**, int, int*); diff --git a/stl/src/xstoll.cpp b/stl/src/xstoll.cpp index 63ad80e1493..4bddd4e19c9 100644 --- a/stl/src/xstoll.cpp +++ b/stl/src/xstoll.cpp @@ -3,13 +3,13 @@ // _Stoll function +#include + #include #include #include #include -#include "xmath.hpp" - _EXTERN_C_UNLESS_PURE _CRTIMP2_PURE unsigned long long __CLRCALL_PURE_OR_CDECL _Stoullx(const char*, char**, int, int*); diff --git a/stl/src/xstoul.cpp b/stl/src/xstoul.cpp index 48f48489b22..9dd8385b8d5 100644 --- a/stl/src/xstoul.cpp +++ b/stl/src/xstoul.cpp @@ -3,6 +3,8 @@ // _Stoul function +#include + #include #include #include @@ -10,15 +12,12 @@ #include #include - _EXTERN_C_UNLESS_PURE -// macros constexpr int _Base_max = 36; // largest valid base // static data -static const char digits[] = // valid digits - "0123456789abcdefghijklmnopqrstuvwxyz"; +static const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; // valid digits // 32-bits! static const char ndigs[_Base_max + 1] = {0, 0, 33, 21, 17, 14, 13, 12, 11, 11, 10, 10, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, diff --git a/stl/src/xstoull.cpp b/stl/src/xstoull.cpp index 8a29d7ab260..3deaf903e6e 100644 --- a/stl/src/xstoull.cpp +++ b/stl/src/xstoull.cpp @@ -3,6 +3,8 @@ // _Stoull function +#include + #include #include #include diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1103c9dd3bc..fab5573e6b1 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,6 +9,8 @@ set(STL_TESTED_HEADERS_DIR "${STL_BUILD_ROOT}/inc") set(LLVM_PROJECT_SOURCE_DIR "${STL_SOURCE_DIR}/llvm-project" CACHE PATH "Location of the llvm-project source tree") +set(LIBCXX_SOURCE_DIR "${LLVM_PROJECT_SOURCE_DIR}/libcxx" CACHE PATH + "Location of the libcxx source tree") add_subdirectory(libcxx) add_subdirectory(std) diff --git a/tests/libcxx/CMakeLists.txt b/tests/libcxx/CMakeLists.txt index 3272b95ff78..cdcc763ff3d 100644 --- a/tests/libcxx/CMakeLists.txt +++ b/tests/libcxx/CMakeLists.txt @@ -3,14 +3,14 @@ set(LIBCXX_ENVLST "${CMAKE_CURRENT_SOURCE_DIR}/usual_matrix.lst") set(LIBCXX_EXPECTED_RESULTS "${CMAKE_CURRENT_SOURCE_DIR}/expected_results.txt") -set(LIBCXX_SOURCE_DIR "${LLVM_PROJECT_SOURCE_DIR}/libcxx" CACHE PATH - "Location of the libcxx source tree") set(LIBCXX_TEST_OUTPUT_DIR "${STL_TEST_OUTPUT_DIR}/libcxx") configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg) -set(LIBCXX_LIT_CONFIG_MAP "map_config(\"${LIBCXX_SOURCE_DIR}/test/lit.cfg\", \"${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg\")\n") +set(LIBCXX_LIT_CONFIG_MAP "map_config(\"${LIBCXX_SOURCE_DIR}/test/lit.cfg.py\", \"${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg\")\n") +string(APPEND LIBCXX_LIT_CONFIG_MAP "map_config(\"${CMAKE_CURRENT_SOURCE_DIR}/lit.cfg\", \"${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg\")\n") + set_property(GLOBAL APPEND_STRING PROPERTY STL_LIT_CONFIG_MAP ${LIBCXX_LIT_CONFIG_MAP}) set_property(GLOBAL APPEND PROPERTY STL_LIT_TEST_DIRS "${LIBCXX_SOURCE_DIR}/test/std") diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 33115b7aed8..86731f4c4d2 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -66,6 +66,12 @@ std/numerics/bit/bit.pow.two/log2p1.pass.cpp FAIL # test emits warning C4310: cast truncates constant value std/numerics/bit/bitops.rot/rotl.pass.cpp:0 FAIL +# libc++ doesn't yet implement P1754R1 or P1964R2, so it expects an old value for `__cpp_lib_concepts` +std/language.support/support.limits/support.limits.general/concepts.version.pass.cpp FAIL + +# libc++ doesn't yet implement P1001R2, so it expects an old value for `__cpp_lib_execution` +std/language.support/support.limits/support.limits.general/execution.version.pass.cpp FAIL + # *** INTERACTIONS WITH CONTEST / C1XX THAT UPSTREAM LIKELY WON'T FIX *** # Tracked by VSO-593630 " Enable libcxx filesystem tests" @@ -191,6 +197,7 @@ std/language.support/support.limits/support.limits.general/type_traits.version.p std/language.support/support.limits/support.limits.general/version.version.pass.cpp FAIL # Contest does not understand .sh tests, which must be run specially +std/namespace/addressable_functions.sh.cpp SKIPPED std/thread/thread.condition/thread.condition.condvarany/wait_terminates.sh.cpp SKIPPED # These tests set an allocator with a max_size() too small to default construct an unordered container @@ -215,8 +222,8 @@ std/containers/sequences/array/empty.verify.cpp SKIPPED std/containers/sequences/deque/deque.capacity/empty.verify.cpp SKIPPED std/containers/sequences/forwardlist/empty.verify.cpp SKIPPED std/containers/sequences/list/list.capacity/empty.verify.cpp SKIPPED -std/containers/sequences/vector/vector.capacity/empty.verify.cpp SKIPPED std/containers/sequences/vector.bool/empty.verify.cpp SKIPPED +std/containers/sequences/vector/vector.capacity/empty.verify.cpp SKIPPED std/containers/sequences/vector/vector.cons/copy.move_only.verify.cpp SKIPPED std/containers/unord/unord.map/empty.verify.cpp SKIPPED std/containers/unord/unord.multimap/empty.verify.cpp SKIPPED @@ -227,31 +234,55 @@ std/depr/depr.lib.binders/depr.lib.bind.2nd/bind2nd.depr_in_cxx11.verify.cpp SKI std/depr/depr.lib.binders/depr.lib.binder.1st/binder1st.depr_in_cxx11.verify.cpp SKIPPED std/depr/depr.lib.binders/depr.lib.binder.2nd/binder2nd.depr_in_cxx11.verify.cpp SKIPPED std/input.output/filesystems/class.path/path.member/path.decompose/empty.verify.cpp SKIPPED +std/input.output/iostream.format/input.streams/istream.rvalue/not_istreamable.verify.cpp SKIPPED +std/input.output/iostream.format/output.streams/ostream.rvalue/not_ostreamable.verify.cpp SKIPPED +std/input.output/iostream.format/quoted.manip/quoted_char.verify.cpp SKIPPED +std/input.output/iostream.format/quoted.manip/quoted_traits.verify.cpp SKIPPED std/iterators/iterator.container/empty.array.verify.cpp SKIPPED std/iterators/iterator.container/empty.container.verify.cpp SKIPPED std/iterators/iterator.container/empty.initializer_list.verify.cpp SKIPPED -std/language.support/support.dynamic/new.delete/new.delete.array/new_size.verify.cpp SKIPPED -std/language.support/support.dynamic/new.delete/new.delete.array/new_size_align.verify.cpp SKIPPED +std/language.support/cmp/cmp.categories.pre/zero_type.verify.cpp SKIPPED std/language.support/support.dynamic/new.delete/new.delete.array/new_size_align_nothrow.verify.cpp SKIPPED +std/language.support/support.dynamic/new.delete/new.delete.array/new_size_align.verify.cpp SKIPPED std/language.support/support.dynamic/new.delete/new.delete.array/new_size_nothrow.verify.cpp SKIPPED +std/language.support/support.dynamic/new.delete/new.delete.array/new_size.verify.cpp SKIPPED std/language.support/support.dynamic/new.delete/new.delete.placement/new_array_ptr.verify.cpp SKIPPED std/language.support/support.dynamic/new.delete/new.delete.placement/new_ptr.verify.cpp SKIPPED -std/language.support/support.dynamic/new.delete/new.delete.single/new_size.verify.cpp SKIPPED -std/language.support/support.dynamic/new.delete/new.delete.single/new_size_align.verify.cpp SKIPPED std/language.support/support.dynamic/new.delete/new.delete.single/new_size_align_nothrow.verify.cpp SKIPPED +std/language.support/support.dynamic/new.delete/new.delete.single/new_size_align.verify.cpp SKIPPED std/language.support/support.dynamic/new.delete/new.delete.single/new_size_nothrow.verify.cpp SKIPPED +std/language.support/support.dynamic/new.delete/new.delete.single/new_size.verify.cpp SKIPPED std/language.support/support.dynamic/ptr.launder/launder.nodiscard.verify.cpp SKIPPED +std/numerics/numbers/illformed.verify.cpp SKIPPED std/re/re.results/re.results.size/empty.verify.cpp SKIPPED std/strings/basic.string/string.capacity/empty.verify.cpp SKIPPED std/strings/string.view/string.view.capacity/empty.verify.cpp SKIPPED std/thread/futures/futures.async/async.verify.cpp SKIPPED -std/utilities/allocator.adaptor/allocator.adaptor.members/allocate_size.verify.cpp SKIPPED +std/thread/futures/futures.promise/copy_assign.verify.cpp SKIPPED +std/thread/futures/futures.promise/copy_ctor.verify.cpp SKIPPED +std/thread/futures/futures.unique_future/copy_assign.verify.cpp SKIPPED +std/thread/futures/futures.unique_future/copy_ctor.verify.cpp SKIPPED std/utilities/allocator.adaptor/allocator.adaptor.members/allocate_size_hint.verify.cpp SKIPPED +std/utilities/allocator.adaptor/allocator.adaptor.members/allocate_size.verify.cpp SKIPPED +std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.verify.cpp SKIPPED +std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_function.verify.cpp SKIPPED +std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_nullptr.verify.cpp SKIPPED +std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_rfunction.verify.cpp SKIPPED +std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc.verify.cpp SKIPPED +std/utilities/function.objects/negators/binary_negate.depr_in_cxx17.verify.cpp SKIPPED std/utilities/function.objects/negators/not1.depr_in_cxx17.verify.cpp SKIPPED std/utilities/function.objects/negators/not2.depr_in_cxx17.verify.cpp SKIPPED +std/utilities/function.objects/negators/unary_negate.depr_in_cxx17.verify.cpp SKIPPED std/utilities/memory/allocator.traits/allocator.traits.members/allocate.verify.cpp SKIPPED +std/utilities/memory/default.allocator/allocator_types.deprecated_in_cxx17.verify.cpp SKIPPED +std/utilities/memory/default.allocator/allocator_types.removed_in_cxx20.verify.cpp SKIPPED +std/utilities/memory/default.allocator/allocator_void.deprecated_in_cxx17.verify.cpp SKIPPED +std/utilities/memory/default.allocator/allocator.members/allocate.constexpr.size.verify.cpp SKIPPED std/utilities/memory/default.allocator/allocator.members/allocate.verify.cpp SKIPPED +# GH-1382: Our machinery doesn't understand compile-only `.compile.pass.cpp` tests +std/strings/string.view/string.view.io/stream_insert_decl_present.compile.pass.cpp SKIPPED + # *** MISSING STL FEATURES *** # C++20 P0355R7 " Calendars And Time Zones" @@ -461,8 +492,20 @@ std/utilities/variant/variant.variant/variant.assign/T.pass.cpp FAIL std/utilities/variant/variant.variant/variant.ctor/conv.pass.cpp FAIL std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp FAIL -# C++20 P0768R1 "Library Support for the Spaceship (Comparison) Operator" -std/language.support/support.limits/support.limits.general/compare.version.pass.cpp FAIL +# C++20 P0784R7 "More constexpr containers" +std/utilities/memory/allocator.traits/allocator.traits.members/allocate.pass.cpp FAIL +std/utilities/memory/allocator.traits/allocator.traits.members/allocate_hint.pass.cpp FAIL +std/utilities/memory/allocator.traits/allocator.traits.members/construct.pass.cpp FAIL +std/utilities/memory/allocator.traits/allocator.traits.members/deallocate.pass.cpp FAIL +std/utilities/memory/allocator.traits/allocator.traits.members/destroy.pass.cpp FAIL +std/utilities/memory/allocator.traits/allocator.traits.members/max_size.pass.cpp FAIL +std/utilities/memory/allocator.traits/allocator.traits.members/select_on_container_copy_construction.pass.cpp FAIL +std/utilities/memory/default.allocator/allocator.globals/eq.pass.cpp FAIL +std/utilities/memory/default.allocator/allocator.members/allocate.pass.cpp:1 FAIL +std/utilities/memory/specialized.algorithms/specialized.construct/construct_at.pass.cpp FAIL +std/utilities/memory/specialized.algorithms/specialized.destroy/destroy.pass.cpp FAIL +std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_at.pass.cpp FAIL +std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_n.pass.cpp FAIL # C++20 P0896R4 "" std/language.support/support.limits/support.limits.general/algorithm.version.pass.cpp FAIL @@ -494,6 +537,11 @@ std/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp:0 FAIL std/containers/views/span.cons/ptr_len.pass.cpp:0 FAIL std/containers/views/span.cons/ptr_ptr.pass.cpp:0 FAIL +# VSO-1168723 "Implicit copy assignment incorrectly not constexpr when subobject has explicit constexpr copy constructor" +std/utilities/utility/pairs/pairs.pair/assign_pair.pass.cpp:0 FAIL +std/utilities/utility/pairs/pairs.pair/assign_rv_pair.pass.cpp:0 FAIL +std/utilities/utility/pairs/pairs.pair/assign_rv_pair_U_V.pass.cpp:0 FAIL + # *** CLANG COMPILER BUGS *** # LLVM-33230 "Clang on Windows should define __STDCPP_THREADS__ to be 1" @@ -503,11 +551,6 @@ std/thread/macro.pass.cpp:1 FAIL std/depr/depr.c.headers/tgmath_h.pass.cpp:1 FAIL -# *** CLANG FEATURES NOT YET IMPLEMENTED *** -# P0960R3 "Allow initializing aggregates from a parenthesized list of values" -std/utilities/tuple/tuple.tuple/tuple.creation/tuple_cat.pass.cpp:0 FAIL - - # *** CLANG ISSUES, NOT YET ANALYZED *** # Clang doesn't enable sized deallocation by default. Should we add -fsized-deallocation or do something else? std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array_fsizeddeallocation.pass.cpp:1 FAIL @@ -617,6 +660,10 @@ std/language.support/support.runtime/cstdlib.pass.cpp FAIL std/thread/thread.threads/thread.thread.class/thread.thread.assign/move2.pass.cpp SKIPPED std/thread/thread.threads/thread.thread.class/thread.thread.member/join.pass.cpp SKIPPED +# OS-29877133 "LDBL_DECIMAL_DIG missing from " +std/depr/depr.c.headers/float_h.pass.cpp:0 FAIL +std/language.support/support.limits/c.limits/cfloat.pass.cpp:0 FAIL + # *** LIKELY BOGUS TESTS *** # "error: _LIBCPP_VERSION not defined" @@ -746,8 +793,6 @@ std/containers/sequences/array/array.creation/to_array.pass.cpp:0 FAIL std/iterators/predef.iterators/insert.iterators/back.insert.iterator/types.pass.cpp FAIL std/iterators/predef.iterators/insert.iterators/front.insert.iterator/types.pass.cpp FAIL std/iterators/predef.iterators/insert.iterators/insert.iterator/types.pass.cpp FAIL -std/iterators/stream.iterators/ostream.iterator/types.pass.cpp FAIL -std/iterators/stream.iterators/ostreambuf.iterator/types.pass.cpp FAIL # Tests emit warning C4244: 'argument': conversion from 'T' to 'const std::complex::_Ty', possible loss of data std/numerics/complex.number/cmplx.over/conj.pass.cpp:0 FAIL diff --git a/tests/libcxx/lit.cfg b/tests/libcxx/lit.cfg new file mode 100644 index 00000000000..e97953f5b8b --- /dev/null +++ b/tests/libcxx/lit.cfg @@ -0,0 +1,7 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +lit_config.fatal( + "You seem to be running Lit directly -- you should be running Lit through " + "/tests/utils/stl-lit/stl-lit.py, which will ensure that the right Lit configuration " + "file is used.") diff --git a/tests/libcxx/lit.site.cfg.in b/tests/libcxx/lit.site.cfg.in index 473dace7e7c..fb530312e8a 100644 --- a/tests/libcxx/lit.site.cfg.in +++ b/tests/libcxx/lit.site.cfg.in @@ -1,28 +1,40 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +import os import site site.addsitedir("@STL_TEST_UTILS_DIR@") +site.addsitedir(os.path.join("@LIBCXX_SOURCE_DIR@", "utils")) +import stl.test.config +import stl.test.features +import stl.test.file_parsing +import stl.test.format +import stl.test.params -config.configuration_variant = "stl" -config.cxx_archive_root = "@CMAKE_ARCHIVE_OUTPUT_DIRECTORY@" -config.cxx_headers = "@STL_TESTED_HEADERS_DIR@" -config.cxx_library_root = "@CMAKE_LIBRARY_OUTPUT_DIRECTORY@" -config.cxx_runtime_root = "@CMAKE_RUNTIME_OUTPUT_DIRECTORY@" -config.envlst_path = "@LIBCXX_ENVLST@" -config.expected_results_list_path = "@LIBCXX_EXPECTED_RESULTS@" -config.format_name = "LibcxxTestFormat" -config.include_dirs = ["@LIBCXX_SOURCE_DIR@/test/support"] -config.libcxx_obj_root = "@LIBCXX_TEST_OUTPUT_DIR@" -config.msvc_toolset_libs_root = "@TOOLSET_LIB@" -config.stl_build_root = "@STL_BUILD_ROOT@" -config.stl_src_root = "@STL_SOURCE_DIR@" -config.target_arch = "@VCLIBS_TARGET_ARCHITECTURE@" -config.test_subdirs = ["@LIBCXX_SOURCE_DIR@/test/std"] +config.envlst_path = '@LIBCXX_ENVLST@' +config.name = 'libc++' +config.suffixes = ['[.]pass[.]cpp$', '[.]fail[.]cpp$'] +config.test_exec_root = '@LIBCXX_TEST_OUTPUT_DIR@' +config.test_format = stl.test.format.LibcxxTestFormat() +config.test_source_root = '@LIBCXX_SOURCE_DIR@/test' -lit_config.params['use_old_format'] = True -config.loaded_site_config = True -lit_config.load_config(config, "@LIBCXX_SOURCE_DIR@/test/lit.cfg") +lit_config.expected_results = getattr(lit_config, 'expected_results', dict()) +lit_config.include_dirs = getattr(lit_config, 'include_dirs', dict()) +lit_config.library_dirs = getattr(lit_config, 'library_dirs', dict()) +lit_config.test_subdirs = getattr(lit_config, 'test_subdirs', dict()) -config.suffixes = [".pass.cpp", ".fail.cpp"] -config.test_exec_root = "@LIBCXX_TEST_OUTPUT_DIR@" +lit_config.expected_results[config.name] = stl.test.file_parsing.parse_result_file('@LIBCXX_EXPECTED_RESULTS@') +lit_config.include_dirs[config.name] = ['@STL_TESTED_HEADERS_DIR@', '@LIBCXX_SOURCE_DIR@/test/support'] +lit_config.library_dirs[config.name] = ['@CMAKE_LIBRARY_OUTPUT_DIRECTORY@', '@TOOLSET_LIB@'] +lit_config.test_subdirs[config.name] = ['@LIBCXX_SOURCE_DIR@/test/std'] + +lit_config.cxx_runtime = '@CMAKE_RUNTIME_OUTPUT_DIRECTORY@' +lit_config.target_arch = '@VCLIBS_TARGET_ARCHITECTURE@' + +# Add parameters and features to the config +stl.test.config.configure( + stl.test.params.getDefaultParameters(config, lit_config), + stl.test.features.getDefaultFeatures(config, lit_config), + config, + lit_config +) diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index 4239de46b5b..c5c7960848f 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -66,6 +66,12 @@ numerics\bit\bit.pow.two\log2p1.pass.cpp # test emits warning C4310: cast truncates constant value numerics\bit\bitops.rot\rotl.pass.cpp +# libc++ doesn't yet implement P1754R1 or P1964R2, so it expects an old value for `__cpp_lib_concepts` +language.support\support.limits\support.limits.general\concepts.version.pass.cpp + +# libc++ doesn't yet implement P1001R2, so it expects an old value for `__cpp_lib_execution` +language.support\support.limits\support.limits.general\execution.version.pass.cpp + # *** INTERACTIONS WITH CONTEST / C1XX THAT UPSTREAM LIKELY WON'T FIX *** # Tracked by VSO-593630 " Enable libcxx filesystem tests" @@ -191,6 +197,7 @@ language.support\support.limits\support.limits.general\type_traits.version.pass. language.support\support.limits\support.limits.general\version.version.pass.cpp # Contest does not understand .sh tests, which must be run specially +namespace\addressable_functions.sh.cpp thread\thread.condition\thread.condition.condvarany\wait_terminates.sh.cpp # These tests set an allocator with a max_size() too small to default construct an unordered container @@ -215,8 +222,8 @@ containers\sequences\array\empty.verify.cpp containers\sequences\deque\deque.capacity\empty.verify.cpp containers\sequences\forwardlist\empty.verify.cpp containers\sequences\list\list.capacity\empty.verify.cpp -containers\sequences\vector\vector.capacity\empty.verify.cpp containers\sequences\vector.bool\empty.verify.cpp +containers\sequences\vector\vector.capacity\empty.verify.cpp containers\sequences\vector\vector.cons\copy.move_only.verify.cpp containers\unord\unord.map\empty.verify.cpp containers\unord\unord.multimap\empty.verify.cpp @@ -227,31 +234,55 @@ depr\depr.lib.binders\depr.lib.bind.2nd\bind2nd.depr_in_cxx11.verify.cpp depr\depr.lib.binders\depr.lib.binder.1st\binder1st.depr_in_cxx11.verify.cpp depr\depr.lib.binders\depr.lib.binder.2nd\binder2nd.depr_in_cxx11.verify.cpp input.output\filesystems\class.path\path.member\path.decompose\empty.verify.cpp +input.output\iostream.format\input.streams\istream.rvalue\not_istreamable.verify.cpp +input.output\iostream.format\output.streams\ostream.rvalue\not_ostreamable.verify.cpp +input.output\iostream.format\quoted.manip\quoted_char.verify.cpp +input.output\iostream.format\quoted.manip\quoted_traits.verify.cpp iterators\iterator.container\empty.array.verify.cpp iterators\iterator.container\empty.container.verify.cpp iterators\iterator.container\empty.initializer_list.verify.cpp -language.support\support.dynamic\new.delete\new.delete.array\new_size.verify.cpp -language.support\support.dynamic\new.delete\new.delete.array\new_size_align.verify.cpp +language.support\cmp\cmp.categories.pre\zero_type.verify.cpp language.support\support.dynamic\new.delete\new.delete.array\new_size_align_nothrow.verify.cpp +language.support\support.dynamic\new.delete\new.delete.array\new_size_align.verify.cpp language.support\support.dynamic\new.delete\new.delete.array\new_size_nothrow.verify.cpp +language.support\support.dynamic\new.delete\new.delete.array\new_size.verify.cpp language.support\support.dynamic\new.delete\new.delete.placement\new_array_ptr.verify.cpp language.support\support.dynamic\new.delete\new.delete.placement\new_ptr.verify.cpp -language.support\support.dynamic\new.delete\new.delete.single\new_size.verify.cpp -language.support\support.dynamic\new.delete\new.delete.single\new_size_align.verify.cpp language.support\support.dynamic\new.delete\new.delete.single\new_size_align_nothrow.verify.cpp +language.support\support.dynamic\new.delete\new.delete.single\new_size_align.verify.cpp language.support\support.dynamic\new.delete\new.delete.single\new_size_nothrow.verify.cpp +language.support\support.dynamic\new.delete\new.delete.single\new_size.verify.cpp language.support\support.dynamic\ptr.launder\launder.nodiscard.verify.cpp +numerics\numbers\illformed.verify.cpp re\re.results\re.results.size\empty.verify.cpp strings\basic.string\string.capacity\empty.verify.cpp strings\string.view\string.view.capacity\empty.verify.cpp thread\futures\futures.async\async.verify.cpp -utilities\allocator.adaptor\allocator.adaptor.members\allocate_size.verify.cpp +thread\futures\futures.promise\copy_assign.verify.cpp +thread\futures\futures.promise\copy_ctor.verify.cpp +thread\futures\futures.unique_future\copy_assign.verify.cpp +thread\futures\futures.unique_future\copy_ctor.verify.cpp utilities\allocator.adaptor\allocator.adaptor.members\allocate_size_hint.verify.cpp +utilities\allocator.adaptor\allocator.adaptor.members\allocate_size.verify.cpp +utilities\function.objects\func.wrap\func.wrap.func\func.wrap.func.con\alloc_F.verify.cpp +utilities\function.objects\func.wrap\func.wrap.func\func.wrap.func.con\alloc_function.verify.cpp +utilities\function.objects\func.wrap\func.wrap.func\func.wrap.func.con\alloc_nullptr.verify.cpp +utilities\function.objects\func.wrap\func.wrap.func\func.wrap.func.con\alloc_rfunction.verify.cpp +utilities\function.objects\func.wrap\func.wrap.func\func.wrap.func.con\alloc.verify.cpp +utilities\function.objects\negators\binary_negate.depr_in_cxx17.verify.cpp utilities\function.objects\negators\not1.depr_in_cxx17.verify.cpp utilities\function.objects\negators\not2.depr_in_cxx17.verify.cpp +utilities\function.objects\negators\unary_negate.depr_in_cxx17.verify.cpp utilities\memory\allocator.traits\allocator.traits.members\allocate.verify.cpp +utilities\memory\default.allocator\allocator_types.deprecated_in_cxx17.verify.cpp +utilities\memory\default.allocator\allocator_types.removed_in_cxx20.verify.cpp +utilities\memory\default.allocator\allocator_void.deprecated_in_cxx17.verify.cpp +utilities\memory\default.allocator\allocator.members\allocate.constexpr.size.verify.cpp utilities\memory\default.allocator\allocator.members\allocate.verify.cpp +# GH-1382: Our machinery doesn't understand compile-only `.compile.pass.cpp` tests +strings\string.view\string.view.io\stream_insert_decl_present.compile.pass.cpp + # *** MISSING STL FEATURES *** # C++20 P0355R7 " Calendars And Time Zones" @@ -461,8 +492,20 @@ utilities\variant\variant.variant\variant.assign\T.pass.cpp utilities\variant\variant.variant\variant.ctor\conv.pass.cpp utilities\variant\variant.variant\variant.ctor\T.pass.cpp -# C++20 P0768R1 "Library Support for the Spaceship (Comparison) Operator" -language.support\support.limits\support.limits.general\compare.version.pass.cpp +# C++20 P0784R7 "More constexpr containers" +utilities\memory\allocator.traits\allocator.traits.members\allocate.pass.cpp +utilities\memory\allocator.traits\allocator.traits.members\allocate_hint.pass.cpp +utilities\memory\allocator.traits\allocator.traits.members\construct.pass.cpp +utilities\memory\allocator.traits\allocator.traits.members\deallocate.pass.cpp +utilities\memory\allocator.traits\allocator.traits.members\destroy.pass.cpp +utilities\memory\allocator.traits\allocator.traits.members\max_size.pass.cpp +utilities\memory\allocator.traits\allocator.traits.members\select_on_container_copy_construction.pass.cpp +utilities\memory\default.allocator\allocator.globals\eq.pass.cpp +utilities\memory\default.allocator\allocator.members\allocate.pass.cpp +utilities\memory\specialized.algorithms\specialized.construct\construct_at.pass.cpp +utilities\memory\specialized.algorithms\specialized.destroy\destroy.pass.cpp +utilities\memory\specialized.algorithms\specialized.destroy\destroy_at.pass.cpp +utilities\memory\specialized.algorithms\specialized.destroy\destroy_n.pass.cpp # C++20 P0896R4 "" language.support\support.limits\support.limits.general\algorithm.version.pass.cpp @@ -494,6 +537,11 @@ utilities\meta\meta.unary\meta.unary.prop\is_constructible.pass.cpp containers\views\span.cons\ptr_len.pass.cpp containers\views\span.cons\ptr_ptr.pass.cpp +# VSO-1168723 "Implicit copy assignment incorrectly not constexpr when subobject has explicit constexpr copy constructor" +utilities\utility\pairs\pairs.pair\assign_pair.pass.cpp +utilities\utility\pairs\pairs.pair\assign_rv_pair.pass.cpp +utilities\utility\pairs\pairs.pair\assign_rv_pair_U_V.pass.cpp + # *** CLANG COMPILER BUGS *** # LLVM-33230 "Clang on Windows should define __STDCPP_THREADS__ to be 1" @@ -503,11 +551,6 @@ thread\macro.pass.cpp depr\depr.c.headers\tgmath_h.pass.cpp -# *** CLANG FEATURES NOT YET IMPLEMENTED *** -# P0960R3 "Allow initializing aggregates from a parenthesized list of values" -utilities\tuple\tuple.tuple\tuple.creation\tuple_cat.pass.cpp - - # *** CLANG ISSUES, NOT YET ANALYZED *** # Clang doesn't enable sized deallocation by default. Should we add -fsized-deallocation or do something else? language.support\support.dynamic\new.delete\new.delete.array\sized_delete_array_fsizeddeallocation.pass.cpp @@ -617,6 +660,10 @@ language.support\support.runtime\cstdlib.pass.cpp thread\thread.threads\thread.thread.class\thread.thread.assign\move2.pass.cpp thread\thread.threads\thread.thread.class\thread.thread.member\join.pass.cpp +# OS-29877133 "LDBL_DECIMAL_DIG missing from " +depr\depr.c.headers\float_h.pass.cpp +language.support\support.limits\c.limits\cfloat.pass.cpp + # *** LIKELY BOGUS TESTS *** # "error: _LIBCPP_VERSION not defined" @@ -746,8 +793,6 @@ containers\sequences\array\array.creation\to_array.pass.cpp iterators\predef.iterators\insert.iterators\back.insert.iterator\types.pass.cpp iterators\predef.iterators\insert.iterators\front.insert.iterator\types.pass.cpp iterators\predef.iterators\insert.iterators\insert.iterator\types.pass.cpp -iterators\stream.iterators\ostream.iterator\types.pass.cpp -iterators\stream.iterators\ostreambuf.iterator\types.pass.cpp # Tests emit warning C4244: 'argument': conversion from 'T' to 'const std::complex::_Ty', possible loss of data numerics\complex.number\cmplx.over\conj.pass.cpp diff --git a/tests/libcxx/usual_matrix.lst b/tests/libcxx/usual_matrix.lst index 5fa9799fff4..a5dd5afec7f 100644 --- a/tests/libcxx/usual_matrix.lst +++ b/tests/libcxx/usual_matrix.lst @@ -5,5 +5,5 @@ RUNALL_INCLUDE ..\universal_prefix.lst RUNALL_CROSSLIST PM_CL="/EHsc /MTd /std:c++latest /permissive- /FImsvc_stdlib_force_include.h /wd4643" RUNALL_CROSSLIST -PM_CL="/analyze /Zc:preprocessor" +PM_CL="/analyze:autolog- /Zc:preprocessor" PM_COMPILER="clang-cl" PM_CL="-fno-ms-compatibility -fno-delayed-template-parsing" diff --git a/tests/std/include/fenv_prefix.hpp b/tests/std/include/fenv_prefix.hpp new file mode 100644 index 00000000000..bd3055a41f7 --- /dev/null +++ b/tests/std/include/fenv_prefix.hpp @@ -0,0 +1,61 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#pragma once + +#ifdef FP_CONFIG_PRESET +#if FP_CONFIG_PRESET == 3 +#define FP_PRESET_FAST 1 +#else // ^^^ FP_CONFIG_PRESET == 3 / FP_CONFIG_PRESET != 3 vvv +#define FP_PRESET_FAST 0 +#endif // ^^^ FP_CONFIG_PRESET != 3 ^^^ +#endif // defined(FP_CONFIG_PRESET) + +#ifdef FP_CONTRACT_MODE +#ifdef __clang__ + +#if FP_CONTRACT_MODE == 0 +#pragma STDC FP_CONTRACT OFF +#elif FP_CONTRACT_MODE == 1 // ^^^ no floating point contraction / standard floating point contraction vvv +#pragma STDC FP_CONTRACT ON +#elif FP_CONTRACT_MODE == 2 // ^^^ standard floating point contraction / fast floating point contraction vvv +#pragma STDC FP_CONTRACT ON +#else // ^^^ fast floating point contraction / invalid FP_CONTRACT_MODE vvv +#error invalid FP_CONTRACT_MODE +#endif // ^^^ invalid FP_CONTRACT_MODE ^^^ + +#else // ^^^ clang / MSVC vvv + +#if FP_CONTRACT_MODE == 0 +#pragma fp_contract(off) +#elif FP_CONTRACT_MODE == 1 // ^^^ no floating point contraction / standard floating point contraction vvv +#pragma fp_contract(on) +#elif FP_CONTRACT_MODE == 2 // ^^^ standard floating point contraction / fast floating point contraction vvv +#pragma fp_contract(on) +#else // ^^^ fast floating point contraction / invalid FP_CONTRACT_MODE vvv +#error invalid FP_CONTRACT_MODE +#endif // ^^^ invalid FP_CONTRACT_MODE ^^^ + +#endif // ^^^ MSVC ^^^ +#endif // defined(FP_CONTRACT_MODE) + +#include +#include + +struct fenv_initializer_t { + fenv_initializer_t() { +#if WITH_FP_ABRUPT_UNDERFLOW + { + const errno_t result = _controlfp_s(nullptr, _DN_FLUSH, _MCW_DN); + assert(result == 0); + } +#endif // WITH_FP_ABRUPT_UNDERFLOW + } + + ~fenv_initializer_t() = default; + + fenv_initializer_t(const fenv_initializer_t&) = delete; + fenv_initializer_t& operator=(const fenv_initializer_t&) = delete; +}; + +const fenv_initializer_t fenv_initializer{}; diff --git a/tests/std/lit.cfg b/tests/std/lit.cfg index fc5389e0361..e97953f5b8b 100644 --- a/tests/std/lit.cfg +++ b/tests/std/lit.cfg @@ -1,29 +1,7 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -from pathlib import Path -import importlib -import site - -site.addsitedir(str(Path(__file__).parents[1] / "utils")) -site.addsitedir(str(Path(__file__).parent / "tests")) - -config.name = 'std' -config.suffixes.add('test.cpp') - -if config.test_source_root is None: - config.test_source_root = str(Path(__file__).parent) - -config.test_exec_root = getattr(config, 'test_exec_root', None) - -if not config.test_exec_root: - import tempfile - config.test_exec_root = tempfile.mkdtemp(prefix=config.name + '-testsuite-') - lit_config.note('Creating temporary directory for tests: %s' % config.test_exec_root) - -config_module_name = getattr(config, 'config_module_name', 'stl.test.config') -config_module = importlib.import_module(config_module_name) - -configuration = config_module.Configuration(lit_config, config) -configuration.configure() -config.test_format = configuration.get_test_format() +lit_config.fatal( + "You seem to be running Lit directly -- you should be running Lit through " + "/tests/utils/stl-lit/stl-lit.py, which will ensure that the right Lit configuration " + "file is used.") diff --git a/tests/std/lit.site.cfg.in b/tests/std/lit.site.cfg.in index e3998e65f93..9a2de0aa09b 100644 --- a/tests/std/lit.site.cfg.in +++ b/tests/std/lit.site.cfg.in @@ -1,18 +1,42 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -config.cxx_archive_root = "@CMAKE_ARCHIVE_OUTPUT_DIRECTORY@" -config.cxx_headers = "@STL_TESTED_HEADERS_DIR@" -config.cxx_library_root = "@CMAKE_LIBRARY_OUTPUT_DIRECTORY@" -config.cxx_runtime_root = "@CMAKE_RUNTIME_OUTPUT_DIRECTORY@" -config.expected_results_list_path = "@STD_EXPECTED_RESULTS@" -config.include_dirs = ["@LIBCXX_SOURCE_DIR@/test/support", "@STL_SOURCE_DIR@/tests/std/include"] -config.msvc_toolset_libs_root = "@TOOLSET_LIB@" -config.stl_build_root = "@STL_BUILD_ROOT@" -config.stl_src_root = "@STL_SOURCE_DIR@" -config.target_arch = "@VCLIBS_TARGET_ARCHITECTURE@" -config.test_exec_root = "@STD_TEST_OUTPUT_DIR@" -config.test_subdirs_file = "@STD_TEST_SUBDIRS_FILE@" -config.test_subdirs_root = "@STD_TEST_SUBDIRS_ROOT@" +import os +import site +site.addsitedir("@STL_TEST_UTILS_DIR@") +site.addsitedir(os.path.join("@LIBCXX_SOURCE_DIR@", "utils")) +import stl.test.config +import stl.test.features +import stl.test.file_parsing +import stl.test.format +import stl.test.params -lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg") +config.name = 'std' +config.suffixes = ['test[.]cpp$', 'test[.]compile[.]pass[.]cpp$'] +config.test_exec_root = "@STD_TEST_OUTPUT_DIR@" +config.test_format = stl.test.format.STLTestFormat() + +lit_config.expected_results = getattr(lit_config, 'expected_results', dict()) +lit_config.include_dirs = getattr(lit_config, 'include_dirs', dict()) +lit_config.library_dirs = getattr(lit_config, 'library_dirs', dict()) +lit_config.test_subdirs = getattr(lit_config, 'test_subdirs', dict()) + +lit_config.expected_results[config.name] = stl.test.file_parsing.parse_result_file('@STD_EXPECTED_RESULTS@') +lit_config.include_dirs[config.name] = \ + ['@STL_TESTED_HEADERS_DIR@', '@LIBCXX_SOURCE_DIR@/test/support', '@STL_SOURCE_DIR@/tests/std/include'] +lit_config.library_dirs[config.name] = ['@CMAKE_LIBRARY_OUTPUT_DIRECTORY@', '@TOOLSET_LIB@'] +lit_config.test_subdirs[config.name] = \ + [os.path.normpath(os.path.join('@STD_TEST_SUBDIRS_ROOT@', path)) for \ + path in stl.test.file_parsing.parse_commented_file('@STD_TEST_SUBDIRS_FILE@')] + +lit_config.cxx_headers = '@STL_TESTED_HEADERS_DIR@' +lit_config.cxx_runtime = '@CMAKE_RUNTIME_OUTPUT_DIRECTORY@' +lit_config.target_arch = '@VCLIBS_TARGET_ARCHITECTURE@' + +# Add parameters and features to the config +stl.test.config.configure( + stl.test.params.getDefaultParameters(config, lit_config), + stl.test.features.getDefaultFeatures(config, lit_config), + config, + lit_config +) diff --git a/tests/std/test.lst b/tests/std/test.lst index 72a031644dc..3d71f043206 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -161,6 +161,7 @@ tests\GH_000625_vector_bool_optimization tests\GH_000685_condition_variable_any tests\GH_000690_overaligned_function tests\GH_000890_pow_template +tests\GH_000935_complex_numerical_accuracy tests\GH_000940_missing_valarray_copy tests\GH_001001_random_rejection_rounding tests\GH_001010_filesystem_error_encoding @@ -168,7 +169,9 @@ tests\GH_001017_discrete_distribution_out_of_range tests\GH_001059_hyperbolic_truncation tests\GH_001086_partial_sort_copy tests\GH_001103_countl_zero_correctness +tests\GH_001105_custom_streambuf_throws tests\GH_001123_random_cast_out_of_range +tests\GH_001411_core_headers tests\LWG2597_complex_branch_cut tests\LWG3018_shared_ptr_function tests\P0019R8_atomic_ref @@ -222,6 +225,7 @@ tests\P0220R1_searchers tests\P0220R1_string_view tests\P0325R4_to_array tests\P0339R6_polymorphic_allocator +tests\P0355R7_calendars_and_time_zones_io tests\P0356R5_bind_front tests\P0357R3_supporting_incomplete_types_in_reference_wrapper tests\P0414R2_shared_ptr_for_arrays @@ -245,6 +249,7 @@ tests\P0660R10_stop_token_death tests\P0674R1_make_shared_for_arrays tests\P0718R2_atomic_smart_ptrs tests\P0758R1_is_nothrow_convertible +tests\P0768R1_spaceship_cpos tests\P0768R1_spaceship_operator tests\P0769R2_shift_left_shift_right tests\P0784R7_library_support_for_more_constexpr_containers @@ -253,6 +258,8 @@ tests\P0896R4_common_iterator tests\P0896R4_common_iterator_death tests\P0896R4_counted_iterator tests\P0896R4_counted_iterator_death +tests\P0896R4_istream_view +tests\P0896R4_istream_view_death tests\P0896R4_P1614R2_comparisons tests\P0896R4_ranges_alg_adjacent_find tests\P0896R4_ranges_alg_all_of @@ -339,13 +346,21 @@ tests\P0896R4_ranges_test_machinery tests\P0896R4_ranges_to_address tests\P0896R4_stream_iterators tests\P0896R4_views_all +tests\P0896R4_views_common +tests\P0896R4_views_counted +tests\P0896R4_views_counted_death tests\P0896R4_views_drop +tests\P0896R4_views_drop_while +tests\P0896R4_views_drop_while_death +tests\P0896R4_views_elements tests\P0896R4_views_empty tests\P0896R4_views_filter tests\P0896R4_views_filter_death tests\P0896R4_views_reverse tests\P0896R4_views_single tests\P0896R4_views_take +tests\P0896R4_views_take_while +tests\P0896R4_views_take_while_death tests\P0896R4_views_transform tests\P0896R4_views_transform_death tests\P0898R3_concepts diff --git a/tests/std/tests/Dev08_527068_scl_no_exceptions/test.cpp b/tests/std/tests/Dev08_527068_scl_no_exceptions/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/Dev08_527068_scl_no_exceptions/test.cpp rename to tests/std/tests/Dev08_527068_scl_no_exceptions/test.compile.pass.cpp diff --git a/tests/std/tests/Dev09_056375_locale_cleanup/custom_format.py b/tests/std/tests/Dev09_056375_locale_cleanup/custom_format.py index 9d7c64eeaec..1792181ec4c 100644 --- a/tests/std/tests/Dev09_056375_locale_cleanup/custom_format.py +++ b/tests/std/tests/Dev09_056375_locale_cleanup/custom_format.py @@ -1,42 +1,23 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -from pathlib import Path +import os from stl.test.format import STLTestFormat, TestStep class CustomTestFormat(STLTestFormat): - def getBuildSteps(self, test, lit_config, shared): - exe_source = Path(test.getSourcePath()) - dll_source = exe_source.parent / 'TestDll.cpp' - shared.exec_dir = test.getExecDir() - output_base = test.getOutputBaseName() - output_dir = test.getOutputDir() - pass_var, fail_var = test.getPassFailResultCodes() - dll_output = output_dir / 'TestDll.DLL' - - dll_compile_cmd, out_files, exec_file = \ - test.cxx.executeBasedOnFlagsCmd([dll_source], output_dir, - shared.exec_dir, 'TestDll', - ['/Fe' + str(dll_output)], - [], ['/DLL']) - - shared.dll_file = dll_output - - yield TestStep(dll_compile_cmd, shared.exec_dir, [dll_source], - test.cxx.compile_env) - - exe_compile_cmd, out_files, shared.exec_file = \ - test.cxx.executeBasedOnFlagsCmd([exe_source], output_dir, - shared.exec_dir, output_base, - [], [], []) - - yield TestStep(exe_compile_cmd, shared.exec_dir, [exe_source], - test.cxx.compile_env) - - def getTestSteps(self, test, lit_config, shared): - if shared.exec_file is not None: - yield TestStep([str(shared.exec_file)], shared.exec_dir, - [shared.exec_file, shared.dll_file], - test.cxx.compile_env) + def getBuildSteps(self, test, litConfig, shared): + exeSource = test.getSourcePath() + dllSource = os.path.join(os.path.dirname(exeSource), 'TestDll.cpp') + + outputDir, outputBase = test.getTempPaths() + dllOutput = os.path.join(outputDir, 'TestDll.DLL') + + cmd = [test.cxx, dllSource, *test.flags, *test.compileFlags, '/Fe' + dllOutput, + '/link', '/DLL', *test.linkFlags] + + yield TestStep(cmd, shared.execDir, shared.env, False) + + for step in super().getBuildSteps(test, litConfig, shared): + yield step diff --git a/tests/std/tests/Dev09_056375_locale_cleanup/lit.local.cfg b/tests/std/tests/Dev09_056375_locale_cleanup/lit.local.cfg index 5a7c740f058..a0ea4769781 100644 --- a/tests/std/tests/Dev09_056375_locale_cleanup/lit.local.cfg +++ b/tests/std/tests/Dev09_056375_locale_cleanup/lit.local.cfg @@ -1,10 +1,9 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +import os +import site +site.addsitedir(os.path.dirname(os.path.dirname(__file__))) import Dev09_056375_locale_cleanup.custom_format -config.test_format = \ - Dev09_056375_locale_cleanup.custom_format.CustomTestFormat(config.test_format.cxx, - config.test_format.execute_external, - config.test_format.build_executor, - config.test_format.test_executor) +config.test_format = Dev09_056375_locale_cleanup.custom_format.CustomTestFormat() diff --git a/tests/std/tests/Dev09_172666_tr1_tuple_odr/custom_format.py b/tests/std/tests/Dev09_172666_tr1_tuple_odr/custom_format.py index 323790ec7cb..fa2efc4372f 100644 --- a/tests/std/tests/Dev09_172666_tr1_tuple_odr/custom_format.py +++ b/tests/std/tests/Dev09_172666_tr1_tuple_odr/custom_format.py @@ -1,23 +1,24 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -from pathlib import Path +import os from stl.test.format import STLTestFormat, TestStep +from stl.test.tests import TestType class CustomTestFormat(STLTestFormat): - def getBuildSteps(self, test, lit_config, shared): - shared.exec_dir = test.getExecDir() - exe_source = Path(test.getSourcePath()) - test2_source = exe_source.parent / 'test2.cpp' - output_base = test.getOutputBaseName() - output_dir = test.getOutputDir() + def getBuildSteps(self, test, litConfig, shared): + exeSource = test.getSourcePath() + test2Source = os.path.join(os.path.dirname(exeSource), 'test2.cpp') - cmd, out_files, shared.exec_file = \ - test.cxx.executeBasedOnFlagsCmd([exe_source, test2_source], - output_dir, shared.exec_dir, - output_base, [], [], []) + outputDir, outputBase = test.getTempPaths() - yield TestStep(cmd, shared.exec_dir, [exe_source, test2_source], - test.cxx.compile_env) + if TestType.COMPILE in test.testType: + cmd = [test.cxx, '/c', exeSource, test2Source, *test.flags, *test.compileFlags] + elif TestType.RUN in test.testType: + shared.execFile = outputBase + '.exe' + cmd = [test.cxx, exeSource, test2Source, *test.flags, *test.compileFlags, '/Fe' + shared.execFile, + '/link', *test.linkFlags] + + yield TestStep(cmd, shared.execDir, shared.env, False) diff --git a/tests/std/tests/Dev09_172666_tr1_tuple_odr/lit.local.cfg b/tests/std/tests/Dev09_172666_tr1_tuple_odr/lit.local.cfg index 4c325b48119..9d2d29f5b71 100644 --- a/tests/std/tests/Dev09_172666_tr1_tuple_odr/lit.local.cfg +++ b/tests/std/tests/Dev09_172666_tr1_tuple_odr/lit.local.cfg @@ -1,10 +1,9 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +import os +import site +site.addsitedir(os.path.dirname(os.path.dirname(__file__))) import Dev09_172666_tr1_tuple_odr.custom_format -config.test_format = \ - Dev09_172666_tr1_tuple_odr.custom_format.CustomTestFormat(config.test_format.cxx, - config.test_format.execute_external, - config.test_format.build_executor, - config.test_format.test_executor) +config.test_format = Dev09_172666_tr1_tuple_odr.custom_format.CustomTestFormat() diff --git a/tests/std/tests/Dev10_609053_ctype_char_table_size/test.cpp b/tests/std/tests/Dev10_609053_ctype_char_table_size/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/Dev10_609053_ctype_char_table_size/test.cpp rename to tests/std/tests/Dev10_609053_ctype_char_table_size/test.compile.pass.cpp diff --git a/tests/std/tests/Dev10_709168_marking_iterators_as_checked/test.cpp b/tests/std/tests/Dev10_709168_marking_iterators_as_checked/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/Dev10_709168_marking_iterators_as_checked/test.cpp rename to tests/std/tests/Dev10_709168_marking_iterators_as_checked/test.compile.pass.cpp diff --git a/tests/std/tests/Dev11_0000000_include_each_header_alone/test.cpp b/tests/std/tests/Dev11_0000000_include_each_header_alone/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/Dev11_0000000_include_each_header_alone/test.cpp rename to tests/std/tests/Dev11_0000000_include_each_header_alone/test.compile.pass.cpp diff --git a/tests/std/tests/Dev11_0272959_make_signed/test.cpp b/tests/std/tests/Dev11_0272959_make_signed/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/Dev11_0272959_make_signed/test.cpp rename to tests/std/tests/Dev11_0272959_make_signed/test.compile.pass.cpp diff --git a/tests/std/tests/Dev11_0437519_container_requirements/test.cpp b/tests/std/tests/Dev11_0437519_container_requirements/test.compile.pass.cpp similarity index 97% rename from tests/std/tests/Dev11_0437519_container_requirements/test.cpp rename to tests/std/tests/Dev11_0437519_container_requirements/test.compile.pass.cpp index 1ce8819796f..a75437f8952 100644 --- a/tests/std/tests/Dev11_0437519_container_requirements/test.cpp +++ b/tests/std/tests/Dev11_0437519_container_requirements/test.compile.pass.cpp @@ -1714,6 +1714,10 @@ DEFINE_TEST(test_ordered_associative_default_constructor_with_comparer, copy_constructible_compare const c((key())); (container_type(c)); container_type a(c); + + // GH-1037 containers should be move constructible with a non-assignable comparator + container_type b{std::move(a)}; + container_type d = std::move(b); } // X() and X a; diff --git a/tests/std/tests/Dev11_0453373_codecvt_compiles/test.cpp b/tests/std/tests/Dev11_0453373_codecvt_compiles/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/Dev11_0453373_codecvt_compiles/test.cpp rename to tests/std/tests/Dev11_0453373_codecvt_compiles/test.compile.pass.cpp diff --git a/tests/std/tests/Dev11_0483851_vector_debug_allocator_use/test.cpp b/tests/std/tests/Dev11_0483851_vector_debug_allocator_use/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/Dev11_0483851_vector_debug_allocator_use/test.cpp rename to tests/std/tests/Dev11_0483851_vector_debug_allocator_use/test.compile.pass.cpp diff --git a/tests/std/tests/Dev11_0704582_ratio/test.cpp b/tests/std/tests/Dev11_0704582_ratio/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/Dev11_0704582_ratio/test.cpp rename to tests/std/tests/Dev11_0704582_ratio/test.compile.pass.cpp diff --git a/tests/std/tests/Dev11_0836436_get_time/test.cpp b/tests/std/tests/Dev11_0836436_get_time/test.cpp index d6279cde33d..2d704e204dd 100644 --- a/tests/std/tests/Dev11_0836436_get_time/test.cpp +++ b/tests/std/tests/Dev11_0836436_get_time/test.cpp @@ -242,6 +242,78 @@ void test_990695() { assert(t.tm_year == 114); } + { + istringstream iss("20200609"); + ios_base::iostate err = Bit; + tm t{}; + const string fmt("%Y%m%d"); + use_facet>(iss.getloc()) + .get(Iter(iss.rdbuf()), Iter(), iss, err, &t, fmt.c_str(), fmt.c_str() + fmt.size()); + assert(t.tm_mon == 5); + assert(t.tm_mday == 9); + assert(t.tm_year == 120); + } + + { + istringstream iss("20201213"); + ios_base::iostate err = Bit; + tm t{}; + const string fmt("%Y%m%d"); + use_facet>(iss.getloc()) + .get(Iter(iss.rdbuf()), Iter(), iss, err, &t, fmt.c_str(), fmt.c_str() + fmt.size()); + assert(t.tm_mon == 11); + assert(t.tm_mday == 13); + assert(t.tm_year == 120); + } + + { + istringstream iss("2020112"); + ios_base::iostate err = Bit; + tm t{}; + const string fmt("%Y%m%d"); + use_facet>(iss.getloc()) + .get(Iter(iss.rdbuf()), Iter(), iss, err, &t, fmt.c_str(), fmt.c_str() + fmt.size()); + assert(t.tm_mon == 10); + assert(t.tm_mday == 2); + assert(t.tm_year == 120); + } + + { + istringstream iss("2020061125"); + ios_base::iostate err = Bit; + tm t{}; + const string fmt("%Y%m%d"); + use_facet>(iss.getloc()) + .get(Iter(iss.rdbuf()), Iter(), iss, err, &t, fmt.c_str(), fmt.c_str() + fmt.size()); + assert(t.tm_mon == 5); + assert(t.tm_mday == 11); + assert(t.tm_year == 120); + } + + { + istringstream iss("2020120625119"); + ios_base::iostate err = Bit; + tm t{}; + const string fmt("%Y12%m25%d"); + use_facet>(iss.getloc()) + .get(Iter(iss.rdbuf()), Iter(), iss, err, &t, fmt.c_str(), fmt.c_str() + fmt.size()); + assert(t.tm_mon == 5); + assert(t.tm_mday == 11); + assert(t.tm_year == 120); + } + + { + istringstream iss("2020092Text"); + ios_base::iostate err = Bit; + tm t{}; + const string fmt("%Y%m%d"); + use_facet>(iss.getloc()) + .get(Iter(iss.rdbuf()), Iter(), iss, err, &t, fmt.c_str(), fmt.c_str() + fmt.size()); + assert(t.tm_mon == 8); + assert(t.tm_mday == 2); + assert(t.tm_year == 120); + } + { istringstream iss("sep 31 2014"); ios_base::iostate err = Bit; @@ -290,6 +362,79 @@ void test_990695() { assert(t.tm_year == 105); } + { + istringstream iss("20200609"); + tm t = {}; + const string fmt("%Y%m%d"); + iss >> get_time(&t, fmt.c_str()); + assert(!iss.fail()); + assert(t.tm_mon == 5); + assert(t.tm_mday == 9); + assert(t.tm_year == 120); + } + + { + istringstream iss("2020112"); + tm t = {}; + const string fmt("%Y%m%d"); + iss >> get_time(&t, fmt.c_str()); + assert(!iss.fail()); + assert(t.tm_mon == 10); + assert(t.tm_mday == 2); + assert(t.tm_year == 120); + } + + { + istringstream iss("2020061125"); + tm t = {}; + const string fmt("%Y%m%d"); + iss >> get_time(&t, fmt.c_str()); + assert(!iss.fail()); + assert(t.tm_mon == 5); + assert(t.tm_mday == 11); + assert(t.tm_year == 120); + } + + { + istringstream iss("2020124"); + tm t = {}; + const string fmt("%Y%d%m"); + iss >> get_time(&t, fmt.c_str()); + assert(!iss.fail()); + assert(t.tm_mon == 3); + assert(t.tm_mday == 12); + assert(t.tm_year == 120); + } + + { + istringstream iss("2020104Text"); + tm t = {}; + const string fmt("%Y%d%m"); + iss >> get_time(&t, fmt.c_str()); + assert(!iss.fail()); + assert(t.tm_mon == 3); + assert(t.tm_mday == 10); + assert(t.tm_year == 120); + } + + { + istringstream iss("202000000000000923"); + tm t = {}; + const string fmt("%Y%m%d"); + iss >> get_time(&t, fmt.c_str()); + assert(iss.fail()); + } + + { + istringstream iss("202000000000000923"); + ios_base::iostate err = Bit; + tm t{}; + const string fmt("%Y%m%d"); + use_facet>(iss.getloc()) + .get(Iter(iss.rdbuf()), Iter(), iss, err, &t, fmt.c_str(), fmt.c_str() + fmt.size()); + assert(err == ios_base::failbit); + } + { // This case should fail istringstream iss("2011-D-18"); diff --git a/tests/std/tests/Dev11_1086953_call_once_overhaul/test.cpp b/tests/std/tests/Dev11_1086953_call_once_overhaul/test.cpp index 27338bff59b..35c969fc237 100644 --- a/tests/std/tests/Dev11_1086953_call_once_overhaul/test.cpp +++ b/tests/std/tests/Dev11_1086953_call_once_overhaul/test.cpp @@ -52,17 +52,7 @@ void ThrowingFunc(int* const p) { } } -// ***** Machinery to test the XP codepath: ***** -// extern "C" { -// extern void * __encodedKERNEL32Functions[40 /* eMaxKernel32Function */]; -// extern uintptr_t __security_cookie; -// } - void run_tests() { - - // ***** Machinery to test the XP codepath: ***** - // __encodedKERNEL32Functions[5 /* eInitOnceExecuteOnce */] = reinterpret_cast(__security_cookie); - // Basic check. { once_flag flag; diff --git a/tests/std/tests/GH_000545_include_compare/custom_format.py b/tests/std/tests/GH_000545_include_compare/custom_format.py index 05c32016fde..2d698f717b2 100644 --- a/tests/std/tests/GH_000545_include_compare/custom_format.py +++ b/tests/std/tests/GH_000545_include_compare/custom_format.py @@ -1,28 +1,27 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -from pathlib import Path import os from stl.test.format import STLTestFormat, TestStep +from stl.test.tests import TestType class CustomTestFormat(STLTestFormat): - def getBuildSteps(self, test, lit_config, shared): - shared.exec_dir = test.getExecDir() - output_base = test.getOutputBaseName() - output_dir = test.getOutputDir() - exe_source_dir = Path(test.getSourcePath()).parent + def getBuildSteps(self, test, litConfig, shared): + exeSourceDir = os.path.dirname(test.getSourcePath()) + _, outputBase = test.getTempPaths() - source_files = [] - for filename in os.listdir(exe_source_dir): + sourceFiles = [] + for filename in os.listdir(exeSourceDir): if filename.endswith('.cpp'): - source_files.append(exe_source_dir / filename) + sourceFiles.append(os.path.join(exeSourceDir, filename)) - cmd, out_files, shared.exec_file = \ - test.cxx.executeBasedOnFlagsCmd(source_files, output_dir, - shared.exec_dir, output_base, - [], [], []) + if TestType.COMPILE in test.testType: + cmd = [test.cxx, '/c', *sourceFiles, *test.flags, *test.compileFlags] + elif TestType.RUN in test.testType: + shared.execFile = outputBase + '.exe' + cmd = [test.cxx, *sourceFiles, *test.flags, *test.compileFlags, '/Fe' + shared.execFile, + '/link', *test.linkFlags] - yield TestStep(cmd, shared.exec_dir, source_files, - test.cxx.compile_env) + yield TestStep(cmd, shared.execDir, shared.env, False) diff --git a/tests/std/tests/GH_000545_include_compare/lit.local.cfg b/tests/std/tests/GH_000545_include_compare/lit.local.cfg index cbdcadad3d6..79640e4ec5e 100644 --- a/tests/std/tests/GH_000545_include_compare/lit.local.cfg +++ b/tests/std/tests/GH_000545_include_compare/lit.local.cfg @@ -1,10 +1,9 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +import os +import site +site.addsitedir(os.path.dirname(os.path.dirname(__file__))) import GH_000545_include_compare.custom_format -config.test_format = \ - GH_000545_include_compare.custom_format.CustomTestFormat(config.test_format.cxx, - config.test_format.execute_external, - config.test_format.build_executor, - config.test_format.test_executor) +config.test_format = GH_000545_include_compare.custom_format.CustomTestFormat() diff --git a/tests/std/tests/GH_000890_pow_template/test.cpp b/tests/std/tests/GH_000890_pow_template/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/GH_000890_pow_template/test.cpp rename to tests/std/tests/GH_000890_pow_template/test.compile.pass.cpp diff --git a/tests/std/tests/GH_000935_complex_numerical_accuracy/env.lst b/tests/std/tests/GH_000935_complex_numerical_accuracy/env.lst new file mode 100644 index 00000000000..a5fd2defde3 --- /dev/null +++ b/tests/std/tests/GH_000935_complex_numerical_accuracy/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\floating_point_model_matrix.lst diff --git a/tests/std/tests/GH_000935_complex_numerical_accuracy/floating_point_utils.hpp b/tests/std/tests/GH_000935_complex_numerical_accuracy/floating_point_utils.hpp new file mode 100644 index 00000000000..0688d763ea7 --- /dev/null +++ b/tests/std/tests/GH_000935_complex_numerical_accuracy/floating_point_utils.hpp @@ -0,0 +1,241 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace fputil { + template + using float_bits_t = typename _STD _Float_traits::type; + + template + _INLINE_VAR constexpr float_bits_t magnitude_mask_v = _STD _Float_traits::_Magnitude_mask; + + template + _INLINE_VAR constexpr float_bits_t exponent_mask_v = _STD _Float_traits::_Exponent_mask; + + template + _INLINE_VAR constexpr float_bits_t significand_mask_v = magnitude_mask_v & ~exponent_mask_v; + + template + _INLINE_VAR constexpr float_bits_t sign_mask_v = _STD _Float_traits::_Sign_mask; + + template + _INLINE_VAR constexpr float_bits_t norm_min_bits_v = significand_mask_v + 1U; + + template + _INLINE_VAR constexpr float_bits_t norm_max_bits_v = exponent_mask_v - 1U; + + template + _INLINE_VAR constexpr float_bits_t infinity_bits_v = exponent_mask_v; + + // not affected by abrupt underflow + template , int> = 0> + constexpr bool iszero(const T& x) { + return _STD _Float_abs_bits(x) == 0; + } + + // not affected by /fp:fast + template , int> = 0> + constexpr bool signbit(const T& x) { + const auto bits = std::_Bit_cast>(x); + return (bits & sign_mask_v) != 0; + } + + enum class rounding_mode { + to_nearest_ties_even = FE_TONEAREST, + toward_zero = FE_TOWARDZERO, + toward_positive = FE_UPWARD, + toward_negative = FE_DOWNWARD, + }; + + bool is_directed_rounding_mode(const rounding_mode mode) { + switch (mode) { + case rounding_mode::to_nearest_ties_even: + return false; + + case rounding_mode::toward_zero: + case rounding_mode::toward_positive: + case rounding_mode::toward_negative: + return true; + + default: + assert(false); + return false; + } + } + +#if TEST_FP_ROUNDING + +#ifdef __clang__ +// TRANSITION, should be #pragma STDC FENV_ACCESS ON +#else // ^^^ clang / MSVC vvv +// TRANSITION, VSO-923474 -- should be #pragma STDC FENV_ACCESS ON +#pragma fenv_access(on) +#endif // ^^^ MSVC ^^^ + + constexpr rounding_mode all_rounding_modes[] = { + rounding_mode::to_nearest_ties_even, + rounding_mode::toward_zero, + rounding_mode::toward_positive, + rounding_mode::toward_negative, + }; + + class rounding_guard { + public: + explicit rounding_guard(const rounding_mode mode) : old_mode{static_cast(std::fegetround())} { + const int result = std::fesetround(static_cast(mode)); + assert(result == 0); + } + + ~rounding_guard() { + const int result = std::fesetround(static_cast(old_mode)); + assert(result == 0); + } + + rounding_guard(const rounding_guard&) = delete; + rounding_guard& operator=(const rounding_guard&) = delete; + + private: + rounding_mode old_mode; + }; + +#else // ^^^ alternative rounding modes / default rounding mode only vvv + + constexpr rounding_mode all_rounding_modes[] = {rounding_mode::to_nearest_ties_even}; + + class rounding_guard { + public: + explicit rounding_guard(const rounding_mode mode) { + static_cast(mode); + } + + ~rounding_guard() = default; + + rounding_guard(const rounding_guard&) = delete; + rounding_guard& operator=(const rounding_guard&) = delete; + }; + +#endif // ^^^ default rounding mode only ^^^ + + // compares whether two floating point values are equal + // all NaNs are equal, +0.0 and -0.0 are not equal + template , int> = 0> + bool precise_equal(const T& actual, const T& expected) { + if (_STD _Is_nan(actual) || _STD _Is_nan(expected)) { + return _STD _Is_nan(actual) == _STD _Is_nan(expected); + } else { + return actual == expected && fputil::signbit(actual) == fputil::signbit(expected); + } + } + + namespace detail { + // 0x80...00 = zero, 0x80...01 = numeric_limits::denorm_min(), 0x7f...ff = -numeric_limits::denorm_min() + template , int> = 0> + float_bits_t offset_representation(const T& x) { + const float_bits_t abs_bits = _STD _Float_abs_bits(x); + return fputil::signbit(x) ? sign_mask_v - abs_bits : sign_mask_v + abs_bits; + } + + template , int> = 0> + float_bits_t is_offset_value_subnormal_or_zero(const float_bits_t offset_value) { + constexpr float_bits_t positive_norm_min_offset = sign_mask_v + norm_min_bits_v; + constexpr float_bits_t negative_norm_min_offset = sign_mask_v - norm_min_bits_v; + + return negative_norm_min_offset < offset_value && offset_value < positive_norm_min_offset; + } + + // number of ulps above zero, if we count [0, numeric_limits::min()) as 1 ulp + template , int> = 0> + double abrupt_underflow_ulp(const float_bits_t offset_value) { + using bits_type = float_bits_t; + + constexpr bits_type offset_positive_norm_min = sign_mask_v + norm_min_bits_v; + constexpr bits_type offset_negative_norm_min = sign_mask_v - norm_min_bits_v; + + if (offset_value >= offset_positive_norm_min) { + return 1.0 + (offset_value - offset_positive_norm_min); + } else if (offset_value <= offset_negative_norm_min) { + return -1.0 - (offset_negative_norm_min - offset_value); + } else if (offset_value >= sign_mask_v) { + return static_cast(offset_value - sign_mask_v) / norm_min_bits_v; + } else { + return -static_cast(sign_mask_v - offset_value) / norm_min_bits_v; + } + } + + template , int> = 0> + bool is_within_ulp_tolerance(const T& actual, const T& expected, const int ulp_tolerance) { + if (_STD _Is_nan(actual) || _STD _Is_nan(expected)) { + return _STD _Is_nan(actual) == _STD _Is_nan(expected); + } + + if (_STD _Is_inf(expected)) { + return actual == expected; + } + + if (fputil::signbit(actual) != fputil::signbit(expected)) { + return false; + } + + using bits_type = float_bits_t; + + // compute ulp difference + const bits_type actual_offset = detail::offset_representation(actual); + const bits_type expected_offset = detail::offset_representation(expected); + const bits_type ulp_diff = + actual_offset < expected_offset ? expected_offset - actual_offset : actual_offset - expected_offset; + + if (ulp_diff <= static_cast(ulp_tolerance) && ulp_tolerance >= 0) { + return true; + } + +#if WITH_FP_ABRUPT_UNDERFLOW + // handle abrupt underflow + if (detail::is_offset_value_subnormal_or_zero(expected_offset) + || detail::is_offset_value_subnormal_or_zero(actual_offset)) { + const double adjusted_actual_ulp = detail::abrupt_underflow_ulp(actual_offset); + const double adjusted_expected_ulp = detail::abrupt_underflow_ulp(expected_offset); + const double adjusted_ulp_diff = std::abs(adjusted_actual_ulp - adjusted_expected_ulp); + + if (adjusted_ulp_diff <= ulp_tolerance) { + return true; + } + } +#endif // WITH_FP_ABRUPT_UNDERFLOW + + return false; + } + + template , int> = 0> + bool is_within_absolute_tolerance(const T& actual, const T& expected, const double absolute_tolerance) { + return _STD _Is_finite(actual) && _STD _Is_finite(expected) + && std::abs(actual - expected) <= absolute_tolerance; + } + } // namespace detail + + // returns whether floating point result is nearly equal to the expected value + template , int> = 0> + bool near_equal( + const T& actual, const T& expected, const int ulp_tolerance = 1, const double absolute_tolerance = 0) { + if (precise_equal(actual, expected)) { + return true; + } + + if (ulp_tolerance > 0 && detail::is_within_ulp_tolerance(actual, expected, ulp_tolerance)) { + return true; + } + + if (absolute_tolerance > 0 && detail::is_within_absolute_tolerance(actual, expected, absolute_tolerance)) { + return true; + } + + return false; + } +} // namespace fputil diff --git a/tests/std/tests/GH_000935_complex_numerical_accuracy/log_test_cases.hpp b/tests/std/tests/GH_000935_complex_numerical_accuracy/log_test_cases.hpp new file mode 100644 index 00000000000..d67e12dd1b5 --- /dev/null +++ b/tests/std/tests/GH_000935_complex_numerical_accuracy/log_test_cases.hpp @@ -0,0 +1,276 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#pragma once + +#include + +#include "floating_point_utils.hpp" +#include "test.hpp" + +template +constexpr T pi_over_4_v = T{0.7853981633974483}; +template +constexpr T pi_over_2_v = T{1.5707963267948966}; +template +constexpr T pi_3_over_4_v = T{2.356194490192345}; +template +constexpr T pi_v = T{3.141592653589793}; + +constexpr complex_unary_test_case log_double_cases[] = { + // normal cases + {{+0x1.8p+0, +0x1p+1}, {+0x1.d5240f0e0e078p-1, +0x1.dac670561bb4fp-1}}, + {{+0x1.8p+0, -0x1p+1}, {+0x1.d5240f0e0e078p-1, -0x1.dac670561bb4fp-1}}, + {{-0x1.8p+0, +0x1p+1}, {+0x1.d5240f0e0e078p-1, +0x1.1b6e192ebbe44p+1}}, + {{-0x1.8p+0, -0x1p+1}, {+0x1.d5240f0e0e078p-1, -0x1.1b6e192ebbe44p+1}}, + {{+0x1.8p-1, +0x1p+0}, {+0x1.c8ff7c79a9a22p-3, +0x1.dac670561bb4fp-1}}, + {{+0x1.8p-1, -0x1p+0}, {+0x1.c8ff7c79a9a22p-3, -0x1.dac670561bb4fp-1}}, + {{-0x1.8p-1, +0x1p+0}, {+0x1.c8ff7c79a9a22p-3, +0x1.1b6e192ebbe44p+1}}, + {{-0x1.8p-1, -0x1p+0}, {+0x1.c8ff7c79a9a22p-3, -0x1.1b6e192ebbe44p+1}}, + {{+0x1.8p-2, +0x1p-1}, {-0x1.e148a1a2726cep-2, +0x1.dac670561bb4fp-1}}, + {{+0x1.8p-2, -0x1p-1}, {-0x1.e148a1a2726cep-2, -0x1.dac670561bb4fp-1}}, + {{-0x1.8p-2, +0x1p-1}, {-0x1.e148a1a2726cep-2, +0x1.1b6e192ebbe44p+1}}, + {{-0x1.8p-2, -0x1p-1}, {-0x1.e148a1a2726cep-2, -0x1.1b6e192ebbe44p+1}}, + + // special cases + {{+1.0, +0.0}, {0.0, +0.0}, {true, true}}, + {{+1.0, -0.0}, {0.0, -0.0}, {true, true}}, + {{+0.0, +1.0}, {0.0, +pi_over_2_v}, {true, false}}, + {{+0.0, -1.0}, {0.0, -pi_over_2_v}, {true, false}}, + {{-0.0, +1.0}, {0.0, +pi_over_2_v}, {true, false}}, + {{-0.0, -1.0}, {0.0, -pi_over_2_v}, {true, false}}, + {{-1.0, +0.0}, {0.0, +pi_v}, {true, false}}, + {{-1.0, -0.0}, {0.0, -pi_v}, {true, false}}, + +#if !FP_PRESET_FAST + {{+0.0, +0.0}, {-double_inf, +0.0}, {true, true}}, + {{+0.0, -0.0}, {-double_inf, -0.0}, {true, true}}, + {{-0.0, +0.0}, {-double_inf, +pi_v}, {true, false}}, + {{-0.0, -0.0}, {-double_inf, -pi_v}, {true, false}}, + {{+double_inf, +0.0}, {+double_inf, +0.0}, {true, true}}, + {{+double_inf, -0.0}, {+double_inf, -0.0}, {true, true}}, + {{+double_inf, +1.0}, {+double_inf, +0.0}, {true, true}}, + {{+double_inf, -1.0}, {+double_inf, -0.0}, {true, true}}, + {{+double_inf, +double_inf}, {+double_inf, +pi_over_4_v}, {true, false}}, + {{+double_inf, -double_inf}, {+double_inf, -pi_over_4_v}, {true, false}}, + {{+1.0, +double_inf}, {+double_inf, +pi_over_2_v}, {true, false}}, + {{+1.0, -double_inf}, {+double_inf, -pi_over_2_v}, {true, false}}, + {{+0.0, +double_inf}, {+double_inf, +pi_over_2_v}, {true, false}}, + {{+0.0, -double_inf}, {+double_inf, -pi_over_2_v}, {true, false}}, + {{-0.0, +double_inf}, {+double_inf, +pi_over_2_v}, {true, false}}, + {{-0.0, -double_inf}, {+double_inf, -pi_over_2_v}, {true, false}}, + {{-1.0, +double_inf}, {+double_inf, +pi_over_2_v}, {true, false}}, + {{-1.0, -double_inf}, {+double_inf, -pi_over_2_v}, {true, false}}, + {{-double_inf, +double_inf}, {+double_inf, +pi_3_over_4_v}, {true, false}}, + {{-double_inf, -double_inf}, {+double_inf, -pi_3_over_4_v}, {true, false}}, + {{-double_inf, +1.0}, {+double_inf, +pi_v}, {true, false}}, + {{-double_inf, -1.0}, {+double_inf, -pi_v}, {true, false}}, + {{-double_inf, +0.0}, {+double_inf, +pi_v}, {true, false}}, + {{-double_inf, -0.0}, {+double_inf, -pi_v}, {true, false}}, + {{+double_inf, double_nan}, {+double_inf, double_nan}, {true, true}}, + {{-double_inf, double_nan}, {+double_inf, double_nan}, {true, true}}, + {{double_nan, +double_inf}, {+double_inf, double_nan}, {true, true}}, + {{double_nan, -double_inf}, {+double_inf, double_nan}, {true, true}}, + {{double_nan, +0.0}, {double_nan, double_nan}, {true, true}}, + {{+0.0, double_nan}, {double_nan, double_nan}, {true, true}}, + {{double_nan, double_nan}, {double_nan, double_nan}, {true, true}}, +#endif // !FP_PRESET_FAST + + // abs(z) overflows + {{+0x1.fffffffffffffp+1023, +0x1.fffffffffffffp+1023}, {+0x1.63108c75a1936p+9, +0x1.921fb54442d18p-1}}, + {{-0x1.bb67ae8584caap+1023, +0x1.0000000000000p+1023}, {+0x1.62e42fefa39efp+9, +0x1.4f1a6c638d03fp+1}}, + {{+0x1.fffffffffffffp+1023, -0x0.0000000000001p-1022}, {+0x1.62e42fefa39efp+9, -0x0.0000000000000p-1022}}, + + // norm(z) overflows + {{-0x1.4e718d7d7625ap+664, -0x1.4e718d7d7625ap+665}, {+0x1.cd525d6474bb8p+8, -0x1.0468a8ace4df6p+1}}, + {{+0x1.ca3d8e6d80cbbp+511, -0x1.57ae2ad22098cp+511}, {+0x1.6300e9ed15a44p+8, -0x1.4978fa3269ee1p-1}}, + +#if !WITH_FP_ABRUPT_UNDERFLOW + // abs(z) underflows + {{-0x0.0000000000001p-1022, +0x0.0000000000001p-1022}, {-0x1.740bf7c0d927cp+9, +0x1.2d97c7f3321d2p+1}}, + {{+0x0.0000000000001p-1022, +0x0.8000000000000p-1022}, {-0x1.628b76e3a7b61p+9, +0x1.921fb54442d16p+0}}, +#endif // !WITH_FP_ABRUPT_UNDERFLOW + + // abs(z) close to underflow + {{+0x1.4p-1022, +0x1p-1022}, {-0x1.61f684c577299p+9, +0x1.5977a5103ea92p-1}}, + + // norm(z) underflows + {{+0x1.87e92154ef7acp-664, -0x1.87e92154ef7acp-665}, {-0x1.cbb65944f5e2bp+8, -0x1.dac670561bb4fp-2}}, + {{-0x1.9be34ac46b18fp-513, -0x1.1297872d9cbb5p-512}, {-0x1.62991d5d62a5ep+8, -0x1.1b6e192ebbe44p+1}}, + + // z close to 1 + {{+0x1.0000000000001p+0, -0.0}, {+0x1.fffffffffffffp-53, -0.0}, {false, true}}, + {{+0x1.fffffffffffffp-1, +0.0}, {-0x1.0000000000000p-53, +0.0}, {false, true}}, +#if !WITH_FP_ABRUPT_UNDERFLOW + {{+0x1.0000000000001p+0, -0x0.0000000000001p-1022}, {+0x1.fffffffffffffp-53, -0x0.0000000000001p-1022}}, + {{+0x1.0000000000000p+0, +0x0.0000000000001p-1022}, {+0x0.0000000000000p-1022, +0x0.0000000000001p-1022}}, + {{+0x1.fffffffffffffp-1, -0x0.0000000000001p-1022}, {-0x1.0000000000000p-53, -0x0.0000000000001p-1022}}, +#endif // !WITH_FP_ABRUPT_UNDERFLOW + {{+0x1.0000000000001p+0, +0x1p-1022}, {+0x1.fffffffffffffp-53, +0x0.fffffffffffffp-1022}}, + {{+0x1.0000000000000p+0, -0x1p-1022}, {+0x0.0000000000000p-1022, -0x1.0000000000000p-1022}}, + {{+0x1.fffffffffffffp-1, +0x1p-1022}, {-0x1.0000000000000p-53, +0x1.0000000000001p-1022}}, + {{+0x1.0000000000001p+0, -0x1p-52}, {+0x1.0000000000000p-52, -0x1.ffffffffffffep-53}}, + {{+0x1.0000000000000p+0, +0x1p-52}, {+0x1.0000000000000p-105, +0x1.0000000000000p-52}}, + {{+0x1.fffffffffffffp-1, -0x1p-52}, {-0x1.ffffffffffffep-54, -0x1.0000000000000p-52}}, + {{+0x1.fffffffffffffp-1, +0x1p-26}, {+0x1.0000000000000p-107, +0x1.0000000000000p-26}}, + + // z close to -1, i, or -i + {{-0x1.0000000000001p+0, -0x1p-52}, {+0x1.0000000000000p-52, -0x1.921fb54442d18p+1}}, + {{-0x1.0000000000000p+0, +0x1p-52}, {+0x1.0000000000000p-105, +0x1.921fb54442d18p+1}}, + {{-0x1.fffffffffffffp-1, -0x1p-52}, {-0x1.ffffffffffffep-54, -0x1.921fb54442d18p+1}}, + {{+0x1p-52, +0x1.0000000000001p+0}, {+0x1.0000000000000p-52, +0x1.921fb54442d17p+0}}, + {{-0x1p-52, +0x1.0000000000000p+0}, {+0x1.0000000000000p-105, +0x1.921fb54442d19p+0}}, + {{+0x1p-52, +0x1.fffffffffffffp-1}, {-0x1.ffffffffffffep-54, +0x1.921fb54442d17p+0}}, + {{-0x1p-52, -0x1.0000000000001p+0}, {+0x1.0000000000000p-52, -0x1.921fb54442d19p+0}}, + {{+0x1p-52, -0x1.0000000000000p+0}, {+0x1.0000000000000p-105, -0x1.921fb54442d17p+0}}, + {{-0x1p-52, -0x1.fffffffffffffp-1}, {-0x1.ffffffffffffep-54, -0x1.921fb54442d19p+0}}, + + // abs(z) close to 1 + {{+0x1.6a09e667f3bccp-1, +0x1.6a09e667f3bccp-1}, {-0x1.98d4d0da05571p-54, +0x1.921fb54442d18p-1}}, + {{+0x1.6a09e667f3bcdp-1, -0x1.6a09e667f3bcdp-1}, {+0x1.3b3efbf5e2229p-54, -0x1.921fb54442d18p-1}}, + {{-0x1.3333333333333p-1, -0x1.999999999999ap-1}, {+0x1.999999999999ap-56, -0x1.1b6e192ebbe44p+1}}, + {{-0x1.3333333333333p-1, +0x1.9999999999999p-1}, {-0x1.3333333333333p-54, +0x1.1b6e192ebbe44p+1}}, + {{+0x1.69fbe76c8b439p-1, +0x1.69fbe76c8b439p-1}, {-0x1.3cb7c059d6699p-13, +0x1.921fb54442d18p-1}}, + {{-0x1.d89d89d89d89ep-1, +0x1.89d89d89d89d6p-2}, {-0x1.3b13b13b13b0cp-57, +0x1.5f97315254857p+1}}, + + // control flow edge cases + {{+0x1p-1, +0x1.fffffffffffffp-2}, {-0x1.62e42fefa39f0p-2, +0x1.921fb54442d18p-1}}, + {{+0x1p-1, +0x1.0000000000000p-1}, {-0x1.62e42fefa39efp-2, +0x1.921fb54442d18p-1}}, + {{+0x1p-1, +0x1.0000000000001p-1}, {-0x1.62e42fefa39edp-2, +0x1.921fb54442d19p-1}}, + {{+0x1p-1, +0x1.a887293fd6f33p+0}, {+0x1.193ea7aad0309p-1, +0x1.4727f6d4d118cp+0}}, + {{+0x1p-1, +0x1.a887293fd6f34p+0}, {+0x1.193ea7aad030ap-1, +0x1.4727f6d4d118dp+0}}, + {{+0x1p-1, +0x1.a887293fd6f35p+0}, {+0x1.193ea7aad030cp-1, +0x1.4727f6d4d118dp+0}}, + {{+6.703903964971297e+153, +6e+153}, {+0x1.627e0d1e7a85dp+8, +0x1.75c8a07421461p-1}}, + {{+6.703903964971298e+153, +6e+153}, {+0x1.627e0d1e7a85dp+8, +0x1.75c8a07421461p-1}}, + {{+1e-154, +1.4156865331029228e-146}, {-0x1.4fd46e5c84953p+8, +0x1.921fb525ec2fcp+0}}, + {{+1e-154, +1.415686533102923e-146}, {-0x1.4fd46e5c84953p+8, +0x1.921fb525ec2fcp+0}}, +}; + +constexpr complex_unary_test_case log_float_cases[] = { + // normal cases + {{+0x1.8p+0F, +0x1p+1F}, {+0x1.d52410p-1F, +0x1.dac670p-1F}}, + {{+0x1.8p+0F, -0x1p+1F}, {+0x1.d52410p-1F, -0x1.dac670p-1F}}, + {{-0x1.8p+0F, +0x1p+1F}, {+0x1.d52410p-1F, +0x1.1b6e1ap+1F}}, + {{-0x1.8p+0F, -0x1p+1F}, {+0x1.d52410p-1F, -0x1.1b6e1ap+1F}}, + {{+0x1.8p-1F, +0x1p+0F}, {+0x1.c8ff7cp-3F, +0x1.dac670p-1F}}, + {{+0x1.8p-1F, -0x1p+0F}, {+0x1.c8ff7cp-3F, -0x1.dac670p-1F}}, + {{-0x1.8p-1F, +0x1p+0F}, {+0x1.c8ff7cp-3F, +0x1.1b6e1ap+1F}}, + {{-0x1.8p-1F, -0x1p+0F}, {+0x1.c8ff7cp-3F, -0x1.1b6e1ap+1F}}, + {{+0x1.8p-2F, +0x1p-1F}, {-0x1.e148a2p-2F, +0x1.dac670p-1F}}, + {{+0x1.8p-2F, -0x1p-1F}, {-0x1.e148a2p-2F, -0x1.dac670p-1F}}, + {{-0x1.8p-2F, +0x1p-1F}, {-0x1.e148a2p-2F, +0x1.1b6e1ap+1F}}, + {{-0x1.8p-2F, -0x1p-1F}, {-0x1.e148a2p-2F, -0x1.1b6e1ap+1F}}, + + // special cases + {{+1.0F, +0.0F}, {0.0F, +0.0F}, {true, true}}, + {{+1.0F, -0.0F}, {0.0F, -0.0F}, {true, true}}, + {{+0.0F, +1.0F}, {0.0F, +pi_over_2_v}, {true, false}}, + {{+0.0F, -1.0F}, {0.0F, -pi_over_2_v}, {true, false}}, + {{-0.0F, +1.0F}, {0.0F, +pi_over_2_v}, {true, false}}, + {{-0.0F, -1.0F}, {0.0F, -pi_over_2_v}, {true, false}}, + {{-1.0F, +0.0F}, {0.0F, +pi_v}, {true, false}}, + {{-1.0F, -0.0F}, {0.0F, -pi_v}, {true, false}}, + +#if !FP_PRESET_FAST + {{+0.0F, +0.0F}, {-float_inf, +0.0F}, {true, true}}, + {{+0.0F, -0.0F}, {-float_inf, -0.0F}, {true, true}}, + {{-0.0F, +0.0F}, {-float_inf, +pi_v}, {true, false}}, + {{-0.0F, -0.0F}, {-float_inf, -pi_v}, {true, false}}, + {{+float_inf, +0.0F}, {+float_inf, +0.0F}, {true, true}}, + {{+float_inf, -0.0F}, {+float_inf, -0.0F}, {true, true}}, + {{+float_inf, +1.0F}, {+float_inf, +0.0F}, {true, true}}, + {{+float_inf, -1.0F}, {+float_inf, -0.0F}, {true, true}}, + {{+float_inf, +float_inf}, {+float_inf, +pi_over_4_v}, {true, false}}, + {{+float_inf, -float_inf}, {+float_inf, -pi_over_4_v}, {true, false}}, + {{+1.0F, +float_inf}, {+float_inf, +pi_over_2_v}, {true, false}}, + {{+1.0F, -float_inf}, {+float_inf, -pi_over_2_v}, {true, false}}, + {{+0.0F, +float_inf}, {+float_inf, +pi_over_2_v}, {true, false}}, + {{+0.0F, -float_inf}, {+float_inf, -pi_over_2_v}, {true, false}}, + {{-0.0F, +float_inf}, {+float_inf, +pi_over_2_v}, {true, false}}, + {{-0.0F, -float_inf}, {+float_inf, -pi_over_2_v}, {true, false}}, + {{-1.0F, +float_inf}, {+float_inf, +pi_over_2_v}, {true, false}}, + {{-1.0F, -float_inf}, {+float_inf, -pi_over_2_v}, {true, false}}, + {{-float_inf, +float_inf}, {+float_inf, +pi_3_over_4_v}, {true, false}}, + {{-float_inf, -float_inf}, {+float_inf, -pi_3_over_4_v}, {true, false}}, + {{-float_inf, +1.0F}, {+float_inf, +pi_v}, {true, false}}, + {{-float_inf, -1.0F}, {+float_inf, -pi_v}, {true, false}}, + {{-float_inf, +0.0F}, {+float_inf, +pi_v}, {true, false}}, + {{-float_inf, -0.0F}, {+float_inf, -pi_v}, {true, false}}, + {{+float_inf, float_nan}, {+float_inf, float_nan}, {true, true}}, + {{-float_inf, float_nan}, {+float_inf, float_nan}, {true, true}}, + {{float_nan, +float_inf}, {+float_inf, float_nan}, {true, true}}, + {{float_nan, -float_inf}, {+float_inf, float_nan}, {true, true}}, + {{float_nan, +0.0F}, {float_nan, float_nan}, {true, true}}, + {{+0.0F, float_nan}, {float_nan, float_nan}, {true, true}}, + {{float_nan, float_nan}, {float_nan, float_nan}, {true, true}}, +#endif // !FP_PRESET_FAST + + // abs(z) overflows + {{+0x1.fffffep+127F, +0x1.fffffep+127F}, {+0x1.644714p+6F, +0x1.921fb6p-1F}}, + {{-0x1.bb67aep+127F, +0x1.000000p+127F}, {+0x1.62e430p+6F, +0x1.4f1a6cp+1F}}, + {{+0x1.fffffep+127F, -0x0.000002p-126F}, {+0x1.62e430p+6F, -0x0.000000p-126F}}, + + // norm(z) overflows + {{-0x1.08b2a2p+83F, -0x1.08b2a2p+84F}, {+0x1.d2f46cp+5F, -0x1.0468a8p+1F}}, + {{+0x1.bc16d6p+63F, -0x1.4d1120p+63F}, {+0x1.6389c2p+5F, -0x1.4978fap-1F}}, + +#if !WITH_FP_ABRUPT_UNDERFLOW + // abs(z) underflows + {{-0x0.000002p-126F, +0x0.000002p-126F}, {-0x1.9bbabcp+6F, +0x1.2d97c8p+1F}}, + {{+0x0.000002p-126F, +0x0.800000p-126F}, {-0x1.601e68p+6F, +0x1.921fb2p+0F}}, +#endif // !WITH_FP_ABRUPT_UNDERFLOW + + // abs(z) close to underflow + {{+0x1.4p-126F, +0x1p-126F}, {-0x1.5b76d6p+6F, +0x1.5977a6p-1F}}, + + // norm(z) underflows + {{+0x1.ef2d10p-83F, -0x1.ef2d10p-84F}, {-0x1.c6144ap+5F, -0x1.dac670p-2F}}, + {{-0x1.622d70p-61F, -0x1.d83c94p-61F}, {-0x1.4b9280p+5F, -0x1.1b6e1ap+1F}}, + + // z close to 1 + {{+0x1.000002p+0F, -0.0F}, {+0x1.fffffep-24F, -0.0F}, {false, true}}, + {{+0x1.fffffep-1F, +0.0F}, {-0x1.000000p-24F, +0.0F}, {false, true}}, +#if !WITH_FP_ABRUPT_UNDERFLOW + {{+0x1.000002p+0F, -0x0.000002p-126F}, {+0x1.fffffep-24F, -0x0.000002p-126F}}, + {{+0x1.000000p+0F, +0x0.000002p-126F}, {+0x0.000000p-126F, +0x0.000002p-126F}}, + {{+0x1.fffffep-1F, -0x0.000002p-126F}, {-0x1.000000p-24F, -0x0.000002p-126F}}, +#endif // !WITH_FP_ABRUPT_UNDERFLOW + {{+0x1.000002p+0F, +0x1.000000p-126F}, {+0x1.fffffep-24F, +0x0.fffffep-126F}}, + {{+0x1.000000p+0F, -0x1.000000p-126F}, {+0x0.000000p+0F, -0x1.000000p-126F}}, + {{+0x1.fffffep-1F, +0x1.000000p-126F}, {-0x1.000000p-24F, +0x1.000002p-126F}}, + {{+0x1.000002p+0F, -0x1.000000p-23F}, {+0x1.000000p-23F, -0x1.fffffcp-24F}}, + {{+0x1.000000p+0F, +0x1.000000p-23F}, {+0x1.000000p-47F, +0x1.000000p-23F}}, + {{+0x1.fffffep-1F, -0x1.000000p-23F}, {-0x1.fffffcp-25F, -0x1.000000p-23F}}, + {{+0x1.fffffep-1F, +0x1.6a09e6p-12F}, {-0x1.302ae0p-52F, +0x1.6a09e6p-12F}}, + + // z close to -1, i, or -i + {{-0x1.000002p+0F, -0x1.000000p-23F}, {+0x1.000000p-23F, -0x1.921fb4p+1F}}, + {{-0x1.000000p+0F, +0x1.000000p-23F}, {+0x1.000000p-47F, +0x1.921fb4p+1F}}, + {{-0x1.fffffep-1F, -0x1.000000p-23F}, {-0x1.fffffcp-25F, -0x1.921fb4p+1F}}, + {{+0x1.000000p-23F, +0x1.000002p+0F}, {+0x1.000000p-23F, +0x1.921fb4p+0F}}, + {{-0x1.000000p-23F, +0x1.000000p+0F}, {+0x1.000000p-47F, +0x1.921fb8p+0F}}, + {{+0x1.000000p-23F, +0x1.fffffep-1F}, {-0x1.fffffcp-25F, +0x1.921fb4p+0F}}, + {{-0x1.000000p-23F, -0x1.000002p+0F}, {+0x1.000000p-23F, -0x1.921fb8p+0F}}, + {{+0x1.000000p-23F, -0x1.000000p+0F}, {+0x1.000000p-47F, -0x1.921fb4p+0F}}, + {{-0x1.000000p-23F, -0x1.fffffep-1F}, {-0x1.fffffcp-25F, -0x1.921fb8p+0F}}, + + // abs(z) close to 1 + {{+0x1.6a09e6p-1F, +0x1.6a09e6p-1F}, {-0x1.26055cp-26F, +0x1.921fb6p-1F}}, + {{+0x1.6a09e8p-1F, -0x1.6a09e8p-1F}, {+0x1.20888ep-24F, -0x1.921fb6p-1F}}, + {{-0x1.333334p-1F, -0x1.99999ap-1F}, {+0x1.99999ap-26F, -0x1.1b6e1ap+1F}}, + {{-0x1.333332p-1F, +0x1.99999ap-1F}, {-0x1.999998p-27F, +0x1.1b6e18p+1F}}, + {{+0x1.69fbe8p-1F, +0x1.69fbe8p-1F}, {-0x1.3caab8p-13F, +0x1.921fb6p-1F}}, + {{-0x1.d89d8ap-1F, +0x1.89d89ep-2F}, {+0x1.d89d8ap-28F, +0x1.5f9732p+1F}}, + + // control flow edge cases + {{+0x1p-1F, +0x1.fffffep-2F}, {-0x1.62e432p-2F, +0x1.921fb4p-1F}}, + {{+0x1p-1F, +0x1.000000p-1F}, {-0x1.62e430p-2F, +0x1.921fb6p-1F}}, + {{+0x1p-1F, +0x1.000002p-1F}, {-0x1.62e42cp-2F, +0x1.921fb8p-1F}}, + {{+0x1p-1F, +0x1.a88728p+0F}, {+0x1.193ea6p-1F, +0x1.4727f6p+0F}}, + {{+0x1p-1F, +0x1.a8872ap+0F}, {+0x1.193ea8p-1F, +0x1.4727f6p+0F}}, + {{+0x1p-1F, +0x1.a8872cp+0F}, {+0x1.193eaap-1F, +0x1.4727f8p+0F}}, + {{+9.223371e+18F, +9e+18F}, {+0x1.60059cp+5F, +0x1.8bd930p-1F}}, + {{+9.2233715e+18F, +9e+18F}, {+0x1.60059cp+5F, +0x1.8bd930p-1F}}, + {{+7e-20F, +4.440892e-16F}, {-0x1.1acdd6p+5F, +0x1.921560p+0F}}, + {{+7e-20F, +4.4408926e-16F}, {-0x1.1acdd6p+5F, +0x1.921560p+0F}}, +}; diff --git a/tests/std/tests/GH_000935_complex_numerical_accuracy/sqrt_test_cases.hpp b/tests/std/tests/GH_000935_complex_numerical_accuracy/sqrt_test_cases.hpp new file mode 100644 index 00000000000..82c45a80c61 --- /dev/null +++ b/tests/std/tests/GH_000935_complex_numerical_accuracy/sqrt_test_cases.hpp @@ -0,0 +1,249 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#pragma once + +#include + +#include "floating_point_utils.hpp" +#include "test.hpp" + +constexpr complex_unary_test_case sqrt_double_cases[] = { + // normal cases + {{+0x3p-0, +0x4p-0}, {+0x2p-0, +0x1p-0}}, + {{+0x3p-0, -0x4p-0}, {+0x2p-0, -0x1p-0}}, + {{-0x3p-0, +0x4p-0}, {+0x1p-0, +0x2p-0}}, + {{-0x3p-0, -0x4p-0}, {+0x1p-0, -0x2p-0}}, + {{+0x3p-2, +0x4p-2}, {+0x2p-1, +0x1p-1}}, + {{+0x3p-2, -0x4p-2}, {+0x2p-1, -0x1p-1}}, + {{-0x3p-2, +0x4p-2}, {+0x1p-1, +0x2p-1}}, + {{-0x3p-2, -0x4p-2}, {+0x1p-1, -0x2p-1}}, + {{+0x3p-4, +0x4p-4}, {+0x2p-2, +0x1p-2}}, + {{+0x3p-4, -0x4p-4}, {+0x2p-2, -0x1p-2}}, + {{-0x3p-4, +0x4p-4}, {+0x1p-2, +0x2p-2}}, + {{-0x3p-4, -0x4p-4}, {+0x1p-2, -0x2p-2}}, + + // special cases + {{+0.0, +0.0}, {+0.0, +0.0}, {true, true}}, + {{+0.0, -0.0}, {+0.0, -0.0}, {true, true}}, + {{-0.0, +0.0}, {+0.0, +0.0}, {true, true}}, + {{-0.0, -0.0}, {+0.0, -0.0}, {true, true}}, + {{+1.0, +0.0}, {+1.0, +0.0}, {false, true}}, + {{+1.0, -0.0}, {+1.0, -0.0}, {false, true}}, + {{-1.0, +0.0}, {+0.0, +1.0}, {true, false}}, + {{-1.0, -0.0}, {+0.0, -1.0}, {true, false}}, + {{+0.0, +1.0}, {+0x1.6a09e667f3bcdp-1, +0x1.6a09e667f3bcdp-1}}, + {{+0.0, -1.0}, {+0x1.6a09e667f3bcdp-1, -0x1.6a09e667f3bcdp-1}}, + {{-0.0, +1.0}, {+0x1.6a09e667f3bcdp-1, +0x1.6a09e667f3bcdp-1}}, + {{-0.0, -1.0}, {+0x1.6a09e667f3bcdp-1, -0x1.6a09e667f3bcdp-1}}, + +#if !FP_PRESET_FAST + {{+double_inf, +0.0}, {+double_inf, +0.0}, {true, true}}, + {{+double_inf, -0.0}, {+double_inf, -0.0}, {true, true}}, + {{-double_inf, +0.0}, {+0.0, +double_inf}, {true, true}}, + {{-double_inf, -0.0}, {+0.0, -double_inf}, {true, true}}, + {{+double_inf, +1.0}, {+double_inf, +0.0}, {true, true}}, + {{+double_inf, -1.0}, {+double_inf, -0.0}, {true, true}}, + {{-double_inf, +1.0}, {+0.0, +double_inf}, {true, true}}, + {{-double_inf, -1.0}, {+0.0, -double_inf}, {true, true}}, + {{+double_inf, +double_inf}, {+double_inf, +double_inf}, {true, true}}, + {{+double_inf, -double_inf}, {+double_inf, -double_inf}, {true, true}}, + {{-double_inf, +double_inf}, {+double_inf, +double_inf}, {true, true}}, + {{-double_inf, -double_inf}, {+double_inf, -double_inf}, {true, true}}, + {{+1.0, +double_inf}, {+double_inf, +double_inf}, {true, true}}, + {{+1.0, -double_inf}, {+double_inf, -double_inf}, {true, true}}, + {{-1.0, +double_inf}, {+double_inf, +double_inf}, {true, true}}, + {{-1.0, -double_inf}, {+double_inf, -double_inf}, {true, true}}, + {{+0.0, +double_inf}, {+double_inf, +double_inf}, {true, true}}, + {{+0.0, -double_inf}, {+double_inf, -double_inf}, {true, true}}, + {{-0.0, +double_inf}, {+double_inf, +double_inf}, {true, true}}, + {{-0.0, -double_inf}, {+double_inf, -double_inf}, {true, true}}, + {{+double_inf, +double_nan}, {+double_inf, +double_nan}, {true, true}}, + {{+double_inf, -double_nan}, {+double_inf, -double_nan}, {true, true}}, + {{-double_inf, +double_nan}, {+double_nan, +double_inf}, {true, true}}, + {{-double_inf, -double_nan}, {+double_nan, -double_inf}, {true, true}}, + {{+double_nan, +double_inf}, {+double_inf, +double_inf}, {true, true}}, + {{+double_nan, -double_inf}, {+double_inf, -double_inf}, {true, true}}, + {{+double_nan, +0.0}, {+double_nan, +double_nan}, {true, true}}, + {{+double_nan, -0.0}, {+double_nan, -double_nan}, {true, true}}, + {{+0.0, +double_nan}, {+double_nan, +double_nan}, {true, true}}, + {{+0.0, -double_nan}, {+double_nan, -double_nan}, {true, true}}, + {{+double_nan, +double_nan}, {+double_nan, +double_nan}, {true, true}}, + {{+double_nan, -double_nan}, {+double_nan, -double_nan}, {true, true}}, +#endif // !FP_PRESET_FAST + + // abs(z) overflows + {{+0x1.fffffffffffffp+1023, +0x1.fffffffffffffp+1023}, {+0x1.19435caffa9f8p+512, +0x1.d203138f6c828p+510}}, + {{-0x1.bb67ae8584caap+1023, +0x1.0000000000000p+1023}, {+0x1.0907dc1930691p+510, +0x1.ee8dd4748bf15p+511}}, + {{+0x1.fffffffffffffp+1023, -0x0.0000000000001p-1022}, {+0x1.fffffffffffffp+511, -0x0.0000000000000p-1022}}, + + // norm(z) overflows + {{-0x1.4e718d7d7625ap+664, -0x1.4e718d7d7625ap+665}, {+0x1.cc1033be914a7p+331, -0x1.7432f2f528ea0p+332}}, + {{+0x1.ca3d8e6d80cbbp+511, -0x1.57ae2ad22098cp+511}, {+0x1.00e0ed3ec75c3p+256, -0x1.56813c53b47afp+254}}, + +#if !WITH_FP_ABRUPT_UNDERFLOW + // abs(z) underflows + {{-0x0.0000000000001p-1022, +0x0.0000000000001p-1022}, {+0x1.d203138f6c828p-539, +0x1.19435caffa9f9p-537}}, + {{+0x0.0000000000001p-1022, +0x0.8000000000000p-1022}, {+0x1.0000000000001p-512, +0x1.ffffffffffffep-513}}, +#endif // !WITH_FP_ABRUPT_UNDERFLOW + + // abs(z) close to underflow + {{+0x1.4p-1022, +0x1p-1022}, {+0x1.31a33f3eb2fd9p-511, +0x1.acd8ff10ebe7ep-513}}, + + // norm(z) underflows + {{+0x1.87e92154ef7acp-664, -0x1.87e92154ef7acp-665}, {+0x1.45f5e3f782563p-332, -0x1.33cb9c4327c54p-334}}, + {{-0x1.9be34ac46b18fp-513, -0x1.1297872d9cbb5p-512}, {+0x1.09220ecd9c241p-257, -0x1.09220ecd9c241p-256}}, + + // control flow edge cases + {{+0x1p-2, +0x1.fffffffffffffp-1}, {+0x1.99b96593b936dp-1, +0x1.3fe72a921c6f4p-1}}, + {{+0x1p-2, +0x1.0000000000000p+0}, {+0x1.99b96593b936ep-1, +0x1.3fe72a921c6f4p-1}}, + {{+0x1p-2, +0x1.0000000000001p+0}, {+0x1.99b96593b936ep-1, +0x1.3fe72a921c6f5p-1}}, + {{+0x1p+0, +0x1p-54}, {+0x1.0000000000000p+0, +0x1.0000000000000p-55}}, + {{+0x1p+0, +0x1p-53}, {+0x1.0000000000000p+0, +0x1.0000000000000p-54}}, + {{+0x1p+0, +0x1p-52}, {+0x1.0000000000000p+0, +0x1.0000000000000p-53}}, + {{+0x1p+0, +0x1.ffffffffffffep-2}, {+0x1.077225f1da572p+0, +0x1.f18773c56f720p-3}}, + {{+0x1p+0, +0x1.fffffffffffffp-2}, {+0x1.077225f1da572p+0, +0x1.f18773c56f721p-3}}, + {{+0x1p+0, +0x1.0000000000000p-1}, {+0x1.077225f1da572p+0, +0x1.f18773c56f721p-3}}, + {{+0x1p+0, +0x1.0000000000001p-1}, {+0x1.077225f1da572p+0, +0x1.f18773c56f723p-3}}, + {{+0x1.ffffffffffffep-970, +0x1.fffffffffffffp-970}, {+0x1.8dc42193d5c02p-485, +0x1.49852f983efddp-486}}, + {{+0x1.fffffffffffffp-970, +0x1.0000000000000p-969}, {+0x1.8dc42193d5c02p-485, +0x1.49852f983efdep-486}}, + {{+0x1.0000000000000p-969, +0x1.0000000000001p-969}, {+0x1.8dc42193d5c03p-485, +0x1.49852f983efdep-486}}, + {{+0x1.ffffffffffffep-971, +0x1.fffffffffffffp-970}, {+0x1.45a3146a88455p-485, +0x1.92826ef258d1bp-486}}, + {{+0x1.fffffffffffffp-971, +0x1.0000000000000p-969}, {+0x1.45a3146a88456p-485, +0x1.92826ef258d1bp-486}}, + {{+0x1.0000000000000p-970, +0x1.0000000000001p-969}, {+0x1.45a3146a88456p-485, +0x1.92826ef258d1cp-486}}, + {{+0x1.fffffffffffffp-971, +0x1.fffffffffffffp-970}, {+0x1.45a3146a88456p-485, +0x1.92826ef258d1bp-486}}, + {{+0x1.0000000000000p-970, +0x1.0000000000000p-969}, {+0x1.45a3146a88456p-485, +0x1.92826ef258d1bp-486}}, + {{+0x1.0000000000001p-970, +0x1.0000000000001p-969}, {+0x1.45a3146a88457p-485, +0x1.92826ef258d1cp-486}}, + {{+0x1.0000000000000p-970, +0x1.fffffffffffffp-970}, {+0x1.45a3146a88456p-485, +0x1.92826ef258d1bp-486}}, + {{+0x1.0000000000001p-970, +0x1.0000000000000p-969}, {+0x1.45a3146a88456p-485, +0x1.92826ef258d1bp-486}}, + {{+0x1.0000000000002p-970, +0x1.0000000000001p-969}, {+0x1.45a3146a88457p-485, +0x1.92826ef258d1cp-486}}, + {{+0x1p-1022, +0x1.fffffffffffffp-970}, {+0x1.0000000000000p-485, +0x1.fffffffffffffp-486}}, + {{+0x1p-1022, +0x1.0000000000000p-969}, {+0x1.0000000000000p-485, +0x1.0000000000000p-485}}, + {{+0x1p-1022, +0x1.0000000000001p-969}, {+0x1.0000000000001p-485, +0x1.0000000000000p-485}}, + +#if !WITH_FP_ABRUPT_UNDERFLOW + {{+0x0.0000000000001p-1022, +0x1.fffffffffffffp-970}, {+0x1.0000000000000p-485, +0x1.fffffffffffffp-486}}, + {{+0x0.0000000000001p-1022, +0x1.0000000000000p-969}, {+0x1.0000000000000p-485, +0x1.0000000000000p-485}}, + {{+0x0.0000000000001p-1022, +0x1.0000000000001p-969}, {+0x1.0000000000001p-485, +0x1.0000000000000p-485}}, +#endif // !WITH_FP_ABRUPT_UNDERFLOW +}; + +constexpr complex_unary_test_case sqrt_float_cases[] = { + // normal cases + {{+0x3p-0F, +0x4p-0F}, {+0x2p-0F, +0x1p-0F}}, + {{+0x3p-0F, -0x4p-0F}, {+0x2p-0F, -0x1p-0F}}, + {{-0x3p-0F, +0x4p-0F}, {+0x1p-0F, +0x2p-0F}}, + {{-0x3p-0F, -0x4p-0F}, {+0x1p-0F, -0x2p-0F}}, + {{+0x3p-2F, +0x4p-2F}, {+0x2p-1F, +0x1p-1F}}, + {{+0x3p-2F, -0x4p-2F}, {+0x2p-1F, -0x1p-1F}}, + {{-0x3p-2F, +0x4p-2F}, {+0x1p-1F, +0x2p-1F}}, + {{-0x3p-2F, -0x4p-2F}, {+0x1p-1F, -0x2p-1F}}, + {{+0x3p-4F, +0x4p-4F}, {+0x2p-2F, +0x1p-2F}}, + {{+0x3p-4F, -0x4p-4F}, {+0x2p-2F, -0x1p-2F}}, + {{-0x3p-4F, +0x4p-4F}, {+0x1p-2F, +0x2p-2F}}, + {{-0x3p-4F, -0x4p-4F}, {+0x1p-2F, -0x2p-2F}}, + + // special cases + {{+0.0F, +0.0F}, {+0.0F, +0.0F}, {true, true}}, + {{+0.0F, -0.0F}, {+0.0F, -0.0F}, {true, true}}, + {{-0.0F, +0.0F}, {+0.0F, +0.0F}, {true, true}}, + {{-0.0F, -0.0F}, {+0.0F, -0.0F}, {true, true}}, + {{+1.0F, +0.0F}, {+1.0F, +0.0F}, {false, true}}, + {{+1.0F, -0.0F}, {+1.0F, -0.0F}, {false, true}}, + {{-1.0F, +0.0F}, {+0.0F, +1.0F}, {true, false}}, + {{-1.0F, -0.0F}, {+0.0F, -1.0F}, {true, false}}, + {{+0.0F, +1.0F}, {+0x1.6a09e6p-1F, +0x1.6a09e6p-1F}}, + {{+0.0F, -1.0F}, {+0x1.6a09e6p-1F, -0x1.6a09e6p-1F}}, + {{-0.0F, +1.0F}, {+0x1.6a09e6p-1F, +0x1.6a09e6p-1F}}, + {{-0.0F, -1.0F}, {+0x1.6a09e6p-1F, -0x1.6a09e6p-1F}}, + +#if !FP_PRESET_FAST + {{+float_inf, +0.0F}, {+float_inf, +0.0F}, {true, true}}, + {{+float_inf, -0.0F}, {+float_inf, -0.0F}, {true, true}}, + {{-float_inf, +0.0F}, {+0.0F, +float_inf}, {true, true}}, + {{-float_inf, -0.0F}, {+0.0F, -float_inf}, {true, true}}, + {{+float_inf, +1.0F}, {+float_inf, +0.0F}, {true, true}}, + {{+float_inf, -1.0F}, {+float_inf, -0.0F}, {true, true}}, + {{-float_inf, +1.0F}, {+0.0F, +float_inf}, {true, true}}, + {{-float_inf, -1.0F}, {+0.0F, -float_inf}, {true, true}}, + {{+float_inf, +float_inf}, {+float_inf, +float_inf}, {true, true}}, + {{+float_inf, -float_inf}, {+float_inf, -float_inf}, {true, true}}, + {{-float_inf, +float_inf}, {+float_inf, +float_inf}, {true, true}}, + {{-float_inf, -float_inf}, {+float_inf, -float_inf}, {true, true}}, + {{+1.0F, +float_inf}, {+float_inf, +float_inf}, {true, true}}, + {{+1.0F, -float_inf}, {+float_inf, -float_inf}, {true, true}}, + {{-1.0F, +float_inf}, {+float_inf, +float_inf}, {true, true}}, + {{-1.0F, -float_inf}, {+float_inf, -float_inf}, {true, true}}, + {{+0.0F, +float_inf}, {+float_inf, +float_inf}, {true, true}}, + {{+0.0F, -float_inf}, {+float_inf, -float_inf}, {true, true}}, + {{-0.0F, +float_inf}, {+float_inf, +float_inf}, {true, true}}, + {{-0.0F, -float_inf}, {+float_inf, -float_inf}, {true, true}}, + {{+float_inf, +float_nan}, {+float_inf, +float_nan}, {true, true}}, + {{+float_inf, -float_nan}, {+float_inf, -float_nan}, {true, true}}, + {{-float_inf, +float_nan}, {+float_nan, +float_inf}, {true, true}}, + {{-float_inf, -float_nan}, {+float_nan, -float_inf}, {true, true}}, + {{+float_nan, +float_inf}, {+float_inf, +float_inf}, {true, true}}, + {{+float_nan, -float_inf}, {+float_inf, -float_inf}, {true, true}}, + {{+float_nan, +0.0}, {+float_nan, +float_nan}, {true, true}}, + {{+float_nan, -0.0}, {+float_nan, -float_nan}, {true, true}}, + {{+0.0, +float_nan}, {+float_nan, +float_nan}, {true, true}}, + {{+0.0, -float_nan}, {+float_nan, -float_nan}, {true, true}}, + {{+float_nan, +float_nan}, {+float_nan, +float_nan}, {true, true}}, + {{+float_nan, -float_nan}, {+float_nan, -float_nan}, {true, true}}, +#endif // !FP_PRESET_FAST + + // abs(z) overflows + {{+0x1.fffffep+127F, +0x1.fffffep+127F}, {+0x1.19435cp+64F, +0x1.d20312p+62F}}, + {{-0x1.bb67aep+127F, +0x1.000000p+127F}, {+0x1.0907dcp+62F, +0x1.ee8dd4p+63F}}, + {{+0x1.fffffep+127F, -0x0.000002p-126F}, {+0x1.fffffep+63F, -0x0.000000p-126F}}, + + // norm(z) overflows + {{-0x1.08b2a2p+83F, -0x1.08b2a2p+84F}, {+0x1.216970p+41F, -0x1.d4473ap+41F}}, + {{+0x1.bc16d6p+63F, -0x1.4d1120p+63F}, {+0x1.f9c31ep+31F, -0x1.512cbep+30F}}, + +#if !WITH_FP_ABRUPT_UNDERFLOW + // abs(z) underflows + {{-0x0.000002p-126F, +0x0.000002p-126F}, {+0x1.498530p-76F, +0x1.8dc422p-75F}}, + {{+0x0.000002p-126F, +0x0.800000p-126F}, {+0x1.000002p-64F, +0x1.fffffcp-65F}}, +#endif // !WITH_FP_ABRUPT_UNDERFLOW + + // abs(z) close to underflow + {{+0x1.4p-126F, +0x1p-126F}, {+0x1.31a340p-63F, +0x1.acd900p-65F}}, + + // norm(z) underflows + {{+0x1.ef2d1p-83F, -0x1.ef2d10p-84F}, {+0x1.0314d8p-41F, -0x1.e9495ep-44F}}, + {{-0x1.622d7p-61F, -0x1.d83c94p-61F}, {+0x1.ebb76ep-32F, -0x1.ebb770p-31F}}, + + // control flow edge cases + {{+0x1p-2F, +0x1.fffffep-1F}, {+0x1.99b964p-1F, +0x1.3fe72ap-1F}}, + {{+0x1p-2F, +0x1.000000p+0F}, {+0x1.99b966p-1F, +0x1.3fe72ap-1F}}, + {{+0x1p-2F, +0x1.000002p+0F}, {+0x1.99b966p-1F, +0x1.3fe72cp-1F}}, + {{+0x1p+0F, +0x1p-25F}, {+0x1.000000p+0F, +0x1.000000p-26F}}, + {{+0x1p+0F, +0x1p-24F}, {+0x1.000000p+0F, +0x1.000000p-25F}}, + {{+0x1p+0F, +0x1p-23F}, {+0x1.000000p+0F, +0x1.000000p-24F}}, + {{+0x1p+0F, +0x1.fffffcp-2F}, {+0x1.077226p+0F, +0x1.f18770p-3F}}, + {{+0x1p+0F, +0x1.fffffep-2F}, {+0x1.077226p+0F, +0x1.f18772p-3F}}, + {{+0x1p+0F, +0x1.000000p-1F}, {+0x1.077226p+0F, +0x1.f18774p-3F}}, + {{+0x1p+0F, +0x1.000002p-1F}, {+0x1.077226p+0F, +0x1.f18778p-3F}}, + {{+0x1.fffffcp-103F, +0x1.fffffep-103F}, {+0x1.19435cp-51F, +0x1.d20314p-53F}}, + {{+0x1.fffffep-103F, +0x1.000000p-102F}, {+0x1.19435cp-51F, +0x1.d20314p-53F}}, + {{+0x1.000000p-102F, +0x1.000002p-102F}, {+0x1.19435ep-51F, +0x1.d20316p-53F}}, + {{+0x1.fffffcp-104F, +0x1.fffffep-103F}, {+0x1.cc8532p-52F, +0x1.1c9e00p-52F}}, + {{+0x1.fffffep-104F, +0x1.000000p-102F}, {+0x1.cc8532p-52F, +0x1.1c9e02p-52F}}, + {{+0x1.000000p-103F, +0x1.000002p-102F}, {+0x1.cc8534p-52F, +0x1.1c9e02p-52F}}, + {{+0x1.fffffep-104F, +0x1.fffffep-103F}, {+0x1.cc8532p-52F, +0x1.1c9e00p-52F}}, + {{+0x1.000000p-103F, +0x1.000000p-102F}, {+0x1.cc8532p-52F, +0x1.1c9e00p-52F}}, + {{+0x1.000002p-103F, +0x1.000002p-102F}, {+0x1.cc8534p-52F, +0x1.1c9e02p-52F}}, + {{+0x1.000000p-103F, +0x1.fffffep-103F}, {+0x1.cc8532p-52F, +0x1.1c9e00p-52F}}, + {{+0x1.000002p-103F, +0x1.000000p-102F}, {+0x1.cc8534p-52F, +0x1.1c9e00p-52F}}, + {{+0x1.000004p-103F, +0x1.000002p-102F}, {+0x1.cc8536p-52F, +0x1.1c9e02p-52F}}, + {{+0x1.000000p-126F, +0x1.fffffep-103F}, {+0x1.6a09e6p-52F, +0x1.6a09e4p-52F}}, + {{+0x1.000000p-126F, +0x1.000000p-102F}, {+0x1.6a09e8p-52F, +0x1.6a09e6p-52F}}, + {{+0x1.000000p-126F, +0x1.000002p-102F}, {+0x1.6a09e8p-52F, +0x1.6a09e8p-52F}}, + +#if !WITH_FP_ABRUPT_UNDERFLOW + {{+0x0.000002p-126F, +0x1.fffffep-103F}, {+0x1.6a09e6p-52F, +0x1.6a09e6p-52F}}, + {{+0x0.000002p-126F, +0x1.000000p-102F}, {+0x1.6a09e6p-52F, +0x1.6a09e6p-52F}}, + {{+0x0.000002p-126F, +0x1.000002p-102F}, {+0x1.6a09e8p-52F, +0x1.6a09e8p-52F}}, +#endif // !WITH_FP_ABRUPT_UNDERFLOW +}; diff --git a/tests/std/tests/GH_000935_complex_numerical_accuracy/test.cpp b/tests/std/tests/GH_000935_complex_numerical_accuracy/test.cpp new file mode 100644 index 00000000000..dc4b03cd6a7 --- /dev/null +++ b/tests/std/tests/GH_000935_complex_numerical_accuracy/test.cpp @@ -0,0 +1,125 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include + +#include "floating_point_utils.hpp" +#include "log_test_cases.hpp" +#include "sqrt_test_cases.hpp" + +using namespace std; +using namespace fputil; + +void test_sqrt(const rounding_mode mode) { +#if FP_PRESET_FAST + constexpr int ulp_tolerance = 4; +#else // ^^^ fp:fast / not fp:fast vvv + const int ulp_tolerance = is_directed_rounding_mode(mode) ? 3 : 2; +#endif // ^^^ not fp:fast ^^^ + + const auto check_result = [&](const auto& result, const auto& test_case) { + const int case_real_ulp_tolerance = test_case.result_exactness.real ? 0 : ulp_tolerance; + const int case_imag_ulp_tolerance = test_case.result_exactness.imag ? 0 : ulp_tolerance; + return near_equal(result.real(), test_case.expected_result.real(), case_real_ulp_tolerance) + && near_equal(result.imag(), test_case.expected_result.imag(), case_imag_ulp_tolerance); + }; + + for (const auto& c : sqrt_double_cases) { + const auto result = [&] { + rounding_guard guard(mode); + return sqrt(c.input); + }(); + + assert(check_result(result, c)); + } + + for (const auto& c : sqrt_float_cases) { + const auto result = [&] { + rounding_guard guard(mode); + return sqrt(c.input); + }(); + + assert(check_result(result, c)); + } + + for (const auto& c : sqrt_double_cases) { + const auto result = [&] { + rounding_guard guard(mode); + return sqrt(static_cast>(c.input)); + }(); + + assert(check_result(static_cast>(result), c)); + } +} + +void test_log(const rounding_mode mode) { +#if FP_PRESET_FAST + constexpr int ulp_tolerance = 4; + // under /fp:fast, allow inaccurate real(log(z)) when |z| is close to 1 + constexpr double real_absolute_epsilon_tolerance = 4; +#else // ^^^ fp:fast / not fp:fast vvv + const int ulp_tolerance = is_directed_rounding_mode(mode) ? 3 : 2; + constexpr double real_absolute_epsilon_tolerance = 0; +#endif // ^^^ not fp:fast ^^^ + + const auto check_result = [&](const auto& result, const auto& test_case) { + using Float = decltype(result.real()); + + constexpr auto epsilon = static_cast(numeric_limits::epsilon()); + const int case_real_ulp_tolerance = test_case.result_exactness.real ? 0 : ulp_tolerance; + const int case_imag_ulp_tolerance = test_case.result_exactness.imag ? 0 : ulp_tolerance; + const double case_real_absolute_tolerance = + test_case.result_exactness.real ? 0.0 : real_absolute_epsilon_tolerance * epsilon; + + // TRANSITION: under rounding toward negative mode, log(1.0) returns +0.0 on x86, -0.0 on x64 + const auto is_mod_exactly_one = [](const auto& z) { + // no other complex has mod of exactly 1 + return (abs(real(z)) == 1 && imag(z) == 0) || (real(z) == 0 && abs(imag(z)) == 1); + }; + + if (mode == rounding_mode::toward_negative && is_mod_exactly_one(test_case.input)) { + return abs(result.real()) <= case_real_absolute_tolerance + && near_equal(result.imag(), test_case.expected_result.imag(), case_imag_ulp_tolerance); + } + + return near_equal(result.real(), test_case.expected_result.real(), case_real_ulp_tolerance, + case_real_absolute_tolerance) + && near_equal(result.imag(), test_case.expected_result.imag(), case_imag_ulp_tolerance); + }; + + for (const auto& c : log_double_cases) { + const auto result = [&] { + rounding_guard guard(mode); + return log(c.input); + }(); + + assert(check_result(result, c)); + } + + for (const auto& c : log_float_cases) { + const auto result = [&] { + rounding_guard guard(mode); + return log(c.input); + }(); + + assert(check_result(result, c)); + } + + for (const auto& c : log_double_cases) { + const auto result = [&] { + rounding_guard guard(mode); + return log(static_cast>(c.input)); + }(); + + assert(check_result(static_cast>(result), c)); + } +} + +int main() { + for (const auto& mode : all_rounding_modes) { + test_sqrt(mode); + test_log(mode); + } +} diff --git a/tests/std/tests/GH_000935_complex_numerical_accuracy/test.hpp b/tests/std/tests/GH_000935_complex_numerical_accuracy/test.hpp new file mode 100644 index 00000000000..681d0e45235 --- /dev/null +++ b/tests/std/tests/GH_000935_complex_numerical_accuracy/test.hpp @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#pragma once + +#include +#include + +#include "floating_point_utils.hpp" + +constexpr double double_inf = std::numeric_limits::infinity(); +constexpr double double_nan = std::numeric_limits::quiet_NaN(); + +constexpr float float_inf = std::numeric_limits::infinity(); +constexpr float float_nan = std::numeric_limits::quiet_NaN(); + +struct complex_result_exactness { + bool real = false; + bool imag = false; +}; + +template +struct complex_unary_test_case { + std::complex input; + std::complex expected_result; + complex_result_exactness result_exactness{}; +}; diff --git a/tests/std/tests/GH_001105_custom_streambuf_throws/env.lst b/tests/std/tests/GH_001105_custom_streambuf_throws/env.lst new file mode 100644 index 00000000000..19f025bd0e6 --- /dev/null +++ b/tests/std/tests/GH_001105_custom_streambuf_throws/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_001105_custom_streambuf_throws/test.cpp b/tests/std/tests/GH_001105_custom_streambuf_throws/test.cpp new file mode 100644 index 00000000000..bb2a2df7c7d --- /dev/null +++ b/tests/std/tests/GH_001105_custom_streambuf_throws/test.cpp @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include + +struct bad_buf : std::streambuf { + bad_buf() { + throw std::runtime_error("throw in constructor!"); + } +}; + +struct custom_stream : std::istream { + custom_stream() : std::istream(new bad_buf{}) {} +}; + +int main() { + + { + // GH-1105 std::istream destructor should not crash if custom streambuf implementation throws. + try { + custom_stream f{}; + } catch (const std::runtime_error&) { + assert(true); + } + } + + return 0; +} diff --git a/tests/std/tests/GH_001411_core_headers/env.lst b/tests/std/tests/GH_001411_core_headers/env.lst new file mode 100644 index 00000000000..19f025bd0e6 --- /dev/null +++ b/tests/std/tests/GH_001411_core_headers/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_001411_core_headers/test.cpp b/tests/std/tests/GH_001411_core_headers/test.cpp new file mode 100644 index 00000000000..5a45bd65689 --- /dev/null +++ b/tests/std/tests/GH_001411_core_headers/test.cpp @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#define _CORE_HEADERS_ONLY + +#include <__msvc_all_public_headers.hpp> + +#ifdef _YVALS +#error Core headers should not include . +#endif + +#include + +#ifndef _YVALS +#error Non-core headers like should include . +#endif + +int main() {} // COMPILE-ONLY diff --git a/tests/std/tests/P0088R3_variant/env.lst b/tests/std/tests/P0088R3_variant/env.lst index d07bd460d62..48e3b76c748 100644 --- a/tests/std/tests/P0088R3_variant/env.lst +++ b/tests/std/tests/P0088R3_variant/env.lst @@ -18,12 +18,12 @@ PM_CL="/EHsc /MDd /D_ITERATOR_DEBUG_LEVEL=1 /std:c++latest /permissive-" PM_CL="/EHsc /MDd /D_ITERATOR_DEBUG_LEVEL=2 /std:c++latest /permissive- /fp:except /Zc:preprocessor" PM_CL="/EHsc /MDd /D_ITERATOR_DEBUG_LEVEL=2 /std:c++17 /permissive-" PM_CL="/EHsc /MT /D_ITERATOR_DEBUG_LEVEL=0 /std:c++latest /permissive-" -PM_CL="/EHsc /MT /D_ITERATOR_DEBUG_LEVEL=0 /std:c++latest /permissive- /analyze:only" +PM_CL="/EHsc /MT /D_ITERATOR_DEBUG_LEVEL=0 /std:c++latest /permissive- /analyze:only /analyze:autolog-" PM_CL="/EHsc /MT /D_ITERATOR_DEBUG_LEVEL=1 /std:c++latest /permissive-" PM_CL="/EHsc /MTd /D_ITERATOR_DEBUG_LEVEL=0 /std:c++latest /permissive- /fp:strict" PM_CL="/EHsc /MTd /D_ITERATOR_DEBUG_LEVEL=1 /std:c++latest /permissive-" PM_CL="/EHsc /MTd /D_ITERATOR_DEBUG_LEVEL=2 /std:c++latest /permissive /DCONSTEXPR_NOTHROW" -PM_CL="/EHsc /MTd /D_ITERATOR_DEBUG_LEVEL=2 /std:c++latest /permissive- /analyze:only" +PM_CL="/EHsc /MTd /D_ITERATOR_DEBUG_LEVEL=2 /std:c++latest /permissive- /analyze:only /analyze:autolog-" PM_CL="/Za /EHsc /MD /std:c++latest /permissive-" PM_CL="/Za /EHsc /MDd /std:c++latest /permissive-" PM_CL="/clr /MD /std:c++17 /DCONSTEXPR_NOTHROW" diff --git a/tests/std/tests/P0088R3_variant/test.cpp b/tests/std/tests/P0088R3_variant/test.cpp index 2857e561b3a..7a66a9f06e0 100644 --- a/tests/std/tests/P0088R3_variant/test.cpp +++ b/tests/std/tests/P0088R3_variant/test.cpp @@ -6617,10 +6617,10 @@ namespace msvc { // //===----------------------------------------------------------------------===// - enum CallType : unsigned { CT_None, CT_NonConst = 1, CT_Const = 2, CT_LValue = 4, CT_RValue = 8 }; + enum CallType : unsigned int { CT_None, CT_NonConst = 1, CT_Const = 2, CT_LValue = 4, CT_RValue = 8 }; constexpr CallType operator|(CallType LHS, CallType RHS) { - return static_cast(static_cast(LHS) | static_cast(RHS)); + return static_cast(static_cast(LHS) | static_cast(RHS)); } struct ForwardingCallObject { diff --git a/tests/std/tests/P0218R1_filesystem/test.cpp b/tests/std/tests/P0218R1_filesystem/test.cpp index 0ff4f084c32..ef6d08aea10 100644 --- a/tests/std/tests/P0218R1_filesystem/test.cpp +++ b/tests/std/tests/P0218R1_filesystem/test.cpp @@ -952,19 +952,11 @@ void check_symlink_permissions(const error_code& ec, const wchar_t* const functi pass = false; } -#ifdef WINDOWS_XP - if (ec.value() != 50) { - wcerr << L"Expected ERROR_NOT_SUPPORTED from " << function_id << L" but it returned " << ec.message().c_str() - << L"\n"; - pass = false; - } -#else // ^^^ WINDOWS_XP ^^^ // vvv !WINDOWS_XP vvv if (ec.value() != 1314) { wcerr << L"Expected ERROR_PRIVILEGE_NOT_HELD from " << function_id << L" but it returned " << ec.message().c_str() << L"\n"; pass = false; } -#endif // WINDOWS_XP wcerr << L"Warning: could not test " << function_id << L" due to symlink creation failure, do you have admin rights?\n"; @@ -1565,12 +1557,7 @@ void test_canonical() { // test that canonical on a directory is not an error (void) canonical(L"."sv, ec); // == canonical(current_path())? -#ifdef WINDOWS_XP - EXPECT(ec.value() == 50 /* ERROR_NOT_SUPPORTED */); - EXPECT(ec.category() == system_category()); -#else // ^^^ WINDOWS_XP ^^^ // vvv !WINDOWS_XP vvv EXPECT(good(ec)); -#endif // WINDOWS_XP // test that canonical on an ordinary file returns that file's DOS path const auto filename = L"test_canonical.txt"sv; @@ -1578,10 +1565,6 @@ void test_canonical() { EXPECT(good(ec)); create_file_containing(L"test_canonical.txt", L"Hello world\n"); const path p(canonical(filename, ec)); -#ifdef WINDOWS_XP - EXPECT(ec.value() == 50 /* ERROR_NOT_SUPPORTED */); - EXPECT(ec.category() == system_category()); -#else // ^^^ WINDOWS_XP ^^^ // vvv !WINDOWS_XP vvv EXPECT(good(ec)); const auto& text = p.native(); assert(text.size() > filename.size() + 1); @@ -1589,7 +1572,6 @@ void test_canonical() { const auto diffSize = static_cast(filename.size()); EXPECT(*(text.end() - diffSize - 1) == L'\\'); EXPECT(equal(text.end() - diffSize, text.end(), filename.begin(), filename.end())); -#endif // WINDOWS_XP EXPECT(remove(L"test_canonical.txt", ec)); EXPECT(good(ec)); } @@ -3193,7 +3175,6 @@ void test_lexically_proximate() { } void test_weakly_canonical() { -#ifndef WINDOWS_XP error_code ec; create_directories(L"test_weakly_canonical/a/b/c"sv, ec); @@ -3277,7 +3258,6 @@ void test_weakly_canonical() { remove_all(L"test_weakly_canonical"sv, ec); EXPECT(good(ec)); -#endif // WINDOWS_XP } void test_remove() { @@ -3511,9 +3491,6 @@ void test_permissions() { EXPECT(good(ec)); // try to make the symlink target not readonly permissions(linkname, perms::all, perm_options::replace, ec); -#ifdef WINDOWS_XP - EXPECT(bad(ec)); // missing SetFileInformationByHandle -#else // ^^^ WINDOWS_XP ^^^ // vvv !WINDOWS_XP vvv EXPECT(good(ec)); // symlink unchanged: EXPECT(symlink_status(linkname).permissions() == readonlyPerms); @@ -3521,7 +3498,6 @@ void test_permissions() { // target changed: EXPECT(status(linkname).permissions() == perms::all); EXPECT(good(ec)); -#endif // WINDOWS_XP } permissions(linkname, perms::all, perm_options::replace | perm_options::nofollow, ec); diff --git a/tests/std/tests/P0355R7_calendars_and_time_zones_io/env.lst b/tests/std/tests/P0355R7_calendars_and_time_zones_io/env.lst new file mode 100644 index 00000000000..642f530ffad --- /dev/null +++ b/tests/std/tests/P0355R7_calendars_and_time_zones_io/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_latest_matrix.lst diff --git a/tests/std/tests/P0355R7_calendars_and_time_zones_io/test.cpp b/tests/std/tests/P0355R7_calendars_and_time_zones_io/test.cpp new file mode 100644 index 00000000000..fefbba69291 --- /dev/null +++ b/tests/std/tests/P0355R7_calendars_and_time_zones_io/test.cpp @@ -0,0 +1,125 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using chrono::duration; + +template +bool test_duration_basic_out(const duration& d, const CharT* expected) { + basic_ostringstream ss; + + ss << d; + return ss.str() == expected; +} + +#define WIDEN(TYPE, STR) get(make_pair(STR, L##STR)); + +template +bool test_duration_locale_out() { + basic_stringstream ss; + const duration d{0.140625}; + ss.precision(3); + ss << d; + ss.setf(ios_base::scientific, ios_base::floatfield); + ss << ' ' << d; + + basic_string expected = WIDEN(CharT, "0.141s 1.406e-01s"); + +#ifdef _DEBUG +#define DEFAULT_IDL_SETTING 2 +#else +#define DEFAULT_IDL_SETTING 0 +#endif + +#if !defined(_DLL) || _ITERATOR_DEBUG_LEVEL == DEFAULT_IDL_SETTING + // When linking dynamically, user-defined facets are incompatible with non-default _ITERATOR_DEBUG_LEVEL settings. + struct comma : numpunct { + CharT do_decimal_point() const { + return ','; + } + }; + + ss.imbue(locale(ss.getloc(), new comma)); + ss << ' ' << d; + expected += WIDEN(CharT, " 1,406e-01s"); +#endif // !defined(_DLL) || _ITERATOR_DEBUG_LEVEL == DEFAULT_IDL_SETTING + + return ss.str() == expected; +} + +#undef WIDEN + +void test_duration_output() { + using LongRatio = ratio; + assert(test_duration_basic_out(duration{1}, "1as")); + assert(test_duration_basic_out(duration{2}, "2fs")); + assert(test_duration_basic_out(duration{3}, "3ps")); + assert(test_duration_basic_out(duration{42}, "42ns")); + assert(test_duration_basic_out(duration{42}, "42us")); + assert(test_duration_basic_out(duration{42}, "42ms")); + assert(test_duration_basic_out(duration{42}, "42cs")); + assert(test_duration_basic_out(duration{42}, "42ds")); + assert(test_duration_basic_out(duration>{42}, "42s")); + assert(test_duration_basic_out(duration{42}, "42das")); + assert(test_duration_basic_out(duration{42}, "42hs")); + assert(test_duration_basic_out(duration{42}, "42ks")); + assert(test_duration_basic_out(duration{42}, "42Ms")); + assert(test_duration_basic_out(duration{42}, "42Gs")); + assert(test_duration_basic_out(duration{42}, "42Ts")); + assert(test_duration_basic_out(duration{42}, "42Ps")); + assert(test_duration_basic_out(duration{42}, "42Es")); + assert(test_duration_basic_out(duration>{42}, "42min")); + assert(test_duration_basic_out(duration>{42}, "42h")); + assert(test_duration_basic_out(duration>{42}, "42d")); + + assert(test_duration_basic_out(duration>{24}, "24[2]s")); + assert(test_duration_basic_out(duration>{24}, "24[1/2]s")); + assert(test_duration_basic_out(duration>{24}, "24[22/7]s")); + assert(test_duration_basic_out(duration{24}, "24[9223372036854775806/9223372036854775807]s")); + + assert(test_duration_basic_out(duration{0.140625}, "0.140625s")); + assert(test_duration_locale_out()); + + assert(test_duration_basic_out(duration{1}, L"1as")); + assert(test_duration_basic_out(duration{2}, L"2fs")); + assert(test_duration_basic_out(duration{3}, L"3ps")); + assert(test_duration_basic_out(duration{42}, L"42ns")); + assert(test_duration_basic_out(duration{42}, L"42us")); + assert(test_duration_basic_out(duration{42}, "42ms")); + assert(test_duration_basic_out(duration{42}, L"42cs")); + assert(test_duration_basic_out(duration{42}, L"42ds")); + assert(test_duration_basic_out(duration>{42}, L"42s")); + assert(test_duration_basic_out(duration{42}, L"42das")); + assert(test_duration_basic_out(duration{42}, L"42hs")); + assert(test_duration_basic_out(duration{42}, L"42ks")); + assert(test_duration_basic_out(duration{42}, L"42Ms")); + assert(test_duration_basic_out(duration{42}, L"42Gs")); + assert(test_duration_basic_out(duration{42}, L"42Ts")); + assert(test_duration_basic_out(duration{42}, L"42Ps")); + assert(test_duration_basic_out(duration{42}, L"42Es")); + assert(test_duration_basic_out(duration>{42}, L"42min")); + assert(test_duration_basic_out(duration>{42}, L"42h")); + assert(test_duration_basic_out(duration>{42}, L"42d")); + + assert(test_duration_basic_out(duration>{24}, L"24[2]s")); + assert(test_duration_basic_out(duration>{24}, L"24[1/2]s")); + assert(test_duration_basic_out(duration>{24}, L"24[22/7]s")); + assert(test_duration_basic_out(duration{24}, L"24[9223372036854775806/9223372036854775807]s")); + + assert(test_duration_basic_out(duration{0.140625}, L"0.140625s")); + assert(test_duration_locale_out()); +} + +int main() { + test_duration_output(); + return 0; +} diff --git a/tests/std/tests/P0357R3_supporting_incomplete_types_in_reference_wrapper/test.cpp b/tests/std/tests/P0357R3_supporting_incomplete_types_in_reference_wrapper/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/P0357R3_supporting_incomplete_types_in_reference_wrapper/test.cpp rename to tests/std/tests/P0357R3_supporting_incomplete_types_in_reference_wrapper/test.compile.pass.cpp diff --git a/tests/std/tests/P0433R2_deduction_guides/test.cpp b/tests/std/tests/P0433R2_deduction_guides/test.cpp index dd11ad849d9..6a819a3216f 100644 --- a/tests/std/tests/P0433R2_deduction_guides/test.cpp +++ b/tests/std/tests/P0433R2_deduction_guides/test.cpp @@ -91,14 +91,12 @@ long add(short x, int y) { return x + y; } -struct UniqueTagCanDeduceFrom {}; // TRANSITION, VSO-587956 - template class ClassTemplate, typename... CtorArgs> struct CanDeduceFromHelper : false_type {}; template