From df08cfc519d35bd4c4fc329d1885a4456fec7330 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 17 Feb 2026 09:39:23 -0800 Subject: [PATCH 01/35] Cycle locations for ARM64. --- azure-devops/create-1es-hosted-pool.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-devops/create-1es-hosted-pool.ps1 b/azure-devops/create-1es-hosted-pool.ps1 index 8bb16ee6a0e..69470e2f1ba 100644 --- a/azure-devops/create-1es-hosted-pool.ps1 +++ b/azure-devops/create-1es-hosted-pool.ps1 @@ -31,7 +31,7 @@ if ($Arch -ieq 'x64') { } else { # CPP_STL_GitHub has quota for 672 cores (21 VMs) in westcentralus, not currently used. $AvailableLocations = @('eastus2', 'northeurope') # Locations where CPP_STL_GitHub has quota for 1024 cores (32 VMs). - $AvailableLocationIdx = 4 # Increment for each new pool, to cycle through the available locations. + $AvailableLocationIdx = 5 # Increment for each new pool, to cycle through the available locations. $Location = $AvailableLocations[$AvailableLocationIdx % $AvailableLocations.Length] $VMSize = 'Standard_D32ps_v6' $PoolSize = 32 From 73f0a696acb3f834e63a151b5e5ead7754199067 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 17 Feb 2026 08:57:53 -0800 Subject: [PATCH 02/35] Python 3.14.3. --- README.md | 2 +- azure-devops/provision-image.ps1 | 4 ++-- tests/CMakeLists.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c3f8676a4c1..a79aefc5583 100644 --- a/README.md +++ b/README.md @@ -151,7 +151,7 @@ Just try to follow these rules, so we can spend more time fixing bugs and implem - "Windows 11 SDK (10.0.26100)" or later - "C++ Clang tools for Windows (20.1.8 - x64/x86)" - *Optional, see Note 2 below:* "MSVC Build Tools for ARM64/ARM64EC (Latest)" -* Install [Python][] 3.14.2 or later. +* Install [Python][] 3.14.3 or later. + Select "Add python.exe to PATH" if you want to follow the instructions below that invoke `python`. Otherwise, you should be familiar with alternative methods. diff --git a/azure-devops/provision-image.ps1 b/azure-devops/provision-image.ps1 index f49b26635c4..a0440b19c66 100644 --- a/azure-devops/provision-image.ps1 +++ b/azure-devops/provision-image.ps1 @@ -67,9 +67,9 @@ $PowerShellArgs = @('/quiet', '/norestart') # https://www.python.org if ($Provisioning_x64) { - $PythonUrl = 'https://www.python.org/ftp/python/3.14.2/python-3.14.2-amd64.exe' + $PythonUrl = 'https://www.python.org/ftp/python/3.14.3/python-3.14.3-amd64.exe' } else { - $PythonUrl = 'https://www.python.org/ftp/python/3.14.2/python-3.14.2-arm64.exe' + $PythonUrl = 'https://www.python.org/ftp/python/3.14.3/python-3.14.3-arm64.exe' } $PythonArgs = @('/quiet', 'InstallAllUsers=1', 'PrependPath=1', 'CompileAll=1', 'Include_doc=0') diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9d49ceb410d..6939015d412 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,7 +1,7 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -find_package(Python "3.14.2" REQUIRED COMPONENTS Interpreter) +find_package(Python "3.14.3" REQUIRED COMPONENTS Interpreter) set(STL_BUILD_ROOT "${PROJECT_BINARY_DIR}/out") set(STL_SOURCE_DIR "${PROJECT_SOURCE_DIR}") From 21957ad75f657a5aac437452393ea4a4c242c6c8 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 17 Feb 2026 09:43:00 -0800 Subject: [PATCH 03/35] CMake 4.2.1. --- CMakeLists.txt | 2 +- benchmarks/CMakeLists.txt | 2 +- tools/CMakeLists.txt | 2 +- tools/format/CMakeLists.txt | 2 +- tools/validate/CMakeLists.txt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3aedb039bb8..d3bb19b34eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required(VERSION 4.1.2) +cmake_minimum_required(VERSION 4.2.1) set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) project(msvc_standard_libraries LANGUAGES CXX) diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt index b62f79465d6..ad9b1f0a436 100644 --- a/benchmarks/CMakeLists.txt +++ b/benchmarks/CMakeLists.txt @@ -1,7 +1,7 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required(VERSION 4.1.2) +cmake_minimum_required(VERSION 4.2.1) project(msvc_standard_libraries_benchmarks LANGUAGES CXX) if(DEFINED STL_BINARY_DIR) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 6ca421fb4ea..5eb8ec12aeb 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,7 +1,7 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required(VERSION 4.1.2) +cmake_minimum_required(VERSION 4.2.1) project(msvc_standard_libraries_tools LANGUAGES CXX) add_subdirectory(format) diff --git a/tools/format/CMakeLists.txt b/tools/format/CMakeLists.txt index 8aedb0fa7c1..be3bfa9ea85 100644 --- a/tools/format/CMakeLists.txt +++ b/tools/format/CMakeLists.txt @@ -1,7 +1,7 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required(VERSION 4.1.2) +cmake_minimum_required(VERSION 4.2.1) project(msvc_standard_libraries_format NONE) find_program(CLANG_FORMAT diff --git a/tools/validate/CMakeLists.txt b/tools/validate/CMakeLists.txt index b254752a1f7..12a182ce6b8 100644 --- a/tools/validate/CMakeLists.txt +++ b/tools/validate/CMakeLists.txt @@ -1,7 +1,7 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required(VERSION 4.1.2) +cmake_minimum_required(VERSION 4.2.1) project(msvc_standard_libraries_validate LANGUAGES CXX) add_executable(validate-binary validate.cpp) From 1d670dc3db4db975603fe5019e40f0af1447c429 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 17 Feb 2026 08:58:59 -0800 Subject: [PATCH 04/35] MSVC Compiler 19.51.36014. Not yet required in yvals_core.h; the internal toolset is still 19.50.35721. --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d3bb19b34eb..afb6a97f978 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,8 +6,8 @@ cmake_minimum_required(VERSION 4.2.1) set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) project(msvc_standard_libraries LANGUAGES CXX) -if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.50.35722") - message(FATAL_ERROR "The STL must be built with MSVC Compiler 19.50.35722 or later.") +if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.51.36014") + message(FATAL_ERROR "The STL must be built with MSVC Compiler 19.51.36014 or later.") endif() include(CheckCXXSourceCompiles) From 58822abdff09b158691d324ab630f152683a3540 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 19 Feb 2026 02:36:12 -0800 Subject: [PATCH 05/35] README.md: Install "(Preview)" Build Tools. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a79aefc5583..19a7beae039 100644 --- a/README.md +++ b/README.md @@ -145,12 +145,12 @@ Just try to follow these rules, so we can spend more time fixing bugs and implem + **You must install Insiders for STL development.** *See Note 1 below.* + Select the "Desktop development with C++" workload. + Select the following components at a minimum: - - "MSVC Build Tools for x64/x86 (Latest)" + - "MSVC Build Tools for x64/x86 (Preview)" - "C++ CMake tools for Windows" - "MSVC AddressSanitizer" - "Windows 11 SDK (10.0.26100)" or later - "C++ Clang tools for Windows (20.1.8 - x64/x86)" - - *Optional, see Note 2 below:* "MSVC Build Tools for ARM64/ARM64EC (Latest)" + - *Optional, see Note 2 below:* "MSVC Build Tools for ARM64/ARM64EC (Preview)" * Install [Python][] 3.14.3 or later. + Select "Add python.exe to PATH" if you want to follow the instructions below that invoke `python`. Otherwise, you should be familiar with alternative methods. From 10deabe1e6487a5b3722523c84b9fd6969cfc7cc Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 19 Feb 2026 02:37:13 -0800 Subject: [PATCH 06/35] README.md: Update Command Prompt instructions, adding `-vcvars_ver=preview`. --- README.md | 61 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 19a7beae039..a1b469e243a 100644 --- a/README.md +++ b/README.md @@ -170,7 +170,7 @@ For example, `` has conditionally compiled code for the `_M_ARM64` and ` 4. Use the IDE's dropdown menu to choose the architecture you want to build. We recommend x64 for general development. 5. Build > Build All. -# How To Build With A Native Tools Command Prompt +# How To Build With The Command Prompt 1. Open a command prompt. 2. Change directories to a location where you'd like a clone of this STL repository. @@ -180,33 +180,35 @@ If you installed VS to a non-default location, change the `vcvarsall.bat` paths To build the x64 target (recommended): -1. `"C:\Program Files\Microsoft Visual Studio\18\Insiders\VC\Auxiliary\Build\vcvarsall.bat" x64` - * Or open an "x64 Native Tools Command Prompt for VS 18 Insiders". -2. Change directories to the previously cloned `STL` directory. -3. `cmake --preset x64` -4. `cmake --build --preset x64` +1. `pushd "%ProgramFiles%\Microsoft Visual Studio\18\Insiders\VC\Auxiliary\Build"` +1. `vcvarsall.bat x64 -vcvars_ver=preview` +1. Change directories to the previously cloned `STL` directory. +1. `cmake --preset x64` +1. `cmake --build --preset x64` To build the x86 target: -1. `"C:\Program Files\Microsoft Visual Studio\18\Insiders\VC\Auxiliary\Build\vcvarsall.bat" x86` - * Or open an "x86 Native Tools Command Prompt for VS 18 Insiders". -2. Change directories to the previously cloned `STL` directory. -3. `cmake --preset x86` -4. `cmake --build --preset x86` +1. `pushd "%ProgramFiles%\Microsoft Visual Studio\18\Insiders\VC\Auxiliary\Build"` +1. `vcvarsall.bat x86 -vcvars_ver=preview` +1. Change directories to the previously cloned `STL` directory. +1. `cmake --preset x86` +1. `cmake --build --preset x86` To build the ARM64 target: -1. `"C:\Program Files\Microsoft Visual Studio\18\Insiders\VC\Auxiliary\Build\vcvarsall.bat" x64_arm64` -2. Change directories to the previously cloned `STL` directory. -3. `cmake --preset ARM64` -4. `cmake --build --preset ARM64` +1. `pushd "%ProgramFiles%\Microsoft Visual Studio\18\Insiders\VC\Auxiliary\Build"` +1. `vcvarsall.bat x64_arm64 -vcvars_ver=preview` +1. Change directories to the previously cloned `STL` directory. +1. `cmake --preset ARM64` +1. `cmake --build --preset ARM64` To build the ARM64EC target: -1. `"C:\Program Files\Microsoft Visual Studio\18\Insiders\VC\Auxiliary\Build\vcvarsall.bat" x64_arm64` -2. Change directories to the previously cloned `STL` directory. -3. `cmake --preset ARM64EC` -4. `cmake --build --preset ARM64EC` +1. `pushd "%ProgramFiles%\Microsoft Visual Studio\18\Insiders\VC\Auxiliary\Build"` +1. `vcvarsall.bat x64_arm64 -vcvars_ver=preview` +1. Change directories to the previously cloned `STL` directory. +1. `cmake --preset ARM64EC` +1. `cmake --build --preset ARM64EC` # How To Consume @@ -227,21 +229,30 @@ your .exe would "win" over the versions in System32. The compiler looks for include directories according to the `INCLUDE` environment variable, and the linker looks for import library directories according to the `LIB` environment variable, and the Windows loader will (eventually) look for DLL dependencies according to directories in the `PATH` environment variable. -The build generates a batch script named `set_environment.bat` in the output directory. If you run this script in a VS -Developer Command Prompt, it will insert the proper directories into the `INCLUDE`, `LIB`, and `PATH` environment +The build generates a batch script named `set_environment.bat` in the output directory. If you run this script, +it will insert the proper directories into the `INCLUDE`, `LIB`, and `PATH` environment variables to ensure that the built headers and libraries are used. ## Complete Example Using x64 DLL Flavor -From an "x64 Native Tools Command Prompt for VS 18 Insiders": - ``` +C:\Temp>pushd "%ProgramFiles%\Microsoft Visual Studio\18\Insiders\VC\Auxiliary\Build" + +C:\Program Files\Microsoft Visual Studio\18\Insiders\VC\Auxiliary\Build>vcvarsall.bat x64 -vcvars_ver=preview +********************************************************************** +** Visual Studio 2026 Developer Command Prompt v18.4.0-insiders +** Copyright (c) 2026 Microsoft Corporation +********************************************************************** +[vcvarsall.bat] Environment initialized for: 'x64' + +C:\Program Files\Microsoft Visual Studio\18\Insiders\VC\Auxiliary\Build>pushd D:\GitHub\STL + D:\GitHub\STL>cmake --preset x64 [...] -- Build files have been written to: D:/GitHub/STL/out/x64 D:\GitHub\STL>cmake --build --preset x64 -[1028/1028] Linking CXX static library out\lib\amd64\libcpmtd0.lib +[762/762] Linking CXX static library out\lib\amd64\libcpmtd0.lib D:\GitHub\STL>out\x64\set_environment.bat @@ -264,7 +275,7 @@ C:\Temp>dumpbin /DEPENDENTS .\example.exe | findstr msvcp msvcp140d_oss.dll ``` -# How To Run The Tests With A Native Tools Command Prompt +# How To Run The Tests Our tests are currently split across three test suites that are located at `tests\std`, `tests\tr1`, and `llvm-project\libcxx\test\std`. The test runner `${PROJECT_BINARY_DIR}\tests\utils\stl-lit\stl-lit.py` accepts paths to From f89c66c3547c3c8ba71bfabce94222e1da0627c0 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 19 Feb 2026 03:05:49 -0800 Subject: [PATCH 07/35] provision-image.ps1: Update to Preview components. --- azure-devops/provision-image.ps1 | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/azure-devops/provision-image.ps1 b/azure-devops/provision-image.ps1 index a0440b19c66..8a322faa2ca 100644 --- a/azure-devops/provision-image.ps1 +++ b/azure-devops/provision-image.ps1 @@ -36,13 +36,12 @@ if ($Arch -ieq 'x64') { $VisualStudioWorkloads = @( 'Microsoft.VisualStudio.Component.VC.ASAN', - 'Microsoft.VisualStudio.Component.VC.CLI.Support', 'Microsoft.VisualStudio.Component.VC.CMake.Project', 'Microsoft.VisualStudio.Component.VC.CoreIde', 'Microsoft.VisualStudio.Component.VC.Llvm.Clang', - 'Microsoft.VisualStudio.Component.VC.Tools.ARM64', - 'Microsoft.VisualStudio.Component.VC.Tools.ARM64EC', - 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64', + 'Microsoft.VisualStudio.Component.VC.Preview.ARM64', + 'Microsoft.VisualStudio.Component.VC.Preview.CLI.Support', + 'Microsoft.VisualStudio.Component.VC.Preview.Tools.x86.x64', 'Microsoft.VisualStudio.Component.Windows11SDK.26100' ) From 9cc1c4f17a79721f2f91c71a88f4ac11f58d1512 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 19 Feb 2026 05:51:42 -0800 Subject: [PATCH 08/35] provision-image.ps1: Patch Launch-VsDevShell.ps1. --- azure-devops/provision-image.ps1 | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/azure-devops/provision-image.ps1 b/azure-devops/provision-image.ps1 index 8a322faa2ca..5fa1a357764 100644 --- a/azure-devops/provision-image.ps1 +++ b/azure-devops/provision-image.ps1 @@ -185,6 +185,13 @@ if ($Provisioning_x64) { EnableNativeNVMe } +# TRANSITION, patch Launch-VsDevShell.ps1 to pass `-vcvars_ver=preview` before a proper parameter is available. +Write-Host 'Patching Launch-VsDevShell.ps1...' +$launchVsDevShell = 'C:\Program Files\Microsoft Visual Studio\18\Insiders\Common7\Tools\Launch-VsDevShell.ps1' +$paramRegex = 'VsInstanceId = \$instanceId' +$paramSubst = '$&; DevCmdArguments = "-vcvars_ver=preview";' +(Get-Content -Raw $launchVsDevShell) -creplace $paramRegex, $paramSubst | Set-Content -NoNewLine $launchVsDevShell + # Tell create-1es-hosted-pool.ps1 that we succeeded. Write-Host 'PROVISION_IMAGE_SUCCEEDED' From 6e17472ee14092cf6a2309c64cd63b38c6506642 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 19 Feb 2026 06:14:03 -0800 Subject: [PATCH 09/35] CMakePresets.json: Set "toolset" with a "value" of "version=preview". This teaches the IDE to pick up the Preview toolset. Thanks to Vivy in the STL Discord. --- CMakePresets.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CMakePresets.json b/CMakePresets.json index 1dbd259ce91..8559f56fa9b 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -10,7 +10,11 @@ "name": "base", "hidden": true, "generator": "Ninja", - "binaryDir": "${sourceDir}/out/${presetName}" + "binaryDir": "${sourceDir}/out/${presetName}", + "toolset": { + "strategy": "external", + "value": "version=preview" + } }, { "name": "x64", From 610de9ccc1e7054ed0a990876c814f8831af4744 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 17 Feb 2026 12:49:59 -0800 Subject: [PATCH 10/35] Use 10 shards for x64/x86 too. --- azure-devops/build-and-test.yml | 2 +- azure-pipelines.yml | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/azure-devops/build-and-test.yml b/azure-devops/build-and-test.yml index 250856fb8e1..c37891ffe60 100644 --- a/azure-devops/build-and-test.yml +++ b/azure-devops/build-and-test.yml @@ -22,7 +22,7 @@ parameters: default: 'STL-CI' - name: numShards type: number - default: 8 + default: 10 - name: configureTesting type: boolean default: true diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 8776d9901e2..d4b418688ab 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -173,7 +173,6 @@ stages: hostArch: arm64 targetArch: arm64 targetPlatform: arm64 - numShards: 10 - stage: Test_ARM64EC dependsOn: @@ -189,4 +188,3 @@ stages: hostArch: arm64 targetArch: arm64 targetPlatform: arm64ec - numShards: 10 From ef449fb26eccfb8881a57b2b5e35b11d4bcf6073 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 19 Feb 2026 06:31:25 -0800 Subject: [PATCH 11/35] VSO-2574432 "C1XX incorrectly handles a requires-expression checking for `r.operator T();`" was fixed on 2025-09-13. --- tests/std/tests/P0019R8_atomic_ref/test.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/std/tests/P0019R8_atomic_ref/test.cpp b/tests/std/tests/P0019R8_atomic_ref/test.cpp index 8a3f10954f8..8b246f42105 100644 --- a/tests/std/tests/P0019R8_atomic_ref/test.cpp +++ b/tests/std/tests/P0019R8_atomic_ref/test.cpp @@ -61,9 +61,7 @@ void test_atomic_ref_constraints_single() { // COMPILE-ONLY static_assert(std::is_same_v); static_assert(requires(const AR& r, TD v, std::memory_order ord) { -#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-2574432 r.operator TD(); -#endif // ^^^ no workaround ^^^ { r.load() } -> std::same_as; { r.load(ord) } -> std::same_as; { r.wait(v) } -> std::same_as; From 0a7f286f75b6d98b4a1741e58001bfef8b540242 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 19 Feb 2026 06:34:41 -0800 Subject: [PATCH 12/35] VSO-1513409 "Bogus `warning C4100: '<_Args_0>': unreferenced formal parameter` when `if constexpr` selects another branch" was fixed on 2025-06-27. --- stl/inc/variant | 3 --- 1 file changed, 3 deletions(-) diff --git a/stl/inc/variant b/stl/inc/variant index dbca56885e2..ed40faa1f6e 100644 --- a/stl/inc/variant +++ b/stl/inc/variant @@ -1422,9 +1422,6 @@ struct _Variant_dispatcher> { template _NODISCARD static constexpr _Ret _Dispatch2(_Callable&& _Obj, _Types&&... _Args) { if constexpr (_Any_valueless) { -#if !defined(__clang__) && !defined(__EDG__) // TRANSITION, VSO-1513409 - ((void) _Args, ...); -#endif // ^^^ workaround ^^^ _STD _Throw_bad_variant_access(); } #if _HAS_CXX20 From e613791b4b3b611d8ac7336ee4d5ae3be00bca3a Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 17 Feb 2026 13:54:11 -0800 Subject: [PATCH 13/35] EDG 6.8 implemented multidimensional subscript. --- stl/inc/mdspan | 2 - .../tests/GH_005090_stl_hardening/test.cpp | 4 -- .../P0009R18_mdspan_layout_left/test.cpp | 34 ------------- .../P0009R18_mdspan_layout_right/test.cpp | 49 ------------------ .../P0009R18_mdspan_layout_stride/test.cpp | 51 ------------------- .../std/tests/P0009R18_mdspan_mdspan/test.cpp | 4 -- .../P0009R18_mdspan_mdspan_death/test.cpp | 4 -- 7 files changed, 148 deletions(-) diff --git a/stl/inc/mdspan b/stl/inc/mdspan index a8d4134ab8e..72b6e73895c 100644 --- a/stl/inc/mdspan +++ b/stl/inc/mdspan @@ -1373,7 +1373,6 @@ public: constexpr mdspan& operator=(const mdspan&) = default; constexpr mdspan& operator=(mdspan&&) = default; -#ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6 template requires conjunction_v..., is_nothrow_constructible...> @@ -1386,7 +1385,6 @@ public: return _Access_impl(static_cast(_STD move(_Indices))...); #endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ } -#endif // ^^^ defined(__cpp_multidimensional_subscript) ^^^ private: template diff --git a/tests/std/tests/GH_005090_stl_hardening/test.cpp b/tests/std/tests/GH_005090_stl_hardening/test.cpp index b455e2df126..cb444a9d138 100644 --- a/tests/std/tests/GH_005090_stl_hardening/test.cpp +++ b/tests/std/tests/GH_005090_stl_hardening/test.cpp @@ -583,13 +583,11 @@ void test_mdspan_ctor_other() { mdspan> md{other}; } -#ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6 void test_mdspan_subscript_multidim() { const auto str{"HissMeowPurr"}; const mdspan> md{str, 3, 4}; (void) md[1, 4]; } -#endif // ^^^ defined(__cpp_multidimensional_subscript) ^^^ void test_mdspan_subscript_array() { const auto str{"HissMeowPurr"}; @@ -732,9 +730,7 @@ int main(int argc, char* argv[]) { test_expected_void_error_rvalue, test_expected_void_error_rvalue_const, test_mdspan_ctor_other, -#ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6 test_mdspan_subscript_multidim, -#endif // ^^^ defined(__cpp_multidimensional_subscript) ^^^ test_mdspan_subscript_array, test_mdspan_subscript_span, test_stacktrace_current, diff --git a/tests/std/tests/P0009R18_mdspan_layout_left/test.cpp b/tests/std/tests/P0009R18_mdspan_layout_left/test.cpp index 55a285b66a0..d241bd74ff2 100644 --- a/tests/std/tests/P0009R18_mdspan_layout_left/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_layout_left/test.cpp @@ -410,57 +410,33 @@ constexpr void check_correctness() { const array values{0, 1, 2}; mdspan, layout_left> vec{values.data()}; -#ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6 assert(vec[0] == 0); assert(vec[1] == 1); assert(vec[2] == 2); -#else // ^^^ defined(__cpp_multidimensional_subscript) / !defined(__cpp_multidimensional_subscript) vvv - assert(vec[array{0}] == 0); - assert(vec[array{1}] == 1); - assert(vec[array{2}] == 2); -#endif // ^^^ !defined(__cpp_multidimensional_subscript) ^^^ } { // 3x2 matrix with column-major order const array values{0, 1, 2, 3, 4, 5}; mdspan, layout_left> matrix{values.data()}; -#ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6 assert((matrix[0, 0] == 0)); assert((matrix[1, 0] == 1)); assert((matrix[2, 0] == 2)); assert((matrix[0, 1] == 3)); assert((matrix[1, 1] == 4)); assert((matrix[2, 1] == 5)); -#else // ^^^ defined(__cpp_multidimensional_subscript) / !defined(__cpp_multidimensional_subscript) vvv - assert((matrix[array{0, 0}] == 0)); - assert((matrix[array{1, 0}] == 1)); - assert((matrix[array{2, 0}] == 2)); - assert((matrix[array{0, 1}] == 3)); - assert((matrix[array{1, 1}] == 4)); - assert((matrix[array{2, 1}] == 5)); -#endif // ^^^ !defined(__cpp_multidimensional_subscript) ^^^ } { // 3x2x4 tensor const array values{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}; mdspan, layout_left> tensor{values.data(), 3, 2, 4}; -#ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6 assert((tensor[0, 0, 0] == 0)); assert((tensor[2, 0, 0] == 2)); assert((tensor[1, 1, 1] == 10)); assert((tensor[0, 0, 3] == 18)); assert((tensor[2, 1, 2] == 17)); assert((tensor[2, 1, 3] == 23)); -#else // ^^^ defined(__cpp_multidimensional_subscript) / !defined(__cpp_multidimensional_subscript) vvv - assert((tensor[array{0, 0, 0}] == 0)); - assert((tensor[array{2, 0, 0}] == 2)); - assert((tensor[array{1, 1, 1}] == 10)); - assert((tensor[array{0, 0, 3}] == 18)); - assert((tensor[array{2, 1, 2}] == 17)); - assert((tensor[array{2, 1, 3}] == 23)); -#endif // ^^^ !defined(__cpp_multidimensional_subscript) ^^^ } { // 2x3x2x3 tensor @@ -468,7 +444,6 @@ constexpr void check_correctness() { 26, 27, 28, 29, 30, 31, 32, 33, 34, 35}; mdspan, layout_left> tensor{values.data(), 2, 3}; -#ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6 assert((tensor[0, 0, 0, 0] == 0)); assert((tensor[1, 0, 0, 0] == 1)); assert((tensor[0, 1, 1, 0] == 8)); @@ -476,15 +451,6 @@ constexpr void check_correctness() { assert((tensor[0, 0, 0, 2] == 24)); assert((tensor[0, 2, 0, 2] == 28)); assert((tensor[1, 2, 1, 2] == 35)); -#else // ^^^ defined(__cpp_multidimensional_subscript) / !defined(__cpp_multidimensional_subscript) vvv - assert((tensor[array{0, 0, 0, 0}] == 0)); - assert((tensor[array{1, 0, 0, 0}] == 1)); - assert((tensor[array{0, 1, 1, 0}] == 8)); - assert((tensor[array{0, 0, 0, 1}] == 12)); - assert((tensor[array{0, 0, 0, 2}] == 24)); - assert((tensor[array{0, 2, 0, 2}] == 28)); - assert((tensor[array{1, 2, 1, 2}] == 35)); -#endif // ^^^ !defined(__cpp_multidimensional_subscript) ^^^ } } diff --git a/tests/std/tests/P0009R18_mdspan_layout_right/test.cpp b/tests/std/tests/P0009R18_mdspan_layout_right/test.cpp index 8702d2f600e..32c74462d4b 100644 --- a/tests/std/tests/P0009R18_mdspan_layout_right/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_layout_right/test.cpp @@ -411,43 +411,27 @@ constexpr void check_correctness() { const array vals{2, 1, 0}; mdspan, layout_right> vec{vals.data()}; -#ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6 assert(vec[0] == 2); assert(vec[1] == 1); assert(vec[2] == 0); -#else // ^^^ defined(__cpp_multidimensional_subscript) / !defined(__cpp_multidimensional_subscript) vvv - assert(vec[array{0}] == 2); - assert(vec[array{1}] == 1); - assert(vec[array{2}] == 0); -#endif // ^^^ !defined(__cpp_multidimensional_subscript) ^^^ } { // 4x3 matrix with row-major order const array vals{11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; mdspan, layout_right> matrix{vals.data()}; -#ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6 assert((matrix[0, 0] == 11)); assert((matrix[0, 2] == 9)); assert((matrix[1, 1] == 7)); assert((matrix[2, 0] == 5)); assert((matrix[2, 2] == 3)); assert((matrix[3, 1] == 1)); -#else // ^^^ defined(__cpp_multidimensional_subscript) / !defined(__cpp_multidimensional_subscript) vvv - assert((matrix[array{0, 0}] == 11)); - assert((matrix[array{0, 2}] == 9)); - assert((matrix[array{1, 1}] == 7)); - assert((matrix[array{2, 0}] == 5)); - assert((matrix[array{2, 2}] == 3)); - assert((matrix[array{3, 1}] == 1)); -#endif // ^^^ !defined(__cpp_multidimensional_subscript) ^^^ } { // 4x3x2 tensor const array vals{23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; mdspan, layout_right> tensor{vals.data(), 4, 3, 2}; -#ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6 assert((tensor[0, 0, 0] == 23)); assert((tensor[0, 0, 1] == 22)); assert((tensor[0, 1, 0] == 21)); @@ -458,18 +442,6 @@ constexpr void check_correctness() { assert((tensor[1, 1, 1] == 14)); assert((tensor[2, 2, 1] == 6)); assert((tensor[3, 2, 1] == 0)); -#else // ^^^ defined(__cpp_multidimensional_subscript) / !defined(__cpp_multidimensional_subscript) vvv - assert((tensor[array{0, 0, 0}] == 23)); - assert((tensor[array{0, 0, 1}] == 22)); - assert((tensor[array{0, 1, 0}] == 21)); - assert((tensor[array{0, 1, 1}] == 20)); - assert((tensor[array{1, 0, 0}] == 17)); - assert((tensor[array{1, 0, 1}] == 16)); - assert((tensor[array{1, 1, 0}] == 15)); - assert((tensor[array{1, 1, 1}] == 14)); - assert((tensor[array{2, 2, 1}] == 6)); - assert((tensor[array{3, 2, 1}] == 0)); -#endif // ^^^ !defined(__cpp_multidimensional_subscript) ^^^ } { // 3x2x3x2 tensor @@ -477,7 +449,6 @@ constexpr void check_correctness() { 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; mdspan, layout_right> tensor{vals.data(), 2, 2}; -#ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6 assert((tensor[0, 0, 0, 0] == 35)); assert((tensor[0, 0, 0, 1] == 34)); assert((tensor[0, 0, 1, 0] == 33)); @@ -496,26 +467,6 @@ constexpr void check_correctness() { assert((tensor[1, 1, 1, 1] == 14)); assert((tensor[2, 0, 2, 0] == 7)); assert((tensor[2, 1, 2, 1] == 0)); -#else // ^^^ defined(__cpp_multidimensional_subscript) / !defined(__cpp_multidimensional_subscript) vvv - assert((tensor[array{0, 0, 0, 0}] == 35)); - assert((tensor[array{0, 0, 0, 1}] == 34)); - assert((tensor[array{0, 0, 1, 0}] == 33)); - assert((tensor[array{0, 0, 1, 1}] == 32)); - assert((tensor[array{0, 1, 0, 0}] == 29)); - assert((tensor[array{0, 1, 0, 1}] == 28)); - assert((tensor[array{0, 1, 1, 0}] == 27)); - assert((tensor[array{0, 1, 1, 1}] == 26)); - assert((tensor[array{1, 0, 0, 0}] == 23)); - assert((tensor[array{1, 0, 0, 1}] == 22)); - assert((tensor[array{1, 0, 1, 0}] == 21)); - assert((tensor[array{1, 0, 1, 1}] == 20)); - assert((tensor[array{1, 1, 0, 0}] == 17)); - assert((tensor[array{1, 1, 0, 1}] == 16)); - assert((tensor[array{1, 1, 1, 0}] == 15)); - assert((tensor[array{1, 1, 1, 1}] == 14)); - assert((tensor[array{2, 0, 2, 0}] == 7)); - assert((tensor[array{2, 1, 2, 1}] == 0)); -#endif // ^^^ !defined(__cpp_multidimensional_subscript) ^^^ } } diff --git a/tests/std/tests/P0009R18_mdspan_layout_stride/test.cpp b/tests/std/tests/P0009R18_mdspan_layout_stride/test.cpp index 484272c8cc8..d2d931ab167 100644 --- a/tests/std/tests/P0009R18_mdspan_layout_stride/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_layout_stride/test.cpp @@ -764,15 +764,9 @@ constexpr void check_correctness() { layout_stride::mapping m{E{}, array{1}}; mdspan, layout_stride> vec{vals.data(), m}; -#ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6 assert((vec[0] == 1)); assert((vec[1] == 2)); assert((vec[2] == 3)); -#else // ^^^ defined(__cpp_multidimensional_subscript) / !defined(__cpp_multidimensional_subscript) vvv - assert((vec[array{0}] == 1)); - assert((vec[array{1}] == 2)); - assert((vec[array{2}] == 3)); -#endif // ^^^ !defined(__cpp_multidimensional_subscript) ^^^ } { // 2x3 matrix with row-major order @@ -781,21 +775,12 @@ constexpr void check_correctness() { layout_stride::mapping m{E{}, array{3, 1}}; mdspan matrix{vals.data(), m}; -#ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6 assert((matrix[0, 0] == 1)); assert((matrix[0, 1] == 2)); assert((matrix[0, 2] == 3)); assert((matrix[1, 0] == 4)); assert((matrix[1, 1] == 5)); assert((matrix[1, 2] == 6)); -#else // ^^^ defined(__cpp_multidimensional_subscript) / !defined(__cpp_multidimensional_subscript) vvv - assert((matrix[array{0, 0}] == 1)); - assert((matrix[array{0, 1}] == 2)); - assert((matrix[array{0, 2}] == 3)); - assert((matrix[array{1, 0}] == 4)); - assert((matrix[array{1, 1}] == 5)); - assert((matrix[array{1, 2}] == 6)); -#endif // ^^^ !defined(__cpp_multidimensional_subscript) ^^^ } { // 3x2x2 tensor @@ -805,7 +790,6 @@ constexpr void check_correctness() { assert(!m.is_exhaustive()); mdspan tensor{vals.data(), m}; -#ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6 assert((tensor[0, 0, 0] == 0)); assert((tensor[0, 0, 1] == 3)); assert((tensor[0, 1, 0] == 1)); @@ -818,20 +802,6 @@ constexpr void check_correctness() { assert((tensor[2, 0, 1] == 17)); assert((tensor[2, 1, 0] == 15)); assert((tensor[2, 1, 1] == 18)); -#else // ^^^ defined(__cpp_multidimensional_subscript) / !defined(__cpp_multidimensional_subscript) vvv - assert((tensor[array{0, 0, 0}] == 0)); - assert((tensor[array{0, 0, 1}] == 3)); - assert((tensor[array{0, 1, 0}] == 1)); - assert((tensor[array{0, 1, 1}] == 4)); - assert((tensor[array{1, 0, 0}] == 7)); - assert((tensor[array{1, 0, 1}] == 10)); - assert((tensor[array{1, 1, 0}] == 8)); - assert((tensor[array{1, 1, 1}] == 11)); - assert((tensor[array{2, 0, 0}] == 14)); - assert((tensor[array{2, 0, 1}] == 17)); - assert((tensor[array{2, 1, 0}] == 15)); - assert((tensor[array{2, 1, 1}] == 18)); -#endif // ^^^ !defined(__cpp_multidimensional_subscript) ^^^ } { // 2x3x3x2 tensor @@ -842,7 +812,6 @@ constexpr void check_correctness() { assert(m.is_exhaustive()); mdspan tensor{vals.data(), m}; -#ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6 assert((tensor[0, 0, 0, 0] == 0)); assert((tensor[0, 0, 0, 1] == 9)); assert((tensor[0, 0, 1, 0] == 3)); @@ -861,26 +830,6 @@ constexpr void check_correctness() { assert((tensor[1, 1, 1, 1] == 31)); assert((tensor[0, 2, 2, 0] == 8)); assert((tensor[1, 2, 2, 1] == 35)); -#else // ^^^ defined(__cpp_multidimensional_subscript) / !defined(__cpp_multidimensional_subscript) vvv - assert((tensor[array{0, 0, 0, 0}] == 0)); - assert((tensor[array{0, 0, 0, 1}] == 9)); - assert((tensor[array{0, 0, 1, 0}] == 3)); - assert((tensor[array{0, 0, 1, 1}] == 12)); - assert((tensor[array{0, 1, 0, 0}] == 1)); - assert((tensor[array{0, 1, 0, 1}] == 10)); - assert((tensor[array{0, 1, 1, 0}] == 4)); - assert((tensor[array{0, 1, 1, 1}] == 13)); - assert((tensor[array{1, 0, 0, 0}] == 18)); - assert((tensor[array{1, 0, 0, 1}] == 27)); - assert((tensor[array{1, 0, 1, 0}] == 21)); - assert((tensor[array{1, 0, 1, 1}] == 30)); - assert((tensor[array{1, 1, 0, 0}] == 19)); - assert((tensor[array{1, 1, 0, 1}] == 28)); - assert((tensor[array{1, 1, 1, 0}] == 22)); - assert((tensor[array{1, 1, 1, 1}] == 31)); - assert((tensor[array{0, 2, 2, 0}] == 8)); - assert((tensor[array{1, 2, 2, 1}] == 35)); -#endif // ^^^ !defined(__cpp_multidimensional_subscript) ^^^ } } diff --git a/tests/std/tests/P0009R18_mdspan_mdspan/test.cpp b/tests/std/tests/P0009R18_mdspan_mdspan/test.cpp index a36411d53e8..ffd632f085d 100644 --- a/tests/std/tests/P0009R18_mdspan_mdspan/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_mdspan/test.cpp @@ -840,7 +840,6 @@ constexpr void check_defaulted_copy_and_move_assignment_operators() { } } -#ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6 template concept CanCallMultidimSubscriptOp = requires(const Mds& mds, IndexTypes... indices) { { mds[indices...] } -> same_as; @@ -926,7 +925,6 @@ constexpr void check_multidimensional_subscript_operator() { assert((mds[i, i, move(i)] == 1)); } } -#endif // __cpp_multidimensional_subscript template concept CanCallSubscriptOp = requires(const Mds& mds, span s, const array& a) { @@ -1356,9 +1354,7 @@ constexpr bool test() { check_data_handle_and_mapping_and_accessor_constructor(); check_construction_from_other_mdspan(); check_defaulted_copy_and_move_assignment_operators(); -#ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6 check_multidimensional_subscript_operator(); -#endif // __cpp_multidimensional_subscript check_span_array_subscript_operator(); check_size(); check_empty(); diff --git a/tests/std/tests/P0009R18_mdspan_mdspan_death/test.cpp b/tests/std/tests/P0009R18_mdspan_mdspan_death/test.cpp index 2e225ae4fa2..c816392ff60 100644 --- a/tests/std/tests/P0009R18_mdspan_mdspan_death/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_mdspan_death/test.cpp @@ -17,7 +17,6 @@ void test_construction_from_other_mdspan() { [[maybe_unused]] mdspan> mds2{mds1}; } -#ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6 void test_access_with_invalid_multidimensional_index_1() { mdspan mds{some_ints.data(), 4, 4}; // I must be a multidimensional index in extents() @@ -28,7 +27,6 @@ void test_access_with_nonrepresentable_index_1() { mdspan mds{some_ints.data(), dextents{2, 3}}; (void) mds[256u, -255]; } -#endif // __cpp_multidimensional_subscript void test_access_with_invalid_multidimensional_index_2() { mdspan mds{some_ints.data(), 5, 5}; @@ -59,10 +57,8 @@ int main(int argc, char* argv[]) { #if _ITERATOR_DEBUG_LEVEL != 0 exec.add_death_tests({ test_construction_from_other_mdspan, -#ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6 test_access_with_invalid_multidimensional_index_1, test_access_with_nonrepresentable_index_1, -#endif // __cpp_multidimensional_subscript test_access_with_invalid_multidimensional_index_2, test_access_with_nonrepresentable_index_2, test_size_when_index_type_is_signed, From 0692042309ee2a4f855ff16e9929e4697181c99f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 19 Feb 2026 08:29:57 -0800 Subject: [PATCH 14/35] Enable P2674R1 is_implicit_lifetime in C++23 mode for MSVC. This was MSVC-PR-675420 on 2025-10-01. --- stl/inc/type_traits | 4 ++-- stl/inc/yvals_core.h | 2 +- tests/libcxx/expected_results.txt | 17 +++++++++++++---- .../test.compile.pass.cpp | 2 +- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/stl/inc/type_traits b/stl/inc/type_traits index f18d731c04d..0815f2df2d0 100644 --- a/stl/inc/type_traits +++ b/stl/inc/type_traits @@ -720,13 +720,13 @@ struct _NO_SPECIALIZATIONS_OF_TYPE_TRAITS is_trivially_copyable : bool_constant< _EXPORT_STD template _NO_SPECIALIZATIONS_OF_TYPE_TRAITS constexpr bool is_trivially_copyable_v = __is_trivially_copyable(_Ty); -#if _HAS_CXX23 && defined(__clang__) // TRANSITION, GH-5738 tracking VSO-2581622 (MSVC) and VSO-2581623 (EDG) +#if _HAS_CXX23 && !defined(__EDG__) // TRANSITION, GH-5738 tracking VSO-2581623 (EDG) _EXPORT_STD template struct _NO_SPECIALIZATIONS_OF_TYPE_TRAITS is_implicit_lifetime : bool_constant<__builtin_is_implicit_lifetime(_Ty)> {}; _EXPORT_STD template _NO_SPECIALIZATIONS_OF_TYPE_TRAITS constexpr bool is_implicit_lifetime_v = __builtin_is_implicit_lifetime(_Ty); -#endif // ^^^ _HAS_CXX23 && defined(__clang__) ^^^ +#endif // ^^^ _HAS_CXX23 && !defined(__EDG__) ^^^ _EXPORT_STD template struct _NO_SPECIALIZATIONS_OF_TYPE_TRAITS has_virtual_destructor : bool_constant<__has_virtual_destructor(_Ty)> { diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index fb3e21ddb35..09d533261db 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1733,7 +1733,7 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #define __cpp_lib_invoke_r 202106L #define __cpp_lib_ios_noreplace 202207L -#ifdef __clang__ // TRANSITION, GH-5738 tracking VSO-2581622 (MSVC) and VSO-2581623 (EDG) +#ifndef __EDG__ // TRANSITION, GH-5738 tracking VSO-2581623 (EDG) #define __cpp_lib_is_implicit_lifetime 202302L #endif // ^^^ no workaround ^^^ diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index e901cd635e9..56abff7b898 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -336,10 +336,6 @@ std/utilities/optional/optional.iterator/iterator.pass.cpp FAIL # *** MISSING COMPILER FEATURES *** -# VSO-2581622 C1XX should implement `__builtin_is_implicit_lifetime` -std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp:0 FAIL -std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp:1 FAIL - # MSVC has not implemented P2448R2 "Relaxing some constexpr restrictions" std/containers/container.adaptors/flat.map/flat.map.access/at_transparent.pass.cpp:0 FAIL std/containers/container.adaptors/flat.map/flat.map.access/at_transparent.pass.cpp:1 FAIL @@ -731,6 +727,11 @@ std/depr/depr.c.headers/stddef_h.compile.pass.cpp:1 FAIL # *** LIKELY BOGUS TESTS *** +# The test for `__cpp_lib_is_implicit_lifetime` is guarded by `__has_builtin(__builtin_is_implicit_lifetime)` +# which MSVC doesn't understand. This is generated by: libcxx/utils/generate_feature_test_macro_components.py +std/language.support/support.limits/support.limits.general/type_traits.version.compile.pass.cpp:0 FAIL +std/language.support/support.limits/support.limits.general/type_traits.version.compile.pass.cpp:1 FAIL + # Test bug after LWG-2899 "is_(nothrow_)move_constructible and tuple, optional and unique_ptr" was accepted. std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move_convert.pass.cpp FAIL std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move_convert.runtime.pass.cpp FAIL @@ -1351,6 +1352,14 @@ std/algorithms/alg.modifying.operations/alg.copy/copy.pass.cpp:1 FAIL std/input.output/file.streams/fstreams/filebuf.virtuals/xsputn.pass.cpp:0 FAIL std/input.output/file.streams/fstreams/filebuf.virtuals/xsputn.pass.cpp:1 FAIL +# Not analyzed. +# warning C4200: nonstandard extension used: zero-sized array in struct/union +# warning C4265: class has virtual functions, but its non-trivial destructor is not virtual; instances of this class may not be destructed correctly +# warning C4624: destructor was implicitly defined as deleted +# Failed assertion in test_is_implicit_lifetime, true>() +std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp:0 FAIL +std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp:1 FAIL + # *** XFAILS WHICH PASS *** # These tests contain `// XFAIL: msvc` comments, which accurately describe runtime failures for x86 and x64. diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp index 1c37b591579..055701d21f3 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp @@ -555,7 +555,7 @@ STATIC_ASSERT(__cpp_lib_is_constant_evaluated == 201811L); STATIC_ASSERT(__cpp_lib_is_final == 201402L); -#if _HAS_CXX23 && defined(__clang__) // TRANSITION, GH-5738 tracking VSO-2581622 (MSVC) and VSO-2581623 (EDG) +#if _HAS_CXX23 && !defined(__EDG__) // TRANSITION, GH-5738 tracking VSO-2581623 (EDG) STATIC_ASSERT(__cpp_lib_is_implicit_lifetime == 202302L); #elif defined(__cpp_lib_is_implicit_lifetime) #error __cpp_lib_is_implicit_lifetime is defined From c526174835585eb6e5c6237946fbe62fb16fc40d Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 19 Feb 2026 08:07:16 -0800 Subject: [PATCH 15/35] Enable P2255R2 reference_meows_from_temporary in C++23 mode for MSVC and EDG. This was MSVC-PR-682362 on 2025-10-27 and VS-PR-688674 on 2025-11-18. CUDA is limited to C++20, so we don't need to worry about it. Reported VSO-2742607 "C1XX __reference_constructs_from_temporary mishandles a couple of cases". Use strict_latest_matrix.lst because there are (predictably) lots of errors in permissive mode due to the Evil Extension. --- stl/inc/memory | 4 +- stl/inc/tuple | 66 +++++-------------- stl/inc/type_traits | 12 ++-- stl/inc/utility | 18 ++--- stl/inc/yvals_core.h | 52 +++++++-------- tests/libcxx/expected_results.txt | 21 +++--- .../P2255R2_invocation/test.compile.pass.cpp | 3 - .../env.lst | 2 +- .../test.compile.pass.cpp | 11 +++- .../env.lst | 2 +- .../test.compile.pass.cpp | 7 +- .../test.compile.pass.cpp | 3 - .../test.compile.pass.cpp | 2 +- 13 files changed, 81 insertions(+), 122 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index 55e08b73bac..a1482c17b66 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -3490,11 +3490,11 @@ public: } _NODISCARD _CONSTEXPR23 add_lvalue_reference_t<_Ty> operator*() const noexcept(noexcept(*_STD declval())) { -#ifdef __cpp_lib_reference_from_temporary +#if _HAS_CXX23 static_assert( !reference_converts_from_temporary_v, decltype(*_STD declval())>, "Can't return a temporary object from unique_ptr::operator*(). (N5014 [unique.ptr.single.observers]/1)"); -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ +#endif // _HAS_CXX23 return *_Mypair._Myval2; } diff --git a/stl/inc/tuple b/stl/inc/tuple index f30a8ecacf8..c5d4092f50b 100644 --- a/stl/inc/tuple +++ b/stl/inc/tuple @@ -208,7 +208,6 @@ using _Three_way_comparison_result_with_tuple_like_t = template concept _Tuple_like_non_tuple = !_Is_specialization_v<_Ty, tuple> && _Tuple_like<_Ty>; -#ifdef __cpp_lib_reference_from_temporary template constexpr bool _Tuple_reference_constructs_from_temporary = false; template @@ -222,7 +221,6 @@ template constexpr bool _Tuple_reference_constructs_from_temporary_for_tuple_like<_Tuple, _TupleLike, index_sequence<_Indices...>> = _Tuple_reference_constructs_from_temporary<_Tuple, decltype(_STD get<_Indices>(_STD declval<_TupleLike>()))...>; -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ #endif // _HAS_CXX23 template <> @@ -366,14 +364,14 @@ public: tuple(_This2&& _This_arg, _Rest2&&... _Rest_arg) noexcept(_Tuple_nothrow_constructible_v) // strengthened : tuple(_Exact_args_t{}, _STD forward<_This2>(_This_arg), _STD forward<_Rest2>(_Rest_arg)...) {} -#ifdef __cpp_lib_reference_from_temporary +#if _HAS_CXX23 template , _STD _Tuple_constructible_val>, int> = 0> requires _Tuple_reference_constructs_from_temporary explicit(_Tuple_conditional_explicit_v) tuple(_This2&&, _Rest2&&...) = delete; -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ +#endif // _HAS_CXX23 tuple(const tuple&) = default; tuple(tuple&&) = default; @@ -385,13 +383,11 @@ public: constexpr explicit(_Tuple_conditional_explicit_v) tuple(tuple<_Other...>& _Right) noexcept(_Tuple_nothrow_constructible_v) // strengthened : tuple(_Unpack_tuple_t{}, _Right) {} -#ifdef __cpp_lib_reference_from_temporary template , _STD _Tuple_convert_val&, _Other...>>, int> = 0> requires _Tuple_reference_constructs_from_temporary explicit(_Tuple_conditional_explicit_v) tuple(tuple<_Other...>&) = delete; -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ #endif // _HAS_CXX23 template , @@ -400,13 +396,13 @@ public: constexpr explicit(_Tuple_conditional_explicit_v) tuple(const tuple<_Other...>& _Right) noexcept(_Tuple_nothrow_constructible_v) // strengthened : tuple(_Unpack_tuple_t{}, _Right) {} -#ifdef __cpp_lib_reference_from_temporary +#if _HAS_CXX23 template , _STD _Tuple_convert_val&, _Other...>>, int> = 0> requires _Tuple_reference_constructs_from_temporary explicit(_Tuple_conditional_explicit_v) tuple(const tuple<_Other...>&) = delete; -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ +#endif // _HAS_CXX23 template , _STD _Tuple_convert_val, _Other...>>, @@ -414,38 +410,32 @@ public: constexpr explicit(_Tuple_conditional_explicit_v) tuple(tuple<_Other...>&& _Right) noexcept(_Tuple_nothrow_constructible_v) // strengthened : tuple(_Unpack_tuple_t{}, _STD move(_Right)) {} -#ifdef __cpp_lib_reference_from_temporary +#if _HAS_CXX23 template , _STD _Tuple_convert_val, _Other...>>, int> = 0> requires _Tuple_reference_constructs_from_temporary explicit(_Tuple_conditional_explicit_v) tuple(tuple<_Other...>&&) = delete; -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ -#if _HAS_CXX23 template , _STD _Tuple_convert_val, _Other...>>, int> = 0> constexpr explicit(_Tuple_conditional_explicit_v) tuple(const tuple<_Other...>&& _Right) noexcept(_Tuple_nothrow_constructible_v) // strengthened : tuple(_Unpack_tuple_t{}, _STD move(_Right)) {} -#ifdef __cpp_lib_reference_from_temporary template , _STD _Tuple_convert_val, _Other...>>, int> = 0> requires _Tuple_reference_constructs_from_temporary explicit(_Tuple_conditional_explicit_v) tuple(const tuple<_Other...>&&) = delete; -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ template , int> = 0> constexpr explicit(_Tuple_conditional_explicit_v) tuple(pair<_First, _Second>& _Right) noexcept(_Tuple_nothrow_constructible_v) // strengthened : tuple(_Unpack_tuple_t{}, _Right) {} -#ifdef __cpp_lib_reference_from_temporary template , int> = 0> requires _Tuple_reference_constructs_from_temporary explicit(_Tuple_conditional_explicit_v) tuple(pair<_First, _Second>&) = delete; -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ #endif // _HAS_CXX23 template & _Right) noexcept(_Tuple_nothrow_constructible_v) // strengthened : tuple(_Unpack_tuple_t{}, _Right) {} -#ifdef __cpp_lib_reference_from_temporary +#if _HAS_CXX23 template , int> = 0> requires _Tuple_reference_constructs_from_temporary explicit(_Tuple_conditional_explicit_v) tuple(const pair<_First, _Second>&) = delete; -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ +#endif // _HAS_CXX23 template , int> = 0> constexpr explicit(_Tuple_conditional_explicit_v) tuple(pair<_First, _Second>&& _Right) noexcept(_Tuple_nothrow_constructible_v) // strengthened : tuple(_Unpack_tuple_t{}, _STD move(_Right)) {} -#ifdef __cpp_lib_reference_from_temporary +#if _HAS_CXX23 template , int> = 0> requires _Tuple_reference_constructs_from_temporary explicit(_Tuple_conditional_explicit_v) tuple(pair<_First, _Second>&&) = delete; -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ -#if _HAS_CXX23 template , int> = 0> constexpr explicit(_Tuple_conditional_explicit_v) tuple(const pair<_First, _Second>&& _Right) noexcept(_Tuple_nothrow_constructible_v) // strengthened : tuple(_Unpack_tuple_t{}, _STD move(_Right)) {} -#ifdef __cpp_lib_reference_from_temporary template , int> = 0> requires _Tuple_reference_constructs_from_temporary explicit(_Tuple_conditional_explicit_v) tuple(const pair<_First, _Second>&&) = delete; -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ template > static constexpr bool _Is_tuple_like_constructor_explicit_v = false; @@ -506,7 +492,6 @@ public: constexpr explicit(_Is_tuple_like_constructor_explicit_v<_Other>) tuple(_Other&& _Right) : tuple(_Unpack_tuple_t{}, _STD forward<_Other>(_Right)) { } -#ifdef __cpp_lib_reference_from_temporary template <_Different_from _Other> requires _Tuple_like_non_subrange<_Other> && (1 + sizeof...(_Rest) == tuple_size_v>) && _Can_construct_values_from_tuple_like_v @@ -514,7 +499,6 @@ public: || (!is_convertible_v<_Other, _This> && !is_constructible_v<_This, _Other>) ) && _Tuple_reference_constructs_from_temporary_for_tuple_like explicit(_Is_tuple_like_constructor_explicit_v<_Other>) tuple(_Other&&) = delete; -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ #endif // _HAS_CXX23 template ) tuple(allocator_arg_t, const _Alloc& _Al, _This2&& _This_arg, _Rest2&&... _Rest_arg) : tuple(_Alloc_exact_args_t{}, _Al, _STD forward<_This2>(_This_arg), _STD forward<_Rest2>(_Rest_arg)...) {} -#ifdef __cpp_lib_reference_from_temporary +#if _HAS_CXX23 template , _STD _Tuple_constructible_val>, @@ -546,7 +530,7 @@ public: requires _Tuple_reference_constructs_from_temporary explicit(_Tuple_conditional_explicit_v) tuple(allocator_arg_t, const _Alloc&, _This2&&, _Rest2&&...) = delete; -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ +#endif // _HAS_CXX23 template , int> = 0> @@ -565,7 +549,6 @@ public: constexpr explicit(_Tuple_conditional_explicit_v) tuple(allocator_arg_t, const _Alloc& _Al, tuple<_Other...>& _Right) : tuple(_Alloc_unpack_tuple_t{}, _Al, _Right) {} -#ifdef __cpp_lib_reference_from_temporary template , _STD _Tuple_convert_val&, _Other...>>, @@ -573,7 +556,6 @@ public: requires _Tuple_reference_constructs_from_temporary explicit(_Tuple_conditional_explicit_v) tuple(allocator_arg_t, const _Alloc&, tuple<_Other...>&) = delete; -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ #endif // _HAS_CXX23 template ) tuple(allocator_arg_t, const _Alloc& _Al, const tuple<_Other...>& _Right) : tuple(_Alloc_unpack_tuple_t{}, _Al, _Right) {} -#ifdef __cpp_lib_reference_from_temporary +#if _HAS_CXX23 template , _STD _Tuple_convert_val&, _Other...>>, @@ -591,7 +573,7 @@ public: requires _Tuple_reference_constructs_from_temporary explicit(_Tuple_conditional_explicit_v) tuple(allocator_arg_t, const _Alloc&, const tuple<_Other...>&) = delete; -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ +#endif // _HAS_CXX23 template , @@ -600,7 +582,7 @@ public: _CONSTEXPR20 explicit(_Tuple_conditional_explicit_v) tuple(allocator_arg_t, const _Alloc& _Al, tuple<_Other...>&& _Right) : tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {} -#ifdef __cpp_lib_reference_from_temporary +#if _HAS_CXX23 template , _STD _Tuple_convert_val, _Other...>>, @@ -608,9 +590,7 @@ public: requires _Tuple_reference_constructs_from_temporary explicit(_Tuple_conditional_explicit_v) tuple(allocator_arg_t, const _Alloc&, tuple<_Other...>&&) = delete; -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ -#if _HAS_CXX23 template , _STD _Tuple_convert_val, _Other...>>, @@ -618,7 +598,6 @@ public: constexpr explicit(_Tuple_conditional_explicit_v) tuple(allocator_arg_t, const _Alloc& _Al, const tuple<_Other...>&& _Right) : tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {} -#ifdef __cpp_lib_reference_from_temporary template , _STD _Tuple_convert_val, _Other...>>, @@ -626,20 +605,17 @@ public: requires _Tuple_reference_constructs_from_temporary explicit(_Tuple_conditional_explicit_v) tuple(allocator_arg_t, const _Alloc&, const tuple<_Other...>&&) = delete; -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ template , int> = 0> constexpr explicit(_Tuple_conditional_explicit_v) tuple(allocator_arg_t, const _Alloc& _Al, pair<_First, _Second>& _Right) : tuple(_Alloc_unpack_tuple_t{}, _Al, _Right) {} -#ifdef __cpp_lib_reference_from_temporary template , int> = 0> requires _Tuple_reference_constructs_from_temporary explicit(_Tuple_conditional_explicit_v) tuple(allocator_arg_t, const _Alloc&, pair<_First, _Second>&) = delete; -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ #endif // _HAS_CXX23 template ) tuple(allocator_arg_t, const _Alloc& _Al, const pair<_First, _Second>& _Right) : tuple(_Alloc_unpack_tuple_t{}, _Al, _Right) {} -#ifdef __cpp_lib_reference_from_temporary +#if _HAS_CXX23 template , int> = 0> requires _Tuple_reference_constructs_from_temporary explicit(_Tuple_conditional_explicit_v) tuple(allocator_arg_t, const _Alloc&, const pair<_First, _Second>&) = delete; -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ +#endif // _HAS_CXX23 template , int> = 0> _CONSTEXPR20 explicit(_Tuple_conditional_explicit_v) tuple(allocator_arg_t, const _Alloc& _Al, pair<_First, _Second>&& _Right) : tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {} -#ifdef __cpp_lib_reference_from_temporary +#if _HAS_CXX23 template , int> = 0> requires _Tuple_reference_constructs_from_temporary explicit(_Tuple_conditional_explicit_v) tuple(allocator_arg_t, const _Alloc&, pair<_First, _Second>&&) = delete; -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ -#if _HAS_CXX23 template , int> = 0> constexpr explicit(_Tuple_conditional_explicit_v) tuple(allocator_arg_t, const _Alloc& _Al, const pair<_First, _Second>&& _Right) : tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {} -#ifdef __cpp_lib_reference_from_temporary template , int> = 0> requires _Tuple_reference_constructs_from_temporary explicit(_Tuple_conditional_explicit_v) tuple(allocator_arg_t, const _Alloc&, const pair<_First, _Second>&&) = delete; -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ #ifdef __EDG__ // TRANSITION, VSO-1900279 template , int> = 0> @@ -694,7 +666,6 @@ public: tuple(allocator_arg_t, const _Alloc& _Al, _Other&& _Right) : tuple(_Alloc_unpack_tuple_t{}, _Al, _STD forward<_Other>(_Right)) { } -#ifdef __cpp_lib_reference_from_temporary template _Other> requires _Tuple_like_non_subrange<_Other> && (1 + sizeof...(_Rest) == tuple_size_v>) && _Can_construct_values_from_tuple_like_v @@ -702,7 +673,6 @@ public: || (!is_convertible_v<_Other, _This> && !is_constructible_v<_This, _Other>) ) && _Tuple_reference_constructs_from_temporary_for_tuple_like explicit(_Is_tuple_like_constructor_explicit_v<_Other>) tuple(allocator_arg_t, const _Alloc&, _Other&&) = delete; -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ #endif // _HAS_CXX23 tuple& operator=(const volatile tuple&) = delete; @@ -1263,12 +1233,12 @@ template #endif // ^^^ !_HAS_CXX20 ^^^ _NODISCARD constexpr _Ty make_from_tuple(_Tuple&& _Tpl) noexcept(noexcept(_STD _Make_from_tuple_impl<_Ty>( _STD forward<_Tuple>(_Tpl), make_index_sequence>>{}))) /* strengthened */ { -#ifdef __cpp_lib_reference_from_temporary +#if _HAS_CXX23 if constexpr (tuple_size_v> == 1) { static_assert(!reference_constructs_from_temporary_v<_Ty, decltype(_STD get<0>(_STD forward<_Tuple>(_Tpl)))>, "Cannot bind a temporary to the returned reference which will always be dangling (N5014 [tuple.apply]/2)."); } -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ +#endif // _HAS_CXX23 // construct _Ty from the elements of _Tpl return _STD _Make_from_tuple_impl<_Ty>( _STD forward<_Tuple>(_Tpl), make_index_sequence>>{}); diff --git a/stl/inc/type_traits b/stl/inc/type_traits index 0815f2df2d0..b50999e136f 100644 --- a/stl/inc/type_traits +++ b/stl/inc/type_traits @@ -746,8 +746,9 @@ struct _NO_SPECIALIZATIONS_OF_TYPE_TRAITS has_unique_object_representations _EXPORT_STD template _NO_SPECIALIZATIONS_OF_TYPE_TRAITS constexpr bool has_unique_object_representations_v = __has_unique_object_representations(_Ty); +#endif // _HAS_CXX17 -#ifdef __cpp_lib_reference_from_temporary +#if _HAS_CXX23 #ifdef __clang__ // TRANSITION, LLVM-114344 template struct _Adjust_ref_binding_source { @@ -786,8 +787,9 @@ struct _NO_SPECIALIZATIONS_OF_TYPE_TRAITS reference_converts_from_temporary _EXPORT_STD template _NO_SPECIALIZATIONS_OF_TYPE_TRAITS constexpr bool reference_converts_from_temporary_v = __reference_converts_from_temporary(_Ty, _Adjust_ref_binding_source_t<_Uty>); -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ +#endif // _HAS_CXX23 +#if _HAS_CXX17 #ifdef __EDG__ // TRANSITION, VSO-1690654 template struct _Is_aggregate_impl : bool_constant<__is_aggregate(_Ty)> {}; @@ -1860,13 +1862,13 @@ struct _NO_SPECIALIZATIONS_OF_TYPE_TRAITS is_nothrow_convertible template struct _Invoke_convertible : false_type {}; -#ifdef __cpp_lib_reference_from_temporary +#if _HAS_CXX23 template using _Not_reference_converts_from_temporary = bool_constant>; -#else // ^^^ defined(__cpp_lib_reference_from_temporary) / !defined(__cpp_lib_reference_from_temporary) vvv +#else // ^^^ _HAS_CXX23 / !_HAS_CXX23 vvv template using _Not_reference_converts_from_temporary = true_type; -#endif // ^^^ !defined(__cpp_lib_reference_from_temporary) ^^^ +#endif // ^^^ !_HAS_CXX23 ^^^ template struct _Invoke_convertible<_From, _To, void_t(_STD _Returns_exactly<_From>()))>> diff --git a/stl/inc/utility b/stl/inc/utility index 662e08c0e27..8c602dc5e67 100644 --- a/stl/inc/utility +++ b/stl/inc/utility @@ -275,14 +275,14 @@ struct pair { // store a pair of values is_nothrow_constructible_v<_Ty1, _Other1> && is_nothrow_constructible_v<_Ty2, _Other2>) // strengthened : first(_STD forward<_Other1>(_Val1)), second(_STD forward<_Other2>(_Val2)) { } -#ifdef __cpp_lib_reference_from_temporary +#if _HAS_CXX23 template , is_constructible<_Ty2, _Other2>>, int> = 0> requires reference_constructs_from_temporary_v<_Ty1, _Other1&&> || reference_constructs_from_temporary_v<_Ty2, _Other2&&> explicit(!conjunction_v, is_convertible<_Other2, _Ty2>>) pair(_Other1&&, _Other2&&) = delete; -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ +#endif // _HAS_CXX23 pair(const pair&) = default; pair(pair&&) = default; @@ -294,14 +294,12 @@ struct pair { // store a pair of values pair(pair<_Other1, _Other2>& _Right) noexcept( is_nothrow_constructible_v<_Ty1, _Other1&> && is_nothrow_constructible_v<_Ty2, _Other2&>) // strengthened : first(_Right.first), second(_Right.second) {} -#ifdef __cpp_lib_reference_from_temporary template requires is_constructible_v<_Ty1, _Other1&> && is_constructible_v<_Ty2, _Other2&> && (reference_constructs_from_temporary_v<_Ty1, _Other1&> || reference_constructs_from_temporary_v<_Ty2, _Other2&>) explicit(!conjunction_v, is_convertible<_Other2&, _Ty2>>) pair(pair<_Other1, _Other2>&) = delete; -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ #endif // _HAS_CXX23 template && is_nothrow_constructible_v<_Ty2, const _Other2&>) // strengthened : first(_Right.first), second(_Right.second) {} -#ifdef __cpp_lib_reference_from_temporary +#if _HAS_CXX23 template , is_constructible<_Ty2, const _Other2&>>, int> = 0> @@ -320,7 +318,7 @@ struct pair { // store a pair of values || reference_constructs_from_temporary_v<_Ty2, const _Other2&> explicit(!conjunction_v, is_convertible>) pair(const pair<_Other1, _Other2>&) = delete; -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ +#endif // _HAS_CXX23 template , is_constructible<_Ty2, _Other2>>, int> = 0> @@ -328,16 +326,14 @@ struct pair { // store a pair of values pair(pair<_Other1, _Other2>&& _Right) noexcept( is_nothrow_constructible_v<_Ty1, _Other1> && is_nothrow_constructible_v<_Ty2, _Other2>) // strengthened : first(_STD forward<_Other1>(_Right.first)), second(_STD forward<_Other2>(_Right.second)) {} -#ifdef __cpp_lib_reference_from_temporary +#if _HAS_CXX23 template , is_constructible<_Ty2, _Other2>>, int> = 0> requires reference_constructs_from_temporary_v<_Ty1, _Other1&&> || reference_constructs_from_temporary_v<_Ty2, _Other2&&> explicit(!conjunction_v, is_convertible<_Other2, _Ty2>>) pair(pair<_Other1, _Other2>&&) = delete; -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ -#if _HAS_CXX23 template requires is_constructible_v<_Ty1, const _Other1> && is_constructible_v<_Ty2, const _Other2> constexpr explicit(!conjunction_v, is_convertible>) @@ -345,14 +341,12 @@ struct pair { // store a pair of values noexcept(is_nothrow_constructible_v<_Ty1, const _Other1> && is_nothrow_constructible_v<_Ty2, const _Other2>) // strengthened : first(_STD forward(_Right.first)), second(_STD forward(_Right.second)) {} -#ifdef __cpp_lib_reference_from_temporary template requires is_constructible_v<_Ty1, const _Other1> && is_constructible_v<_Ty2, const _Other2> && (reference_constructs_from_temporary_v<_Ty1, const _Other1 &&> || reference_constructs_from_temporary_v<_Ty2, const _Other2 &&>) explicit(!conjunction_v, is_convertible>) pair(const pair<_Other1, _Other2>&&) = delete; -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ #ifdef __EDG__ // TRANSITION, VSO-1900279 template , int> = 0> @@ -367,7 +361,6 @@ struct pair { // store a pair of values && is_nothrow_constructible_v<_Ty2, decltype(_STD get<1>(_STD declval<_Other>()))>) // strengthened : first(_STD get<0>(_STD forward<_Other>(_Right))), second(_STD get<1>(_STD forward<_Other>(_Right))) { } -#ifdef __cpp_lib_reference_from_temporary template <_Pair_like_non_subrange _Other> requires conjunction_v(_STD declval<_Other>()))>, is_constructible<_Ty2, decltype(_STD get<1>(_STD declval<_Other>()))>> @@ -375,7 +368,6 @@ struct pair { // store a pair of values || reference_constructs_from_temporary_v<_Ty2, decltype(_STD get<1>(_STD declval<_Other>()))>) explicit(!conjunction_v(_STD declval<_Other>())), _Ty1>, is_convertible(_STD declval<_Other>())), _Ty2>>) pair(_Other&&) = delete; -#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ #endif // _HAS_CXX23 template diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 09d533261db..7155ec2566f 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -360,7 +360,6 @@ // P2166R1 Prohibiting basic_string And basic_string_view Construction From nullptr // P2186R2 Removing Garbage Collection Support // P2255R2 Type Traits To Detect References Binding To Temporaries -// (for Clang only) // P2273R3 constexpr unique_ptr // P2278R4 cbegin Should Always Return A Constant Iterator // P2286R8 Formatting Ranges @@ -1737,34 +1736,29 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #define __cpp_lib_is_implicit_lifetime 202302L #endif // ^^^ no workaround ^^^ -#define __cpp_lib_is_scoped_enum 202011L -#define __cpp_lib_mdspan 202207L -#define __cpp_lib_move_only_function 202110L -#define __cpp_lib_out_ptr 202311L -#define __cpp_lib_print 202406L -#define __cpp_lib_ranges_as_const 202311L -#define __cpp_lib_ranges_as_rvalue 202207L -#define __cpp_lib_ranges_cartesian_product 202207L -#define __cpp_lib_ranges_chunk 202202L -#define __cpp_lib_ranges_chunk_by 202202L -#define __cpp_lib_ranges_contains 202207L -#define __cpp_lib_ranges_enumerate 202302L -#define __cpp_lib_ranges_find_last 202207L -#define __cpp_lib_ranges_fold 202207L -#define __cpp_lib_ranges_iota 202202L -#define __cpp_lib_ranges_join_with 202202L -#define __cpp_lib_ranges_repeat 202207L -#define __cpp_lib_ranges_slide 202202L -#define __cpp_lib_ranges_starts_ends_with 202106L -#define __cpp_lib_ranges_stride 202207L -#define __cpp_lib_ranges_to_container 202202L -#define __cpp_lib_ranges_zip 202110L - -// TRANSITION, MSVC and EDG haven't implemented intrinsics needed for P2255R2. -#if defined(__clang__) && !defined(__EDG__) -#define __cpp_lib_reference_from_temporary 202202L -#endif // ^^^ no workaround ^^^ - +#define __cpp_lib_is_scoped_enum 202011L +#define __cpp_lib_mdspan 202207L +#define __cpp_lib_move_only_function 202110L +#define __cpp_lib_out_ptr 202311L +#define __cpp_lib_print 202406L +#define __cpp_lib_ranges_as_const 202311L +#define __cpp_lib_ranges_as_rvalue 202207L +#define __cpp_lib_ranges_cartesian_product 202207L +#define __cpp_lib_ranges_chunk 202202L +#define __cpp_lib_ranges_chunk_by 202202L +#define __cpp_lib_ranges_contains 202207L +#define __cpp_lib_ranges_enumerate 202302L +#define __cpp_lib_ranges_find_last 202207L +#define __cpp_lib_ranges_fold 202207L +#define __cpp_lib_ranges_iota 202202L +#define __cpp_lib_ranges_join_with 202202L +#define __cpp_lib_ranges_repeat 202207L +#define __cpp_lib_ranges_slide 202202L +#define __cpp_lib_ranges_starts_ends_with 202106L +#define __cpp_lib_ranges_stride 202207L +#define __cpp_lib_ranges_to_container 202202L +#define __cpp_lib_ranges_zip 202110L +#define __cpp_lib_reference_from_temporary 202202L #define __cpp_lib_spanstream 202106L #define __cpp_lib_stacktrace 202011L #define __cpp_lib_stdatomic_h 202011L diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 56abff7b898..c045c6426cf 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -2,6 +2,9 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # *** ISSUES REPORTED/KNOWN UPSTREAM *** +# LLVM-48860: P0466R5 Layout-Compatibility And Pointer-Interconvertibility Traits +std/language.support/support.limits/support.limits.general/type_traits.version.compile.pass.cpp:2 FAIL + # LLVM-73836: warning C5101: use of preprocessor directive in function-like macro argument list is undefined behavior std/time/time.syn/formatter.duration.pass.cpp:0 FAIL std/time/time.syn/formatter.duration.pass.cpp:1 FAIL @@ -185,8 +188,8 @@ std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_allocate_over std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_deallocate_matches_allocate.pass.cpp FAIL # libc++ hasn't completely implemented P2255R2 "Type Traits To Detect References Binding To Temporaries" -std/utilities/meta/meta.rel/is_invocable_r.compile.pass.cpp:2 FAIL -std/utilities/meta/meta.rel/is_invocable_r_v.compile.pass.cpp:2 FAIL +std/utilities/meta/meta.rel/is_invocable_r.compile.pass.cpp FAIL +std/utilities/meta/meta.rel/is_invocable_r_v.compile.pass.cpp FAIL # libc++ is missing various Ranges DRs std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp FAIL @@ -291,14 +294,6 @@ std/numerics/numeric.ops/numeric.ops.sat/sub_sat.pass.cpp FAIL std/utilities/intseq/intseq.binding/structured_binding.pass.cpp FAIL std/utilities/intseq/intseq.binding/tuple_interface.compile.pass.cpp FAIL -# P2255R2 "Type Traits To Detect References Binding To Temporaries" -# (type_traits.version.compile.pass.cpp still fails for Clang due to LLVM-48860) -std/language.support/support.limits/support.limits.general/type_traits.version.compile.pass.cpp FAIL -std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp:0 FAIL -std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp:1 FAIL -std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp:0 FAIL -std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp:1 FAIL - # P2592R3 Hashing Support For chrono Value Classes # Add 'std-at-least-c++26' to tests/utils/stl/test/tests.py when beginning work on C++26. std/time/time.hash/time.hash_enabled.pass.cpp FAIL @@ -593,6 +588,12 @@ std/algorithms/alg.nonmodifying/alg.equal/equal.pass.cpp:1 FAIL std/algorithms/alg.nonmodifying/alg.equal/ranges.equal.pass.cpp:0 FAIL std/algorithms/alg.nonmodifying/alg.equal/ranges.equal.pass.cpp:1 FAIL +# VSO-2742607 C1XX __reference_constructs_from_temporary mishandles a couple of cases +std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp:0 FAIL +std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp:1 FAIL +std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp:0 FAIL +std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp:1 FAIL + # *** CLANG COMPILER BUGS *** # LLVM-46207 Clang's tgmath.h interferes with the UCRT's tgmath.h diff --git a/tests/std/tests/P2255R2_invocation/test.compile.pass.cpp b/tests/std/tests/P2255R2_invocation/test.compile.pass.cpp index caf1e348283..ba84249144b 100644 --- a/tests/std/tests/P2255R2_invocation/test.compile.pass.cpp +++ b/tests/std/tests/P2255R2_invocation/test.compile.pass.cpp @@ -6,8 +6,6 @@ using namespace std; -// TRANSITION, MSVC and EDG haven't implemented intrinsics needed for P2255R2. -#ifdef __cpp_lib_reference_from_temporary struct LvalueTempFunctor { int operator()() const& noexcept; const int& operator()() const&& noexcept; @@ -61,4 +59,3 @@ static_assert(!is_constructible_v, LvalueTempFunctor>); static_assert(is_constructible_v, LvalueTempFunctor>); #endif // defined(__cpp_noexcept_function_type) -#endif // ^^^ no workaround ^^^ diff --git a/tests/std/tests/P2255R2_reference_constructs_from_temporary/env.lst b/tests/std/tests/P2255R2_reference_constructs_from_temporary/env.lst index 642f530ffad..b2dc2c0f570 100644 --- a/tests/std/tests/P2255R2_reference_constructs_from_temporary/env.lst +++ b/tests/std/tests/P2255R2_reference_constructs_from_temporary/env.lst @@ -1,4 +1,4 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -RUNALL_INCLUDE ..\usual_latest_matrix.lst +RUNALL_INCLUDE ..\strict_latest_matrix.lst diff --git a/tests/std/tests/P2255R2_reference_constructs_from_temporary/test.compile.pass.cpp b/tests/std/tests/P2255R2_reference_constructs_from_temporary/test.compile.pass.cpp index 1e2d1fa4a19..756fd945381 100644 --- a/tests/std/tests/P2255R2_reference_constructs_from_temporary/test.compile.pass.cpp +++ b/tests/std/tests/P2255R2_reference_constructs_from_temporary/test.compile.pass.cpp @@ -5,8 +5,6 @@ using namespace std; -// TRANSITION, MSVC and EDG haven't implemented intrinsics needed for P2255R2. -#ifdef __cpp_lib_reference_from_temporary enum class conv_explicitly : bool { no, yes, @@ -174,11 +172,15 @@ void test_to_int_ref() { static_assert(reference_constructs_from_temporary>::value == !static_cast(Explicitly)); static_assert(!reference_constructs_from_temporary>::value); +#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-2742607 static_assert(!reference_constructs_from_temporary>::value); +#endif // ^^^ no workaround ^^^ static_assert(reference_constructs_from_temporary>::value == !static_cast(Explicitly)); static_assert(!reference_constructs_from_temporary>::value); +#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-2742607 static_assert(reference_constructs_from_temporary>::value); +#endif // ^^^ no workaround ^^^ static_assert(reference_constructs_from_temporary>::value == !static_cast(Explicitly)); @@ -187,12 +189,16 @@ void test_to_int_ref() { static_assert(reference_constructs_from_temporary_v> == !static_cast(Explicitly)); static_assert(!reference_constructs_from_temporary_v>); +#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-2742607 static_assert(!reference_constructs_from_temporary_v>); +#endif // ^^^ no workaround ^^^ static_assert(reference_constructs_from_temporary_v> == !static_cast(Explicitly)); static_assert(!reference_constructs_from_temporary_v>); +#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-2742607 static_assert(reference_constructs_from_temporary_v>); +#endif // ^^^ no workaround ^^^ static_assert(reference_constructs_from_temporary_v> == !static_cast(Explicitly)); } @@ -201,4 +207,3 @@ void test_to_int_ref_all() { test_to_int_ref(); test_to_int_ref(); } -#endif // ^^^ no workaround ^^^ diff --git a/tests/std/tests/P2255R2_reference_converts_from_temporary/env.lst b/tests/std/tests/P2255R2_reference_converts_from_temporary/env.lst index 642f530ffad..b2dc2c0f570 100644 --- a/tests/std/tests/P2255R2_reference_converts_from_temporary/env.lst +++ b/tests/std/tests/P2255R2_reference_converts_from_temporary/env.lst @@ -1,4 +1,4 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -RUNALL_INCLUDE ..\usual_latest_matrix.lst +RUNALL_INCLUDE ..\strict_latest_matrix.lst diff --git a/tests/std/tests/P2255R2_reference_converts_from_temporary/test.compile.pass.cpp b/tests/std/tests/P2255R2_reference_converts_from_temporary/test.compile.pass.cpp index bd6e916c64f..d154277d011 100644 --- a/tests/std/tests/P2255R2_reference_converts_from_temporary/test.compile.pass.cpp +++ b/tests/std/tests/P2255R2_reference_converts_from_temporary/test.compile.pass.cpp @@ -5,8 +5,6 @@ using namespace std; -// TRANSITION, MSVC and EDG haven't implemented intrinsics needed for P2255R2. -#ifdef __cpp_lib_reference_from_temporary enum class conv_explicitly : bool { no, yes, @@ -174,7 +172,9 @@ void test_to_int_ref() { static_assert(reference_converts_from_temporary>::value == !static_cast(Explicitly)); static_assert(!reference_converts_from_temporary>::value); +#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-2742607 static_assert(!reference_converts_from_temporary>::value); +#endif // ^^^ no workaround ^^^ static_assert(reference_converts_from_temporary>::value == !static_cast(Explicitly)); static_assert(!reference_converts_from_temporary>::value); @@ -188,7 +188,9 @@ void test_to_int_ref() { static_assert( reference_converts_from_temporary_v> == !static_cast(Explicitly)); static_assert(!reference_converts_from_temporary_v>); +#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-2742607 static_assert(!reference_converts_from_temporary_v>); +#endif // ^^^ no workaround ^^^ static_assert( reference_converts_from_temporary_v> == !static_cast(Explicitly)); @@ -203,4 +205,3 @@ void test_to_int_ref_all() { test_to_int_ref(); test_to_int_ref(); } -#endif // ^^^ no workaround ^^^ diff --git a/tests/std/tests/P2255R2_tuple_pair_construction/test.compile.pass.cpp b/tests/std/tests/P2255R2_tuple_pair_construction/test.compile.pass.cpp index 4e19495b8c5..b45bd1b511e 100644 --- a/tests/std/tests/P2255R2_tuple_pair_construction/test.compile.pass.cpp +++ b/tests/std/tests/P2255R2_tuple_pair_construction/test.compile.pass.cpp @@ -7,8 +7,6 @@ using namespace std; -// TRANSITION, MSVC and EDG haven't implemented intrinsics needed for P2255R2. -#ifdef __cpp_lib_reference_from_temporary template void assert_constref_constructible_single() { static_assert(is_constructible_v == Expected); @@ -88,4 +86,3 @@ void assert_lvalue_temp_converter() { assert_lvalue_temp_converter_single, const int&>(); assert_lvalue_temp_converter_single, int&&>(); } -#endif // ^^^ no workaround ^^^ diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp index 055701d21f3..5e334d2b4bf 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp @@ -847,7 +847,7 @@ STATIC_ASSERT(__cpp_lib_raw_memory_algorithms == 201606L); #error __cpp_lib_raw_memory_algorithms is defined #endif -#if _HAS_CXX23 && defined(__clang__) // TRANSITION, MSVC and EDG haven't implemented intrinsics needed for P2255R2. +#if _HAS_CXX23 STATIC_ASSERT(__cpp_lib_reference_from_temporary == 202202L); #elif defined(__cpp_lib_reference_from_temporary) #error __cpp_lib_reference_from_temporary is defined From 6e409bd0e2880c694dd9c1240ecfc03ff47feb81 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 19 Feb 2026 13:12:12 -0800 Subject: [PATCH 16/35] MSVC implemented P2448R2 "Relaxing some constexpr restrictions" with MSVC-PR-686379 on 2025-12-03. --- tests/libcxx/expected_results.txt | 134 +----------------------------- 1 file changed, 1 insertion(+), 133 deletions(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index c045c6426cf..45fca59fd5f 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -331,139 +331,7 @@ std/utilities/optional/optional.iterator/iterator.pass.cpp FAIL # *** MISSING COMPILER FEATURES *** -# MSVC has not implemented P2448R2 "Relaxing some constexpr restrictions" -std/containers/container.adaptors/flat.map/flat.map.access/at_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.map/flat.map.access/at_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.map/flat.map.access/index_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.map/flat.map.access/index_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.map/flat.map.capacity/max_size.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.map/flat.map.capacity/max_size.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.map/flat.map.iterators/iterator.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.map/flat.map.iterators/iterator.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.map/flat.map.modifiers/erase_key_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.map/flat.map.modifiers/erase_key_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.map/flat.map.modifiers/extract.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.map/flat.map.modifiers/extract.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.map/flat.map.modifiers/insert_iter_iter.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.map/flat.map.modifiers/insert_iter_iter.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.map/flat.map.modifiers/insert_or_assign_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.map/flat.map.modifiers/insert_or_assign_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.map/flat.map.modifiers/insert_range_sorted_unique.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.map/flat.map.modifiers/insert_range_sorted_unique.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.map/flat.map.modifiers/insert_range.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.map/flat.map.modifiers/insert_range.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.map/flat.map.modifiers/insert_rv.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.map/flat.map.modifiers/insert_rv.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.map/flat.map.modifiers/insert_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.map/flat.map.modifiers/insert_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.map/flat.map.modifiers/try_emplace_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.map/flat.map.modifiers/try_emplace_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.map/flat.map.observers/comp.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.map/flat.map.observers/comp.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.map/flat.map.operations/contains_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.map/flat.map.operations/contains_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.map/flat.map.operations/count_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.map/flat.map.operations/count_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.map/flat.map.operations/equal_range_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.map/flat.map.operations/equal_range_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.map/flat.map.operations/find_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.map/flat.map.operations/find_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.map/flat.map.operations/lower_bound_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.map/flat.map.operations/lower_bound_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.map/flat.map.operations/upper_bound_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.map/flat.map.operations/upper_bound_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.map/op_compare.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.map/op_compare.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.capacity/max_size.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.capacity/max_size.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.iterators/iterator.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.iterators/iterator.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/erase_key_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/erase_key_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/extract.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/extract.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/insert_iter_iter.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/insert_iter_iter.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/insert_range_sorted_equivalent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/insert_range_sorted_equivalent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/insert_range.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/insert_range.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/insert_rv.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/insert_rv.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/insert_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/insert_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.observers/comp.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.observers/comp.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.operations/contains_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.operations/contains_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.operations/count_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.operations/count_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.operations/equal_range_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.operations/equal_range_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.operations/find_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.operations/find_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.operations/lower_bound_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.operations/lower_bound_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.operations/upper_bound_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multimap/flat.multimap.operations/upper_bound_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multiset/flat.multiset.capacity/max_size.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multiset/flat.multiset.capacity/max_size.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/erase_key_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/erase_key_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/extract.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/extract.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_iter_iter.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_iter_iter.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_range_sorted_equivalent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_range_sorted_equivalent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_range.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_range.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multiset/flat.multiset.observers/comp.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multiset/flat.multiset.observers/comp.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multiset/flat.multiset.operations/contains_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multiset/flat.multiset.operations/contains_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multiset/flat.multiset.operations/count_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multiset/flat.multiset.operations/count_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multiset/flat.multiset.operations/equal_range_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multiset/flat.multiset.operations/equal_range_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multiset/flat.multiset.operations/find_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multiset/flat.multiset.operations/find_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multiset/flat.multiset.operations/lower_bound_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multiset/flat.multiset.operations/lower_bound_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multiset/flat.multiset.operations/upper_bound_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multiset/flat.multiset.operations/upper_bound_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.multiset/op_compare.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.multiset/op_compare.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.set/flat.set.capacity/max_size.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.set/flat.set.capacity/max_size.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.set/flat.set.modifiers/erase_key_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.set/flat.set.modifiers/erase_key_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.set/flat.set.modifiers/extract.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.set/flat.set.modifiers/extract.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_iter_iter.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_iter_iter.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_range_sorted_unique.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_range_sorted_unique.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_range.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_range.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.set/flat.set.observers/comp.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.set/flat.set.observers/comp.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.set/flat.set.operations/contains_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.set/flat.set.operations/contains_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.set/flat.set.operations/count_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.set/flat.set.operations/count_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.set/flat.set.operations/equal_range_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.set/flat.set.operations/equal_range_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.set/flat.set.operations/find_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.set/flat.set.operations/find_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.set/flat.set.operations/lower_bound_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.set/flat.set.operations/lower_bound_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.set/flat.set.operations/upper_bound_transparent.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.set/flat.set.operations/upper_bound_transparent.pass.cpp:1 FAIL -std/containers/container.adaptors/flat.set/op_compare.pass.cpp:0 FAIL -std/containers/container.adaptors/flat.set/op_compare.pass.cpp:1 FAIL +# None! # *** MISSING LWG ISSUE RESOLUTIONS *** From 931a8f61338a38da39a8ec4bee89e44ce1d869d7 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 19 Feb 2026 13:14:40 -0800 Subject: [PATCH 17/35] MSVC fixed a constexpr bug! --- tests/libcxx/expected_results.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 45fca59fd5f..e29bb6a222b 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -933,10 +933,8 @@ std/ranges/range.adaptors/range.lazy.split/ctor.copy_move.pass.cpp FAIL std/ranges/range.adaptors/range.lazy.split/range.lazy.split.inner/iter_swap.pass.cpp FAIL # Not analyzed. -# MSVC error C2131: expression did not evaluate to a constant -# MSVC note: failure was caused by a read of an uninitialized symbol # Clang error: non-type template argument is not a constant expression -std/utilities/tuple/tuple.tuple/tuple.cnstr/convert_const_move.pass.cpp FAIL +std/utilities/tuple/tuple.tuple/tuple.cnstr/convert_const_move.pass.cpp:2 FAIL # Not analyzed, possible path length issue. With a repo root of D:\GitHub\STL (13 characters), fails with: # "error RC2136 : missing '=' in EXSTYLE=" followed by "LINK : fatal error LNK1327: failure during running rc.exe" From 0ac907896a2fc14fb29d325f9795636936ec3883 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 19 Feb 2026 14:40:44 -0800 Subject: [PATCH 18/35] Reported LLVM-182390. --- tests/libcxx/expected_results.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index e29bb6a222b..54cdd49c10d 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -101,6 +101,9 @@ std/atomics/atomics.ref/operator_plus_equals.pass.cpp SKIPPED std/atomics/atomics.ref/store.pass.cpp SKIPPED std/atomics/atomics.ref/wait.pass.cpp SKIPPED +# LLVM-182390: [libc++][test] facet.num.get.members/get_long.pass.cpp uses std::to_string() without including +std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long.pass.cpp FAIL + # Non-Standard regex behavior. # "It seems likely that the test is still non-conforming due to how libc++ handles the 'w' character class." std/re/re.traits/lookup_classname.pass.cpp FAIL @@ -741,9 +744,6 @@ std/containers/sequences/vector/trivial_relocation.pass.cpp:1 FAIL # Not analyzed, likely bogus test. constexpr fails with "vector iterators incompatible". std/ranges/range.adaptors/range.join.with/range.join.with.iterator/ctor.default.pass.cpp FAIL -# Test uses std::to_string() without including . -std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long.pass.cpp FAIL - # *** LIKELY STL BUGS *** # Not analyzed, likely STL bugs. Various assertions. From 08e79b6c27b7325f4af93ae1842b1f289c047132 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 19 Feb 2026 14:47:27 -0800 Subject: [PATCH 19/35] Reported LLVM-182392. --- tests/libcxx/expected_results.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 54cdd49c10d..c221f0c0742 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -104,6 +104,10 @@ std/atomics/atomics.ref/wait.pass.cpp SKIPPED # LLVM-182390: [libc++][test] facet.num.get.members/get_long.pass.cpp uses std::to_string() without including std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long.pass.cpp FAIL +# LLVM-182392: [libc++][test] vector/trivial_relocation.pass.cpp uses implementation-specific attribute [[clang::trivial_abi]] +std/containers/sequences/vector/trivial_relocation.pass.cpp:0 FAIL +std/containers/sequences/vector/trivial_relocation.pass.cpp:1 FAIL + # Non-Standard regex behavior. # "It seems likely that the test is still non-conforming due to how libc++ handles the 'w' character class." std/re/re.traits/lookup_classname.pass.cpp FAIL @@ -737,10 +741,6 @@ std/containers/sequences/vector/vector.capacity/resize_size_value_exceptions.pas # error: incomplete type 'std::char_traits' named in nested name specifier std/iterators/iterator.requirements/iterator.assoc.types/readable.traits/indirectly_readable_traits.compile.pass.cpp FAIL -# warning C5030: attribute [[clang::trivial_abi]] is not recognized -std/containers/sequences/vector/trivial_relocation.pass.cpp:0 FAIL -std/containers/sequences/vector/trivial_relocation.pass.cpp:1 FAIL - # Not analyzed, likely bogus test. constexpr fails with "vector iterators incompatible". std/ranges/range.adaptors/range.join.with/range.join.with.iterator/ctor.default.pass.cpp FAIL From 80469c78cb61011ce7f06e5fbb1498849a5cace3 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 19 Feb 2026 15:03:51 -0800 Subject: [PATCH 20/35] Reported LLVM-182397. --- tests/libcxx/expected_results.txt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index c221f0c0742..9544533f8bf 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -108,6 +108,9 @@ std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get std/containers/sequences/vector/trivial_relocation.pass.cpp:0 FAIL std/containers/sequences/vector/trivial_relocation.pass.cpp:1 FAIL +# LLVM-182397: [libc++][test] rand.dist.bern.negbin/eval.pass.cpp constructs with p == 1, which has undefined behavior +std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.negbin/eval.pass.cpp FAIL + # Non-Standard regex behavior. # "It seems likely that the test is still non-conforming due to how libc++ handles the 'w' character class." std/re/re.traits/lookup_classname.pass.cpp FAIL @@ -673,10 +676,6 @@ std/numerics/complex.number/cmplx.over/proj.pass.cpp:1 FAIL # libc++ handles those input values differently std/numerics/complex.number/complex.value.ops/polar.pass.cpp FAIL -# Assertion failed: invalid beta argument for gamma_distribution -# test4() constructs a negative_binomial_distribution from (40, 1); [rand.dist.bern.negbin] says p == 1 generates undefined probabilities. -std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.negbin/eval.pass.cpp FAIL - # Assertion failed: (std::lerp(T(2.3), T(2.3), inf) == T(2.3)) # Asserts `(std::lerp(T(2.3), T(2.3), inf) == T(2.3))` and `std::isnan(std::lerp(T( 0), T( 0), inf))` # They shouldn't behave differently. Both of them should probably return NaN. From cb9463b80e5bcaef0fb6637ed452434e7c9a91cc Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 20 Feb 2026 04:40:23 -0800 Subject: [PATCH 21/35] Template parameters: `_Pc` => `_ParseContext` --- stl/inc/__msvc_formatter.hpp | 15 ++++++++------- stl/inc/format | 14 ++++++++------ stl/inc/thread | 4 ++-- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/stl/inc/__msvc_formatter.hpp b/stl/inc/__msvc_formatter.hpp index 2c8758a24b8..01fa6969364 100644 --- a/stl/inc/__msvc_formatter.hpp +++ b/stl/inc/__msvc_formatter.hpp @@ -147,8 +147,9 @@ struct formatter { _FMT_P2286_BEGIN // TRANSITION, VSO-1236041: Avoid declaring and defining member functions in different headers. -template <_Basic_format_arg_type _ArgType, class _CharT, class _Pc> -constexpr _Pc::iterator _Formatter_base_parse(_Dynamic_format_specs<_CharT>& _Specs, _Pc& _ParseCtx); +template <_Basic_format_arg_type _ArgType, class _CharT, class _ParseContext> +constexpr _ParseContext::iterator _Formatter_base_parse( + _Dynamic_format_specs<_CharT>& _Specs, _ParseContext& _ParseCtx); template _FormatContext::iterator _Formatter_base_format( @@ -165,8 +166,8 @@ struct _Formatter_base { } #endif // _HAS_CXX23 - template > - constexpr _Pc::iterator parse(type_identity_t<_Pc&> _ParseCtx) { + template > + constexpr _ParseContext::iterator parse(type_identity_t<_ParseContext&> _ParseCtx) { return _Formatter_base_parse<_ArgType>(_Specs, _ParseCtx); } @@ -420,9 +421,9 @@ struct _Fill_align_and_width_specs { }; // TRANSITION, VSO-1236041: Avoid declaring and defining member functions in different headers. -template -_NODISCARD constexpr _Pc::iterator _Fill_align_and_width_formatter_parse( - _Fill_align_and_width_specs<_CharT>& _Specs, _Pc& _Parse_ctx); +template +_NODISCARD constexpr _ParseContext::iterator _Fill_align_and_width_formatter_parse( + _Fill_align_and_width_specs<_CharT>& _Specs, _ParseContext& _Parse_ctx); template _NODISCARD _FormatContext::iterator _Fill_align_and_width_formatter_format( diff --git a/stl/inc/format b/stl/inc/format index 472d3017e9f..7289d86101b 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -2890,9 +2890,11 @@ struct _Format_handler { } }; -template <_Basic_format_arg_type _ArgType, class _CharT, class _Pc> -constexpr _Pc::iterator _Formatter_base_parse(_Dynamic_format_specs<_CharT>& _Specs, _Pc& _ParseCtx) { - _Specs_checker<_Dynamic_specs_handler<_Pc>> _Handler(_Dynamic_specs_handler<_Pc>{_Specs, _ParseCtx}, _ArgType); +template <_Basic_format_arg_type _ArgType, class _CharT, class _ParseContext> +constexpr _ParseContext::iterator _Formatter_base_parse( + _Dynamic_format_specs<_CharT>& _Specs, _ParseContext& _ParseCtx) { + _Specs_checker<_Dynamic_specs_handler<_ParseContext>> _Handler( + _Dynamic_specs_handler<_ParseContext>{_Specs, _ParseCtx}, _ArgType); const auto _It = _Parse_format_specs(_ParseCtx._Unchecked_begin(), _ParseCtx._Unchecked_end(), _Handler); if (_It != _ParseCtx._Unchecked_end() && *_It != '}') { _Throw_format_error("Missing '}' in format string."); @@ -3693,9 +3695,9 @@ _NODISCARD constexpr const _CharT* _Parse_fill_align_and_width_specs( } // TRANSITION, VSO-1236041: Avoid declaring and defining member functions in different headers. -template -_NODISCARD constexpr _Pc::iterator _Fill_align_and_width_formatter_parse( - _Fill_align_and_width_specs<_CharT>& _Specs, _Pc& _Parse_ctx) { +template +_NODISCARD constexpr _ParseContext::iterator _Fill_align_and_width_formatter_parse( + _Fill_align_and_width_specs<_CharT>& _Specs, _ParseContext& _Parse_ctx) { _Fill_align_and_width_specs_setter<_CharT> _Callback{_Specs, _Parse_ctx}; const auto _It = _Parse_fill_align_and_width_specs(_Parse_ctx._Unchecked_begin(), _Parse_ctx._Unchecked_end(), _Callback); diff --git a/stl/inc/thread b/stl/inc/thread index 661eb6d2baf..c7d5b2676d1 100644 --- a/stl/inc/thread +++ b/stl/inc/thread @@ -309,8 +309,8 @@ basic_ostream<_Ch, _Tr>& operator<<(basic_ostream<_Ch, _Tr>& _Str, thread::id _I // constrained to character types supported by `format`. template <_Format_supported_charT _CharT> struct formatter { - template > // improves throughput, see GH-5003 - constexpr _Pc::iterator parse(type_identity_t<_Pc&> _Parse_ctx) { + template > // improves throughput, see GH-5003 + constexpr _ParseContext::iterator parse(type_identity_t<_ParseContext&> _Parse_ctx) { return _Impl._Parse(_Parse_ctx); } From 7a94b6ba5f5b7668b5456a6c26fe3402bad20e17 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 20 Feb 2026 04:42:25 -0800 Subject: [PATCH 22/35] Function parameters: `_Pc` => `_Parse_ctx` --- stl/inc/format | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/format b/stl/inc/format index 7289d86101b..95efcce220a 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -2797,7 +2797,7 @@ struct _Arg_formatter { // care about avoiding code bloat for code that never runs at runtime, and we can't form // the erased basic_format_args structure at compile time. template -consteval _ParseContext::iterator _Compile_time_parse_format_specs(_ParseContext& _Pc) { +consteval _ParseContext::iterator _Compile_time_parse_format_specs(_ParseContext& _Parse_ctx) { using _CharT = _ParseContext::char_type; using _Context = basic_format_context>, _CharT>; using _ArgTraits = _Format_arg_traits<_Context>; @@ -2808,7 +2808,7 @@ consteval _ParseContext::iterator _Compile_time_parse_format_specs(_ParseContext using _FormattedType = conditional_t::handle>, _Ty, _FormattedTypeMapping>; formatter<_FormattedType, _CharT> _Formatter{}; - return _Formatter.parse(_Pc); + return _Formatter.parse(_Parse_ctx); } // set of format parsing actions that only checks for validity From 2bfcd9edf9f4aa455d339d4e6cecef40c511a967 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 20 Feb 2026 04:45:03 -0800 Subject: [PATCH 23/35] Template parameters: `_ParseCtx` => `_ParseContext` --- stl/inc/__msvc_ranges_tuple_formatter.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/__msvc_ranges_tuple_formatter.hpp b/stl/inc/__msvc_ranges_tuple_formatter.hpp index 43c6c51b5b7..968b36bbd67 100644 --- a/stl/inc/__msvc_ranges_tuple_formatter.hpp +++ b/stl/inc/__msvc_ranges_tuple_formatter.hpp @@ -1128,8 +1128,8 @@ struct _Adaptor_formatter_base { formatter<_RefView<_Maybe_const_container>, _CharT> _Underlying; public: - template - constexpr _ParseCtx::iterator parse(_ParseCtx& _Ctx) { + template + constexpr _ParseContext::iterator parse(_ParseContext& _Ctx) { return _Underlying.parse(_Ctx); } From 51cf20033682b6dbe466904edc5fc6a41826d787 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 20 Feb 2026 04:46:21 -0800 Subject: [PATCH 24/35] Function parameters: `_ParseCtx` => `_Parse_ctx` --- stl/inc/__msvc_formatter.hpp | 6 +++--- stl/inc/format | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/stl/inc/__msvc_formatter.hpp b/stl/inc/__msvc_formatter.hpp index 01fa6969364..615fc2a5428 100644 --- a/stl/inc/__msvc_formatter.hpp +++ b/stl/inc/__msvc_formatter.hpp @@ -149,7 +149,7 @@ _FMT_P2286_BEGIN // TRANSITION, VSO-1236041: Avoid declaring and defining member functions in different headers. template <_Basic_format_arg_type _ArgType, class _CharT, class _ParseContext> constexpr _ParseContext::iterator _Formatter_base_parse( - _Dynamic_format_specs<_CharT>& _Specs, _ParseContext& _ParseCtx); + _Dynamic_format_specs<_CharT>& _Specs, _ParseContext& _Parse_ctx); template _FormatContext::iterator _Formatter_base_format( @@ -167,8 +167,8 @@ struct _Formatter_base { #endif // _HAS_CXX23 template > - constexpr _ParseContext::iterator parse(type_identity_t<_ParseContext&> _ParseCtx) { - return _Formatter_base_parse<_ArgType>(_Specs, _ParseCtx); + constexpr _ParseContext::iterator parse(type_identity_t<_ParseContext&> _Parse_ctx) { + return _Formatter_base_parse<_ArgType>(_Specs, _Parse_ctx); } template diff --git a/stl/inc/format b/stl/inc/format index 95efcce220a..b804301fd05 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -2892,14 +2892,14 @@ struct _Format_handler { template <_Basic_format_arg_type _ArgType, class _CharT, class _ParseContext> constexpr _ParseContext::iterator _Formatter_base_parse( - _Dynamic_format_specs<_CharT>& _Specs, _ParseContext& _ParseCtx) { + _Dynamic_format_specs<_CharT>& _Specs, _ParseContext& _Parse_ctx) { _Specs_checker<_Dynamic_specs_handler<_ParseContext>> _Handler( - _Dynamic_specs_handler<_ParseContext>{_Specs, _ParseCtx}, _ArgType); - const auto _It = _Parse_format_specs(_ParseCtx._Unchecked_begin(), _ParseCtx._Unchecked_end(), _Handler); - if (_It != _ParseCtx._Unchecked_end() && *_It != '}') { + _Dynamic_specs_handler<_ParseContext>{_Specs, _Parse_ctx}, _ArgType); + const auto _It = _Parse_format_specs(_Parse_ctx._Unchecked_begin(), _Parse_ctx._Unchecked_end(), _Handler); + if (_It != _Parse_ctx._Unchecked_end() && *_It != '}') { _Throw_format_error("Missing '}' in format string."); } - return _ParseCtx.begin() + (_It - _ParseCtx._Unchecked_begin()); + return _Parse_ctx.begin() + (_It - _Parse_ctx._Unchecked_begin()); } template From 9fe4ce0d568d129747c5d50f165aa440fdec2f87 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 20 Feb 2026 04:49:05 -0800 Subject: [PATCH 25/35] Function parameters: `_FormatCtx` => `_Format_ctx` --- stl/inc/__msvc_formatter.hpp | 6 +++--- stl/inc/chrono | 38 ++++++++++++++++++------------------ stl/inc/format | 8 ++++---- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/stl/inc/__msvc_formatter.hpp b/stl/inc/__msvc_formatter.hpp index 615fc2a5428..12505084f88 100644 --- a/stl/inc/__msvc_formatter.hpp +++ b/stl/inc/__msvc_formatter.hpp @@ -153,7 +153,7 @@ constexpr _ParseContext::iterator _Formatter_base_parse( template _FormatContext::iterator _Formatter_base_format( - const _Dynamic_format_specs<_CharT>& _Specs, const _Ty& _Val, _FormatContext& _FormatCtx); + const _Dynamic_format_specs<_CharT>& _Specs, const _Ty& _Val, _FormatContext& _Format_ctx); template struct _Formatter_base { @@ -172,8 +172,8 @@ struct _Formatter_base { } template - _FormatContext::iterator format(const _Ty& _Val, _FormatContext& _FormatCtx) const { - return _Formatter_base_format(_Specs, _Val, _FormatCtx); + _FormatContext::iterator format(const _Ty& _Val, _FormatContext& _Format_ctx) const { + return _Formatter_base_format(_Specs, _Val, _Format_ctx); } private: diff --git a/stl/inc/chrono b/stl/inc/chrono index dbf2c37a6c3..b0a8bf31a2a 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -5457,10 +5457,10 @@ namespace chrono { } template - _NODISCARD auto _Write(_FormatContext& _FormatCtx, const _Ty& _Val, const tm& _Time) const { + _NODISCARD auto _Write(_FormatContext& _Format_ctx, const _Ty& _Val, const tm& _Time) const { basic_ostringstream<_CharT> _Stream; - _Stream.imbue(_Specs._Localized ? _FormatCtx.locale() : locale::classic()); + _Stream.imbue(_Specs._Localized ? _Format_ctx.locale() : locale::classic()); if (_Specs._Chrono_specs_list.empty()) { _Stream << _Val; // N4950 [time.format]/7 } else { @@ -5492,7 +5492,7 @@ namespace chrono { if constexpr (is_same_v<_CharT, char>) { if (_Specs._Localized) { wostringstream _Wstream; - _Wstream.imbue(_FormatCtx.locale()); + _Wstream.imbue(_Format_ctx.locale()); wchar_t _Fmt_str[4]; _Chrono_spec _Wspec{._Modifier = _Spec._Modifier, ._Type = _Spec._Type}; @@ -5517,10 +5517,10 @@ namespace chrono { auto _Format_specs = _Specs; if (_Specs._Dynamic_width_index >= 0) { _Format_specs._Width = _STD _Get_dynamic_specs<_Width_checker>( - _FormatCtx.arg(static_cast(_Specs._Dynamic_width_index))); + _Format_ctx.arg(static_cast(_Specs._Dynamic_width_index))); } - return _STD _Write_aligned(_STD move(_FormatCtx.out()), _Estimated_width, _Format_specs, _Fmt_align::_Left, + return _STD _Write_aligned(_STD move(_Format_ctx.out()), _Estimated_width, _Format_specs, _Fmt_align::_Left, [&](auto _Out) { return _STD _Fmt_write(_STD move(_Out), _Stream.view()); }); } @@ -5857,8 +5857,8 @@ struct _Fill_tm_formatter { } template - auto format(const _Ty& _Val, _FormatContext& _FormatCtx) const { - return _Impl._Write(_FormatCtx, _Val, _CHRONO _Fill_tm(_Val)); + auto format(const _Ty& _Val, _FormatContext& _Format_ctx) const { + return _Impl._Write(_Format_ctx, _Val, _CHRONO _Fill_tm(_Val)); } private: @@ -6031,8 +6031,8 @@ struct formatter<_CHRONO sys_time<_Duration>, _CharT> { } template - auto format(const _CHRONO sys_time<_Duration>& _Val, _FormatContext& _FormatCtx) const { - return _Impl._Write(_FormatCtx, _Val, _CHRONO _Fill_tm(_Val)); + auto format(const _CHRONO sys_time<_Duration>& _Val, _FormatContext& _Format_ctx) const { + return _Impl._Write(_Format_ctx, _Val, _CHRONO _Fill_tm(_Val)); } private: @@ -6051,9 +6051,9 @@ struct formatter<_CHRONO utc_time<_Duration>, _CharT> { } template - auto format(const _CHRONO utc_time<_Duration>& _Val, _FormatContext& _FormatCtx) const { + auto format(const _CHRONO utc_time<_Duration>& _Val, _FormatContext& _Format_ctx) const { const auto _Sys = _CHRONO utc_clock::to_sys(_Val); - return _Impl._Write(_FormatCtx, _Val, _CHRONO _Fill_tm(_Sys)); + return _Impl._Write(_Format_ctx, _Val, _CHRONO _Fill_tm(_Sys)); } private: @@ -6072,12 +6072,12 @@ struct formatter<_CHRONO tai_time<_Duration>, _CharT> { } template - auto format(const _CHRONO tai_time<_Duration>& _Val, _FormatContext& _FormatCtx) const { + auto format(const _CHRONO tai_time<_Duration>& _Val, _FormatContext& _Format_ctx) const { using namespace chrono; using _Common = common_type_t<_Duration, days>; // slightly optimize by performing conversion at compile time constexpr _Common _Offset{sys_days{year{1970} / January / 1} - sys_days{year{1958} / January / 1}}; const auto _Sys = sys_time<_Duration>{_Val.time_since_epoch()} - _Offset; - return _Impl._Write(_FormatCtx, _Val, _CHRONO _Fill_tm(_Sys)); + return _Impl._Write(_Format_ctx, _Val, _CHRONO _Fill_tm(_Sys)); } private: @@ -6096,12 +6096,12 @@ struct formatter<_CHRONO gps_time<_Duration>, _CharT> { } template - auto format(const _CHRONO gps_time<_Duration>& _Val, _FormatContext& _FormatCtx) const { + auto format(const _CHRONO gps_time<_Duration>& _Val, _FormatContext& _Format_ctx) const { using namespace chrono; using _Common = common_type_t<_Duration, days>; // slightly optimize by performing conversion at compile time constexpr _Common _Offset{sys_days{year{1980} / January / Sunday[1]} - sys_days{year{1970} / January / 1}}; const auto _Sys = sys_time<_Duration>{_Val.time_since_epoch()} + _Offset; - return _Impl._Write(_FormatCtx, _Val, _CHRONO _Fill_tm(_Sys)); + return _Impl._Write(_Format_ctx, _Val, _CHRONO _Fill_tm(_Sys)); } private: @@ -6120,10 +6120,10 @@ struct formatter<_CHRONO file_time<_Duration>, _CharT> { } template - auto format(const _CHRONO file_time<_Duration>& _Val, _FormatContext& _FormatCtx) const { + auto format(const _CHRONO file_time<_Duration>& _Val, _FormatContext& _Format_ctx) const { const auto _Utc = _CHRONO file_clock::to_utc(_Val); const auto _Sys = _CHRONO utc_clock::to_sys(_Utc); - return _Impl._Write(_FormatCtx, _Utc, _CHRONO _Fill_tm(_Sys)); + return _Impl._Write(_Format_ctx, _Utc, _CHRONO _Fill_tm(_Sys)); } private: @@ -6156,10 +6156,10 @@ template struct formatter<_CHRONO zoned_time<_Duration, _TimeZonePtr>, _CharT> : formatter<_CHRONO _Local_time_format_t>, _CharT> { template - auto format(const _CHRONO zoned_time<_Duration, _TimeZonePtr>& _Val, _FormatContext& _FormatCtx) const { + auto format(const _CHRONO zoned_time<_Duration, _TimeZonePtr>& _Val, _FormatContext& _Format_ctx) const { using _Mybase = formatter<_CHRONO _Local_time_format_t>, _CharT>; const auto _Info = _Val.get_info(); - return _Mybase::format({_Val.get_local_time(), &_Info.abbrev, &_Info.offset}, _FormatCtx); + return _Mybase::format({_Val.get_local_time(), &_Info.abbrev, &_Info.offset}, _Format_ctx); } }; diff --git a/stl/inc/format b/stl/inc/format index b804301fd05..798a81d8259 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -2904,21 +2904,21 @@ constexpr _ParseContext::iterator _Formatter_base_parse( template _FormatContext::iterator _Formatter_base_format( - const _Dynamic_format_specs<_CharT>& _Specs, const _Ty& _Val, _FormatContext& _FormatCtx) { + const _Dynamic_format_specs<_CharT>& _Specs, const _Ty& _Val, _FormatContext& _Format_ctx) { _Dynamic_format_specs<_CharT> _Format_specs = _Specs; if (_Specs._Dynamic_width_index >= 0) { _Format_specs._Width = - _Get_dynamic_specs<_Width_checker>(_FormatCtx.arg(static_cast(_Specs._Dynamic_width_index))); + _Get_dynamic_specs<_Width_checker>(_Format_ctx.arg(static_cast(_Specs._Dynamic_width_index))); } if (_Specs._Dynamic_precision_index >= 0) { _Format_specs._Precision = _Get_dynamic_specs<_Precision_checker>( - _FormatCtx.arg(static_cast(_Specs._Dynamic_precision_index))); + _Format_ctx.arg(static_cast(_Specs._Dynamic_precision_index))); } return _STD visit_format_arg( _Arg_formatter{ - ._Ctx = _STD addressof(_FormatCtx), ._Specs = _STD addressof(_Format_specs)}, + ._Ctx = _STD addressof(_Format_ctx), ._Specs = _STD addressof(_Format_specs)}, basic_format_arg<_FormatContext>::_Make_from(_Val)); } _FMT_P2286_END From ec5c9cd854bae1674dca43d847988ae1613f804f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 20 Feb 2026 04:53:15 -0800 Subject: [PATCH 26/35] Template parameters: `_FmtCtx` => `_FormatContext` --- stl/inc/__msvc_ranges_tuple_formatter.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/__msvc_ranges_tuple_formatter.hpp b/stl/inc/__msvc_ranges_tuple_formatter.hpp index 968b36bbd67..e28732dc1e6 100644 --- a/stl/inc/__msvc_ranges_tuple_formatter.hpp +++ b/stl/inc/__msvc_ranges_tuple_formatter.hpp @@ -1133,8 +1133,8 @@ struct _Adaptor_formatter_base { return _Underlying.parse(_Ctx); } - template - _FmtCtx::iterator format(_Maybe_const_adaptor& _Adaptor, _FmtCtx& _Ctx) const { + template + _FormatContext::iterator format(_Maybe_const_adaptor& _Adaptor, _FormatContext& _Ctx) const { struct _Container_exposer : _AdaptorType { using _AdaptorType::c; From e5b5349966ba54ca8a47888d9352a9386ba0cfd5 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 20 Feb 2026 04:56:28 -0800 Subject: [PATCH 27/35] `_Fill_align_and_width_formatter::_Format()` shouldn't be `constexpr`. This was bogus because `_Fill_align_and_width_formatter_format()` was correctly non-`constexpr`. --- stl/inc/__msvc_formatter.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/__msvc_formatter.hpp b/stl/inc/__msvc_formatter.hpp index 12505084f88..12d3ae259a7 100644 --- a/stl/inc/__msvc_formatter.hpp +++ b/stl/inc/__msvc_formatter.hpp @@ -439,7 +439,7 @@ struct _Fill_align_and_width_formatter { } template - _NODISCARD constexpr auto _Format( + _NODISCARD auto _Format( _FormatContext& _Format_ctx, const int _Width, _Fmt_align _Default_align, _Func&& _Fn) const { return _STD _Fill_align_and_width_formatter_format( _Specs, _Format_ctx, _Width, _Default_align, _STD forward<_Func>(_Fn)); From 75b34871ff0825c78d2feca965992892d5bbf94e Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 20 Feb 2026 05:19:13 -0800 Subject: [PATCH 28/35] `_Fill_align_and_width_formatter::_Format()` return type: `auto` => `_FormatContext::iterator` --- stl/inc/__msvc_formatter.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/__msvc_formatter.hpp b/stl/inc/__msvc_formatter.hpp index 12d3ae259a7..014bd1d2ec3 100644 --- a/stl/inc/__msvc_formatter.hpp +++ b/stl/inc/__msvc_formatter.hpp @@ -439,7 +439,7 @@ struct _Fill_align_and_width_formatter { } template - _NODISCARD auto _Format( + _NODISCARD _FormatContext::iterator _Format( _FormatContext& _Format_ctx, const int _Width, _Fmt_align _Default_align, _Func&& _Fn) const { return _STD _Fill_align_and_width_formatter_format( _Specs, _Format_ctx, _Width, _Default_align, _STD forward<_Func>(_Fn)); From f23891292c81ca986574e7b855842f3915e56729 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 20 Feb 2026 08:40:46 -0800 Subject: [PATCH 29/35] Update citations: VSO-1236041 => VSO-2744645 VSO-1236041 was reportedly fixed on 2025-09-08, but it didn't work. I've reported VSO-2744645 "Standard Library Header Units: Declaring and defining constexpr member functions in different headers fails to compile". --- stl/inc/__msvc_formatter.hpp | 4 ++-- stl/inc/__msvc_ranges_tuple_formatter.hpp | 4 ++-- stl/inc/format | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/stl/inc/__msvc_formatter.hpp b/stl/inc/__msvc_formatter.hpp index 014bd1d2ec3..ef208f949fa 100644 --- a/stl/inc/__msvc_formatter.hpp +++ b/stl/inc/__msvc_formatter.hpp @@ -146,7 +146,7 @@ struct formatter { }; _FMT_P2286_BEGIN -// TRANSITION, VSO-1236041: Avoid declaring and defining member functions in different headers. +// TRANSITION, VSO-2744645: Avoid declaring and defining member functions in different headers. template <_Basic_format_arg_type _ArgType, class _CharT, class _ParseContext> constexpr _ParseContext::iterator _Formatter_base_parse( _Dynamic_format_specs<_CharT>& _Specs, _ParseContext& _Parse_ctx); @@ -420,7 +420,7 @@ struct _Fill_align_and_width_specs { _CharT _Fill[4 / sizeof(_CharT)]{' '}; }; -// TRANSITION, VSO-1236041: Avoid declaring and defining member functions in different headers. +// TRANSITION, VSO-2744645: Avoid declaring and defining member functions in different headers. template _NODISCARD constexpr _ParseContext::iterator _Fill_align_and_width_formatter_parse( _Fill_align_and_width_specs<_CharT>& _Specs, _ParseContext& _Parse_ctx); diff --git a/stl/inc/__msvc_ranges_tuple_formatter.hpp b/stl/inc/__msvc_ranges_tuple_formatter.hpp index e28732dc1e6..d2a1ee49e6e 100644 --- a/stl/inc/__msvc_ranges_tuple_formatter.hpp +++ b/stl/inc/__msvc_ranges_tuple_formatter.hpp @@ -903,7 +903,7 @@ struct _Range_specs : _Fill_align_and_width_specs<_CharT> { char _Type = '\0'; }; -// TRANSITION, VSO-1236041: Avoid declaring and defining member functions in different headers. +// TRANSITION, VSO-2744645: Avoid declaring and defining member functions in different headers. template _NODISCARD constexpr _ParseContext::iterator _Range_formatter_parse(formatter<_Ty, _CharT>& _Underlying, basic_string_view<_CharT>& _Separator, basic_string_view<_CharT>& _Opening_bracket, @@ -1148,7 +1148,7 @@ struct _Adaptor_formatter_base { } }; -// TRANSITION, VSO-1236041: Avoid declaring and defining member functions in different headers. +// TRANSITION, VSO-2744645: Avoid declaring and defining member functions in different headers. template _NODISCARD constexpr _ParseContext::iterator _Tuple_formatter_parse(tuple...>& _Underlying, basic_string_view<_CharT>& _Separator, basic_string_view<_CharT>& _Opening_bracket, diff --git a/stl/inc/format b/stl/inc/format index 798a81d8259..9083dd2d749 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -3273,7 +3273,7 @@ _NODISCARD constexpr const _CharT* _Parse_range_specs( return _Begin; } -// TRANSITION, VSO-1236041: Avoid declaring and defining member functions in different headers. +// TRANSITION, VSO-2744645: Avoid declaring and defining member functions in different headers. template _NODISCARD constexpr _ParseContext::iterator _Range_formatter_parse(formatter<_Ty, _CharT>& _Underlying, basic_string_view<_CharT>& _Separator, basic_string_view<_CharT>& _Opening_bracket, @@ -3551,7 +3551,7 @@ constexpr void _Set_tuple_debug_format(_FormatterType& _Formatter, _ParseContext } } -// TRANSITION, VSO-1236041: Avoid declaring and defining member functions in different headers. +// TRANSITION, VSO-2744645: Avoid declaring and defining member functions in different headers. template _NODISCARD constexpr _ParseContext::iterator _Tuple_formatter_parse(tuple...>& _Underlying, basic_string_view<_CharT>& _Separator, basic_string_view<_CharT>& _Opening_bracket, @@ -3694,7 +3694,7 @@ _NODISCARD constexpr const _CharT* _Parse_fill_align_and_width_specs( return _Parse_width(_Begin, _End, _Callbacks); } -// TRANSITION, VSO-1236041: Avoid declaring and defining member functions in different headers. +// TRANSITION, VSO-2744645: Avoid declaring and defining member functions in different headers. template _NODISCARD constexpr _ParseContext::iterator _Fill_align_and_width_formatter_parse( _Fill_align_and_width_specs<_CharT>& _Specs, _ParseContext& _Parse_ctx) { From 75ffc424da478698c7107c4734838395587743c6 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 20 Feb 2026 08:56:06 -0800 Subject: [PATCH 30/35] Drop `_NODISCARD` on workaround functions to match their callers. This will reduce code churn when we unify them. --- stl/inc/__msvc_ranges_tuple_formatter.hpp | 8 ++++---- stl/inc/format | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/stl/inc/__msvc_ranges_tuple_formatter.hpp b/stl/inc/__msvc_ranges_tuple_formatter.hpp index d2a1ee49e6e..70224273588 100644 --- a/stl/inc/__msvc_ranges_tuple_formatter.hpp +++ b/stl/inc/__msvc_ranges_tuple_formatter.hpp @@ -905,12 +905,12 @@ struct _Range_specs : _Fill_align_and_width_specs<_CharT> { // TRANSITION, VSO-2744645: Avoid declaring and defining member functions in different headers. template -_NODISCARD constexpr _ParseContext::iterator _Range_formatter_parse(formatter<_Ty, _CharT>& _Underlying, +constexpr _ParseContext::iterator _Range_formatter_parse(formatter<_Ty, _CharT>& _Underlying, basic_string_view<_CharT>& _Separator, basic_string_view<_CharT>& _Opening_bracket, basic_string_view<_CharT>& _Closing_bracket, _Range_specs<_CharT>& _Specs, _ParseContext& _Ctx); template -_NODISCARD _FormatContext::iterator _Range_formatter_format(const formatter<_Ty, _CharT>& _Underlying, +_FormatContext::iterator _Range_formatter_format(const formatter<_Ty, _CharT>& _Underlying, basic_string_view<_CharT> _Separator, basic_string_view<_CharT> _Opening_bracket, basic_string_view<_CharT> _Closing_bracket, const _Range_specs<_CharT>& _Specs, _Range&& _Rng, _FormatContext& _Ctx); @@ -1150,12 +1150,12 @@ struct _Adaptor_formatter_base { // TRANSITION, VSO-2744645: Avoid declaring and defining member functions in different headers. template -_NODISCARD constexpr _ParseContext::iterator _Tuple_formatter_parse(tuple...>& _Underlying, +constexpr _ParseContext::iterator _Tuple_formatter_parse(tuple...>& _Underlying, basic_string_view<_CharT>& _Separator, basic_string_view<_CharT>& _Opening_bracket, basic_string_view<_CharT>& _Closing_bracket, _Fill_align_and_width_specs<_CharT>& _Specs, _ParseContext& _Ctx); template -_NODISCARD _FormatContext::iterator _Tuple_formatter_format(const tuple...>& _Underlying, +_FormatContext::iterator _Tuple_formatter_format(const tuple...>& _Underlying, basic_string_view<_CharT> _Separator, basic_string_view<_CharT> _Opening_bracket, basic_string_view<_CharT> _Closing_bracket, const _Fill_align_and_width_specs<_CharT>& _Specs, _FormatContext& _Fmt_ctx, _ArgTypes&... _Args); diff --git a/stl/inc/format b/stl/inc/format index 9083dd2d749..1c902c68d7b 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -3275,7 +3275,7 @@ _NODISCARD constexpr const _CharT* _Parse_range_specs( // TRANSITION, VSO-2744645: Avoid declaring and defining member functions in different headers. template -_NODISCARD constexpr _ParseContext::iterator _Range_formatter_parse(formatter<_Ty, _CharT>& _Underlying, +constexpr _ParseContext::iterator _Range_formatter_parse(formatter<_Ty, _CharT>& _Underlying, basic_string_view<_CharT>& _Separator, basic_string_view<_CharT>& _Opening_bracket, basic_string_view<_CharT>& _Closing_bracket, _Range_specs<_CharT>& _Specs, _ParseContext& _Ctx) { _Range_specs_setter<_CharT> _Callback{_Specs, _Ctx}; @@ -3398,7 +3398,7 @@ void _Range_formatter_format_as_string(_Range&& _Rng, _FormatContext& _Ctx, cons } template -_NODISCARD _FormatContext::iterator _Range_formatter_format(const formatter<_Ty, _CharT>& _Underlying, +_FormatContext::iterator _Range_formatter_format(const formatter<_Ty, _CharT>& _Underlying, const basic_string_view<_CharT> _Separator, const basic_string_view<_CharT> _Opening_bracket, const basic_string_view<_CharT> _Closing_bracket, const _Range_specs<_CharT>& _Specs, _Range&& _Rng, _FormatContext& _Ctx) { @@ -3553,7 +3553,7 @@ constexpr void _Set_tuple_debug_format(_FormatterType& _Formatter, _ParseContext // TRANSITION, VSO-2744645: Avoid declaring and defining member functions in different headers. template -_NODISCARD constexpr _ParseContext::iterator _Tuple_formatter_parse(tuple...>& _Underlying, +constexpr _ParseContext::iterator _Tuple_formatter_parse(tuple...>& _Underlying, basic_string_view<_CharT>& _Separator, basic_string_view<_CharT>& _Opening_bracket, basic_string_view<_CharT>& _Closing_bracket, _Fill_align_and_width_specs<_CharT>& _Specs, _ParseContext& _Ctx) { _Fmt_tuple_type _Fmt_type = _Fmt_tuple_type::_None; @@ -3598,7 +3598,7 @@ void _Tuple_formatter_format_to_context(const tuple... } template -_NODISCARD _FormatContext::iterator _Tuple_formatter_format(const tuple...>& _Underlying, +_FormatContext::iterator _Tuple_formatter_format(const tuple...>& _Underlying, const basic_string_view<_CharT> _Separator, const basic_string_view<_CharT> _Opening_bracket, const basic_string_view<_CharT> _Closing_bracket, const _Fill_align_and_width_specs<_CharT>& _Specs, _FormatContext& _Fmt_ctx, _ArgTypes&... _Args) { From ce586f5a8bf9848bb4dd2e002e6726677914da9b Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 20 Feb 2026 05:47:49 -0800 Subject: [PATCH 31/35] ``: Remove workarounds for declaring and defining member functions in different headers. For `pair`'s piecewise constructor, we used `_Tuple_get()` as a perma-workaround, and I don't want to change that now. Note that I'm transferring an `_STL_INTERNAL_STATIC_ASSERT` in `_Tuple_formatter_common_base::_Format()`. Reported VSO-2744645 "Standard Library Header Units: Declaring and defining constexpr member functions in different headers fails to compile" which should be a very easy fix according to Cameron. --- stl/inc/__msvc_formatter.hpp | 40 ++-------- stl/inc/__msvc_ranges_tuple_formatter.hpp | 45 +---------- stl/inc/format | 79 +++++++++++-------- .../include/test_header_units_and_modules.hpp | 4 + 4 files changed, 60 insertions(+), 108 deletions(-) diff --git a/stl/inc/__msvc_formatter.hpp b/stl/inc/__msvc_formatter.hpp index ef208f949fa..0f70edd3590 100644 --- a/stl/inc/__msvc_formatter.hpp +++ b/stl/inc/__msvc_formatter.hpp @@ -146,15 +146,6 @@ struct formatter { }; _FMT_P2286_BEGIN -// TRANSITION, VSO-2744645: Avoid declaring and defining member functions in different headers. -template <_Basic_format_arg_type _ArgType, class _CharT, class _ParseContext> -constexpr _ParseContext::iterator _Formatter_base_parse( - _Dynamic_format_specs<_CharT>& _Specs, _ParseContext& _Parse_ctx); - -template -_FormatContext::iterator _Formatter_base_format( - const _Dynamic_format_specs<_CharT>& _Specs, const _Ty& _Val, _FormatContext& _Format_ctx); - template struct _Formatter_base { public: @@ -167,14 +158,10 @@ struct _Formatter_base { #endif // _HAS_CXX23 template > - constexpr _ParseContext::iterator parse(type_identity_t<_ParseContext&> _Parse_ctx) { - return _Formatter_base_parse<_ArgType>(_Specs, _Parse_ctx); - } + constexpr _ParseContext::iterator parse(type_identity_t<_ParseContext&> _Parse_ctx); // defined in template - _FormatContext::iterator format(const _Ty& _Val, _FormatContext& _Format_ctx) const { - return _Formatter_base_format(_Specs, _Val, _Format_ctx); - } + _FormatContext::iterator format(const _Ty& _Val, _FormatContext& _Format_ctx) const; // defined in private: _Dynamic_format_specs<_CharT> _Specs; @@ -420,30 +407,17 @@ struct _Fill_align_and_width_specs { _CharT _Fill[4 / sizeof(_CharT)]{' '}; }; -// TRANSITION, VSO-2744645: Avoid declaring and defining member functions in different headers. -template -_NODISCARD constexpr _ParseContext::iterator _Fill_align_and_width_formatter_parse( - _Fill_align_and_width_specs<_CharT>& _Specs, _ParseContext& _Parse_ctx); - -template -_NODISCARD _FormatContext::iterator _Fill_align_and_width_formatter_format( - const _Fill_align_and_width_specs<_CharT>& _Specs, _FormatContext& _Format_ctx, int _Width, - _Fmt_align _Default_align, _Func&& _Fn); - template struct _Fill_align_and_width_formatter { public: template > // improves throughput, see GH-5003 - _NODISCARD constexpr _ParseContext::iterator _Parse(type_identity_t<_ParseContext&> _Parse_ctx) { - return _STD _Fill_align_and_width_formatter_parse(_Specs, _Parse_ctx); - } + _NODISCARD constexpr _ParseContext::iterator _Parse( + type_identity_t<_ParseContext&> _Parse_ctx); // defined in template - _NODISCARD _FormatContext::iterator _Format( - _FormatContext& _Format_ctx, const int _Width, _Fmt_align _Default_align, _Func&& _Fn) const { - return _STD _Fill_align_and_width_formatter_format( - _Specs, _Format_ctx, _Width, _Default_align, _STD forward<_Func>(_Fn)); - } + _NODISCARD _FormatContext::iterator _Format(_FormatContext& _Format_ctx, const int _Width, + _Fmt_align _Default_align, + _Func&& _Fn) const; // defined in private: _Fill_align_and_width_specs<_CharT> _Specs; diff --git a/stl/inc/__msvc_ranges_tuple_formatter.hpp b/stl/inc/__msvc_ranges_tuple_formatter.hpp index 70224273588..0836727e693 100644 --- a/stl/inc/__msvc_ranges_tuple_formatter.hpp +++ b/stl/inc/__msvc_ranges_tuple_formatter.hpp @@ -903,18 +903,6 @@ struct _Range_specs : _Fill_align_and_width_specs<_CharT> { char _Type = '\0'; }; -// TRANSITION, VSO-2744645: Avoid declaring and defining member functions in different headers. -template -constexpr _ParseContext::iterator _Range_formatter_parse(formatter<_Ty, _CharT>& _Underlying, - basic_string_view<_CharT>& _Separator, basic_string_view<_CharT>& _Opening_bracket, - basic_string_view<_CharT>& _Closing_bracket, _Range_specs<_CharT>& _Specs, _ParseContext& _Ctx); - -template -_FormatContext::iterator _Range_formatter_format(const formatter<_Ty, _CharT>& _Underlying, - basic_string_view<_CharT> _Separator, basic_string_view<_CharT> _Opening_bracket, - basic_string_view<_CharT> _Closing_bracket, const _Range_specs<_CharT>& _Specs, _Range&& _Rng, - _FormatContext& _Ctx); - _EXPORT_STD template requires same_as, _Ty> && formattable<_Ty, _CharT> class range_formatter { @@ -944,9 +932,7 @@ class range_formatter { } template - constexpr _ParseContext::iterator parse(_ParseContext& _Ctx) { - return _STD _Range_formatter_parse(_Underlying, _Separator, _Opening_bracket, _Closing_bracket, _Specs, _Ctx); - } + constexpr _ParseContext::iterator parse(_ParseContext& _Ctx); // defined in template <_RANGES input_range _Range, class _FormatContext> requires formattable<_RANGES range_reference_t<_Range>, _CharT> @@ -964,10 +950,7 @@ class range_formatter { template <_RANGES input_range _Range, class _FormatContext> requires _Is_specialization_v && derived_from> - _FormatContext::iterator _Format(_Range&& _Rng, _FormatContext& _Ctx) const { - return _STD _Range_formatter_format( - _Underlying, _Separator, _Opening_bracket, _Closing_bracket, _Specs, _STD forward<_Range>(_Rng), _Ctx); - } + _FormatContext::iterator _Format(_Range&& _Rng, _FormatContext& _Ctx) const; // defined in }; template @@ -1148,18 +1131,6 @@ struct _Adaptor_formatter_base { } }; -// TRANSITION, VSO-2744645: Avoid declaring and defining member functions in different headers. -template -constexpr _ParseContext::iterator _Tuple_formatter_parse(tuple...>& _Underlying, - basic_string_view<_CharT>& _Separator, basic_string_view<_CharT>& _Opening_bracket, - basic_string_view<_CharT>& _Closing_bracket, _Fill_align_and_width_specs<_CharT>& _Specs, _ParseContext& _Ctx); - -template -_FormatContext::iterator _Tuple_formatter_format(const tuple...>& _Underlying, - basic_string_view<_CharT> _Separator, basic_string_view<_CharT> _Opening_bracket, - basic_string_view<_CharT> _Closing_bracket, const _Fill_align_and_width_specs<_CharT>& _Specs, - _FormatContext& _Fmt_ctx, _ArgTypes&... _Args); - template ... _Types> class _Tuple_formatter_common_base { private: @@ -1174,13 +1145,7 @@ class _Tuple_formatter_common_base { static constexpr bool _Is_const_formattable = (formattable && ...); template - _FormatContext::iterator _Format(_FormatContext& _Fmt_ctx, _ArgTypes&... _Args) const { - _STL_INTERNAL_STATIC_ASSERT( - (is_same_v<_ArgTypes, remove_reference_t<_Maybe_const<_Is_const_formattable, _Types>>> && ...)); - - return _STD _Tuple_formatter_format( - _Underlying, _Separator, _Opening_bracket, _Closing_bracket, _Specs, _Fmt_ctx, _Args...); - } + _FormatContext::iterator _Format(_FormatContext& _Fmt_ctx, _ArgTypes&... _Args) const; // defined in public: constexpr void set_separator(const basic_string_view<_CharT> _Sep) noexcept { @@ -1194,9 +1159,7 @@ class _Tuple_formatter_common_base { } template - constexpr _ParseContext::iterator parse(_ParseContext& _Ctx) { - return _STD _Tuple_formatter_parse(_Underlying, _Separator, _Opening_bracket, _Closing_bracket, _Specs, _Ctx); - } + constexpr _ParseContext::iterator parse(_ParseContext& _Ctx); // defined in }; // formatter definition for all pairs and tuples, the deleted default constructor diff --git a/stl/inc/format b/stl/inc/format index 1c902c68d7b..e694918a68c 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -2890,9 +2890,11 @@ struct _Format_handler { } }; -template <_Basic_format_arg_type _ArgType, class _CharT, class _ParseContext> -constexpr _ParseContext::iterator _Formatter_base_parse( - _Dynamic_format_specs<_CharT>& _Specs, _ParseContext& _Parse_ctx) { +// declared in <__msvc_formatter.hpp> +template +template +constexpr _ParseContext::iterator _Formatter_base<_Ty, _CharT, _ArgType>::parse( + type_identity_t<_ParseContext&> _Parse_ctx) { _Specs_checker<_Dynamic_specs_handler<_ParseContext>> _Handler( _Dynamic_specs_handler<_ParseContext>{_Specs, _Parse_ctx}, _ArgType); const auto _It = _Parse_format_specs(_Parse_ctx._Unchecked_begin(), _Parse_ctx._Unchecked_end(), _Handler); @@ -2902,9 +2904,11 @@ constexpr _ParseContext::iterator _Formatter_base_parse( return _Parse_ctx.begin() + (_It - _Parse_ctx._Unchecked_begin()); } -template -_FormatContext::iterator _Formatter_base_format( - const _Dynamic_format_specs<_CharT>& _Specs, const _Ty& _Val, _FormatContext& _Format_ctx) { +// declared in <__msvc_formatter.hpp> +template +template +_FormatContext::iterator _Formatter_base<_Ty, _CharT, _ArgType>::format( + const _Ty& _Val, _FormatContext& _Format_ctx) const { _Dynamic_format_specs<_CharT> _Format_specs = _Specs; if (_Specs._Dynamic_width_index >= 0) { _Format_specs._Width = @@ -3273,11 +3277,11 @@ _NODISCARD constexpr const _CharT* _Parse_range_specs( return _Begin; } -// TRANSITION, VSO-2744645: Avoid declaring and defining member functions in different headers. -template -constexpr _ParseContext::iterator _Range_formatter_parse(formatter<_Ty, _CharT>& _Underlying, - basic_string_view<_CharT>& _Separator, basic_string_view<_CharT>& _Opening_bracket, - basic_string_view<_CharT>& _Closing_bracket, _Range_specs<_CharT>& _Specs, _ParseContext& _Ctx) { +// declared in <__msvc_ranges_tuple_formatter.hpp> +template + requires same_as, _Ty> && formattable<_Ty, _CharT> +template +constexpr _ParseContext::iterator range_formatter<_Ty, _CharT>::parse(_ParseContext& _Ctx) { _Range_specs_setter<_CharT> _Callback{_Specs, _Ctx}; auto _It = _STD _Parse_range_specs(_Ctx._Unchecked_begin(), _Ctx._Unchecked_end(), _Callback); @@ -3397,11 +3401,14 @@ void _Range_formatter_format_as_string(_Range&& _Rng, _FormatContext& _Ctx, cons } } -template -_FormatContext::iterator _Range_formatter_format(const formatter<_Ty, _CharT>& _Underlying, - const basic_string_view<_CharT> _Separator, const basic_string_view<_CharT> _Opening_bracket, - const basic_string_view<_CharT> _Closing_bracket, const _Range_specs<_CharT>& _Specs, _Range&& _Rng, - _FormatContext& _Ctx) { +// declared in <__msvc_ranges_tuple_formatter.hpp> +template + requires same_as, _Ty> + && formattable<_Ty, _CharT> + template <_RANGES input_range _Range, class _FormatContext> + requires _Is_specialization_v + && derived_from> +_FormatContext::iterator range_formatter<_Ty, _CharT>::_Format(_Range&& _Rng, _FormatContext& _Ctx) const { auto _Format_specs = _Specs; if (_Specs._Dynamic_width_index >= 0) { _Format_specs._Width = @@ -3551,11 +3558,10 @@ constexpr void _Set_tuple_debug_format(_FormatterType& _Formatter, _ParseContext } } -// TRANSITION, VSO-2744645: Avoid declaring and defining member functions in different headers. -template -constexpr _ParseContext::iterator _Tuple_formatter_parse(tuple...>& _Underlying, - basic_string_view<_CharT>& _Separator, basic_string_view<_CharT>& _Opening_bracket, - basic_string_view<_CharT>& _Closing_bracket, _Fill_align_and_width_specs<_CharT>& _Specs, _ParseContext& _Ctx) { +// declared in <__msvc_ranges_tuple_formatter.hpp> +template ... _Types> +template +constexpr _ParseContext::iterator _Tuple_formatter_common_base<_CharT, _Types...>::parse(_ParseContext& _Ctx) { _Fmt_tuple_type _Fmt_type = _Fmt_tuple_type::_None; _Tuple_format_specs_setter<_CharT, sizeof...(_Types) == 2> _Callback{_Specs, _Fmt_type, _Ctx}; const auto _It = _STD _Parse_tuple_format_specs(_Ctx._Unchecked_begin(), _Ctx._Unchecked_end(), _Callback); @@ -3597,11 +3603,14 @@ void _Tuple_formatter_format_to_context(const tuple... _STD _Copy_unchecked(_Closing_bracket._Unchecked_begin(), _Closing_bracket._Unchecked_end(), _Fmt_ctx.out()); } -template -_FormatContext::iterator _Tuple_formatter_format(const tuple...>& _Underlying, - const basic_string_view<_CharT> _Separator, const basic_string_view<_CharT> _Opening_bracket, - const basic_string_view<_CharT> _Closing_bracket, const _Fill_align_and_width_specs<_CharT>& _Specs, - _FormatContext& _Fmt_ctx, _ArgTypes&... _Args) { +// declared in <__msvc_ranges_tuple_formatter.hpp> +template ... _Types> +template +_FormatContext::iterator _Tuple_formatter_common_base<_CharT, _Types...>::_Format( + _FormatContext& _Fmt_ctx, _ArgTypes&... _Args) const { + _STL_INTERNAL_STATIC_ASSERT( + (is_same_v<_ArgTypes, remove_reference_t<_Maybe_const<_Is_const_formattable, _Types>>> && ...)); + auto _Format_specs = _Specs; if (_Specs._Dynamic_width_index >= 0) { _Format_specs._Width = @@ -3694,10 +3703,11 @@ _NODISCARD constexpr const _CharT* _Parse_fill_align_and_width_specs( return _Parse_width(_Begin, _End, _Callbacks); } -// TRANSITION, VSO-2744645: Avoid declaring and defining member functions in different headers. -template -_NODISCARD constexpr _ParseContext::iterator _Fill_align_and_width_formatter_parse( - _Fill_align_and_width_specs<_CharT>& _Specs, _ParseContext& _Parse_ctx) { +// declared in <__msvc_formatter.hpp> +template +template +_NODISCARD constexpr _ParseContext::iterator _Fill_align_and_width_formatter<_CharT>::_Parse( + type_identity_t<_ParseContext&> _Parse_ctx) { _Fill_align_and_width_specs_setter<_CharT> _Callback{_Specs, _Parse_ctx}; const auto _It = _Parse_fill_align_and_width_specs(_Parse_ctx._Unchecked_begin(), _Parse_ctx._Unchecked_end(), _Callback); @@ -3708,10 +3718,11 @@ _NODISCARD constexpr _ParseContext::iterator _Fill_align_and_width_formatter_par return _Parse_ctx.begin() + (_It - _Parse_ctx._Unchecked_begin()); } -template -_NODISCARD _FormatContext::iterator _Fill_align_and_width_formatter_format( - const _Fill_align_and_width_specs<_CharT>& _Specs, _FormatContext& _Format_ctx, const int _Width, - _Fmt_align _Default_align, _Func&& _Fn) { +// declared in <__msvc_formatter.hpp> +template +template +_NODISCARD _FormatContext::iterator _Fill_align_and_width_formatter<_CharT>::_Format( + _FormatContext& _Format_ctx, const int _Width, _Fmt_align _Default_align, _Func&& _Fn) const { _Fill_align_and_width_specs _Format_specs = _Specs; if (_Specs._Dynamic_width_index >= 0) { _Format_specs._Width = diff --git a/tests/std/include/test_header_units_and_modules.hpp b/tests/std/include/test_header_units_and_modules.hpp index 71aaf6a6632..52db10859f1 100644 --- a/tests/std/include/test_header_units_and_modules.hpp +++ b/tests/std/include/test_header_units_and_modules.hpp @@ -293,8 +293,10 @@ void test_flat_set() { void test_format() { using namespace std; puts("Testing ."); +#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-2744645 assert(format("{} {}", 1729, "kittens") == "1729 kittens"); assert(format(L"{} {}", 1729, L"kittens") == L"1729 kittens"); +#endif // ^^^ no workaround ^^^ } void test_forward_list() { @@ -612,7 +614,9 @@ void test_print() { println(); #ifdef _CPPRTTI +#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-2744645 println(cout, "The answer to life, the universe, and everything: {}", 42); +#endif // ^^^ no workaround ^^^ println(cout); #endif // _CPPRTTI } From 610ea09d8a4fa80d3675c0c2b02bef53075a4a6d Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 20 Feb 2026 09:37:09 -0800 Subject: [PATCH 32/35] libcxx/expected_results.txt: Overhaul the "XFAILS WHICH PASS" section. Now that we have full ARM64 test coverage, and we're enabling ARM64 ASan, this needs to be updated. Transfer the tests that actually contain "XFAIL: msvc" to the section for the MSVC-internal test harness. A couple of tests don't contain "XFAIL: msvc" (anymore?) and are simply passing, so drop their mentions completely: std/time/time.cal/time.cal.ymd/time.cal.ymd.nonmembers/ostream.pass.cpp std/time/time.clock/time.clock.system/sys_date.ostream.pass.cpp --- tests/libcxx/expected_results.txt | 41 ++++++------------------------- 1 file changed, 8 insertions(+), 33 deletions(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 9544533f8bf..1a2ce760d80 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -1227,39 +1227,6 @@ std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp:0 FA std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp:1 FAIL -# *** XFAILS WHICH PASS *** -# These tests contain `// XFAIL: msvc` comments, which accurately describe runtime failures for x86 and x64. -# However, for ARM64, they successfully compile, then we don't run them. -# Our test harness properly handles the ambiguity of whether a FAIL line in this file means "fails to compile" -# or "fails to run", combined with the `build_only` setting that we use for ARM64. -# The upstream logic that parses `// XFAIL: msvc` bypasses this, so it's interpreted as "this always fails", -# so compilation success for ARM64 is reported as unexpectedly passing. -# The test harness should be fixed to treat `// XFAIL: msvc` the same way that FAIL lines here are treated. -# In the meantime, because this is platform-dependent and we don't have a way to express that in this file, -# we need to mark these tests as SKIPPED. -# Finally, note that only :0 (MSVC) and :2 (Clang) configurations are mentioned here, -# because we don't run :1 (ASan) for ARM64. -std/time/time.cal/time.cal.ymd/time.cal.ymd.nonmembers/ostream.pass.cpp:0 SKIPPED -std/time/time.cal/time.cal.ymd/time.cal.ymd.nonmembers/ostream.pass.cpp:2 SKIPPED -std/time/time.clock/time.clock.system/sys_date.ostream.pass.cpp:0 SKIPPED -std/time/time.clock/time.clock.system/sys_date.ostream.pass.cpp:2 SKIPPED -std/time/time.syn/formatter.day.pass.cpp:0 SKIPPED -std/time/time.syn/formatter.day.pass.cpp:2 SKIPPED -std/time/time.syn/formatter.month_day.pass.cpp:0 SKIPPED -std/time/time.syn/formatter.month_day.pass.cpp:2 SKIPPED -std/time/time.syn/formatter.weekday_index.pass.cpp:0 SKIPPED -std/time/time.syn/formatter.weekday_index.pass.cpp:2 SKIPPED -std/time/time.syn/formatter.weekday_last.pass.cpp:0 SKIPPED -std/time/time.syn/formatter.weekday_last.pass.cpp:2 SKIPPED -std/time/time.syn/formatter.weekday.pass.cpp:0 SKIPPED -std/time/time.syn/formatter.weekday.pass.cpp:2 SKIPPED -std/time/time.syn/formatter.year_month_day.pass.cpp:2 SKIPPED -std/language.support/support.exception/except.nested/rethrow_if_nested.pass.cpp:0 SKIPPED -std/language.support/support.exception/except.nested/rethrow_if_nested.pass.cpp:2 SKIPPED -std/language.support/support.exception/propagation/current_exception.pass.cpp:0 SKIPPED -std/language.support/support.exception/propagation/current_exception.pass.cpp:2 SKIPPED - - # *** MSVC-INTERNAL TEST HARNESS ISSUES (note: configuration :9 restricts these skips to be MSVC-internal) *** # These tests need ADDITIONAL_COMPILE_FLAGS(cl-style-warnings) and/or ADDITIONAL_COMPILE_FLAGS(gcc-style-warnings) @@ -1292,6 +1259,14 @@ std/utilities/meta/meta.unary/dependent_return_type.pass.cpp:9 SKIPPED # These tests are marked as `XFAIL: msvc`, but the MSVC-internal test harness doesn't yet parse XFAIL. std/algorithms/algorithms.results/no_unique_address.compile.pass.cpp:9 SKIPPED std/input.output/iostream.format/print.fun/no_file_description.pass.cpp:9 SKIPPED +std/language.support/support.exception/except.nested/rethrow_if_nested.pass.cpp:9 SKIPPED +std/language.support/support.exception/propagation/current_exception.pass.cpp:9 SKIPPED +std/time/time.syn/formatter.day.pass.cpp:9 SKIPPED +std/time/time.syn/formatter.month_day.pass.cpp:9 SKIPPED +std/time/time.syn/formatter.weekday_index.pass.cpp:9 SKIPPED +std/time/time.syn/formatter.weekday_last.pass.cpp:9 SKIPPED +std/time/time.syn/formatter.weekday.pass.cpp:9 SKIPPED +std/time/time.syn/formatter.year_month_day.pass.cpp:9 SKIPPED std/utilities/function.objects/func.wrap/func.wrap.func/noncopyable_return_type.pass.cpp:9 SKIPPED # This test is marked as `REQUIRES: large_tests`. The GitHub test harness doesn't define that feature, so it doesn't From 51d55d4de1ea164c92984331f5eabc633b360f99 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sun, 2 Nov 2025 03:19:16 -0800 Subject: [PATCH 33/35] Partially enable ARM64 ASan, add test coverage. And mention ASan in the ASan pipeline's stage and display names. Add `dependsOn: []` to the x64 stage for symmetry, following the example of the Code Format stage in azure-pipelines.yml. azure-pipelines.yml: Update comment to follow our preferred arch order. Not enabling GH_002030_asan_annotate_string/GH_002030_asan_annotate_vector yet due to Clang issues. --- azure-devops/asan-pipeline.yml | 26 ++++++++++++++----- azure-pipelines.yml | 2 +- .../__msvc_sanitizer_annotate_container.hpp | 2 +- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/azure-devops/asan-pipeline.yml b/azure-devops/asan-pipeline.yml index 75f31fb4dbd..a035ffb76f8 100644 --- a/azure-devops/asan-pipeline.yml +++ b/azure-devops/asan-pipeline.yml @@ -1,7 +1,7 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -# Build STL targeting x86 and x64, and run extra ASan testing +# Build STL targeting x64, x86, and arm64, then run extra ASan testing variables: - template: config.yml @@ -16,8 +16,9 @@ schedules: - main stages: - - stage: Build_And_Test_x64 - displayName: 'Build and Test x64' + - stage: Test_x64_ASan + displayName: 'Test x64 ASan' + dependsOn: [] pool: name: ${{ variables.poolName }} demands: ${{ variables.poolDemands }} @@ -30,8 +31,8 @@ stages: asanBuild: true testTargets: STL-ASan-CI - - stage: Build_And_Test_x86 - displayName: 'Build and Test x86' + - stage: Test_x86_ASan + displayName: 'Test x86 ASan' dependsOn: [] pool: name: ${{ variables.poolName }} @@ -45,4 +46,17 @@ stages: asanBuild: true testTargets: STL-ASan-CI - # no coverage for ARM64 + - stage: Test_ARM64_ASan + displayName: 'Test ARM64 ASan' + dependsOn: [] + pool: + name: ${{ variables.arm64PoolName }} + demands: ${{ variables.poolDemands }} + jobs: + - template: build-and-test.yml + parameters: + hostArch: arm64 + targetArch: arm64 + targetPlatform: arm64 + asanBuild: true + testTargets: STL-ASan-CI diff --git a/azure-pipelines.yml b/azure-pipelines.yml index d4b418688ab..ac47cc3a498 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,7 +1,7 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -# Build STL targeting x86, x64, arm64, arm64ec +# Build STL targeting x64, x86, arm64, arm64ec variables: - template: azure-devops/config.yml diff --git a/stl/inc/__msvc_sanitizer_annotate_container.hpp b/stl/inc/__msvc_sanitizer_annotate_container.hpp index 057d68e7c0f..53e6f8a388c 100644 --- a/stl/inc/__msvc_sanitizer_annotate_container.hpp +++ b/stl/inc/__msvc_sanitizer_annotate_container.hpp @@ -28,7 +28,7 @@ _STL_DISABLE_CLANG_WARNINGS #if !defined(_DISABLE_STL_ANNOTATION) && !defined(_ENABLE_STL_ANNOTATION_ON_UNSUPPORTED_PLATFORMS) -#if defined(_M_ARM64EC) || defined(_M_ARM64) || defined(_M_CEE_PURE) +#if defined(_M_ARM64EC) || defined(_M_CEE_PURE) #define _DISABLE_STL_ANNOTATION #endif // ^^^ unsupported platform ^^^ From fdda15cbea9378bc2573af2066ebdf309b3e48e1 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 20 Feb 2026 10:46:02 -0800 Subject: [PATCH 34/35] New pools. --- azure-devops/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-devops/config.yml b/azure-devops/config.yml index 0bf5093a947..a311bbe8b95 100644 --- a/azure-devops/config.yml +++ b/azure-devops/config.yml @@ -5,10 +5,10 @@ variables: - name: poolName - value: 'Stl-2026-01-13T1248-x64-Pool' + value: 'Stl-2026-02-20T0952-x64-Pool' readonly: true - name: arm64PoolName - value: 'Stl-2026-01-13T1248-arm64-Pool' + value: 'Stl-2026-02-20T0952-arm64-Pool' readonly: true - name: poolDemands value: 'EnableSpotVM -equals false' From fdd46bf91d18fedec8cde0931236f23cbd81e726 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 20 Feb 2026 11:41:59 -0800 Subject: [PATCH 35/35] Upgrade all "constexpr step limits" tests to SKIPPED. And remove the few :2 (Clang-specific) configs; if Clang has trouble, C1XX is very likely to also have trouble. std/containers/sequences/vector.bool/flip.pass.cpp:0 was unexpectedly passing for x86. Playing whack-a-mole is just not worth my time. --- tests/libcxx/expected_results.txt | 38 +++++++++++++++---------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 1a2ce760d80..2d6517ca278 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -939,28 +939,26 @@ std/utilities/tuple/tuple.tuple/tuple.cnstr/convert_const_move.pass.cpp:2 FAIL # "error RC2136 : missing '=' in EXSTYLE=" followed by "LINK : fatal error LNK1327: failure during running rc.exe" std/thread/thread.mutex/thread.mutex.requirements/thread.sharedtimedmutex.requirements/thread.sharedtimedmutex.class/try_lock_until_deadlock_bug.pass.cpp SKIPPED -# Not analyzed, failing due to constexpr step limits. -std/algorithms/alg.modifying.operations/alg.copy/ranges.copy_backward.pass.cpp:2 FAIL -std/algorithms/alg.modifying.operations/alg.move/move.pass.cpp:2 FAIL -std/algorithms/alg.modifying.operations/alg.rotate/rotate.pass.cpp FAIL -std/algorithms/alg.modifying.operations/alg.swap/ranges.swap_ranges.pass.cpp FAIL -std/algorithms/alg.nonmodifying/alg.contains/ranges.contains_subrange.pass.cpp:2 FAIL -std/algorithms/alg.nonmodifying/alg.count/count.pass.cpp FAIL -std/algorithms/alg.nonmodifying/alg.count/ranges.count.pass.cpp FAIL -std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp:2 FAIL -std/containers/sequences/vector.bool/append_range.pass.cpp FAIL -std/containers/sequences/vector.bool/assign_range.pass.cpp FAIL -std/containers/sequences/vector.bool/flip.pass.cpp FAIL -std/containers/sequences/vector.bool/insert_range.pass.cpp FAIL -std/containers/sequences/vector/vector.modifiers/destroy_elements.pass.cpp FAIL -std/containers/sequences/vector/vector.modifiers/emplace.pass.cpp FAIL -std/containers/sequences/vector/vector.modifiers/insert_range.pass.cpp FAIL -std/ranges/range.adaptors/range.join.with/range.join.with.view/end.pass.cpp FAIL -std/strings/basic.string/string.modifiers/string_replace/replace_with_range.pass.cpp FAIL -std/utilities/charconv/charconv.to.chars/integral.pass.cpp FAIL - # Not analyzed, failing due to constexpr step limits. SKIPPED because they occasionally pass in certain configurations. +std/algorithms/alg.modifying.operations/alg.copy/ranges.copy_backward.pass.cpp SKIPPED +std/algorithms/alg.modifying.operations/alg.move/move.pass.cpp SKIPPED +std/algorithms/alg.modifying.operations/alg.rotate/rotate.pass.cpp SKIPPED std/algorithms/alg.modifying.operations/alg.shift/ranges.shift_left.pass.cpp SKIPPED +std/algorithms/alg.modifying.operations/alg.swap/ranges.swap_ranges.pass.cpp SKIPPED +std/algorithms/alg.nonmodifying/alg.contains/ranges.contains_subrange.pass.cpp SKIPPED +std/algorithms/alg.nonmodifying/alg.count/count.pass.cpp SKIPPED +std/algorithms/alg.nonmodifying/alg.count/ranges.count.pass.cpp SKIPPED +std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp SKIPPED +std/containers/sequences/vector.bool/append_range.pass.cpp SKIPPED +std/containers/sequences/vector.bool/assign_range.pass.cpp SKIPPED +std/containers/sequences/vector.bool/flip.pass.cpp SKIPPED +std/containers/sequences/vector.bool/insert_range.pass.cpp SKIPPED +std/containers/sequences/vector/vector.modifiers/destroy_elements.pass.cpp SKIPPED +std/containers/sequences/vector/vector.modifiers/emplace.pass.cpp SKIPPED +std/containers/sequences/vector/vector.modifiers/insert_range.pass.cpp SKIPPED +std/ranges/range.adaptors/range.join.with/range.join.with.view/end.pass.cpp SKIPPED +std/strings/basic.string/string.modifiers/string_replace/replace_with_range.pass.cpp SKIPPED +std/utilities/charconv/charconv.to.chars/integral.pass.cpp SKIPPED std/utilities/template.bitset/bitset.members/left_shift_eq.pass.cpp SKIPPED std/utilities/template.bitset/bitset.members/op_and_eq.pass.cpp SKIPPED std/utilities/template.bitset/bitset.members/op_or_eq.pass.cpp SKIPPED