From da0790989b8a3c4bd1efc8246a271537eff71f2e Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 22 Feb 2023 06:30:31 -0800 Subject: [PATCH 01/14] GH 3490 --- CMakeLists.txt | 5 +---- README.md | 8 ++++---- azure-pipelines.yml | 2 +- benchmarks/CMakeLists.txt | 2 +- stl/CMakeLists.txt | 8 +++++--- stl/inc/type_traits | 4 ++-- stl/inc/yvals_core.h | 4 ++-- tests/libcxx/expected_results.txt | 6 ------ tools/CMakeLists.txt | 2 +- tools/format/CMakeLists.txt | 2 +- tools/validate/CMakeLists.txt | 2 +- 11 files changed, 19 insertions(+), 26 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 599067f005e..17ebf7456f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,7 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required(VERSION 3.25) - -# TRANSITION, CMake-24249 -cmake_policy(SET CMP0141 OLD) +cmake_minimum_required(VERSION 3.25.2) set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) project(msvc_standard_libraries LANGUAGES CXX) diff --git a/README.md b/README.md index 1d6177109be..0b3c8b3221e 100644 --- a/README.md +++ b/README.md @@ -141,11 +141,11 @@ Just try to follow these rules, so we can spend more time fixing bugs and implem # How To Build With The Visual Studio IDE -1. Install Visual Studio 2022 17.5 Preview 6 or later. +1. Install Visual Studio 2022 17.6 Preview 1 or later. * Select "Windows 11 SDK (10.0.22000.0)" in the VS Installer. * We recommend selecting "C++ CMake tools for Windows" in the VS Installer. This will ensure that you're using supported versions of CMake and Ninja. - * Otherwise, install [CMake][] 3.25 or later, and [Ninja][] 1.11.0 or later. + * Otherwise, install [CMake][] 3.25.2 or later, and [Ninja][] 1.11.0 or later. * We recommend selecting "Python 3 64-bit" in the VS Installer. * Otherwise, make sure [Python][] 3.9 or later is available to CMake. 2. Open Visual Studio, and choose the "Clone or check out code" option. Enter the URL of this repository, @@ -157,11 +157,11 @@ Just try to follow these rules, so we can spend more time fixing bugs and implem # How To Build With A Native Tools Command Prompt -1. Install Visual Studio 2022 17.5 Preview 6 or later. +1. Install Visual Studio 2022 17.6 Preview 1 or later. * Select "Windows 11 SDK (10.0.22000.0)" in the VS Installer. * We recommend selecting "C++ CMake tools for Windows" in the VS Installer. This will ensure that you're using supported versions of CMake and Ninja. - * Otherwise, install [CMake][] 3.25 or later, and [Ninja][] 1.11.0 or later. + * Otherwise, install [CMake][] 3.25.2 or later, and [Ninja][] 1.11.0 or later. * We recommend selecting "Python 3 64-bit" in the VS Installer. * Otherwise, make sure [Python][] 3.9 or later is available to CMake. 2. Open a command prompt. diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 2b10bc1b439..9a0f22ce43c 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -9,7 +9,7 @@ variables: benchmarkBuildOutputLocation: 'D:\benchmark' pool: - name: 'StlBuild-2023-02-14T1520-Pool' + name: 'StlBuild-2023-02-21T1058-Pool' demands: EnableSpotVM -equals true pr: diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt index 403c9d5ee7c..594b1db0c3c 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 3.25) +cmake_minimum_required(VERSION 3.25.2) project(msvc_standard_libraries_benchmarks LANGUAGES CXX) if(DEFINED STL_BINARY_DIR) diff --git a/stl/CMakeLists.txt b/stl/CMakeLists.txt index fc12494a3f8..4bc93c646ca 100644 --- a/stl/CMakeLists.txt +++ b/stl/CMakeLists.txt @@ -492,10 +492,12 @@ set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "") # Toolset options must appear before add_library() for the options to take effect. add_compile_definitions(_CRTBLD _VCRT_ALLOW_INTERNALS _HAS_OLD_IOSTREAMS_MEMBERS=1 _STL_CONCRT_SUPPORT) +# /Z7 for MSVC, /Zi for MASM +set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "Embedded") + add_compile_options(/WX /Gy - "$<$:/diagnostics:caret;/W4;/w14265;/w15038;/fastfail;/guard:cf;/Z7;/Zp8;/std:c++latest;/permissive-;/Zc:threadSafeInit-;/Zl>" - # note that /Zi generates debug info inside the object file, it's the same as /Z7 for msvc - "$<$:/Zi;/W3;/nologo>" + "$<$:/diagnostics:caret;/W4;/w14265;/w15038;/fastfail;/guard:cf;/Zp8;/std:c++latest;/permissive-;/Zc:threadSafeInit-;/Zl>" + "$<$:/W3;/nologo>" ) include_directories(BEFORE diff --git a/stl/inc/type_traits b/stl/inc/type_traits index 2364ac2ec91..103cb1fa5c9 100644 --- a/stl/inc/type_traits +++ b/stl/inc/type_traits @@ -615,8 +615,8 @@ struct has_unique_object_representations : bool_constant<__has_unique_object_rep _EXPORT_STD template _INLINE_VAR constexpr bool has_unique_object_representations_v = __has_unique_object_representations(_Ty); -// TRANSITION, Clang 16, VSO-1690654, and VS17.6p1 -#if defined(__clang__) || defined(__EDG__) || !defined(_MSVC_INTERNAL_TESTING) +// TRANSITION, Clang 16 and VSO-1690654 +#if defined(__clang__) || defined(__EDG__) template struct _Is_aggregate_impl : bool_constant<__is_aggregate(_Ty)> {}; diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index ce8d39dcec3..b106c0950ba 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -829,8 +829,8 @@ _EMIT_STL_ERROR(STL1002, "Unexpected compiler version, expected CUDA 11.6 or new _EMIT_STL_ERROR(STL1000, "Unexpected compiler version, expected Clang 15.0.0 or newer."); #endif // ^^^ old Clang ^^^ #elif defined(_MSC_VER) -#if _MSC_VER < 1935 // Coarse-grained, not inspecting _MSC_FULL_VER -_EMIT_STL_ERROR(STL1001, "Unexpected compiler version, expected MSVC 19.35 or newer."); +#if _MSC_VER < 1936 // Coarse-grained, not inspecting _MSC_FULL_VER +_EMIT_STL_ERROR(STL1001, "Unexpected compiler version, expected MSVC 19.36 or newer."); #endif // ^^^ old MSVC ^^^ #else // vvv other compilers vvv // not attempting to detect other compilers diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 8784fe8023b..fe8d0c78429 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -364,9 +364,6 @@ std/language.support/support.coroutines/end.to.end/go.pass.cpp:0 FAIL # DevCom-10026599: conditional expression has two different types std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp:0 FAIL -# DevCom-10165380: [ICE] constexpr evaluation confused by complicated use of string literals -std/utilities/format/format.fmt.string/get.pass.cpp:0 FAIL - # DevCom-10284753: Overload resolution is sometimes wrong for templated classes whose template argument are cv void std/utilities/function.objects/func.wrap/func.wrap.func/noncopyable_return_type.pass.cpp SKIPPED @@ -648,9 +645,6 @@ std/utilities/meta/meta.unary/dependent_return_type.compile.pass.cpp SKIPPED std/utilities/format/format.functions/escaped_output.ascii.pass.cpp SKIPPED std/utilities/variant/variant.variant/implicit_ctad.pass.cpp SKIPPED -# MoveOnlyForwardIterator (a misnomer) has mixed-type comparisons and conversions -std/ranges/range.utility/range.subrange/primitives.pass.cpp:0 FAIL - # libc++ speculatively implements LWG-3645 std/strings/basic.string/string.capacity/resize_and_overwrite.pass.cpp FAIL diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index def39ca7a80..3b12cfd5fd9 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 3.25) +cmake_minimum_required(VERSION 3.25.2) project(msvc_standard_libraries_tools LANGUAGES CXX) add_subdirectory(format) diff --git a/tools/format/CMakeLists.txt b/tools/format/CMakeLists.txt index 8224193c82b..1986474dfa6 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 3.25) +cmake_minimum_required(VERSION 3.25.2) project(msvc_standard_libraries_format NONE) set(did_search OFF) diff --git a/tools/validate/CMakeLists.txt b/tools/validate/CMakeLists.txt index f794b9d0bcd..0c14d4f86ec 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 3.25) +cmake_minimum_required(VERSION 3.25.2) project(msvc_standard_libraries_validate LANGUAGES CXX) add_executable(validate-binary validate.cpp) From e391f09c44ac022f4966698f27a4df96b6dbf0e2 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 22 Feb 2023 06:30:34 -0800 Subject: [PATCH 02/14] GH 3405 --- stl/inc/xiosbase | 76 +++++++++--------- .../P2467R1_exclusive_mode_fstreams/test.cpp | 78 +++++++++++++++++++ 2 files changed, 116 insertions(+), 38 deletions(-) diff --git a/stl/inc/xiosbase b/stl/inc/xiosbase index 2cb71f18821..338f5f1adf0 100644 --- a/stl/inc/xiosbase +++ b/stl/inc/xiosbase @@ -29,52 +29,52 @@ public: _Fmtzero = 0 }; - static constexpr _Fmtflags skipws = static_cast<_Fmtflags>(0x0001); - static constexpr _Fmtflags unitbuf = static_cast<_Fmtflags>(0x0002); - static constexpr _Fmtflags uppercase = static_cast<_Fmtflags>(0x0004); - static constexpr _Fmtflags showbase = static_cast<_Fmtflags>(0x0008); - static constexpr _Fmtflags showpoint = static_cast<_Fmtflags>(0x0010); - static constexpr _Fmtflags showpos = static_cast<_Fmtflags>(0x0020); - static constexpr _Fmtflags left = static_cast<_Fmtflags>(0x0040); - static constexpr _Fmtflags right = static_cast<_Fmtflags>(0x0080); - static constexpr _Fmtflags internal = static_cast<_Fmtflags>(0x0100); - static constexpr _Fmtflags dec = static_cast<_Fmtflags>(0x0200); - static constexpr _Fmtflags oct = static_cast<_Fmtflags>(0x0400); - static constexpr _Fmtflags hex = static_cast<_Fmtflags>(0x0800); - static constexpr _Fmtflags scientific = static_cast<_Fmtflags>(0x1000); - static constexpr _Fmtflags fixed = static_cast<_Fmtflags>(0x2000); - - static constexpr _Fmtflags hexfloat = static_cast<_Fmtflags>(0x3000); // TRANSITION, ABI, GH-3296 - - static constexpr _Fmtflags boolalpha = static_cast<_Fmtflags>(0x4000); - static constexpr _Fmtflags _Stdio = static_cast<_Fmtflags>(0x8000); - static constexpr _Fmtflags adjustfield = static_cast<_Fmtflags>(0x01C0); // left | right | internal - static constexpr _Fmtflags basefield = static_cast<_Fmtflags>(0x0E00); // dec | oct | hex - static constexpr _Fmtflags floatfield = static_cast<_Fmtflags>(0x3000); // scientific | fixed + static constexpr int skipws = 0x0001; + static constexpr int unitbuf = 0x0002; + static constexpr int uppercase = 0x0004; + static constexpr int showbase = 0x0008; + static constexpr int showpoint = 0x0010; + static constexpr int showpos = 0x0020; + static constexpr int left = 0x0040; + static constexpr int right = 0x0080; + static constexpr int internal = 0x0100; + static constexpr int dec = 0x0200; + static constexpr int oct = 0x0400; + static constexpr int hex = 0x0800; + static constexpr int scientific = 0x1000; + static constexpr int fixed = 0x2000; + + static constexpr int hexfloat = 0x3000; // TRANSITION, ABI, GH-3296 + + static constexpr int boolalpha = 0x4000; + static constexpr int _Stdio = 0x8000; + static constexpr int adjustfield = 0x01C0; // left | right | internal + static constexpr int basefield = 0x0E00; // dec | oct | hex + static constexpr int floatfield = 0x3000; // scientific | fixed enum _Iostate { // constants for stream states _Statmask = 0x17 }; - static constexpr _Iostate goodbit = static_cast<_Iostate>(0x0); - static constexpr _Iostate eofbit = static_cast<_Iostate>(0x1); - static constexpr _Iostate failbit = static_cast<_Iostate>(0x2); - static constexpr _Iostate badbit = static_cast<_Iostate>(0x4); + static constexpr int goodbit = 0x0; + static constexpr int eofbit = 0x1; + static constexpr int failbit = 0x2; + static constexpr int badbit = 0x4; enum _Openmode { // constants for file opening options _Openmask = 0xff }; - static constexpr _Openmode in = static_cast<_Openmode>(0x01); - static constexpr _Openmode out = static_cast<_Openmode>(0x02); - static constexpr _Openmode ate = static_cast<_Openmode>(0x04); - static constexpr _Openmode app = static_cast<_Openmode>(0x08); - static constexpr _Openmode trunc = static_cast<_Openmode>(0x10); - static constexpr _Openmode _Nocreate = static_cast<_Openmode>(0x40); - static constexpr _Openmode _Noreplace = static_cast<_Openmode>(0x80); - static constexpr _Openmode binary = static_cast<_Openmode>(0x20); + static constexpr int in = 0x01; + static constexpr int out = 0x02; + static constexpr int ate = 0x04; + static constexpr int app = 0x08; + static constexpr int trunc = 0x10; + static constexpr int _Nocreate = 0x40; + static constexpr int _Noreplace = 0x80; + static constexpr int binary = 0x20; #if _HAS_CXX23 - static constexpr _Openmode noreplace = _Noreplace; + static constexpr int noreplace = _Noreplace; #endif enum _Seekdir { // constants for file positioning options @@ -83,9 +83,9 @@ public: _Seekend }; - static constexpr _Seekdir beg = _Seekbeg; - static constexpr _Seekdir cur = _Seekcur; - static constexpr _Seekdir end = _Seekend; + static constexpr int beg = _Seekbeg; + static constexpr int cur = _Seekcur; + static constexpr int end = _Seekend; enum { // TRANSITION, ABI _Openprot = _SH_DENYNO diff --git a/tests/std/tests/P2467R1_exclusive_mode_fstreams/test.cpp b/tests/std/tests/P2467R1_exclusive_mode_fstreams/test.cpp index 183f891152e..953c6b0d6bc 100644 --- a/tests/std/tests/P2467R1_exclusive_mode_fstreams/test.cpp +++ b/tests/std/tests/P2467R1_exclusive_mode_fstreams/test.cpp @@ -5,6 +5,7 @@ #include #include #include +#include namespace fs = std::filesystem; @@ -44,6 +45,80 @@ void test_file_create_fail(const std::ios_base::openmode bad_mode) { assert(!fs::exists(test_file)); } +// Also test GH-3401: : std::ios_base::openmode is not a bitmask type +constexpr bool test_gh_3401() { + using namespace std; + using IB = ios_base; + auto test_flags = [](const auto first, const auto second) { + auto flags = first; + assert(flags & first); + + flags |= second; + assert(flags & first); + assert(flags & second); + + flags &= ~second; + assert(flags & first); + assert(!(flags & second)); + + flags = first | second; + assert(flags & first); + assert(flags & second); + + flags = first ^ second; + assert(flags & first); + assert(flags & second); + + flags ^= second; + assert(flags & first); + assert(!(flags & second)); + }; + test_flags(IB::binary, IB::app); + test_flags(IB::dec, IB::oct); + test_flags(IB::badbit, IB::failbit); + test_flags(IB::cur, IB::end); + + static_assert(is_same_v, IB::seekdir>); + static_assert(is_same_v, IB::seekdir>); + static_assert(is_same_v, IB::seekdir>); + + static_assert(is_same_v, IB::openmode>); + static_assert(is_same_v, IB::openmode>); + static_assert(is_same_v, IB::openmode>); + static_assert(is_same_v, IB::openmode>); + static_assert(is_same_v, IB::openmode>); + static_assert(is_same_v, IB::openmode>); +#if _HAS_CXX23 + static_assert(is_same_v, IB::openmode>); +#endif + + static_assert(is_same_v, IB::iostate>); + static_assert(is_same_v, IB::iostate>); + static_assert(is_same_v, IB::iostate>); + static_assert(is_same_v, IB::iostate>); + + static_assert(is_same_v, IB::fmtflags>); + static_assert(is_same_v, IB::fmtflags>); + static_assert(is_same_v, IB::fmtflags>); + static_assert(is_same_v, IB::fmtflags>); + static_assert(is_same_v, IB::fmtflags>); + static_assert(is_same_v, IB::fmtflags>); + static_assert(is_same_v, IB::fmtflags>); + static_assert(is_same_v, IB::fmtflags>); + static_assert(is_same_v, IB::fmtflags>); + static_assert(is_same_v, IB::fmtflags>); + static_assert(is_same_v, IB::fmtflags>); + static_assert(is_same_v, IB::fmtflags>); + static_assert(is_same_v, IB::fmtflags>); + static_assert(is_same_v, IB::fmtflags>); + static_assert(is_same_v, IB::fmtflags>); + static_assert(is_same_v, IB::fmtflags>); + static_assert(is_same_v, IB::fmtflags>); + static_assert(is_same_v, IB::fmtflags>); + + return true; +} + int main() { using IB = std::ios_base; @@ -65,4 +140,7 @@ int main() { test_file_create_fail(IB::in | IB::trunc | IB::noreplace); test_file_create_fail(IB::in | IB::binary | IB::noreplace); test_file_create_fail(IB::in | IB::binary | IB::trunc | IB::noreplace); + + test_gh_3401(); + static_assert(test_gh_3401()); } From 630f2f692808cc2fe673bfc006c29400998dd19e Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 22 Feb 2023 06:30:36 -0800 Subject: [PATCH 03/14] GH 3469 --- stl/inc/mutex | 66 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 4 deletions(-) diff --git a/stl/inc/mutex b/stl/inc/mutex index 0b2c363967d..46a75447559 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -31,6 +31,34 @@ _STD_BEGIN _EXPORT_STD class condition_variable; _EXPORT_STD class condition_variable_any; +struct _Mtx_internal_imp_mirror { +#ifdef _CRT_WINDOWS +#ifdef _WIN64 + static constexpr size_t _Critical_section_size = 8; +#else // _WIN64 + static constexpr size_t _Critical_section_size = 4; +#endif // _WIN64 +#else // _CRT_WINDOWS +#ifdef _WIN64 + static constexpr size_t _Critical_section_size = 56; +#else // _WIN64 + static constexpr size_t _Critical_section_size = 32; +#endif // _WIN64 +#endif // _CRT_WINDOWS + + int _Type; + const void* _Vptr; + union { + void* _Srw_lock_placeholder; + unsigned char _Padding[_Critical_section_size]; + }; + long _Thread_id; + int _Count; +}; + +static_assert(sizeof(_Mtx_internal_imp_mirror) == _Mtx_internal_imp_size, "inconsistent size for mutex"); +static_assert(alignof(_Mtx_internal_imp_mirror) == _Mtx_internal_imp_alignment, "inconsistent alignment for mutex"); + class _Mutex_base { // base class for all mutex types public: _Mutex_base(int _Flags = 0) noexcept { @@ -45,10 +73,21 @@ public: _Mutex_base& operator=(const _Mutex_base&) = delete; void lock() { - _Check_C_return(_Mtx_lock(_Mymtx())); + if (_Mtx_lock(_Mymtx()) != _Thrd_success) { + // undefined behavior, only occurs for plain mutexes (N4928 [thread.mutex.requirements.mutex.general]/6) + _STD _Throw_Cpp_error(_RESOURCE_DEADLOCK_WOULD_OCCUR); + } + + if (!_Verify_ownership_levels()) { + // only occurs for recursive mutexes (N4928 [thread.mutex.recursive]/3) + // POSIX specifies EAGAIN in the corresponding situation: + // https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_lock.html + _STD _Throw_Cpp_error(_RESOURCE_UNAVAILABLE_TRY_AGAIN); + } } _NODISCARD_TRY_CHANGE_STATE bool try_lock() noexcept /* strengthened */ { + // false may be from undefined behavior for plain mutexes (N4928 [thread.mutex.requirements.mutex.general]/6) return _Mtx_trylock(_Mymtx()) == _Thrd_success; } @@ -62,17 +101,34 @@ public: return _Mtx_getconcrtcs(_Mymtx()); } +protected: + _NODISCARD_TRY_CHANGE_STATE bool _Verify_ownership_levels() noexcept { + if (_Mtx_storage_mirror._Count == INT_MAX) { + // only occurs for recursive mutexes (N4928 [thread.mutex.recursive]/3) + --_Mtx_storage_mirror._Count; + return false; + } + + return true; + } + private: friend condition_variable; friend condition_variable_any; - _Aligned_storage_t<_Mtx_internal_imp_size, _Mtx_internal_imp_alignment> _Mtx_storage; + union { + _Aligned_storage_t<_Mtx_internal_imp_size, _Mtx_internal_imp_alignment> _Mtx_storage; + _Mtx_internal_imp_mirror _Mtx_storage_mirror; + }; _Mtx_t _Mymtx() noexcept { // get pointer to _Mtx_internal_imp_t inside _Mtx_storage return reinterpret_cast<_Mtx_t>(&_Mtx_storage); } }; +static_assert(sizeof(_Mutex_base) == _Mtx_internal_imp_size, "inconsistent size for mutex"); +static_assert(alignof(_Mutex_base) == _Mtx_internal_imp_alignment, "inconsistent alignment for mutex"); + _EXPORT_STD class mutex : public _Mutex_base { // class for mutual exclusion public: /* constexpr */ mutex() noexcept // TRANSITION, ABI @@ -88,7 +144,7 @@ public: : _Mutex_base(_Mtx_recursive) {} _NODISCARD_TRY_CHANGE_STATE bool try_lock() noexcept { - return _Mutex_base::try_lock(); + return _Mutex_base::try_lock() && _Verify_ownership_levels(); } recursive_mutex(const recursive_mutex&) = delete; @@ -852,7 +908,9 @@ public: if (_My_locked < UINT_MAX) { ++_My_locked; } else { - _Throw_system_error(errc::device_or_resource_busy); + // POSIX specifies EAGAIN in the corresponding situation: + // https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_lock.html + _STD _Throw_system_error(errc::resource_unavailable_try_again); } } else { while (_My_locked != 0) { From bc4c47d8335124bcb5feea8ab1e50b6c19665a86 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 22 Feb 2023 06:30:40 -0800 Subject: [PATCH 04/14] GH 3470 --- stl/inc/xutility | 11 ++++++++++- tests/std/tests/P2278R4_basic_const_iterator/env.lst | 2 +- .../std/tests/P2278R4_basic_const_iterator/test.cpp | 12 ++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index c53c060d248..47070a61aee 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -1758,6 +1758,9 @@ _NODISCARD constexpr const _Elem* data(initializer_list<_Elem> _Ilist) noexcept _EXPORT_STD template using iter_const_reference_t = common_reference_t&&, iter_reference_t<_Ty>>; +template +using _Iter_const_rvalue_reference_t = common_reference_t&&, iter_rvalue_reference_t<_Iter>>; + template concept _Constant_iterator = input_iterator<_Ty> && same_as, iter_reference_t<_Ty>>; @@ -1810,7 +1813,8 @@ class basic_const_iterator : public _Basic_const_iterator_category<_Iter> { private: /* [[no_unique_address]] */ _Iter _Current{}; - using _Reference = iter_const_reference_t<_Iter>; + using _Reference = iter_const_reference_t<_Iter>; + using _Rvalue_reference = _Iter_const_rvalue_reference_t<_Iter>; _NODISCARD static _CONSTEVAL auto _Get_iter_concept() noexcept { if constexpr (contiguous_iterator<_Iter>) { @@ -2059,6 +2063,11 @@ public: noexcept(_Se - _It._Current)) /* strengthened */ { return _Se - _It._Current; } + + _NODISCARD_FRIEND constexpr _Rvalue_reference iter_move(const basic_const_iterator& _It) noexcept( + noexcept(static_cast<_Rvalue_reference>(_RANGES iter_move(_It._Current)))) { + return static_cast<_Rvalue_reference>(_RANGES iter_move(_It._Current)); + } }; template _Ty2> diff --git a/tests/std/tests/P2278R4_basic_const_iterator/env.lst b/tests/std/tests/P2278R4_basic_const_iterator/env.lst index 18e2d7c71ec..8ac7033b206 100644 --- a/tests/std/tests/P2278R4_basic_const_iterator/env.lst +++ b/tests/std/tests/P2278R4_basic_const_iterator/env.lst @@ -1,4 +1,4 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -RUNALL_INCLUDE ..\concepts_latest_matrix.lst +RUNALL_INCLUDE ..\strict_concepts_latest_matrix.lst diff --git a/tests/std/tests/P2278R4_basic_const_iterator/test.cpp b/tests/std/tests/P2278R4_basic_const_iterator/test.cpp index 2f8de04de8d..ee9ceef33cf 100644 --- a/tests/std/tests/P2278R4_basic_const_iterator/test.cpp +++ b/tests/std/tests/P2278R4_basic_const_iterator/test.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -239,6 +240,13 @@ constexpr void test_one(It iter) { static_assert(noexcept(citer == sent) == noexcept(iter == sent)); // strengthened } + { // Validate basic_const_iterator::iter_move() + using Expected = common_reference_t&&, iter_rvalue_reference_t>; + [[maybe_unused]] same_as decltype(auto) val = ranges::iter_move(citer); + static_assert( + noexcept(ranges::iter_move(citer)) == noexcept(static_cast(ranges::iter_move(citer.base())))); + } + { // Validate basic_const_iterator::base() const& [[maybe_unused]] same_as decltype(auto) base = citer.base(); static_assert(noexcept(citer.base())); @@ -257,6 +265,10 @@ void test_lwg3853() { // COMPILE-ONLY static constexpr int some_ints[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; +// Check LWG-3872 +using Zipped = decltype(views::zip(some_ints) | views::as_const | views::as_rvalue); +static_assert(same_as, tuple>); + struct instantiator { template static constexpr void call() { From 940b319c2ff2d09d9ceb87e8a821664bfc00a64b Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 22 Feb 2023 06:30:44 -0800 Subject: [PATCH 05/14] GH 3471 --- stl/inc/xutility | 3 + .../test.compile.pass.cpp | 76 +++++++++++++++++-- 2 files changed, 73 insertions(+), 6 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index 47070a61aee..c5b5afa5da5 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -2071,16 +2071,19 @@ public: }; template _Ty2> + requires input_iterator> struct common_type, _Ty2> { using type = basic_const_iterator>; }; template _Ty2> + requires input_iterator> struct common_type<_Ty2, basic_const_iterator<_Ty1>> { using type = basic_const_iterator>; }; template _Ty2> + requires input_iterator> struct common_type, basic_const_iterator<_Ty2>> { using type = basic_const_iterator>; }; diff --git a/tests/std/tests/P2278R4_ranges_const_iterator_machinery/test.compile.pass.cpp b/tests/std/tests/P2278R4_ranges_const_iterator_machinery/test.compile.pass.cpp index f5c2bfdc7cb..62071d7a2f1 100644 --- a/tests/std/tests/P2278R4_ranges_const_iterator_machinery/test.compile.pass.cpp +++ b/tests/std/tests/P2278R4_ranges_const_iterator_machinery/test.compile.pass.cpp @@ -31,6 +31,76 @@ static_assert(!CanIterConstRef); static_assert(!CanIterConstRef>); static_assert(!CanIterConstRef>); +namespace test_common_type { + struct CommonThing {}; + + template + struct InIter { + using value_type = T; + using difference_type = ptrdiff_t; + + value_type& operator*() const; // not defined + InIter& operator++(); // not defined + void operator++(int); // not defined + operator CommonThing() const; // not defined + }; + + static_assert(input_iterator>); + static_assert(input_iterator>); +} // namespace test_common_type + +template +struct std::common_type, test_common_type::InIter> { + using type = test_common_type::CommonThing; +}; + +static_assert(common_with, test_common_type::InIter>); + +namespace test_common_type { + template + concept CanCommonType = requires { typename common_type_t; }; + + // Validate invalid common types + static_assert(!CanCommonType, long*>); + static_assert(!CanCommonType>); + static_assert(!CanCommonType, basic_const_iterator>); + static_assert(!CanCommonType>, InIter>); + static_assert(!CanCommonType, basic_const_iterator>>); + static_assert(!CanCommonType>, basic_const_iterator>>); + + // Validate common_type + static_assert(same_as, const int*>, basic_const_iterator>); + static_assert(same_as>, basic_const_iterator>); + static_assert(same_as, int*>, basic_const_iterator>); + static_assert(same_as>, basic_const_iterator>); + static_assert(same_as, basic_const_iterator>, + basic_const_iterator>); + static_assert(same_as, basic_const_iterator>, + basic_const_iterator>); + + static_assert(same_as, const int*>, + basic_const_iterator>); + static_assert(same_as>, + basic_const_iterator>); + static_assert(same_as>, + basic_const_iterator>); + static_assert(same_as, volatile int*>, + basic_const_iterator>); + + template + requires requires { + typename common_type_t>; + typename common_type_t, U>; + typename common_type_t, basic_const_iterator>; + } + void test_lwg3862(); // not defined + + template + concept VerifyLWG3862 = requires { test_lwg3862(); }; + + static_assert(!VerifyLWG3862, InIter>); // Hard error before LWG-3862 +} // namespace test_common_type + namespace test_pointer { using Ptr = int*; static_assert(CanIterConstRef); @@ -50,12 +120,6 @@ namespace test_pointer { static_assert(same_as, ConstPtr>); static_assert(same_as>, const int&>); static_assert(same_as, ConstPtr>); - - // Validate common_type - static_assert(same_as, ConstPtr>, basic_const_iterator>); - static_assert(same_as>, basic_const_iterator>); - static_assert(same_as, basic_const_iterator>, - basic_const_iterator>); } // namespace test_pointer namespace test_random_access_iter { From 9f0bf0cea1f50bf8f3cfeb27c4484ff599fa3174 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 22 Feb 2023 06:30:46 -0800 Subject: [PATCH 06/14] GH 3476 --- stl/inc/utility | 31 ++++++++++--------- tests/libcxx/expected_results.txt | 3 ++ .../test.cpp | 22 +++++++++++++ 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/stl/inc/utility b/stl/inc/utility index 0d420327631..35834b57111 100644 --- a/stl/inc/utility +++ b/stl/inc/utility @@ -480,15 +480,16 @@ constexpr void swap(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Righ } #endif // _HAS_CXX23 -_EXPORT_STD template -_NODISCARD constexpr bool operator==(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) { +_EXPORT_STD template +_NODISCARD constexpr bool operator==(const pair<_Ty1, _Ty2>& _Left, const pair<_Uty1, _Uty2>& _Right) { return _Left.first == _Right.first && _Left.second == _Right.second; } #ifdef __cpp_lib_concepts -_EXPORT_STD template -_NODISCARD constexpr common_comparison_category_t<_Synth_three_way_result<_Ty1>, _Synth_three_way_result<_Ty2>> - operator<=>(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) { +_EXPORT_STD template +_NODISCARD constexpr common_comparison_category_t<_Synth_three_way_result<_Ty1, _Uty1>, + _Synth_three_way_result<_Ty2, _Uty2>> + operator<=>(const pair<_Ty1, _Ty2>& _Left, const pair<_Uty1, _Uty2>& _Right) { if (auto _Result = _Synth_three_way{}(_Left.first, _Right.first); _Result != 0) { return _Result; } @@ -496,29 +497,29 @@ _NODISCARD constexpr common_comparison_category_t<_Synth_three_way_result<_Ty1>, } #else // ^^^ defined(__cpp_lib_concepts) / !defined(__cpp_lib_concepts) vvv #if !_HAS_CXX20 -template -_NODISCARD constexpr bool operator!=(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) { +template +_NODISCARD constexpr bool operator!=(const pair<_Ty1, _Ty2>& _Left, const pair<_Uty1, _Uty2>& _Right) { return !(_Left == _Right); } #endif // !_HAS_CXX20 -template -_NODISCARD constexpr bool operator<(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) { +template +_NODISCARD constexpr bool operator<(const pair<_Ty1, _Ty2>& _Left, const pair<_Uty1, _Uty2>& _Right) { return _Left.first < _Right.first || (!(_Right.first < _Left.first) && _Left.second < _Right.second); } -template -_NODISCARD constexpr bool operator>(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) { +template +_NODISCARD constexpr bool operator>(const pair<_Ty1, _Ty2>& _Left, const pair<_Uty1, _Uty2>& _Right) { return _Right < _Left; } -template -_NODISCARD constexpr bool operator<=(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) { +template +_NODISCARD constexpr bool operator<=(const pair<_Ty1, _Ty2>& _Left, const pair<_Uty1, _Uty2>& _Right) { return !(_Right < _Left); } -template -_NODISCARD constexpr bool operator>=(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) { +template +_NODISCARD constexpr bool operator>=(const pair<_Ty1, _Ty2>& _Left, const pair<_Uty1, _Uty2>& _Right) { return !(_Left < _Right); } #endif // ^^^ !defined(__cpp_lib_concepts) ^^^ diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index fe8d0c78429..261c92e5d5c 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -138,6 +138,9 @@ std/ranges/range.access/rbegin.pass.cpp FAIL std/ranges/range.access/rend.pass.cpp FAIL std/ranges/range.access/size.pass.cpp FAIL +# libc++ doesn't implement LWG-3865 Sorting a range of pairs +std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp FAIL + # *** INTERACTIONS WITH CONTEST / C1XX THAT UPSTREAM LIKELY WON'T FIX *** # Tracked by VSO-593630 " Enable libcxx filesystem tests" diff --git a/tests/std/tests/Dev11_1140665_unique_ptr_array_conversions/test.cpp b/tests/std/tests/Dev11_1140665_unique_ptr_array_conversions/test.cpp index eebeebf7a6f..768f2d9204f 100644 --- a/tests/std/tests/Dev11_1140665_unique_ptr_array_conversions/test.cpp +++ b/tests/std/tests/Dev11_1140665_unique_ptr_array_conversions/test.cpp @@ -183,6 +183,25 @@ void my_swap(unique_ptr& lhs, unique_ptr& rhs) { swap(lhs, rhs); } +// also test LWG-3865 Sorting a range of pairs +constexpr bool test_lwg3865() { + const pair a{1, 2}; + const pair b{1, 2}; + const pair c{2, 2}; + assert(a == b); + assert(a != c); + assert(c >= a); + assert(b >= a); + assert(c > a); + assert(!(b > a)); + assert(a < c); + assert(!(a < b)); + assert(a <= c); + assert(a <= b); + + return true; +} + int main() { { assert(g_objects == 0); @@ -271,4 +290,7 @@ int main() { }; (void) make_unique[]>(42); } + + test_lwg3865(); + STATIC_ASSERT(test_lwg3865()); } From 2756a2f72841cccff9d2ffe7b63955c47c34110b Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 22 Feb 2023 06:30:49 -0800 Subject: [PATCH 07/14] GH 3477 --- stl/inc/format | 4 ---- 1 file changed, 4 deletions(-) diff --git a/stl/inc/format b/stl/inc/format index ecfad75dbe7..1706947036d 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -3364,10 +3364,6 @@ struct formatter template <_Format_supported_charT _CharT, size_t _Nx> struct formatter<_CharT[_Nx], _CharT> : _Formatter_base<_CharT[_Nx], _CharT, _Basic_format_arg_type::_CString_type> {}; -template <_Format_supported_charT _CharT, size_t _Nx> -struct formatter - : _Formatter_base<_CharT[_Nx], _CharT, _Basic_format_arg_type::_CString_type> {}; - template <_Format_supported_charT _CharT, class _Traits, class _Allocator> struct formatter, _CharT> : _Formatter_base, _CharT, _Basic_format_arg_type::_String_type> {}; From 9d4273d3f7cbdb627d0e638ea9bad65c77f0a016 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 22 Feb 2023 06:30:53 -0800 Subject: [PATCH 08/14] GH 3479 --- stl/inc/ranges | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/stl/inc/ranges b/stl/inc/ranges index 78b1c04e432..c8858c69b77 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -8402,6 +8402,9 @@ namespace ranges { _EXPORT_STD template requires (!view<_Container>) _NODISCARD constexpr _Container to(_Rng&& _Range, _Types&&... _Args) { + static_assert(!is_const_v<_Container>, "C must not be const. ([range.utility.conv.to])"); + static_assert(!is_volatile_v<_Container>, "C must not be volatile. ([range.utility.conv.to])"); + static_assert(is_class_v<_Container>, "C must be a class type. ([range.utility.conv.to])"); if constexpr (_Converts_direct_constructible<_Rng, _Container, _Types...>) { return _Container(_STD forward<_Rng>(_Range), _STD forward<_Types>(_Args)...); } else if constexpr (_Converts_tag_constructible<_Rng, _Container, _Types...>) { @@ -8427,6 +8430,9 @@ namespace ranges { template struct _To_class_fn { + _STL_INTERNAL_STATIC_ASSERT(!is_const_v<_Container>); + _STL_INTERNAL_STATIC_ASSERT(!is_volatile_v<_Container>); + _STL_INTERNAL_STATIC_ASSERT(is_class_v<_Container>); _STL_INTERNAL_STATIC_ASSERT(!view<_Container>); template @@ -8440,6 +8446,9 @@ namespace ranges { _EXPORT_STD template requires (!view<_Container>) _NODISCARD constexpr auto to(_Types&&... _Args) { + static_assert(!is_const_v<_Container>, "C must not be const. ([range.utility.conv.adaptors])"); + static_assert(!is_volatile_v<_Container>, "C must not be volatile. ([range.utility.conv.adaptors])"); + static_assert(is_class_v<_Container>, "C must be a class type. ([range.utility.conv.adaptors])"); return _Range_closure<_To_class_fn<_Container>, decay_t<_Types>...>{_STD forward<_Types>(_Args)...}; } From 455388e93aed44b721a9552443250c6fa0204278 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 22 Feb 2023 06:30:56 -0800 Subject: [PATCH 09/14] GH 3480 --- stl/inc/xutility | 3 +++ tests/std/tests/P0896R4_ranges_range_machinery/test.cpp | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/stl/inc/xutility b/stl/inc/xutility index c5b5afa5da5..2424a4f9da0 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -2459,6 +2459,9 @@ namespace ranges { _EXPORT_STD template using range_rvalue_reference_t = iter_rvalue_reference_t>; + _EXPORT_STD template + using range_common_reference_t = iter_common_reference_t>; + #if _HAS_CXX23 _EXPORT_STD template concept constant_range = input_range<_Rng> && _Constant_iterator>; diff --git a/tests/std/tests/P0896R4_ranges_range_machinery/test.cpp b/tests/std/tests/P0896R4_ranges_range_machinery/test.cpp index 083e1348d6d..3f77e227e47 100644 --- a/tests/std/tests/P0896R4_ranges_range_machinery/test.cpp +++ b/tests/std/tests/P0896R4_ranges_range_machinery/test.cpp @@ -399,6 +399,12 @@ constexpr bool test_input_range() { STATIC_ASSERT(std::same_as, RvalueReference>); STATIC_ASSERT(std::same_as, RvalueReference>); + // LWG-3860, validate ranges::range_common_reference_t + using CommonReference = std::iter_common_reference_t; + STATIC_ASSERT(std::same_as, CommonReference>); + STATIC_ASSERT(std::same_as, CommonReference>); + STATIC_ASSERT(std::same_as, CommonReference>); + return true; } From 84112196b6e54a1a9f97ddfd725f36252268bf24 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 22 Feb 2023 06:30:59 -0800 Subject: [PATCH 10/14] GH 3483 --- stl/inc/ranges | 18 ++-- stl/inc/xutility | 118 ++++++++++----------- tests/std/tests/P0323R12_expected/test.cpp | 2 +- 3 files changed, 70 insertions(+), 68 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index c8858c69b77..09b57e12922 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -7570,6 +7570,12 @@ namespace ranges { && (convertible_to, sentinel_t> && ...); #endif // ^^^ workaround ^^^ + template + concept _Zip_transform_constraints = move_constructible<_Func> && is_object_v<_Func> && (sizeof...(_Views) > 0) + && (input_range<_Views> && ...) && (view<_Views> && ...) + && regular_invocable<_Func&, range_reference_t<_Views>...> + && _Can_reference...>>; + _EXPORT_STD template requires (view<_ViewTypes> && ...) && (sizeof...(_ViewTypes) > 0) class zip_view : public view_interface> { @@ -7590,10 +7596,8 @@ namespace ranges { private: friend zip_view; - template - requires ((view<_OtherViews> && ...) && (sizeof...(_OtherViews) > 0) - && is_object_v<_Func> && regular_invocable<_Func&, range_reference_t<_OtherViews>...> - && _Can_reference...>>) + template + requires _Zip_transform_constraints<_Func, _OtherViews...> friend class zip_transform_view; using _My_tuple = tuple>...>; @@ -7988,10 +7992,8 @@ namespace ranges { _EXPORT_STD inline constexpr _Zip_fn zip{}; } // namespace views - _EXPORT_STD template - requires ((view<_ViewTypes> && ...) && (sizeof...(_ViewTypes) > 0) - && is_object_v<_Func> && regular_invocable<_Func&, range_reference_t<_ViewTypes>...> - && _Can_reference...>>) + _EXPORT_STD template + requires _Zip_transform_constraints<_Func, _ViewTypes...> class zip_transform_view : public view_interface> { private: using _Inner_view = zip_view<_ViewTypes...>; diff --git a/stl/inc/xutility b/stl/inc/xutility index 2424a4f9da0..ac2a26855d1 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -3614,99 +3614,99 @@ _EXPORT_STD template _NODISCARD constexpr const tuple_element_t<_Index, tuple<_Types...>>&& get(const tuple<_Types...>&& _Tuple) noexcept; namespace ranges { - // clang-format off template concept _Uses_nonqualification_pointer_conversion = is_pointer_v<_From> && is_pointer_v<_To> - && !convertible_to(*)[], remove_pointer_t<_To>(*)[]>; + && (!convertible_to (*)[], remove_pointer_t<_To> (*)[]>); template concept _Convertible_to_non_slicing = convertible_to<_From, _To> - && !_Uses_nonqualification_pointer_conversion, decay_t<_To>>; + && (!_Uses_nonqualification_pointer_conversion, decay_t<_To>>); template - concept _Pair_like = !is_reference_v<_Ty> && requires(_Ty __t) { - typename tuple_size<_Ty>::type; - requires derived_from, integral_constant>; - typename tuple_element_t<0, remove_const_t<_Ty>>; - typename tuple_element_t<1, remove_const_t<_Ty>>; - { _STD get<0>(__t) } -> convertible_to&>; - { _STD get<1>(__t) } -> convertible_to&>; - }; + concept _Pair_like = + (!is_reference_v<_Ty>) && requires(_Ty __t) { + typename tuple_size<_Ty>::type; + requires derived_from, integral_constant>; + typename tuple_element_t<0, remove_const_t<_Ty>>; + typename tuple_element_t<1, remove_const_t<_Ty>>; + { _STD get<0>(__t) } -> convertible_to&>; + { _STD get<1>(__t) } -> convertible_to&>; + }; template - concept _Pair_like_convertible_from = !range<_Ty> && _Pair_like<_Ty> - && constructible_from<_Ty, _First, _Second> - && _Convertible_to_non_slicing<_First, tuple_element_t<0, _Ty>> - && convertible_to<_Second, tuple_element_t<1, _Ty>>; - // clang-format on + concept _Pair_like_convertible_from = (!range<_Ty>) && _Pair_like<_Ty> && constructible_from<_Ty, _First, _Second> + && _Convertible_to_non_slicing<_First, tuple_element_t<0, _Ty>> + && convertible_to<_Second, tuple_element_t<1, _Ty>>; - template > - class _Subrange_base : public view_interface> { // TRANSITION, [[no_unique_address]] - protected: - using _Size_type = _Make_unsigned_like_t>; - static constexpr bool _Store_size = true; + template + concept _Store_size = (_Ki == subrange_kind::sized) && (!sized_sentinel_for<_Se, _It>); - _Size_type _Size = 0; + template + class _Subrange_base : public view_interface> { + protected: + using _Size_type = _Make_unsigned_like_t>; public: _Subrange_base() = default; - constexpr explicit _Subrange_base(const _Size_type& _Size_) noexcept : _Size(_Size_) {} + constexpr explicit _Subrange_base(const _Size_type&) noexcept {} }; template - class _Subrange_base<_It, _Se, _Ki, false> : public view_interface> { + requires _Store_size<_It, _Se, _Ki> + class _Subrange_base<_It, _Se, _Ki> : public view_interface> { protected: - using _Size_type = _Make_unsigned_like_t>; - static constexpr bool _Store_size = false; + using _Size_type = _Make_unsigned_like_t>; + + _Size_type _Size = 0; public: _Subrange_base() = default; - constexpr explicit _Subrange_base(const _Size_type&) noexcept {} + constexpr explicit _Subrange_base(const _Size_type& _Size_) noexcept : _Size(_Size_) {} }; #if 1 // TRANSITION, VSO-1695918 - Warning C4324 incorrectly firing in the presence of `pragma pack` #pragma warning(push) #pragma warning(disable : 4324) // structure was padded due to alignment specifier -#endif // TRANSITION, VSO-1695918 - Warning C4324 incorrectly firing in the presence of `pragma pack` +#endif // ^^^ workaround ^^^ _EXPORT_STD template _Se, subrange_kind _Ki> requires (_Ki == subrange_kind::sized || !sized_sentinel_for<_Se, _It>) class subrange : public _Subrange_base<_It, _Se, _Ki> { private: - using _Mybase = _Subrange_base<_It, _Se, _Ki>; - using _Mybase::_Store_size; - using typename _Mybase::_Size_type; + using _Size_type = _Make_unsigned_like_t>; // TRANSITION, [[no_unique_address]]: /* [[no_unique_address]] */ _It _First{}; /* [[no_unique_address]] */ _Se _Last{}; - // [[no_unique_address]] conditional_t<_Store_size, _Size_type, _Nil> _Size{}; + // [[no_unique_address]] conditional_t<_Store_size<_It, _Se, _Ki>, _Size_type, _Nil> _Size{}; template constexpr subrange(true_type, _Rng&& _Val) : subrange(_STD forward<_Rng>(_Val), static_cast<_Size_type>(_RANGES size(_Val))) { // delegation target for subrange(_Rng&&) when we must store the range size - _STL_INTERNAL_STATIC_ASSERT(_Store_size); + _STL_INTERNAL_STATIC_ASSERT(_Store_size<_It, _Se, _Ki>); } template constexpr subrange(false_type, _Rng&& _Val) : subrange(_RANGES begin(_Val), _RANGES end(_Val)) { // delegation target for subrange(_Rng&&) when we need not store the range size - _STL_INTERNAL_STATIC_ASSERT(!_Store_size); + _STL_INTERNAL_STATIC_ASSERT(!_Store_size<_It, _Se, _Ki>); } public: // clang-format off subrange() requires default_initializable<_It> = default; + // clang-format on template <_Convertible_to_non_slicing<_It> _It2> - constexpr subrange(_It2 _First_, _Se _Last_) requires (!_Store_size) + constexpr subrange(_It2 _First_, _Se _Last_) + requires (!_Store_size<_It, _Se, _Ki>) : _First(_STD move(_First_)), _Last(_STD move(_Last_)) {} template <_Convertible_to_non_slicing<_It> _It2> - constexpr subrange(_It2 _First_, _Se _Last_, const _Size_type _Size_) requires (_Ki == subrange_kind::sized) - : _Mybase(_Size_), _First(_STD move(_First_)), _Last(_STD move(_Last_)) { + constexpr subrange(_It2 _First_, _Se _Last_, const _Size_type _Size_) + requires (_Ki == subrange_kind::sized) + : _Subrange_base<_It, _Se, _Ki>(_Size_), _First(_STD move(_First_)), _Last(_STD move(_Last_)) { if constexpr (sized_sentinel_for<_Se, _It>) { _STL_ASSERT(_Size_ == static_cast<_Size_type>(_Last - _First), "This constructor's third argument should be equal to the distance " @@ -3715,17 +3715,17 @@ namespace ranges { } template <_Different_from _Rng> - requires borrowed_range<_Rng> - && _Convertible_to_non_slicing, _It> - && convertible_to, _Se> - constexpr subrange(_Rng&& _Val) requires (!_Store_size || sized_range<_Rng>) - : subrange{bool_constant<_Store_size>{}, _STD forward<_Rng>(_Val)} {} + requires (borrowed_range<_Rng> && _Convertible_to_non_slicing, _It> + && convertible_to, _Se>) + constexpr subrange(_Rng&& _Val) + requires (!_Store_size<_It, _Se, _Ki> || sized_range<_Rng>) + : subrange{bool_constant<_Store_size<_It, _Se, _Ki>>{}, _STD forward<_Rng>(_Val)} {} template - requires _Convertible_to_non_slicing, _It> && convertible_to, _Se> - constexpr subrange(_Rng&& _Val, const _Size_type _Count) requires (_Ki == subrange_kind::sized) + requires (_Convertible_to_non_slicing, _It> && convertible_to, _Se>) + constexpr subrange(_Rng&& _Val, const _Size_type _Count) + requires (_Ki == subrange_kind::sized) : subrange{_RANGES begin(_Val), _RANGES end(_Val), _Count} {} - // clang-format on template <_Different_from _Pair_like> requires _Pair_like_convertible_from<_Pair_like, const _It&, const _Se&> @@ -3738,9 +3738,9 @@ namespace ranges { { return _First; } - // clang-format off - _NODISCARD constexpr _It begin() requires (!copyable<_It>) { - // clang-format on + _NODISCARD constexpr _It begin() + requires (!copyable<_It>) + { return _STD move(_First); } @@ -3752,10 +3752,10 @@ namespace ranges { return _First == _Last; } - // clang-format off - _NODISCARD constexpr _Size_type size() const requires (_Ki == subrange_kind::sized) { - // clang-format on - if constexpr (_Store_size) { + _NODISCARD constexpr _Size_type size() const + requires (_Ki == subrange_kind::sized) + { + if constexpr (_Store_size<_It, _Se, _Ki>) { return this->_Size; } else { return static_cast<_Size_type>(_Last - _First); @@ -3768,7 +3768,7 @@ namespace ranges { auto _Tmp = *this; if (_Tmp._First != _Tmp._Last) { ++_Tmp._First; - if constexpr (_Store_size) { + if constexpr (_Store_size<_It, _Se, _Ki>) { --_Tmp._Size; } } @@ -3785,7 +3785,7 @@ namespace ranges { _NODISCARD constexpr subrange next() && { if (_First != _Last) { ++_First; - if constexpr (_Store_size) { + if constexpr (_Store_size<_It, _Se, _Ki>) { --this->_Size; } } @@ -3801,7 +3801,7 @@ namespace ranges { { auto _Tmp = *this; --_Tmp._First; - if constexpr (_Store_size) { + if constexpr (_Store_size<_It, _Se, _Ki>) { ++_Tmp._Size; } return _Tmp; @@ -3818,7 +3818,7 @@ namespace ranges { if constexpr (bidirectional_iterator<_It>) { if (_Count < 0) { _RANGES advance(_First, _Count); - if constexpr (_Store_size) { + if constexpr (_Store_size<_It, _Se, _Ki>) { this->_Size += static_cast<_Size_type>(-_Count); } return *this; @@ -3826,7 +3826,7 @@ namespace ranges { } const auto _Remainder = _RANGES advance(_First, _Count, _Last); - if constexpr (_Store_size) { + if constexpr (_Store_size<_It, _Se, _Ki>) { this->_Size -= static_cast<_Size_type>(_Count - _Remainder); } return *this; @@ -3834,7 +3834,7 @@ namespace ranges { }; #if 1 // TRANSITION, VSO-1695918 - Warning C4324 incorrectly firing in the presence of `pragma pack` #pragma warning(pop) -#endif // TRANSITION, VSO-1695918 - Warning C4324 incorrectly firing in the presence of `pragma pack` +#endif // ^^^ workaround ^^^ template _Se> subrange(_It, _Se) -> subrange<_It, _Se>; diff --git a/tests/std/tests/P0323R12_expected/test.cpp b/tests/std/tests/P0323R12_expected/test.cpp index 1f02f528726..14bfc85b158 100644 --- a/tests/std/tests/P0323R12_expected/test.cpp +++ b/tests/std/tests/P0323R12_expected/test.cpp @@ -202,7 +202,7 @@ namespace test_expected { struct payload_default_constructor { constexpr payload_default_constructor() - requires (should_be_defaultable) + requires (IsYes(defaultConstructible)) : _val(42) {} [[nodiscard]] constexpr bool operator==(const int val) const noexcept { From 00306c0a99207a9a02664348ba37bc1dbe6e491f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 22 Feb 2023 06:31:03 -0800 Subject: [PATCH 11/14] GH 3485 --- stl/inc/ranges | 19 ++++++++++++++++--- tests/std/tests/P2474R2_views_repeat/test.cpp | 11 +++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index 09b57e12922..1a435dccc76 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -1389,9 +1389,23 @@ namespace ranges { } // namespace views #if _HAS_CXX23 + template + concept _Integer_like_with_usable_difference_type = _Signed_integer_like<_Ty> + || (_Integer_like<_Ty> && weakly_incrementable<_Ty>); + + template + struct _Repeat_view_difference_type { + using type = _Iota_diff_t<_Ty>; + }; + + template <_Signed_integer_like _Ty> + struct _Repeat_view_difference_type<_Ty> { + using type = _Ty; + }; + _EXPORT_STD template requires (is_object_v<_Ty> && same_as<_Ty, remove_cv_t<_Ty>> - && (_Integer_like<_Bo> || same_as<_Bo, unreachable_sentinel_t>) ) + && (_Integer_like_with_usable_difference_type<_Bo> || same_as<_Bo, unreachable_sentinel_t>) ) class repeat_view : public view_interface> { private: friend views::_Take_fn; @@ -1416,8 +1430,7 @@ namespace ranges { using iterator_concept = random_access_iterator_tag; using iterator_category = random_access_iterator_tag; using value_type = _Ty; - using difference_type = - conditional_t<_Signed_integer_like<_Index_type>, _Index_type, _Iota_diff_t<_Index_type>>; + using difference_type = typename _Repeat_view_difference_type<_Index_type>::type; _Iterator() = default; diff --git a/tests/std/tests/P2474R2_views_repeat/test.cpp b/tests/std/tests/P2474R2_views_repeat/test.cpp index 9bd4fc8c73b..4c360593b13 100644 --- a/tests/std/tests/P2474R2_views_repeat/test.cpp +++ b/tests/std/tests/P2474R2_views_repeat/test.cpp @@ -325,6 +325,17 @@ constexpr bool test() { return true; } +// Check LWG-3875 +static_assert(CanViewRepeat); +static_assert(CanViewRepeat); +static_assert(CanViewRepeat); +static_assert( + !CanViewRepeat); // _Unsigned128 does not satisfy 'integer-like-with-usable-difference-type' + +// Check GH-3392 +static_assert(ranges::range); +static_assert(ranges::range); + int main() { assert(test()); static_assert(test()); From 83d928a75776b479e4332b7011e082c4755826a0 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 22 Feb 2023 06:31:07 -0800 Subject: [PATCH 12/14] GH 3486 --- stl/inc/xutility | 107 +++++++++--------- stl/inc/yvals_core.h | 5 +- tests/std/test.lst | 1 + .../env.lst | 4 + .../test.compile.pass.cpp | 67 +++++++++++ .../test.compile.pass.cpp | 6 +- 6 files changed, 132 insertions(+), 58 deletions(-) create mode 100644 tests/std/tests/P2609R3_relaxing_ranges_just_a_smidge/env.lst create mode 100644 tests/std/tests/P2609R3_relaxing_ranges_just_a_smidge/test.compile.pass.cpp diff --git a/stl/inc/xutility b/stl/inc/xutility index ac2a26855d1..d4df0ef4614 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -493,24 +493,33 @@ _EXPORT_STD template { _RANGES iter_move(__t) } -> _Can_reference; } using iter_rvalue_reference_t = decltype(_RANGES iter_move(_STD declval<_Ty&>())); +// clang-format on template -concept _Indirectly_readable_impl = requires(const _It __i) { - typename iter_value_t<_It>; - typename iter_reference_t<_It>; - typename iter_rvalue_reference_t<_It>; - { *__i } -> same_as>; - { _RANGES iter_move(__i) } -> same_as>; -} && common_reference_with&&, iter_value_t<_It>&> - && common_reference_with&&, iter_rvalue_reference_t<_It>&&> - && common_reference_with&&, const iter_value_t<_It>&>; +concept _Indirectly_readable_impl = + requires(const _It __i) { + typename iter_value_t<_It>; + typename iter_reference_t<_It>; + typename iter_rvalue_reference_t<_It>; + { *__i } -> same_as>; + { _RANGES iter_move(__i) } -> same_as>; + } && common_reference_with&&, iter_value_t<_It>&> + && common_reference_with&&, iter_rvalue_reference_t<_It>&&> + && common_reference_with&&, const iter_value_t<_It>&>; _EXPORT_STD template concept indirectly_readable = _Indirectly_readable_impl>; -// clang-format on + +template +struct _Indirect_value_impl { + using type = iter_value_t<_Ty>&; +}; + +template +using _Indirect_value_t = typename _Indirect_value_impl<_It>::type; _EXPORT_STD template -using iter_common_reference_t = common_reference_t, iter_value_t<_Ty>&>; +using iter_common_reference_t = common_reference_t, _Indirect_value_t<_Ty>>; _EXPORT_STD template concept indirectly_writable = @@ -629,69 +638,56 @@ concept contiguous_iterator = random_access_iterator<_It> && requires(const _It& __i) { { _STD to_address(__i) } -> same_as>>; }; +// clang-format on _EXPORT_STD template -concept indirectly_unary_invocable = indirectly_readable<_It> - && copy_constructible<_Fn> - && invocable<_Fn&, iter_value_t<_It>&> - && invocable<_Fn&, iter_reference_t<_It>> - && invocable<_Fn&, iter_common_reference_t<_It>> - && common_reference_with< - invoke_result_t<_Fn&, iter_value_t<_It>&>, +concept indirectly_unary_invocable = + indirectly_readable<_It> && copy_constructible<_Fn> && invocable<_Fn&, _Indirect_value_t<_It>> + && invocable<_Fn&, iter_reference_t<_It>> && invocable<_Fn&, iter_common_reference_t<_It>> + && common_reference_with>, invoke_result_t<_Fn&, iter_reference_t<_It>>>; _EXPORT_STD template -concept indirectly_regular_unary_invocable = indirectly_readable<_It> - && copy_constructible<_Fn> - && regular_invocable<_Fn&, iter_value_t<_It>&> - && regular_invocable<_Fn&, iter_reference_t<_It>> - && regular_invocable<_Fn&, iter_common_reference_t<_It>> - && common_reference_with< - invoke_result_t<_Fn&, iter_value_t<_It>&>, +concept indirectly_regular_unary_invocable = + indirectly_readable<_It> && copy_constructible<_Fn> && regular_invocable<_Fn&, _Indirect_value_t<_It>> + && regular_invocable<_Fn&, iter_reference_t<_It>> && regular_invocable<_Fn&, iter_common_reference_t<_It>> + && common_reference_with>, invoke_result_t<_Fn&, iter_reference_t<_It>>>; _EXPORT_STD template -concept indirect_unary_predicate = indirectly_readable<_It> - && copy_constructible<_Fn> - && predicate<_Fn&, iter_value_t<_It>&> - && predicate<_Fn&, iter_reference_t<_It>> - && predicate<_Fn&, iter_common_reference_t<_It>>; +concept indirect_unary_predicate = + indirectly_readable<_It> && copy_constructible<_Fn> && predicate<_Fn&, _Indirect_value_t<_It>> + && predicate<_Fn&, iter_reference_t<_It>> && predicate<_Fn&, iter_common_reference_t<_It>>; _EXPORT_STD template -concept indirect_binary_predicate = indirectly_readable<_It1> - && indirectly_readable<_It2> - && copy_constructible<_Fn> - && predicate<_Fn&, iter_value_t<_It1>&, iter_value_t<_It2>&> - && predicate<_Fn&, iter_value_t<_It1>&, iter_reference_t<_It2>> - && predicate<_Fn&, iter_reference_t<_It1>, iter_value_t<_It2>&> - && predicate<_Fn&, iter_reference_t<_It1>, iter_reference_t<_It2>> - && predicate<_Fn&, iter_common_reference_t<_It1>, iter_common_reference_t<_It2>>; +concept indirect_binary_predicate = indirectly_readable<_It1> && indirectly_readable<_It2> && copy_constructible<_Fn> + && predicate<_Fn&, _Indirect_value_t<_It1>, _Indirect_value_t<_It2>> + && predicate<_Fn&, _Indirect_value_t<_It1>, iter_reference_t<_It2>> + && predicate<_Fn&, iter_reference_t<_It1>, _Indirect_value_t<_It2>> + && predicate<_Fn&, iter_reference_t<_It1>, iter_reference_t<_It2>> + && predicate<_Fn&, iter_common_reference_t<_It1>, iter_common_reference_t<_It2>>; _EXPORT_STD template -concept indirect_equivalence_relation = indirectly_readable<_It1> - && indirectly_readable<_It2> - && copy_constructible<_Fn> - && equivalence_relation<_Fn&, iter_value_t<_It1>&, iter_value_t<_It2>&> - && equivalence_relation<_Fn&, iter_value_t<_It1>&, iter_reference_t<_It2>> - && equivalence_relation<_Fn&, iter_reference_t<_It1>, iter_value_t<_It2>&> +concept indirect_equivalence_relation = + indirectly_readable<_It1> && indirectly_readable<_It2> && copy_constructible<_Fn> + && equivalence_relation<_Fn&, _Indirect_value_t<_It1>, _Indirect_value_t<_It2>> + && equivalence_relation<_Fn&, _Indirect_value_t<_It1>, iter_reference_t<_It2>> + && equivalence_relation<_Fn&, iter_reference_t<_It1>, _Indirect_value_t<_It2>> && equivalence_relation<_Fn&, iter_reference_t<_It1>, iter_reference_t<_It2>> && equivalence_relation<_Fn&, iter_common_reference_t<_It1>, iter_common_reference_t<_It2>>; _EXPORT_STD template -concept indirect_strict_weak_order = indirectly_readable<_It1> - && indirectly_readable<_It2> - && copy_constructible<_Fn> - && strict_weak_order<_Fn&, iter_value_t<_It1>&, iter_value_t<_It2>&> - && strict_weak_order<_Fn&, iter_value_t<_It1>&, iter_reference_t<_It2>> - && strict_weak_order<_Fn&, iter_reference_t<_It1>, iter_value_t<_It2>&> +concept indirect_strict_weak_order = + indirectly_readable<_It1> && indirectly_readable<_It2> && copy_constructible<_Fn> + && strict_weak_order<_Fn&, _Indirect_value_t<_It1>, _Indirect_value_t<_It2>> + && strict_weak_order<_Fn&, _Indirect_value_t<_It1>, iter_reference_t<_It2>> + && strict_weak_order<_Fn&, iter_reference_t<_It1>, _Indirect_value_t<_It2>> && strict_weak_order<_Fn&, iter_reference_t<_It1>, iter_reference_t<_It2>> && strict_weak_order<_Fn&, iter_common_reference_t<_It1>, iter_common_reference_t<_It2>>; _EXPORT_STD template - requires (indirectly_readable<_Its> && ...) - && invocable<_Fn, iter_reference_t<_Its>...> + requires (indirectly_readable<_Its> && ...) && invocable<_Fn, iter_reference_t<_Its>...> using indirect_result_t = invoke_result_t<_Fn, iter_reference_t<_Its>...>; -// clang-format on _EXPORT_STD template _Proj> struct projected { @@ -701,6 +697,11 @@ struct projected { } }; +template +struct _Indirect_value_impl> { + using type = invoke_result_t<_Proj&, _Indirect_value_t<_It>>; +}; + template struct incrementable_traits> { using difference_type = iter_difference_t<_It>; diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index b106c0950ba..d27e652212c 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -286,6 +286,8 @@ // P2508R1 basic_format_string, format_string, wformat_string // P2520R0 move_iterator Should Be A Random-Access Iterator // P2588R3 barrier's Phase Completion Guarantees +// P2602R2 Poison Pills Are Too Toxic +// P2609R3 Relaxing Ranges Just A Smidge // P2711R1 Making Multi-Param Constructors Of Views explicit // _HAS_CXX20 indirectly controls: @@ -351,7 +353,6 @@ // P2499R0 string_view Range Constructor Should Be explicit // P2505R5 Monadic Functions For expected // P2549R1 unexpected::error() -// P2602R2 Poison Pills Are Too Toxic // Parallel Algorithms Notes // C++ allows an implementation to implement parallel algorithms as calls to the serial algorithms. @@ -1762,7 +1763,7 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #if defined(__cpp_lib_concepts) // TRANSITION, GH-395 #if _HAS_CXX23 -#define __cpp_lib_ranges 202211L // P2602R2 Poison Pills Are Too Toxic +#define __cpp_lib_ranges 202302L // P2609R3 Relaxing Ranges Just A Smidge #elif _HAS_CXX20 // ^^^ _HAS_CXX23 / _HAS_CXX20 vvv #define __cpp_lib_ranges 202110L // P2415R2 What Is A view? #endif // _HAS_CXX20 diff --git a/tests/std/test.lst b/tests/std/test.lst index dc8519a3ce6..22e1b45d8f6 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -592,6 +592,7 @@ tests\P2474R2_views_repeat_death tests\P2494R2_move_only_range_adaptors tests\P2505R5_monadic_functions_for_std_expected tests\P2517R1_apply_conditional_noexcept +tests\P2609R3_relaxing_ranges_just_a_smidge tests\VSO_0000000_allocator_propagation tests\VSO_0000000_any_calling_conventions tests\VSO_0000000_c_math_functions diff --git a/tests/std/tests/P2609R3_relaxing_ranges_just_a_smidge/env.lst b/tests/std/tests/P2609R3_relaxing_ranges_just_a_smidge/env.lst new file mode 100644 index 00000000000..18e2d7c71ec --- /dev/null +++ b/tests/std/tests/P2609R3_relaxing_ranges_just_a_smidge/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\concepts_latest_matrix.lst diff --git a/tests/std/tests/P2609R3_relaxing_ranges_just_a_smidge/test.compile.pass.cpp b/tests/std/tests/P2609R3_relaxing_ranges_just_a_smidge/test.compile.pass.cpp new file mode 100644 index 00000000000..5d57fe16882 --- /dev/null +++ b/tests/std/tests/P2609R3_relaxing_ranges_just_a_smidge/test.compile.pass.cpp @@ -0,0 +1,67 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include + +using namespace std; + +void test() { + auto ints = views::iota(0, 5); + auto project_to_unique_ptr = [](T v) { return make_unique(move(v)); }; + + using It = ranges::iterator_t; + using Proj = decltype(project_to_unique_ptr); + using ProjectedIt = projected; + + { // Check indirectly_unary_invocable + auto consume = [](auto) {}; + static_assert(indirectly_unary_invocable); + + ranges::for_each(ints, consume, project_to_unique_ptr); + ranges::for_each(ints.begin(), ints.end(), consume, project_to_unique_ptr); + } + + { // Check indirectly_regular_unary_invocable + static_assert(indirectly_regular_unary_invocable); + using Check [[maybe_unused]] = projected; + } + + { // Check indirect_unary_predicate + auto unary_pred = [](auto) { return false; }; + static_assert(indirect_unary_predicate); + + (void) ranges::find_if(ints, unary_pred, project_to_unique_ptr); + (void) ranges::find_if(ints.begin(), ints.end(), unary_pred, project_to_unique_ptr); + (void) ranges::count_if(ints, unary_pred, project_to_unique_ptr); + (void) ranges::count_if(ints.begin(), ints.end(), unary_pred, project_to_unique_ptr); + } + + { // Check indirect_binary_predicate + auto binary_pred = [](auto, auto) { return false; }; + static_assert(indirect_binary_predicate); + + (void) ranges::adjacent_find(ints, binary_pred, project_to_unique_ptr); + (void) ranges::adjacent_find(ints.begin(), ints.end(), binary_pred, project_to_unique_ptr); + } + + { // Check indirect_equivalence_relation + auto rel = [](auto, auto) { return false; }; + static_assert(indirect_equivalence_relation); + + vector out; + (void) ranges::unique_copy(ints, back_inserter(out), rel, project_to_unique_ptr); + (void) ranges::unique_copy(ints.begin(), ints.end(), back_inserter(out), rel, project_to_unique_ptr); + } + + { // Check indirect_strict_weak_order + auto rel = [](auto x, auto y) { return x < y; }; + static_assert(indirect_strict_weak_order); + + (void) ranges::is_sorted_until(ints, rel, project_to_unique_ptr); + (void) ranges::is_sorted_until(ints.begin(), ints.end(), rel, project_to_unique_ptr); + } +} 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 473e2d94748..7dedee3a9d1 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 @@ -1505,10 +1505,10 @@ STATIC_ASSERT(__cpp_lib_quoted_string_io == 201304L); #if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 #ifndef __cpp_lib_ranges #error __cpp_lib_ranges is not defined -#elif __cpp_lib_ranges != 202211L -#error __cpp_lib_ranges is not 202211L +#elif __cpp_lib_ranges != 202302L +#error __cpp_lib_ranges is not 202302L #else -STATIC_ASSERT(__cpp_lib_ranges == 202211L); +STATIC_ASSERT(__cpp_lib_ranges == 202302L); #endif #elif _HAS_CXX20 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 #ifndef __cpp_lib_ranges From 1fd56efb949327517345d0db5af5075f2b1da0af Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 22 Feb 2023 06:31:09 -0800 Subject: [PATCH 13/14] GH 3487 --- stl/inc/xerrc.h | 156 +++++++++++++------------- stl/inc/yvals_core.h | 21 +++- stl/src/syserror.cpp | 2 + tests/tr1/tests/system_error/test.cpp | 2 + 4 files changed, 101 insertions(+), 80 deletions(-) diff --git a/stl/inc/xerrc.h b/stl/inc/xerrc.h index 86bb85850e5..ac1ce3dada1 100644 --- a/stl/inc/xerrc.h +++ b/stl/inc/xerrc.h @@ -18,84 +18,84 @@ _STL_DISABLE_CLANG_WARNINGS _STD_BEGIN _EXPORT_STD enum class errc { // names for generic error codes - address_family_not_supported = 102, // EAFNOSUPPORT - address_in_use = 100, // EADDRINUSE - address_not_available = 101, // EADDRNOTAVAIL - already_connected = 113, // EISCONN - argument_list_too_long = 7, // E2BIG - argument_out_of_domain = 33, // EDOM - bad_address = 14, // EFAULT - bad_file_descriptor = 9, // EBADF - bad_message = 104, // EBADMSG - broken_pipe = 32, // EPIPE - connection_aborted = 106, // ECONNABORTED - connection_already_in_progress = 103, // EALREADY - connection_refused = 107, // ECONNREFUSED - connection_reset = 108, // ECONNRESET - cross_device_link = 18, // EXDEV - destination_address_required = 109, // EDESTADDRREQ - device_or_resource_busy = 16, // EBUSY - directory_not_empty = 41, // ENOTEMPTY - executable_format_error = 8, // ENOEXEC - file_exists = 17, // EEXIST - file_too_large = 27, // EFBIG - filename_too_long = 38, // ENAMETOOLONG - function_not_supported = 40, // ENOSYS - host_unreachable = 110, // EHOSTUNREACH - identifier_removed = 111, // EIDRM - illegal_byte_sequence = 42, // EILSEQ - inappropriate_io_control_operation = 25, // ENOTTY - interrupted = 4, // EINTR - invalid_argument = 22, // EINVAL - invalid_seek = 29, // ESPIPE - io_error = 5, // EIO - is_a_directory = 21, // EISDIR - message_size = 115, // EMSGSIZE - network_down = 116, // ENETDOWN - network_reset = 117, // ENETRESET - network_unreachable = 118, // ENETUNREACH - no_buffer_space = 119, // ENOBUFS - no_child_process = 10, // ECHILD - no_link = 121, // ENOLINK - no_lock_available = 39, // ENOLCK - no_message_available = 120, // ENODATA - no_message = 122, // ENOMSG - no_protocol_option = 123, // ENOPROTOOPT - no_space_on_device = 28, // ENOSPC - no_stream_resources = 124, // ENOSR - no_such_device_or_address = 6, // ENXIO - no_such_device = 19, // ENODEV - no_such_file_or_directory = 2, // ENOENT - no_such_process = 3, // ESRCH - not_a_directory = 20, // ENOTDIR - not_a_socket = 128, // ENOTSOCK - not_a_stream = 125, // ENOSTR - not_connected = 126, // ENOTCONN - not_enough_memory = 12, // ENOMEM - not_supported = 129, // ENOTSUP - operation_canceled = 105, // ECANCELED - operation_in_progress = 112, // EINPROGRESS - operation_not_permitted = 1, // EPERM - operation_not_supported = 130, // EOPNOTSUPP - operation_would_block = 140, // EWOULDBLOCK - owner_dead = 133, // EOWNERDEAD - permission_denied = 13, // EACCES - protocol_error = 134, // EPROTO - protocol_not_supported = 135, // EPROTONOSUPPORT - read_only_file_system = 30, // EROFS - resource_deadlock_would_occur = 36, // EDEADLK - resource_unavailable_try_again = 11, // EAGAIN - result_out_of_range = 34, // ERANGE - state_not_recoverable = 127, // ENOTRECOVERABLE - stream_timeout = 137, // ETIME - text_file_busy = 139, // ETXTBSY - timed_out = 138, // ETIMEDOUT - too_many_files_open_in_system = 23, // ENFILE - too_many_files_open = 24, // EMFILE - too_many_links = 31, // EMLINK - too_many_symbolic_link_levels = 114, // ELOOP - value_too_large = 132, // EOVERFLOW - wrong_protocol_type = 136 // EPROTOTYPE + address_family_not_supported = 102, // EAFNOSUPPORT + address_in_use = 100, // EADDRINUSE + address_not_available = 101, // EADDRNOTAVAIL + already_connected = 113, // EISCONN + argument_list_too_long = 7, // E2BIG + argument_out_of_domain = 33, // EDOM + bad_address = 14, // EFAULT + bad_file_descriptor = 9, // EBADF + bad_message = 104, // EBADMSG + broken_pipe = 32, // EPIPE + connection_aborted = 106, // ECONNABORTED + connection_already_in_progress = 103, // EALREADY + connection_refused = 107, // ECONNREFUSED + connection_reset = 108, // ECONNRESET + cross_device_link = 18, // EXDEV + destination_address_required = 109, // EDESTADDRREQ + device_or_resource_busy = 16, // EBUSY + directory_not_empty = 41, // ENOTEMPTY + executable_format_error = 8, // ENOEXEC + file_exists = 17, // EEXIST + file_too_large = 27, // EFBIG + filename_too_long = 38, // ENAMETOOLONG + function_not_supported = 40, // ENOSYS + host_unreachable = 110, // EHOSTUNREACH + identifier_removed = 111, // EIDRM + illegal_byte_sequence = 42, // EILSEQ + inappropriate_io_control_operation = 25, // ENOTTY + interrupted = 4, // EINTR + invalid_argument = 22, // EINVAL + invalid_seek = 29, // ESPIPE + io_error = 5, // EIO + is_a_directory = 21, // EISDIR + message_size = 115, // EMSGSIZE + network_down = 116, // ENETDOWN + network_reset = 117, // ENETRESET + network_unreachable = 118, // ENETUNREACH + no_buffer_space = 119, // ENOBUFS + no_child_process = 10, // ECHILD + no_link = 121, // ENOLINK + no_lock_available = 39, // ENOLCK + no_message_available _CXX23_DEPRECATE_UNIX_STREAMS = 120, // ENODATA + no_message = 122, // ENOMSG + no_protocol_option = 123, // ENOPROTOOPT + no_space_on_device = 28, // ENOSPC + no_stream_resources _CXX23_DEPRECATE_UNIX_STREAMS = 124, // ENOSR + no_such_device_or_address = 6, // ENXIO + no_such_device = 19, // ENODEV + no_such_file_or_directory = 2, // ENOENT + no_such_process = 3, // ESRCH + not_a_directory = 20, // ENOTDIR + not_a_socket = 128, // ENOTSOCK + not_a_stream _CXX23_DEPRECATE_UNIX_STREAMS = 125, // ENOSTR + not_connected = 126, // ENOTCONN + not_enough_memory = 12, // ENOMEM + not_supported = 129, // ENOTSUP + operation_canceled = 105, // ECANCELED + operation_in_progress = 112, // EINPROGRESS + operation_not_permitted = 1, // EPERM + operation_not_supported = 130, // EOPNOTSUPP + operation_would_block = 140, // EWOULDBLOCK + owner_dead = 133, // EOWNERDEAD + permission_denied = 13, // EACCES + protocol_error = 134, // EPROTO + protocol_not_supported = 135, // EPROTONOSUPPORT + read_only_file_system = 30, // EROFS + resource_deadlock_would_occur = 36, // EDEADLK + resource_unavailable_try_again = 11, // EAGAIN + result_out_of_range = 34, // ERANGE + state_not_recoverable = 127, // ENOTRECOVERABLE + stream_timeout _CXX23_DEPRECATE_UNIX_STREAMS = 137, // ETIME + text_file_busy = 139, // ETXTBSY + timed_out = 138, // ETIMEDOUT + too_many_files_open_in_system = 23, // ENFILE + too_many_files_open = 24, // EMFILE + too_many_links = 31, // EMLINK + too_many_symbolic_link_levels = 114, // ELOOP + value_too_large = 132, // EOVERFLOW + wrong_protocol_type = 136 // EPROTOTYPE }; _STD_END diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index d27e652212c..85bebe3ffbc 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -315,7 +315,6 @@ // P1223R5 ranges::find_last, ranges::find_last_if, ranges::find_last_if_not // P1272R4 byteswap() // P1328R1 constexpr type_info::operator==() -// P1413R3 Deprecate aligned_storage And aligned_union // P1425R4 Iterator Pair Constructors For stack And queue // P1659R3 ranges::starts_with, ranges::ends_with // P1679R3 contains() For basic_string/basic_string_view @@ -354,6 +353,10 @@ // P2505R5 Monadic Functions For expected // P2549R1 unexpected::error() +// _HAS_CXX23 and _SILENCE_ALL_CXX23_DEPRECATION_WARNINGS control: +// P1413R3 Deprecate aligned_storage And aligned_union +// Other C++23 deprecation warnings + // Parallel Algorithms Notes // C++ allows an implementation to implement parallel algorithms as calls to the serial algorithms. // This implementation parallelizes several common algorithm calls, but not all. @@ -1404,7 +1407,21 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect // STL4040 is used to warn that "The contents of require static RTTI." -// next warning number: STL4041 +#if _HAS_CXX23 && !defined(_SILENCE_CXX23_UNIX_STREAMS_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX23_DEPRECATION_WARNINGS) +#define _CXX23_DEPRECATE_UNIX_STREAMS \ + [[deprecated( \ + "warning STL4041: " \ + "std::errc enumerators std::errc::no_message_available, std::errc::no_stream_resources, " \ + "std::errc::not_a_stream, and std::errc::stream_timeout and their corresponding errno macros ENODATA, ENOSR, " \ + "ENOSTR, and ETIME are deprecated in C++23 by LWG-3869. These errno macros are deprecated in POSIX 2008 and " \ + "removed in POSIX 202x. You can define _SILENCE_CXX23_UNIX_STREAMS_DEPRECATION_WARNING or " \ + "_SILENCE_ALL_CXX23_DEPRECATION_WARNINGS to suppress this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX23_DEPRECATE_UNIX_STREAMS +#endif // ^^^ warning disabled ^^^ + +// next warning number: STL4042 // next error number: STL1006 diff --git a/stl/src/syserror.cpp b/stl/src/syserror.cpp index ca926166cf0..002862555df 100644 --- a/stl/src/syserror.cpp +++ b/stl/src/syserror.cpp @@ -3,6 +3,8 @@ // system_error message mapping +#define _SILENCE_CXX23_UNIX_STREAMS_DEPRECATION_WARNING + #include #include #include diff --git a/tests/tr1/tests/system_error/test.cpp b/tests/tr1/tests/system_error/test.cpp index a80cbf3b373..af3252993f5 100644 --- a/tests/tr1/tests/system_error/test.cpp +++ b/tests/tr1/tests/system_error/test.cpp @@ -4,6 +4,8 @@ // test #define TEST_NAME "" +#define _SILENCE_CXX23_UNIX_STREAMS_DEPRECATION_WARNING + #include "tdefs.h" #include #include From b36a71106846ef6d51f4481923e4b781b43304c7 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 22 Feb 2023 06:31:12 -0800 Subject: [PATCH 14/14] GH 3489 --- stl/inc/charconv | 5 ++--- stl/inc/system_error | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/charconv b/stl/inc/charconv index cdf1d167a9f..c26313fb9b3 100644 --- a/stl/inc/charconv +++ b/stl/inc/charconv @@ -444,11 +444,10 @@ _NODISCARD inline uint32_t _Bit_scan_reverse(const _Big_integer_flt& _Xval) noex const uint32_t _Bx = _Xval._Myused - 1; - _STL_INTERNAL_CHECK(_Xval._Mydata[_Bx] != 0); // _Big_integer_flt should always be trimmed - unsigned long _Index; // Intentionally uninitialized for better codegen - _BitScanReverse(&_Index, _Xval._Mydata[_Bx]); // assumes _Xval._Mydata[_Bx] != 0 + _STL_INTERNAL_CHECK(_Xval._Mydata[_Bx] != 0); // _Big_integer_flt should always be trimmed + _BitScanReverse(&_Index, _Xval._Mydata[_Bx]); // lgtm [cpp/conditionallyuninitializedvariable] return _Index + 1 + _Bx * _Big_integer_flt::_Element_bits; } diff --git a/stl/inc/system_error b/stl/inc/system_error index aa0a28c3a25..60ccf897eb2 100644 --- a/stl/inc/system_error +++ b/stl/inc/system_error @@ -579,7 +579,8 @@ public: constexpr size_t _Unknown_error_length = sizeof(_Unknown_error) - 1; // TRANSITION, DevCom-906503 return string{_Unknown_error, _Unknown_error_length}; } else { - return string{_Msg._Str, _Msg._Length}; + _STL_INTERNAL_CHECK(_Msg._Str != nullptr); + return string{_Msg._Str, _Msg._Length}; // lgtm [cpp/uninitializedptrfield] } }