From 10f26f0f3c6ac9e1bce600ab6389b1f518ca0aab Mon Sep 17 00:00:00 2001 From: "S. B. Tam" Date: Fri, 23 Jun 2023 02:51:36 +0800 Subject: [PATCH 01/35] `mutex.cpp`, `cond.cpp`: Use static dispatch (#3770) Co-authored-by: Stephan T. Lavavej --- stl/inc/mutex | 12 +--- stl/src/cond.cpp | 12 ++-- stl/src/mutex.cpp | 8 +-- stl/src/primitives.hpp | 63 +++++-------------- .../tests/Dev11_1150223_shared_mutex/test.cpp | 3 - 5 files changed, 28 insertions(+), 70 deletions(-) diff --git a/stl/inc/mutex b/stl/inc/mutex index 1d4faf58c49..ed72ac0834a 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -93,11 +93,7 @@ public: _Mtx_unlock(_Mymtx()); } - using native_handle_type = void*; - - _NODISCARD native_handle_type native_handle() noexcept /* strengthened */ { - return _Mtx_getconcrtcs(_Mymtx()); - } + // native_handle_type and native_handle() have intentionally been removed. See GH-3820. protected: _NODISCARD_TRY_CHANGE_STATE bool _Verify_ownership_levels() noexcept { @@ -636,8 +632,6 @@ _EXPORT_STD enum class cv_status { // names for wait returns _EXPORT_STD class condition_variable { // class for waiting for conditions public: - using native_handle_type = _Cnd_t; - condition_variable() noexcept /* strengthened */ { _Cnd_init_in_situ(_Mycnd()); } @@ -725,9 +719,7 @@ public: return _Wait_until1(_Lck, _Abs_time, _Pred); } - _NODISCARD native_handle_type native_handle() noexcept /* strengthened */ { - return _Mycnd(); - } + // native_handle_type and native_handle() have intentionally been removed. See GH-3820. void _Register(unique_lock& _Lck, int* _Ready) noexcept { // register this object for release at thread exit _Cnd_register_at_thread_exit(_Mycnd(), _Lck.release()->_Mymtx(), _Ready); diff --git a/stl/src/cond.cpp b/stl/src/cond.cpp index e9eb1c642b7..153b59974ee 100644 --- a/stl/src/cond.cpp +++ b/stl/src/cond.cpp @@ -15,9 +15,9 @@ struct _Cnd_internal_imp_t { // condition variable implementation for ConcRT typename std::_Aligned_storage::type cv; - [[nodiscard]] Concurrency::details::stl_condition_variable_interface* _get_cv() noexcept { + [[nodiscard]] Concurrency::details::stl_condition_variable_win7* _get_cv() noexcept { // get pointer to implementation - return reinterpret_cast(&cv); + return reinterpret_cast(&cv); } }; @@ -28,9 +28,7 @@ void _Cnd_init_in_situ(const _Cnd_t cond) { // initialize condition variable in Concurrency::details::create_stl_condition_variable(cond->_get_cv()); } -void _Cnd_destroy_in_situ(const _Cnd_t cond) { // destroy condition variable in situ - cond->_get_cv()->destroy(); -} +void _Cnd_destroy_in_situ(_Cnd_t) {} // destroy condition variable in situ int _Cnd_init(_Cnd_t* const pcond) { // initialize *pcond = nullptr; @@ -53,7 +51,7 @@ void _Cnd_destroy(const _Cnd_t cond) { // clean up } int _Cnd_wait(const _Cnd_t cond, const _Mtx_t mtx) { // wait until signaled - const auto cs = static_cast(_Mtx_getconcrtcs(mtx)); + const auto cs = static_cast(_Mtx_getconcrtcs(mtx)); _Mtx_clear_owner(mtx); cond->_get_cv()->wait(cs); _Mtx_reset_owner(mtx); @@ -63,7 +61,7 @@ int _Cnd_wait(const _Cnd_t cond, const _Mtx_t mtx) { // wait until signaled // wait until signaled or timeout int _Cnd_timedwait(const _Cnd_t cond, const _Mtx_t mtx, const _timespec64* const target) { int res = _Thrd_success; - const auto cs = static_cast(_Mtx_getconcrtcs(mtx)); + const auto cs = static_cast(_Mtx_getconcrtcs(mtx)); if (target == nullptr) { // no target time specified, wait on mutex _Mtx_clear_owner(mtx); cond->_get_cv()->wait(cs); diff --git a/stl/src/mutex.cpp b/stl/src/mutex.cpp index dad5b4f7655..6deb0e8ebd3 100644 --- a/stl/src/mutex.cpp +++ b/stl/src/mutex.cpp @@ -43,8 +43,8 @@ struct _Mtx_internal_imp_t { // ConcRT mutex Concurrency::details::stl_critical_section_max_alignment>::type cs; long thread_id; int count; - Concurrency::details::stl_critical_section_interface* _get_cs() { // get pointer to implementation - return reinterpret_cast(&cs); + [[nodiscard]] Concurrency::details::stl_critical_section_win7* _get_cs() { // get pointer to implementation + return reinterpret_cast(&cs); } }; @@ -65,7 +65,7 @@ void _Mtx_init_in_situ(_Mtx_t mtx, int type) { // initialize mutex in situ void _Mtx_destroy_in_situ(_Mtx_t mtx) { // destroy mutex in situ _THREAD_ASSERT(mtx->count == 0, "mutex destroyed while busy"); - mtx->_get_cs()->destroy(); + (void) mtx; } int _Mtx_init(_Mtx_t* mtx, int type) { // initialize mutex @@ -126,7 +126,7 @@ static int mtx_do_lock(_Mtx_t mtx, const _timespec64* target) { // lock mutex while (now.tv_sec < target->tv_sec || now.tv_sec == target->tv_sec && now.tv_nsec < target->tv_nsec) { // time has not expired if (mtx->thread_id == static_cast(GetCurrentThreadId()) - || mtx->_get_cs()->try_lock_for(_Xtime_diff_to_millis2(target, &now))) { // stop waiting + || mtx->_get_cs()->try_lock()) { // stop waiting res = WAIT_OBJECT_0; break; } else { diff --git a/stl/src/primitives.hpp b/stl/src/primitives.hpp index a61e7755474..b3d2db32367 100644 --- a/stl/src/primitives.hpp +++ b/stl/src/primitives.hpp @@ -10,25 +10,7 @@ namespace Concurrency { namespace details { - class __declspec(novtable) stl_critical_section_interface { - public: - virtual void lock() = 0; - virtual bool try_lock() = 0; - virtual bool try_lock_for(unsigned int) = 0; - virtual void unlock() = 0; - virtual void destroy() = 0; - }; - - class __declspec(novtable) stl_condition_variable_interface { - public: - virtual void wait(stl_critical_section_interface*) = 0; - virtual bool wait_for(stl_critical_section_interface*, unsigned int) = 0; - virtual void notify_one() = 0; - virtual void notify_all() = 0; - virtual void destroy() = 0; - }; - - class stl_critical_section_win7 final : public stl_critical_section_interface { + class stl_critical_section_win7 { public: stl_critical_section_win7() = default; @@ -36,22 +18,15 @@ namespace Concurrency { stl_critical_section_win7(const stl_critical_section_win7&) = delete; stl_critical_section_win7& operator=(const stl_critical_section_win7&) = delete; - void destroy() override {} - - void lock() override { + void lock() { AcquireSRWLockExclusive(&m_srw_lock); } - bool try_lock() override { + bool try_lock() { return TryAcquireSRWLockExclusive(&m_srw_lock) != 0; } - bool try_lock_for(unsigned int) override { - // STL will call try_lock_for once again if this call will not succeed - return stl_critical_section_win7::try_lock(); - } - - void unlock() override { + void unlock() { _Analysis_assume_lock_held_(m_srw_lock); ReleaseSRWLockExclusive(&m_srw_lock); } @@ -61,50 +36,46 @@ namespace Concurrency { } private: + void* unused = nullptr; // TRANSITION, ABI: was the vptr SRWLOCK m_srw_lock = SRWLOCK_INIT; }; - class stl_condition_variable_win7 final : public stl_condition_variable_interface { + class stl_condition_variable_win7 { public: - stl_condition_variable_win7() { - InitializeConditionVariable(&m_condition_variable); - } + stl_condition_variable_win7() = default; ~stl_condition_variable_win7() = delete; stl_condition_variable_win7(const stl_condition_variable_win7&) = delete; stl_condition_variable_win7& operator=(const stl_condition_variable_win7&) = delete; - void destroy() override {} - - void wait(stl_critical_section_interface* lock) override { - if (!stl_condition_variable_win7::wait_for(lock, INFINITE)) { + void wait(stl_critical_section_win7* lock) { + if (!wait_for(lock, INFINITE)) { std::terminate(); } } - bool wait_for(stl_critical_section_interface* lock, unsigned int timeout) override { - return SleepConditionVariableSRW(&m_condition_variable, - static_cast(lock)->native_handle(), timeout, 0) - != 0; + bool wait_for(stl_critical_section_win7* lock, unsigned int timeout) { + return SleepConditionVariableSRW(&m_condition_variable, lock->native_handle(), timeout, 0) != 0; } - void notify_one() override { + void notify_one() { WakeConditionVariable(&m_condition_variable); } - void notify_all() override { + void notify_all() { WakeAllConditionVariable(&m_condition_variable); } private: - CONDITION_VARIABLE m_condition_variable; + void* unused = nullptr; // TRANSITION, ABI: was the vptr + CONDITION_VARIABLE m_condition_variable = CONDITION_VARIABLE_INIT; }; - inline void create_stl_critical_section(stl_critical_section_interface* p) { + inline void create_stl_critical_section(stl_critical_section_win7* p) { new (p) stl_critical_section_win7; } - inline void create_stl_condition_variable(stl_condition_variable_interface* p) { + inline void create_stl_condition_variable(stl_condition_variable_win7* p) { new (p) stl_condition_variable_win7; } diff --git a/tests/std/tests/Dev11_1150223_shared_mutex/test.cpp b/tests/std/tests/Dev11_1150223_shared_mutex/test.cpp index 44ca1f2b6f4..4a5ecdf2786 100644 --- a/tests/std/tests/Dev11_1150223_shared_mutex/test.cpp +++ b/tests/std/tests/Dev11_1150223_shared_mutex/test.cpp @@ -58,10 +58,7 @@ STATIC_ASSERT(noexcept(declval().native_handle())); #if _HAS_CXX20 STATIC_ASSERT(noexcept(declval().native_handle())); #endif // _HAS_CXX20 -STATIC_ASSERT(noexcept(declval().native_handle())); -STATIC_ASSERT(noexcept(declval().native_handle())); STATIC_ASSERT(noexcept(declval().native_handle())); -STATIC_ASSERT(noexcept(declval().native_handle())); // Also test mandatory and strengthened exception specification for try_lock(). STATIC_ASSERT(noexcept(declval().try_lock())); // strengthened From 518f4495ff585fe6052eaf0402e5da04701bd621 Mon Sep 17 00:00:00 2001 From: achabense <60953653+achabense@users.noreply.github.com> Date: Fri, 23 Jun 2023 02:52:34 +0800 Subject: [PATCH 02/35] Fix `fstream.seekp(0, ios::cur)` (#3773) Co-authored-by: Stephan T. Lavavej Co-authored-by: Casey Carter --- stl/inc/__msvc_filebuf.hpp | 3 +- tests/std/test.lst | 1 + .../GH_003572_fstream_seekp_0_cur/env.lst | 4 ++ .../GH_003572_fstream_seekp_0_cur/test.cpp | 47 +++++++++++++++++++ 4 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 tests/std/tests/GH_003572_fstream_seekp_0_cur/env.lst create mode 100644 tests/std/tests/GH_003572_fstream_seekp_0_cur/test.cpp diff --git a/stl/inc/__msvc_filebuf.hpp b/stl/inc/__msvc_filebuf.hpp index 7e420846cfa..f06907a888c 100644 --- a/stl/inc/__msvc_filebuf.hpp +++ b/stl/inc/__msvc_filebuf.hpp @@ -651,8 +651,7 @@ class basic_filebuf : public basic_streambuf<_Elem, _Traits> { // stream buffer _Off -= static_cast(sizeof(_Elem)); // back up over _Elem bytes } - if (!_Myfile || !_Endwrite() - || ((_Off != 0 || _Way != ios_base::cur) && _CSTD _fseeki64(_Myfile, _Off, _Way) != 0) + if (!_Myfile || !_Endwrite() || _CSTD _fseeki64(_Myfile, _Off, _Way) != 0 || _CSTD fgetpos(_Myfile, &_Fileposition) != 0) { return pos_type{off_type{-1}}; // report failure } diff --git a/tests/std/test.lst b/tests/std/test.lst index 822cf153b82..094f4c7d4fe 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -223,6 +223,7 @@ tests\GH_003105_piecewise_densities tests\GH_003119_error_category_ctor tests\GH_003246_cmath_narrowing tests\GH_003570_allocate_at_least +tests\GH_003572_fstream_seekp_0_cur tests\GH_003617_vectorized_meow_element tests\GH_003676_format_large_hh_mm_ss_values tests\GH_003735_char_traits_signatures diff --git a/tests/std/tests/GH_003572_fstream_seekp_0_cur/env.lst b/tests/std/tests/GH_003572_fstream_seekp_0_cur/env.lst new file mode 100644 index 00000000000..19f025bd0e6 --- /dev/null +++ b/tests/std/tests/GH_003572_fstream_seekp_0_cur/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_matrix.lst diff --git a/tests/std/tests/GH_003572_fstream_seekp_0_cur/test.cpp b/tests/std/tests/GH_003572_fstream_seekp_0_cur/test.cpp new file mode 100644 index 00000000000..72d15f50bcb --- /dev/null +++ b/tests/std/tests/GH_003572_fstream_seekp_0_cur/test.cpp @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include + +int main() { + using namespace std; + + fstream f("test.txt", ios::in | ios::out | ios::trunc); + + f << "123"; + + auto check = [&f](const char(&content)[4]) { + char buffer[4]{}; + f.seekg(0); + f.read(buffer, 3); + assert(f); + assert(memcmp(buffer, content, 4) == 0); + }; + + f.seekg(0); + (void) f.get(); + f.seekp(f.tellp()); + f << "*"; + check("1*3"); + + f.seekg(0); + (void) f.get(); + f.seekp(0, ios::cur); + f << "!"; + check("1!3"); + + f.seekg(0); + (void) f.get(); + f.seekp(1, ios::cur); + f << "!"; + check("1!!"); + + f.seekg(0); + (void) f.get(); + f.seekp(-1, ios::cur); + f << "!"; + check("!!!"); +} From 51fd0c071d81cb1868087e24012ca45cd6dce00e Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 22 Jun 2023 11:53:28 -0700 Subject: [PATCH 03/35] Avoid evil macros (#3776) --- stl/inc/__msvc_bit_utils.hpp | 20 ++++++++++---------- stl/inc/complex | 32 ++++++++++++++++---------------- stl/inc/deque | 6 +++--- stl/inc/mutex | 2 +- stl/inc/random | 16 ++++++++-------- stl/inc/regex | 4 ++-- 6 files changed, 40 insertions(+), 40 deletions(-) diff --git a/stl/inc/__msvc_bit_utils.hpp b/stl/inc/__msvc_bit_utils.hpp index 04f45b03f29..89d5d4c1947 100644 --- a/stl/inc/__msvc_bit_utils.hpp +++ b/stl/inc/__msvc_bit_utils.hpp @@ -49,19 +49,19 @@ _INLINE_VAR constexpr int _Unsigned_integer_digits = sizeof(_UInt) * CHAR_BIT; // see "Hacker's Delight" section 5-3 template _NODISCARD constexpr int _Countl_zero_fallback(_Ty _Val) noexcept { - _Ty _Yy = 0; + _Ty _Yx = 0; - unsigned int _Nn = _Unsigned_integer_digits<_Ty>; - unsigned int _Cc = _Unsigned_integer_digits<_Ty> / 2; + unsigned int _Nx = _Unsigned_integer_digits<_Ty>; + unsigned int _Cx = _Unsigned_integer_digits<_Ty> / 2; do { - _Yy = static_cast<_Ty>(_Val >> _Cc); - if (_Yy != 0) { - _Nn -= _Cc; - _Val = _Yy; + _Yx = static_cast<_Ty>(_Val >> _Cx); + if (_Yx != 0) { + _Nx -= _Cx; + _Val = _Yx; } - _Cc >>= 1; - } while (_Cc != 0); - return static_cast(_Nn) - static_cast(_Val); + _Cx >>= 1; + } while (_Cx != 0); + return static_cast(_Nx) - static_cast(_Val); } #if !defined(_M_CEE_PURE) && !defined(__CUDACC__) && !defined(__INTEL_COMPILER) diff --git a/stl/inc/complex b/stl/inc/complex index c95ed2d8b2c..6420abadcec 100644 --- a/stl/inc/complex +++ b/stl/inc/complex @@ -1531,8 +1531,8 @@ _NODISCARD _Ty abs(const complex<_Ty>& _Left) { _EXPORT_STD template _NODISCARD complex<_Ty> acos(const complex<_Ty>& _Left) { - const _Ty _Arcbig = static_cast<_Ty>(0.25) * _Ctraits<_Ty>::sqrt(_Ctraits<_Ty>::_Flt_max()); - constexpr _Ty _Pi = static_cast<_Ty>(3.1415926535897932384626433832795029L); + const _Ty _Arcbig = static_cast<_Ty>(0.25) * _Ctraits<_Ty>::sqrt(_Ctraits<_Ty>::_Flt_max()); + constexpr _Ty _Pi_val = static_cast<_Ty>(3.1415926535897932384626433832795029L); const _Ty _Re = real(_Left); const _Ty _Im = imag(_Left); @@ -1545,18 +1545,18 @@ _NODISCARD complex<_Ty> acos(const complex<_Ty>& _Left) { } else if (_Ctraits<_Ty>::_Isinf(_Re)) { // (+/-Inf, not NaN) if (_Ctraits<_Ty>::_Isinf(_Im)) { if (_Re < 0) { - _Ux = static_cast<_Ty>(0.75) * _Pi; // (-Inf, +/-Inf) + _Ux = static_cast<_Ty>(0.75) * _Pi_val; // (-Inf, +/-Inf) } else { - _Ux = static_cast<_Ty>(0.25) * _Pi; // (+Inf, +/-Inf) + _Ux = static_cast<_Ty>(0.25) * _Pi_val; // (+Inf, +/-Inf) } } else if (_Re < 0) { - _Ux = _Pi; // (-Inf, finite) + _Ux = _Pi_val; // (-Inf, finite) } else { _Ux = 0; // (+Inf, finite) } _Vx = -_Ctraits<_Ty>::_Copysign(_Ctraits<_Ty>::_Infv(), _Im); } else if (_Ctraits<_Ty>::_Isinf(_Im)) { // (finite, finite) - _Ux = static_cast<_Ty>(0.50) * _Pi; // (finite, +/-Inf) + _Ux = static_cast<_Ty>(0.50) * _Pi_val; // (finite, +/-Inf) _Vx = -_Im; } else { // (finite, finite) const complex<_Ty> _Wx = sqrt(complex<_Ty>(1 + _Re, -_Im)); @@ -1598,8 +1598,8 @@ _NODISCARD complex<_Ty> acos(const complex<_Ty>& _Left) { _EXPORT_STD template _NODISCARD complex<_Ty> acosh(const complex<_Ty>& _Left) { - const _Ty _Arcbig = static_cast<_Ty>(0.25) * _Ctraits<_Ty>::sqrt(_Ctraits<_Ty>::_Flt_max()); - constexpr _Ty _Pi = static_cast<_Ty>(3.1415926535897932384626433832795029L); + const _Ty _Arcbig = static_cast<_Ty>(0.25) * _Ctraits<_Ty>::sqrt(_Ctraits<_Ty>::_Flt_max()); + constexpr _Ty _Pi_val = static_cast<_Ty>(3.1415926535897932384626433832795029L); const _Ty _Re = real(_Left); _Ty _Im = imag(_Left); @@ -1614,12 +1614,12 @@ _NODISCARD complex<_Ty> acosh(const complex<_Ty>& _Left) { if (_Ctraits<_Ty>::_Isinf(_Im)) { if (_Re < 0) { - _Vx = static_cast<_Ty>(0.75) * _Pi; // (-Inf, +/-Inf) + _Vx = static_cast<_Ty>(0.75) * _Pi_val; // (-Inf, +/-Inf) } else { - _Vx = static_cast<_Ty>(0.25) * _Pi; // (+Inf, +/-Inf) + _Vx = static_cast<_Ty>(0.25) * _Pi_val; // (+Inf, +/-Inf) } } else if (_Re < 0) { - _Vx = _Pi; // (-Inf, finite) + _Vx = _Pi_val; // (-Inf, finite) } else { _Vx = 0; // (+Inf, finite) } @@ -1627,7 +1627,7 @@ _NODISCARD complex<_Ty> acosh(const complex<_Ty>& _Left) { _Vx = _Ctraits<_Ty>::_Copysign(_Vx, _Im); } else if (_Ctraits<_Ty>::_Isinf(_Im)) { // (finite, +/-Inf) _Ux = _Ctraits<_Ty>::_Infv(); - _Vx = _Ctraits<_Ty>::_Copysign(static_cast<_Ty>(0.50) * _Pi, _Im); + _Vx = _Ctraits<_Ty>::_Copysign(static_cast<_Ty>(0.50) * _Pi_val, _Im); } else { // (finite, finite) const complex<_Ty> _Wx = sqrt(complex<_Ty>(_Re - 1, -_Im)); const complex<_Ty> _Zx = sqrt(complex<_Ty>(_Re + 1, _Im)); @@ -1668,8 +1668,8 @@ _NODISCARD complex<_Ty> acosh(const complex<_Ty>& _Left) { _EXPORT_STD template _NODISCARD complex<_Ty> asinh(const complex<_Ty>& _Left) { - const _Ty _Arcbig = static_cast<_Ty>(0.25) * _Ctraits<_Ty>::sqrt(_Ctraits<_Ty>::_Flt_max()); - constexpr _Ty _Pi = static_cast<_Ty>(3.1415926535897932384626433832795029L); + const _Ty _Arcbig = static_cast<_Ty>(0.25) * _Ctraits<_Ty>::sqrt(_Ctraits<_Ty>::_Flt_max()); + constexpr _Ty _Pi_val = static_cast<_Ty>(3.1415926535897932384626433832795029L); const _Ty _Re = real(_Left); _Ty _Im = imag(_Left); @@ -1684,14 +1684,14 @@ _NODISCARD complex<_Ty> asinh(const complex<_Ty>& _Left) { if (_Ctraits<_Ty>::_Isinf(_Im)) { // (+/-Inf, +/-Inf) _Ux = _Re; - _Vx = _Ctraits<_Ty>::_Copysign(static_cast<_Ty>(0.25) * _Pi, _Im); + _Vx = _Ctraits<_Ty>::_Copysign(static_cast<_Ty>(0.25) * _Pi_val, _Im); } else { // (+/-Inf, finite) _Ux = _Re; _Vx = _Ctraits<_Ty>::_Copysign(_Ty{0}, _Im); } } else if (_Ctraits<_Ty>::_Isinf(_Im)) { // (finite, +/-Inf) _Ux = _Ctraits<_Ty>::_Copysign(_Ctraits<_Ty>::_Infv(), _Re); - _Vx = _Ctraits<_Ty>::_Copysign(static_cast<_Ty>(0.50) * _Pi, _Im); + _Vx = _Ctraits<_Ty>::_Copysign(static_cast<_Ty>(0.50) * _Pi_val, _Im); } else { // (finite, finite) const complex<_Ty> _Wx = sqrt(complex<_Ty>(1 - _Im, _Re)); const complex<_Ty> _Zx = sqrt(complex<_Ty>(1 + _Im, -_Re)); diff --git a/stl/inc/deque b/stl/inc/deque index 2eb29ec475d..9eb2cfd6f44 100644 --- a/stl/inc/deque +++ b/stl/inc/deque @@ -1316,7 +1316,7 @@ private: } }; - enum class _Is_bidi : bool { _No, _Yes }; + enum class _Is_bidi : bool { _Nope, _Yes }; template <_Is_bidi _Bidi, class _Iter, class _Sent> iterator _Insert_range(const size_type _Off, _Iter _First, _Sent _Last) { @@ -1352,7 +1352,7 @@ private: const auto _Num = static_cast(_Mysize() - _Oldsize); const auto _Myfirst = _Unchecked_begin(); const auto _Mymid = _Myfirst + _Num; - if constexpr (_Bidi == _Is_bidi::_No) { + if constexpr (_Bidi == _Is_bidi::_Nope) { _STD reverse(_Myfirst, _Mymid); // flip new stuff in place } _STD rotate(_Myfirst, _Mymid, _Mymid + static_cast(_Off)); @@ -1392,7 +1392,7 @@ public: return _Insert_range<_Is_bidi::_Yes>( _Off, _RANGES _Ubegin(_Range), _RANGES _Get_final_iterator_unwrapped(_Range)); } else { - return _Insert_range<_Is_bidi::_No>(_Off, _RANGES _Ubegin(_Range), _RANGES _Uend(_Range)); + return _Insert_range<_Is_bidi::_Nope>(_Off, _RANGES _Ubegin(_Range), _RANGES _Uend(_Range)); } } #endif // _HAS_CXX23 && defined(__cpp_lib_concepts) diff --git a/stl/inc/mutex b/stl/inc/mutex index ed72ac0834a..a17c022650c 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -49,7 +49,7 @@ struct _Mtx_internal_imp_mirror { static constexpr size_t _Critical_section_align = alignof(void*); int _Type; - _Aligned_storage_t<_Critical_section_size, _Critical_section_align> _Cs; + _Aligned_storage_t<_Critical_section_size, _Critical_section_align> _Cs_storage; long _Thread_id; int _Count; }; diff --git a/stl/inc/random b/stl/inc/random index 6960de75eb3..d892acd566e 100644 --- a/stl/inc/random +++ b/stl/inc/random @@ -61,10 +61,10 @@ using _Enable_if_seed_seq_t = && !is_same_v, _Self> && !is_same_v, _Engine>, int>; -_INLINE_VAR constexpr long double _Pi = 3.14159265358979323846264338327950288L; -_INLINE_VAR constexpr long double _Exp1 = 2.71828182845904523536028747135266250L; -_INLINE_VAR constexpr long double _Two32 = 4294967296.0L; -_INLINE_VAR constexpr long double _Two31 = 2147483648.0L; +_INLINE_VAR constexpr long double _Pi_val = 3.14159265358979323846264338327950288L; +_INLINE_VAR constexpr long double _Exp1 = 2.71828182845904523536028747135266250L; +_INLINE_VAR constexpr long double _Two32 = 4294967296.0L; +_INLINE_VAR constexpr long double _Two31 = 2147483648.0L; extern "C++" _CRTIMP2_PURE float __CLRCALL_PURE_OR_CDECL _XLgamma(float); extern "C++" _CRTIMP2_PURE double __CLRCALL_PURE_OR_CDECL _XLgamma(double); @@ -2466,7 +2466,7 @@ private: _Ty _Res; _Ty1 _Yx; for (;;) { // generate a tentative value - _Yx = static_cast<_Ty1>(_CSTD tan(_Pi * _NRAND(_Eng, _Ty1))); + _Yx = static_cast<_Ty1>(_CSTD tan(_Pi_val * _NRAND(_Eng, _Ty1))); const _Ty1 _Mx{_Par0._Sqrt * _Yx + _Par0._Mean}; if (0.0 <= _Mx && _Mx < _Ty1_max) { _Res = static_cast<_Ty>(_Mx); @@ -2661,7 +2661,7 @@ private: for (;;) { // generate and reject _Ty1 _Yx; for (;;) { // generate a tentative value - _Yx = static_cast<_Ty1>(_CSTD tan(_Pi * _NRAND(_Eng, _Ty1))); + _Yx = static_cast<_Ty1>(_CSTD tan(_Pi_val * _NRAND(_Eng, _Ty1))); const _Ty1 _Mx{_Par0._Sqrt * _Yx + _Par0._Mean}; if (0.0 <= _Mx && _Mx < _Ty1_Tx) { _Res = static_cast<_Ty>(_Mx); @@ -3317,7 +3317,7 @@ private: // no shortcuts for (;;) { // generate and reject - _Yx = static_cast<_Ty>(_CSTD tan(_Pi * _NRAND(_Eng, _Ty))); + _Yx = static_cast<_Ty>(_CSTD tan(_Pi_val * _NRAND(_Eng, _Ty))); _Xx = _Par0._Sqrt * _Yx + _Par0._Alpha - 1; if (0 < _Xx && _NRAND(_Eng, _Ty) <= (1 + _Yx * _Yx) @@ -3949,7 +3949,7 @@ private: template result_type _Eval(_Engine& _Eng, const param_type& _Par0) const { // generate pseudo-random value _Ty Px = _NRAND(_Eng, _Ty); - return static_cast<_Ty>(_Par0._Ax + _Par0._Bx * _CSTD tan(_Pi * (Px - static_cast<_Ty>(0.5)))); + return static_cast<_Ty>(_Par0._Ax + _Par0._Bx * _CSTD tan(_Pi_val * (Px - static_cast<_Ty>(0.5)))); } param_type _Par; diff --git a/stl/inc/regex b/stl/inc/regex index bb831fa32c2..a370a56c0b9 100644 --- a/stl/inc/regex +++ b/stl/inc/regex @@ -1486,8 +1486,8 @@ struct _Loop_vals_t { // storage for loop administration class _Node_rep : public _Node_base { // node that marks the beginning of a repetition public: - _Node_rep(bool _Greedy, int _Mn, int _Mx, _Node_end_rep* _End, unsigned int _Number) - : _Node_base(_N_rep, _Greedy ? _Fl_greedy : _Fl_none), _Min(_Mn), _Max(_Mx), _End_rep(_End), + _Node_rep(bool _Greedy, int _Min_, int _Max_, _Node_end_rep* _End, unsigned int _Number) + : _Node_base(_N_rep, _Greedy ? _Fl_greedy : _Fl_none), _Min(_Min_), _Max(_Max_), _End_rep(_End), _Loop_number(_Number), _Simple_loop(-1) {} const int _Min; From ac138a5a89119836ac84ef539d8d51e94a270e73 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Fri, 23 Jun 2023 02:54:25 +0800 Subject: [PATCH 04/35] Don't include `` in `` (#3777) --- stl/inc/xutility | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index 0e7933c44ad..681fb49c0bc 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -14,10 +14,6 @@ #include #include -#if _HAS_CXX23 -#include -#endif // _HAS_CXX23 - #pragma pack(push, _CRT_PACKING) #pragma warning(push, _STL_WARNING_LEVEL) #pragma warning(disable : _STL_DISABLED_WARNINGS) @@ -7179,7 +7175,9 @@ _NODISCARD constexpr bool _Mul_overflow(const _Int _Left, const _Int _Right, _In #endif // __clang__ { if constexpr (!_Signed_integer_like<_Int>) { - const bool _Overflow = _Left != 0 && _Right > (numeric_limits<_Int>::max)() / _Left; + // use instead of numeric_limits::max; avoid dependency + constexpr auto _UInt_max = static_cast<_Int>(-1); + const bool _Overflow = _Left != 0 && _Right > _UInt_max / _Left; if (!_Overflow) { _Out = static_cast<_Int>(_Left * _Right); } @@ -7207,10 +7205,12 @@ _NODISCARD constexpr bool _Mul_overflow(const _Int _Left, const _Int _Right, _In return false; } + // use instead of numeric_limits::max; avoid dependency + constexpr auto _Int_max = static_cast<_UInt>(static_cast<_UInt>(-1) / 2); if (_Negative) { - return _ULeft > (static_cast<_UInt>((numeric_limits<_Int>::max)()) + _UInt{1}) / _URight; + return _ULeft > (_Int_max + _UInt{1}) / _URight; } else { - return _ULeft > static_cast<_UInt>((numeric_limits<_Int>::max)()) / _URight; + return _ULeft > _Int_max / _URight; } // ^^^ Based on llvm::MulOverflow ^^^ } From 1b532befbb365336747a2da2f97425cf0603e9b1 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Fri, 23 Jun 2023 02:55:42 +0800 Subject: [PATCH 05/35] Implement LWG-3904 lazy_split_view::outer-iterator's const-converting constructor isn't setting trailing_empty_ (#3781) --- stl/inc/ranges | 2 +- tests/std/tests/P0896R4_views_lazy_split/test.cpp | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index 753272269d1..a9fa0e88f6e 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -4596,7 +4596,7 @@ namespace ranges { constexpr _Outer_iter(_Outer_iter _It) requires _Const && convertible_to, iterator_t<_BaseTy>> - : _Mybase{_STD move(_It._Current)}, _Parent{_It._Parent} {} + : _Mybase{_STD move(_It._Current)}, _Parent{_It._Parent}, _Trailing_empty{_It._Trailing_empty} {} _NODISCARD constexpr auto operator*() const noexcept(noexcept(value_type{*this})) /* strengthened */ { return value_type{*this}; diff --git a/tests/std/tests/P0896R4_views_lazy_split/test.cpp b/tests/std/tests/P0896R4_views_lazy_split/test.cpp index 55a785f3e23..9616e3eb214 100644 --- a/tests/std/tests/P0896R4_views_lazy_split/test.cpp +++ b/tests/std/tests/P0896R4_views_lazy_split/test.cpp @@ -337,7 +337,18 @@ constexpr bool instantiation_test() { return true; } +constexpr bool test_lwg_3904() { + auto r = views::single(0) | views::lazy_split(0); + auto i = r.begin(); + ++i; + decltype(as_const(r).begin()) j = i; + return j != r.end(); +} + int main() { STATIC_ASSERT(instantiation_test()); instantiation_test(); + + STATIC_ASSERT(test_lwg_3904()); + assert(test_lwg_3904()); } From 9a85476a8362d512c484263aa0a7b1cf4f297684 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Fri, 23 Jun 2023 02:56:40 +0800 Subject: [PATCH 06/35] Implement LWG-3893 LWG-3661 broke `atomic> a; a = nullptr;` (#3782) --- stl/inc/memory | 4 ++++ tests/std/tests/P0718R2_atomic_smart_ptrs/test.cpp | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/stl/inc/memory b/stl/inc/memory index 00a358493d1..5ed5de5528f 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -4003,6 +4003,10 @@ public: store(_STD move(_Value)); } + void operator=(nullptr_t) noexcept { + store(nullptr); + } + ~atomic() { const auto _Rep = this->_Repptr._Unsafe_load_relaxed(); if (_Rep) { diff --git a/tests/std/tests/P0718R2_atomic_smart_ptrs/test.cpp b/tests/std/tests/P0718R2_atomic_smart_ptrs/test.cpp index 710a09a4545..0150911878d 100644 --- a/tests/std/tests/P0718R2_atomic_smart_ptrs/test.cpp +++ b/tests/std/tests/P0718R2_atomic_smart_ptrs/test.cpp @@ -2,9 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include +#include #include #include #include +#include #ifdef _DEBUG #include #endif // _DEBUG @@ -632,6 +634,13 @@ int main() { ensure_member_calls_compile>>(); ensure_member_calls_compile>>(); + // LWG-3893: LWG 3661 broke atomic> a; a = nullptr; + static_assert(is_nothrow_assignable_v>, nullptr_t>); + static_assert(is_nothrow_assignable_v>, nullptr_t>); + static_assert(is_nothrow_assignable_v>, nullptr_t>); + static_assert(is_nothrow_assignable_v>, nullptr_t>); + static_assert(is_nothrow_assignable_v>, nullptr_t>); + #ifdef _DEBUG sptr0 = {}; sptr1 = {}; From 9e073711cb8db4ca6a59a06ab3943d8e14e689fc Mon Sep 17 00:00:00 2001 From: Jacob Ogle <123908271+JacobOgle@users.noreply.github.com> Date: Thu, 22 Jun 2023 14:57:35 -0400 Subject: [PATCH 07/35] Documentation Fix for #3780 (#3784) --- stl/inc/ranges | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index a9fa0e88f6e..76f11b526bd 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -6124,7 +6124,7 @@ namespace ranges { } _NODISCARD_FRIEND constexpr difference_type operator-( - const _Iterator& _Left, const _Iterator& _Right) noexcept /* strengthened */ { + const _Iterator& _Left, const _Iterator& _Right) noexcept { return _Left._Pos - _Right._Pos; } From f6d61a857c40afde9777ce6b0c93c36bf42c802c Mon Sep 17 00:00:00 2001 From: Ashad <93534298+Ashad001@users.noreply.github.com> Date: Thu, 22 Jun 2023 23:58:42 +0500 Subject: [PATCH 08/35] Documentation fix for #3779 (#3785) --- stl/inc/expected | 1 - tests/libcxx/expected_results.txt | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index 4156fbf52db..ce22ebf67ed 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -1423,7 +1423,6 @@ public: } } constexpr void value() && { - // per LWG-3940 // TRANSITION, DevCom-1638273 and LLVM-53224 static_assert(is_copy_constructible_v<_Err>, "is_copy_constructible_v must be true"); static_assert(is_move_constructible_v<_Err>, "is_move_constructible_v must be true"); diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 4c39a78d079..e0f46e6c3ef 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -155,7 +155,7 @@ std/utilities/memory/specialized.algorithms/uninitialized.fill.n/ranges_uninitia std/utilities/memory/specialized.algorithms/uninitialized.move/ranges_uninitialized_move.pass.cpp FAIL std/utilities/memory/specialized.algorithms/uninitialized.move/ranges_uninitialized_move_n.pass.cpp FAIL -# libc++ doesn't speculatively implement LWG-3940 +# libc++ doesn't implement LWG-3940 std/utilities/expected/expected.void/observers/value.pass.cpp FAIL # libc++ doesn't implement P1957R2 "Converting from `T*` to `bool` should be considered narrowing" From 4768199ec14bc15eca670856965b930cf1f1a1b4 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Fri, 23 Jun 2023 02:59:59 +0800 Subject: [PATCH 09/35] ``: Move the major part of `visit_format_arg` into a member function of `basic_format_arg` (#3787) --- stl/inc/format | 75 ++++++++++--------- .../P0645R10_text_formatting_args/test.cpp | 16 ++++ 2 files changed, 55 insertions(+), 36 deletions(-) diff --git a/stl/inc/format b/stl/inc/format index 56f5b11bb6c..3f673b2f8a1 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -745,10 +745,45 @@ public: } } -private: - template - friend decltype(auto) visit_format_arg(_Visitor&&, basic_format_arg<_Ctx>); + template + decltype(auto) _Visit(_Visitor&& _Vis) { + switch (_Active_state) { + case _Basic_format_arg_type::_None: + return _STD forward<_Visitor>(_Vis)(_No_state); + case _Basic_format_arg_type::_Int_type: + return _STD forward<_Visitor>(_Vis)(_Int_state); + case _Basic_format_arg_type::_UInt_type: + return _STD forward<_Visitor>(_Vis)(_UInt_state); + case _Basic_format_arg_type::_Long_long_type: + return _STD forward<_Visitor>(_Vis)(_Long_long_state); + case _Basic_format_arg_type::_ULong_long_type: + return _STD forward<_Visitor>(_Vis)(_ULong_long_state); + case _Basic_format_arg_type::_Bool_type: + return _STD forward<_Visitor>(_Vis)(_Bool_state); + case _Basic_format_arg_type::_Char_type: + return _STD forward<_Visitor>(_Vis)(_Char_state); + case _Basic_format_arg_type::_Float_type: + return _STD forward<_Visitor>(_Vis)(_Float_state); + case _Basic_format_arg_type::_Double_type: + return _STD forward<_Visitor>(_Vis)(_Double_state); + case _Basic_format_arg_type::_Long_double_type: + return _STD forward<_Visitor>(_Vis)(_Long_double_state); + case _Basic_format_arg_type::_Pointer_type: + return _STD forward<_Visitor>(_Vis)(_Pointer_state); + case _Basic_format_arg_type::_CString_type: + return _STD forward<_Visitor>(_Vis)(_CString_state); + case _Basic_format_arg_type::_String_type: + return _STD forward<_Visitor>(_Vis)(_String_state); + case _Basic_format_arg_type::_Custom_type: + return _STD forward<_Visitor>(_Vis)(_Custom_state); + default: + _STL_VERIFY(false, "basic_format_arg is in impossible state"); + int _Dummy{}; + return _STD forward<_Visitor>(_Vis)(_Dummy); + } + } +private: friend basic_format_args<_Context>; friend _Format_handler<_CharType>; friend _Format_arg_traits<_Context>; @@ -838,39 +873,7 @@ auto _Format_arg_traits<_Context>::_Type_eraser() { _EXPORT_STD template decltype(auto) visit_format_arg(_Visitor&& _Vis, basic_format_arg<_Context> _Arg) { - switch (_Arg._Active_state) { - case _Basic_format_arg_type::_None: - return _STD forward<_Visitor>(_Vis)(_Arg._No_state); - case _Basic_format_arg_type::_Int_type: - return _STD forward<_Visitor>(_Vis)(_Arg._Int_state); - case _Basic_format_arg_type::_UInt_type: - return _STD forward<_Visitor>(_Vis)(_Arg._UInt_state); - case _Basic_format_arg_type::_Long_long_type: - return _STD forward<_Visitor>(_Vis)(_Arg._Long_long_state); - case _Basic_format_arg_type::_ULong_long_type: - return _STD forward<_Visitor>(_Vis)(_Arg._ULong_long_state); - case _Basic_format_arg_type::_Bool_type: - return _STD forward<_Visitor>(_Vis)(_Arg._Bool_state); - case _Basic_format_arg_type::_Char_type: - return _STD forward<_Visitor>(_Vis)(_Arg._Char_state); - case _Basic_format_arg_type::_Float_type: - return _STD forward<_Visitor>(_Vis)(_Arg._Float_state); - case _Basic_format_arg_type::_Double_type: - return _STD forward<_Visitor>(_Vis)(_Arg._Double_state); - case _Basic_format_arg_type::_Long_double_type: - return _STD forward<_Visitor>(_Vis)(_Arg._Long_double_state); - case _Basic_format_arg_type::_Pointer_type: - return _STD forward<_Visitor>(_Vis)(_Arg._Pointer_state); - case _Basic_format_arg_type::_CString_type: - return _STD forward<_Visitor>(_Vis)(_Arg._CString_state); - case _Basic_format_arg_type::_String_type: - return _STD forward<_Visitor>(_Vis)(_Arg._String_state); - case _Basic_format_arg_type::_Custom_type: - return _STD forward<_Visitor>(_Vis)(_Arg._Custom_state); - default: - _STL_VERIFY(false, "basic_format_arg is in impossible state"); - return _STD forward<_Visitor>(_Vis)(0); - } + return _Arg._Visit(_STD forward<_Visitor>(_Vis)); } // we need to implement this ourselves because from_chars does not work with wide characters and isn't constexpr diff --git a/tests/std/tests/P0645R10_text_formatting_args/test.cpp b/tests/std/tests/P0645R10_text_formatting_args/test.cpp index 98802790b38..24ceead553d 100644 --- a/tests/std/tests/P0645R10_text_formatting_args/test.cpp +++ b/tests/std/tests/P0645R10_text_formatting_args/test.cpp @@ -252,6 +252,18 @@ void test_lwg3810() { static_assert(same_as>); } +struct lvalue_only_visitor { + template + void operator()(T&&) const = delete; + template + void operator()(T&) const noexcept {} +}; + +template +void test_lvalue_only_visitation() { + visit_format_arg(lvalue_only_visitor{}, basic_format_arg{}); +} + int main() { test_basic_format_arg(); test_basic_format_arg(); @@ -259,6 +271,10 @@ int main() { test_format_arg_store(); test_visit_monostate(); test_visit_monostate(); + test_lwg3810(); test_lwg3810(); + + test_lvalue_only_visitation(); + test_lvalue_only_visitation(); } From 057adf2b6fd2979094913d87399030938041b78c Mon Sep 17 00:00:00 2001 From: achabense <60953653+achabense@users.noreply.github.com> Date: Fri, 23 Jun 2023 03:00:45 +0800 Subject: [PATCH 10/35] ``: fix `std::format("{:#.precision}", floating)` (#3815) Co-authored-by: A. Jiang Co-authored-by: Stephan T. Lavavej --- stl/inc/format | 10 +++--- tests/libcxx/expected_results.txt | 4 --- tests/std/test.lst | 1 + .../GH_003003_format_decimal_point/env.lst | 4 +++ .../GH_003003_format_decimal_point/test.cpp | 33 +++++++++++++++++++ 5 files changed, 42 insertions(+), 10 deletions(-) create mode 100644 tests/std/tests/GH_003003_format_decimal_point/env.lst create mode 100644 tests/std/tests/GH_003003_format_decimal_point/test.cpp diff --git a/stl/inc/format b/stl/inc/format index 3f673b2f8a1..1ed63d4ec7d 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -2867,7 +2867,7 @@ _NODISCARD _OutputIt _Fmt_write( auto _To_upper = false; auto _Format = chars_format::general; - auto _Exponent = '\0'; + auto _Exponent = 'e'; auto _Precision = _Specs._Precision; switch (_Specs._Type) { @@ -2885,8 +2885,7 @@ _NODISCARD _OutputIt _Fmt_write( if (_Precision == -1) { _Precision = 6; } - _Format = chars_format::scientific; - _Exponent = 'e'; + _Format = chars_format::scientific; break; case 'F': _To_upper = true; @@ -2904,8 +2903,7 @@ _NODISCARD _OutputIt _Fmt_write( if (_Precision == -1) { _Precision = 6; } - _Format = chars_format::general; - _Exponent = 'e'; + _Format = chars_format::general; break; } @@ -3018,7 +3016,7 @@ _NODISCARD _OutputIt _Fmt_write( _Zeroes_to_append = _Extra_precision; break; case chars_format::general: - if (_Specs._Alt) { + if (_Specs._Alt && (_Specs._Type == 'g' || _Specs._Type == 'G')) { auto _Digits = static_cast(_Exponent_start - _Buffer_start); if (!_Append_decimal) { diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index e0f46e6c3ef..a815353ffd2 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -1062,11 +1062,7 @@ std/ranges/range.adaptors/range.take/adaptor.pass.cpp FAIL std/ranges/range.factories/range.single.view/cpo.pass.cpp FAIL std/thread/futures/futures.task/futures.task.members/ctor2.compile.pass.cpp FAIL std/utilities/format/format.functions/escaped_output.ascii.pass.cpp FAIL -std/utilities/format/format.functions/format.locale.pass.cpp FAIL -std/utilities/format/format.functions/format.pass.cpp FAIL std/utilities/format/format.functions/locale-specific_form.pass.cpp FAIL -std/utilities/format/format.functions/vformat.locale.pass.cpp FAIL -std/utilities/format/format.functions/vformat.pass.cpp FAIL std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/ctad.static.compile.pass.cpp FAIL std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.inv/invoke.pass.cpp:0 FAIL std/utilities/function.objects/refwrap/refwrap.const/type_conv_ctor.pass.cpp:0 FAIL diff --git a/tests/std/test.lst b/tests/std/test.lst index 094f4c7d4fe..b6511acf8b0 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -218,6 +218,7 @@ tests\GH_002769_handle_deque_block_pointers tests\GH_002789_Hash_vec_Tidy tests\GH_002989_nothrow_unwrappable tests\GH_002992_unwrappable_iter_sent_pairs +tests\GH_003003_format_decimal_point tests\GH_003022_substr_allocator tests\GH_003105_piecewise_densities tests\GH_003119_error_category_ctor diff --git a/tests/std/tests/GH_003003_format_decimal_point/env.lst b/tests/std/tests/GH_003003_format_decimal_point/env.lst new file mode 100644 index 00000000000..d6d824b5879 --- /dev/null +++ b/tests/std/tests/GH_003003_format_decimal_point/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\concepts_20_matrix.lst diff --git a/tests/std/tests/GH_003003_format_decimal_point/test.cpp b/tests/std/tests/GH_003003_format_decimal_point/test.cpp new file mode 100644 index 00000000000..1b5d1e99f92 --- /dev/null +++ b/tests/std/tests/GH_003003_format_decimal_point/test.cpp @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include + +int main() { + assert(std::format("{:#.0}", 0.0) == "0."); + assert(std::format("{:#.1}", 0.0) == "0."); + assert(std::format("{:#.2}", 0.0) == "0."); + + assert(std::format("{:#.0}", 1200.0) == "1.e+03"); + assert(std::format("{:#.1}", 1200.0) == "1.e+03"); + assert(std::format("{:#.2}", 1200.0) == "1.2e+03"); + assert(std::format("{:#.3}", 1200.0) == "1.2e+03"); + assert(std::format("{:#.4}", 1200.0) == "1200."); + assert(std::format("{:#.5}", 1200.0) == "1200."); + assert(std::format("{:#.6}", 1200.0) == "1200."); + + assert(std::format("{:#.0}", 0.123) == "0.1"); + assert(std::format("{:#.1}", 0.123) == "0.1"); + assert(std::format("{:#.2}", 0.123) == "0.12"); + assert(std::format("{:#.3}", 0.123) == "0.123"); + assert(std::format("{:#.4}", 0.123) == "0.123"); + assert(std::format("{:#.5}", 0.123) == "0.123"); + + assert(std::format("{:#.0}", 10.1) == "1.e+01"); + assert(std::format("{:#.1}", 10.1) == "1.e+01"); + assert(std::format("{:#.2}", 10.1) == "10."); + assert(std::format("{:#.3}", 10.1) == "10.1"); + assert(std::format("{:#.4}", 10.1) == "10.1"); + assert(std::format("{:#.5}", 10.1) == "10.1"); +} From c5f19602c8aeae8acd7a3e6c1d804b086aae5316 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 22 Jun 2023 12:01:28 -0700 Subject: [PATCH 11/35] Standard Library Modules: Add workaround for `` `/utf-8` (#3816) --- stl/inc/ostream | 2 +- tests/std/tests/P2465R3_standard_library_modules/env.lst | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/stl/inc/ostream b/stl/inc/ostream index 6658a75d81e..beef34bae1e 100644 --- a/stl/inc/ostream +++ b/stl/inc/ostream @@ -1126,7 +1126,7 @@ void _Vprint_nonunicode_impl( _Ostr.setstate(_State); } -template +_EXPORT_STD /* TRANSITION, VSO-1538698 */ template ios_base::iostate _Print_noformat_unicode(ostream& _Ostr, const string_view _Str) { // *LOCKED* // diff --git a/tests/std/tests/P2465R3_standard_library_modules/env.lst b/tests/std/tests/P2465R3_standard_library_modules/env.lst index bce5b396773..759f0d18023 100644 --- a/tests/std/tests/P2465R3_standard_library_modules/env.lst +++ b/tests/std/tests/P2465R3_standard_library_modules/env.lst @@ -15,3 +15,4 @@ PM_CL="/MT" PM_CL="/MTd" PM_CL="/MDd /analyze:only /analyze:autolog-" PM_CL="/MDd /GR- /D_HAS_STATIC_RTTI=0" +PM_CL="/MDd /utf-8" From 40640c6df9754ea031f8df7c720b89714d19df97 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Thu, 22 Jun 2023 17:37:44 -0700 Subject: [PATCH 12/35] Deallocate at least (#3819) Co-authored-by: Stephan T. Lavavej --- stl/inc/deque | 5 +- stl/inc/sstream | 9 +- stl/inc/syncstream | 13 +-- stl/inc/vector | 60 +++++----- stl/inc/xmemory | 12 -- stl/inc/xstring | 61 ++++------ tests/std/test.lst | 1 - .../tests/GH_003570_allocate_at_least/env.lst | 4 - .../GH_003570_allocate_at_least/test.cpp | 104 ------------------ 9 files changed, 59 insertions(+), 210 deletions(-) delete mode 100644 tests/std/tests/GH_003570_allocate_at_least/env.lst delete mode 100644 tests/std/tests/GH_003570_allocate_at_least/test.cpp diff --git a/stl/inc/deque b/stl/inc/deque index 9eb2cfd6f44..80b4571d1a2 100644 --- a/stl/inc/deque +++ b/stl/inc/deque @@ -1557,13 +1557,12 @@ private: _Newsize *= 2; } + _Count = _Newsize - _Mapsize(); size_type _Myboff = _Myoff() / _Block_size; - _Mapptr _Newmap = _Allocate_at_least_helper(_Almap, _Newsize); + _Mapptr _Newmap = _Almap.allocate(_Mapsize() + _Count); _Mapptr _Myptr = _Newmap + _Myboff; - _Count = _Newsize - _Mapsize(); - _Myptr = _STD uninitialized_copy(_Map() + _Myboff, _Map() + _Mapsize(), _Myptr); // copy initial to end if (_Myboff <= _Count) { // increment greater than offset of initial block _Myptr = _STD uninitialized_copy(_Map(), _Map() + _Myboff, _Myptr); // copy rest of old diff --git a/stl/inc/sstream b/stl/inc/sstream index 222dd025793..15584a80853 100644 --- a/stl/inc/sstream +++ b/stl/inc/sstream @@ -261,7 +261,7 @@ protected: return _Traits::eof(); } - const auto _Newptr = _Unfancy(_Allocate_at_least_helper(_Al, _Newsize)); + const auto _Newptr = _Unfancy(_Al.allocate(_Newsize)); _Traits::copy(_Newptr, _Oldptr, _Oldsize); const auto _New_pnext = _Newptr + _Oldsize; @@ -430,7 +430,7 @@ protected: return pos_type{_Off}; } - void _Init(const _Elem* _Ptr, const _Mysize_type _Count, int _State) { + void _Init(const _Elem* _Ptr, _Mysize_type _Count, int _State) { // initialize buffer to [_Ptr, _Ptr + _Count), set state _State &= ~_From_rvalue; @@ -440,10 +440,9 @@ protected: if (_Count != 0 && (_State & (_Noread | _Constant)) != (_Noread | _Constant)) { // finite buffer that can be read or written, set it up - _Mysize_type _Newsize = _Count; - const auto _Pnew = _Unfancy(_Allocate_at_least_helper(_Al, _Newsize)); + const auto _Pnew = _Unfancy(_Al.allocate(_Count)); _Traits::copy(_Pnew, _Ptr, _Count); - _Seekhigh = _Pnew + _Newsize; + _Seekhigh = _Pnew + _Count; if (!(_State & _Noread)) { _Mysb::setg(_Pnew, _Pnew, _Seekhigh); // setup read buffer diff --git a/stl/inc/syncstream b/stl/inc/syncstream index 969d756a051..ec106eeff8a 100644 --- a/stl/inc/syncstream +++ b/stl/inc/syncstream @@ -120,10 +120,10 @@ public: if (_Al != _Right_al) { _Tidy(); - _Size_type _Right_buf_size = _Right._Get_buffer_size(); + const _Size_type _Right_buf_size = _Right._Get_buffer_size(); const _Size_type _Right_data_size = _Right._Get_data_size(); - _Elem* const _New_ptr = _Unfancy(_Allocate_at_least_helper(_Al, _Right_buf_size)); + _Elem* const _New_ptr = _Unfancy(_Al.allocate(_Right_buf_size)); _Traits::copy(_New_ptr, _Right.pbase(), _Right_data_size); streambuf_type::setp(_New_ptr, _New_ptr + _Right_data_size, _New_ptr + _Right_buf_size); @@ -217,11 +217,11 @@ protected: return _Traits::eof(); } - _Size_type _New_capacity = _Calculate_growth(_Buf_size, _Buf_size + 1, _Max_allocation); + const _Size_type _New_capacity = _Calculate_growth(_Buf_size, _Buf_size + 1, _Max_allocation); _Elem* const _Old_ptr = streambuf_type::pbase(); const _Size_type _Old_data_size = _Get_data_size(); - _Elem* const _New_ptr = _Unfancy(_Allocate_at_least_helper(_Al, _New_capacity)); + _Elem* const _New_ptr = _Unfancy(_Al.allocate(_New_capacity)); _Traits::copy(_New_ptr, _Old_ptr, _Old_data_size); if (0 < _Buf_size) { _Al.deallocate(_Refancy<_Pointer>(_Old_ptr), _Buf_size); @@ -237,9 +237,8 @@ private: static constexpr _Size_type _Min_size = 32; // constant for minimum buffer size void _Init() { - _Size_type _New_capacity = _Min_size; - _Elem* const _New_ptr = _Unfancy(_Allocate_at_least_helper(_Getal(), _New_capacity)); - streambuf_type::setp(_New_ptr, _New_ptr + _New_capacity); + _Elem* const _New_ptr = _Unfancy(_Getal().allocate(_Min_size)); + streambuf_type::setp(_New_ptr, _New_ptr + _Min_size); } void _Tidy() noexcept { diff --git a/stl/inc/vector b/stl/inc/vector index c6552845a31..5b05f4afa40 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -825,10 +825,10 @@ private: _Xlength(); } - const size_type _Newsize = _Oldsize + 1; - size_type _Newcapacity = _Calculate_growth(_Newsize); + const size_type _Newsize = _Oldsize + 1; + const size_type _Newcapacity = _Calculate_growth(_Newsize); - const pointer _Newvec = _Allocate_at_least_helper(_Al, _Newcapacity); + const pointer _Newvec = _Al.allocate(_Newcapacity); const pointer _Constructed_last = _Newvec + _Whereoff + 1; pointer _Constructed_first = _Constructed_last; @@ -912,10 +912,10 @@ private: _Xlength(); } - const size_type _Newsize = _Oldsize + _Count; - size_type _Newcapacity = _Calculate_growth(_Newsize); + const size_type _Newsize = _Oldsize + _Count; + const size_type _Newcapacity = _Calculate_growth(_Newsize); - const pointer _Newvec = _Allocate_at_least_helper(_Al, _Newcapacity); + const pointer _Newvec = _Al.allocate(_Newcapacity); const pointer _Constructed_last = _Newvec + _Oldsize + _Count; pointer _Constructed_first = _Constructed_last; @@ -1033,10 +1033,10 @@ public: _Xlength(); } - const size_type _Newsize = _Oldsize + _Count; - size_type _Newcapacity = _Calculate_growth(_Newsize); + const size_type _Newsize = _Oldsize + _Count; + const size_type _Newcapacity = _Calculate_growth(_Newsize); - const pointer _Newvec = _Allocate_at_least_helper(_Al, _Newcapacity); + const pointer _Newvec = _Al.allocate(_Newcapacity); const pointer _Constructed_last = _Newvec + _Whereoff + _Count; pointer _Constructed_first = _Constructed_last; @@ -1128,10 +1128,10 @@ private: _Xlength(); } - const size_type _Newsize = _Oldsize + _Count; - size_type _Newcapacity = _Calculate_growth(_Newsize); + const size_type _Newsize = _Oldsize + _Count; + const size_type _Newcapacity = _Calculate_growth(_Newsize); - const pointer _Newvec = _Allocate_at_least_helper(_Al, _Newcapacity); + const pointer _Newvec = _Al.allocate(_Newcapacity); const auto _Whereoff = static_cast(_Whereptr - _Oldfirst); const pointer _Constructed_last = _Newvec + _Whereoff + _Count; pointer _Constructed_first = _Constructed_last; @@ -1518,10 +1518,10 @@ private: pointer& _Myfirst = _My_data._Myfirst; pointer& _Mylast = _My_data._Mylast; - const auto _Oldsize = static_cast(_Mylast - _Myfirst); - size_type _Newcapacity = _Calculate_growth(_Newsize); + const auto _Oldsize = static_cast(_Mylast - _Myfirst); + const size_type _Newcapacity = _Calculate_growth(_Newsize); - const pointer _Newvec = _Allocate_at_least_helper(_Al, _Newcapacity); + const pointer _Newvec = _Al.allocate(_Newcapacity); const pointer _Appended_first = _Newvec + _Oldsize; pointer _Appended_last = _Appended_first; @@ -1598,10 +1598,7 @@ public: } private: - enum class _Reallocation_policy { _At_least, _Exactly }; - - template <_Reallocation_policy _Policy> - _CONSTEXPR20 void _Reallocate(size_type& _Newcapacity) { + _CONSTEXPR20 void _Reallocate_exactly(const size_type _Newcapacity) { // set capacity to _Newcapacity (without geometric growth), provide strong guarantee auto& _Al = _Getal(); auto& _My_data = _Mypair._Myval2; @@ -1610,13 +1607,7 @@ private: const auto _Size = static_cast(_Mylast - _Myfirst); - pointer _Newvec; - if constexpr (_Policy == _Reallocation_policy::_At_least) { - _Newvec = _Allocate_at_least_helper(_Al, _Newcapacity); - } else { - _STL_INTERNAL_STATIC_ASSERT(_Policy == _Reallocation_policy::_Exactly); - _Newvec = _Al.allocate(_Newcapacity); - } + const pointer _Newvec = _Al.allocate(_Newcapacity); _TRY_BEGIN if constexpr (is_nothrow_move_constructible_v<_Ty> || !is_copy_constructible_v<_Ty>) { @@ -1684,14 +1675,14 @@ private: } public: - _CONSTEXPR20 void reserve(_CRT_GUARDOVERFLOW size_type _Newcapacity) { + _CONSTEXPR20 void reserve(_CRT_GUARDOVERFLOW const size_type _Newcapacity) { // increase capacity to _Newcapacity (without geometric growth), provide strong guarantee if (_Newcapacity > capacity()) { // something to do (reserve() never shrinks) if (_Newcapacity > max_size()) { _Xlength(); } - _Reallocate<_Reallocation_policy::_At_least>(_Newcapacity); + _Reallocate_exactly(_Newcapacity); } } @@ -1703,8 +1694,7 @@ public: if (_Oldfirst == _Oldlast) { _Tidy(); } else { - size_type _Newcapacity = static_cast(_Oldlast - _Oldfirst); - _Reallocate<_Reallocation_policy::_Exactly>(_Newcapacity); + _Reallocate_exactly(static_cast(_Oldlast - _Oldfirst)); } } } @@ -1986,7 +1976,7 @@ private: return _Geometric; // geometric growth is sufficient } - _CONSTEXPR20 void _Buy_raw(size_type _Newcapacity) { + _CONSTEXPR20 void _Buy_raw(const size_type _Newcapacity) { // allocate array with _Newcapacity elements auto& _My_data = _Mypair._Myval2; pointer& _Myfirst = _My_data._Myfirst; @@ -1996,10 +1986,10 @@ private: _STL_INTERNAL_CHECK(!_Myfirst && !_Mylast && !_Myend); // check that *this is tidy _STL_INTERNAL_CHECK(0 < _Newcapacity && _Newcapacity <= max_size()); - const pointer _Newvec = _Allocate_at_least_helper(_Getal(), _Newcapacity); - _Myfirst = _Newvec; - _Mylast = _Newvec; - _Myend = _Newvec + _Newcapacity; + const auto _Newvec = _Getal().allocate(_Newcapacity); + _Myfirst = _Newvec; + _Mylast = _Newvec; + _Myend = _Newvec + _Newcapacity; } _CONSTEXPR20 void _Buy_nonzero(const size_type _Newcapacity) { diff --git a/stl/inc/xmemory b/stl/inc/xmemory index c2c73ef5906..6c8992f47a2 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -2174,18 +2174,6 @@ _NODISCARD constexpr bool _Allocators_equal(const _Alloc& _Lhs, const _Alloc& _R } } -template -_NODISCARD_RAW_PTR_ALLOC _CONSTEXPR20 typename allocator_traits<_Alloc>::pointer _Allocate_at_least_helper( - _Alloc& _Al, _CRT_GUARDOVERFLOW typename allocator_traits<_Alloc>::size_type& _Count) { -#if _HAS_CXX23 - auto [_Ptr, _Allocated] = allocator_traits<_Alloc>::allocate_at_least(_Al, _Count); - _Count = _Allocated; - return _Ptr; -#else // _HAS_CXX23 - return _Al.allocate(_Count); -#endif // _HAS_CXX23 -} - _EXPORT_STD template _NODISCARD_REMOVE_ALG _CONSTEXPR20 _FwdIt remove(_FwdIt _First, const _FwdIt _Last, const _Ty& _Val) { // remove each matching _Val diff --git a/stl/inc/xstring b/stl/inc/xstring index b034af94254..b5ab9511a73 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -2647,11 +2647,9 @@ private: return; } - _My_data._Myres = _BUF_SIZE - 1; - size_type _New_capacity = _Calculate_growth(_Count); - ++_New_capacity; - const pointer _New_ptr = _Allocate_at_least_helper(_Al, _New_capacity); // throws - --_New_capacity; + _My_data._Myres = _BUF_SIZE - 1; + const size_type _New_capacity = _Calculate_growth(_Count); + const pointer _New_ptr = _Al.allocate(_New_capacity + 1); // throws _Construct_in_place(_My_data._Bx._Ptr, _New_ptr); _Start_element_lifetimes(_Unfancy(_New_ptr), _New_capacity + 1); @@ -2693,10 +2691,8 @@ private: } if (_Count >= _BUF_SIZE) { - size_type _New_capacity = _Calculate_growth(_Count); - ++_New_capacity; - const pointer _New_ptr = _Allocate_at_least_helper(_Al, _New_capacity); // throws - --_New_capacity; + const size_type _New_capacity = _Calculate_growth(_Count); + const pointer _New_ptr = _Al.allocate(_New_capacity + 1); // throws _Construct_in_place(_My_data._Bx._Ptr, _New_ptr); _My_data._Myres = _New_capacity; @@ -2712,11 +2708,9 @@ private: _Xlen_string(); // result too long } - const auto _Old_ptr = _My_data._Myptr(); - size_type _New_capacity = _Calculate_growth(_My_data._Mysize); - ++_New_capacity; - const pointer _New_ptr = _Allocate_at_least_helper(_Al, _New_capacity); // throws - --_New_capacity; + const auto _Old_ptr = _My_data._Myptr(); + const size_type _New_capacity = _Calculate_growth(_My_data._Mysize); + const pointer _New_ptr = _Al.allocate(_New_capacity + 1); // throws _Start_element_lifetimes(_Unfancy(_New_ptr), _New_capacity + 1); _Traits::copy(_Unfancy(_New_ptr), _Old_ptr, _My_data._Mysize); @@ -2798,11 +2792,9 @@ public: _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _My_data); // throws if (_New_capacity < _New_size) { - _New_capacity = _Calculate_growth(_New_size, _BUF_SIZE - 1, max_size()); - ++_New_capacity; - const pointer _Fancyptr = _Allocate_at_least_helper(_Getal(), _New_capacity); // throws - --_New_capacity; - _Ptr = _Unfancy(_Fancyptr); + _New_capacity = _Calculate_growth(_New_size, _BUF_SIZE - 1, max_size()); + const pointer _Fancyptr = _Getal().allocate(_New_capacity + 1); // throws + _Ptr = _Unfancy(_Fancyptr); _Construct_in_place(_My_data._Bx._Ptr, _Fancyptr); _Start_element_lifetimes(_Ptr, _New_capacity + 1); @@ -2871,12 +2863,10 @@ public: _Xlen_string(); } - auto _New_capacity = _Calculate_growth(_New_size, _BUF_SIZE - 1, _Max); - auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); + const auto _New_capacity = _Calculate_growth(_New_size, _BUF_SIZE - 1, _Max); + auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _My_data); // throws - ++_New_capacity; - const pointer _Fancyptr = _Allocate_at_least_helper(_Getal(), _New_capacity); // throws - --_New_capacity; + const pointer _Fancyptr = _Getal().allocate(_New_capacity + 1); // throws // nothrow hereafter _Start_element_lifetimes(_Unfancy(_Fancyptr), _New_capacity + 1); _Construct_in_place(_My_data._Bx._Ptr, _Fancyptr); @@ -2956,10 +2946,9 @@ public: _Result._Res = _My_data._Myres + 1; } else { // use _BUF_SIZE + 1 to avoid SSO, if the buffer is assigned back - size_type _Allocated = _BUF_SIZE + 1; - _Result._Ptr = _Allocate_at_least_helper(_Al, _Allocated); + _Result._Ptr = _Al.allocate(_BUF_SIZE + 1); _Traits::copy(_Unfancy(_Result._Ptr), _My_data._Bx._Buf, _BUF_SIZE); - _Result._Res = _Allocated; + _Result._Res = _BUF_SIZE + 1; } _My_data._Orphan_all(); _Tidy_init(); @@ -3178,11 +3167,9 @@ public: if (_Right._Mypair._Myval2._Large_string_engaged()) { const auto _New_size = _Right._Mypair._Myval2._Mysize; - auto _New_capacity = _Calculate_growth(_New_size, 0, _Right.max_size()); + const auto _New_capacity = _Calculate_growth(_New_size, 0, _Right.max_size()); auto _Right_al_non_const = _Right_al; - ++_New_capacity; - const auto _New_ptr = _Allocate_at_least_helper(_Right_al_non_const, _New_capacity); // throws - --_New_capacity; + const auto _New_ptr = _Right_al_non_const.allocate(_New_capacity + 1); // throws _Start_element_lifetimes(_Unfancy(_New_ptr), _New_capacity + 1); @@ -4749,11 +4736,9 @@ private: } const size_type _Old_capacity = _Mypair._Myval2._Myres; - size_type _New_capacity = _Calculate_growth(_New_size); + const size_type _New_capacity = _Calculate_growth(_New_size); auto& _Al = _Getal(); - ++_New_capacity; - const pointer _New_ptr = _Allocate_at_least_helper(_Al, _New_capacity); // throws - --_New_capacity; + const pointer _New_ptr = _Al.allocate(_New_capacity + 1); // throws _Start_element_lifetimes(_Unfancy(_New_ptr), _New_capacity + 1); _Mypair._Myval2._Orphan_all(); @@ -4784,11 +4769,9 @@ private: const size_type _New_size = _Old_size + _Size_increase; const size_type _Old_capacity = _My_data._Myres; - size_type _New_capacity = _Calculate_growth(_New_size); + const size_type _New_capacity = _Calculate_growth(_New_size); auto& _Al = _Getal(); - ++_New_capacity; - const pointer _New_ptr = _Allocate_at_least_helper(_Al, _New_capacity); // throws - --_New_capacity; + const pointer _New_ptr = _Al.allocate(_New_capacity + 1); // throws _Start_element_lifetimes(_Unfancy(_New_ptr), _New_capacity + 1); _My_data._Orphan_all(); diff --git a/tests/std/test.lst b/tests/std/test.lst index b6511acf8b0..3059eef1402 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -223,7 +223,6 @@ tests\GH_003022_substr_allocator tests\GH_003105_piecewise_densities tests\GH_003119_error_category_ctor tests\GH_003246_cmath_narrowing -tests\GH_003570_allocate_at_least tests\GH_003572_fstream_seekp_0_cur tests\GH_003617_vectorized_meow_element tests\GH_003676_format_large_hh_mm_ss_values diff --git a/tests/std/tests/GH_003570_allocate_at_least/env.lst b/tests/std/tests/GH_003570_allocate_at_least/env.lst deleted file mode 100644 index 642f530ffad..00000000000 --- a/tests/std/tests/GH_003570_allocate_at_least/env.lst +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -RUNALL_INCLUDE ..\usual_latest_matrix.lst diff --git a/tests/std/tests/GH_003570_allocate_at_least/test.cpp b/tests/std/tests/GH_003570_allocate_at_least/test.cpp deleted file mode 100644 index 65821ea0090..00000000000 --- a/tests/std/tests/GH_003570_allocate_at_least/test.cpp +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; - -struct signaller { - [[nodiscard]] bool consume() { - return exchange(is_set, false); - } - - void set() { - is_set = true; - } - -private: - bool is_set = false; -}; - -signaller allocate_at_least_signal; - -template -struct signalling_allocator { - using value_type = T; - - signalling_allocator() = default; - - template - signalling_allocator(const signalling_allocator&) {} - - T* allocate(size_t count) { - T* const ptr = static_cast(malloc(count * sizeof(T))); - if (ptr) { - return ptr; - } - - throw bad_alloc(); - } - - allocation_result allocate_at_least(size_t count) { - allocate_at_least_signal.set(); - return {allocate(count * 2), count * 2}; - } - - void deallocate(T* ptr, size_t) noexcept { - free(ptr); - } - - friend bool operator==(const signalling_allocator&, const signalling_allocator&) = default; -}; - -template -void test_container() { - T container; - const size_t reserve_count = container.capacity() + 100; - container.reserve(reserve_count); - assert(allocate_at_least_signal.consume()); - assert(container.capacity() >= reserve_count * 2); - assert(container.size() == 0); -} - -void test_deque() { - deque> d; - d.resize(100); - assert(allocate_at_least_signal.consume()); - assert(d.size() == 100); -} - -void test_stream_overflow(auto& stream) { - stream << "my very long string that is indeed very long in order to make sure " - << "that overflow is called, hopefully calling allocate_at_least in return"; - assert(allocate_at_least_signal.consume()); -} - -void test_sstream() { - basic_stringstream, signalling_allocator> ss; - ss.str("my_cool_string"); - assert(allocate_at_least_signal.consume()); - test_stream_overflow(ss); -} - -void test_syncstream() { - basic_syncbuf, signalling_allocator> buf; - basic_osyncstream, signalling_allocator> ss(&buf); - test_stream_overflow(ss); -} - -int main() { - test_deque(); - test_container, signalling_allocator>>(); - test_container>>(); - test_sstream(); - test_syncstream(); -} From 2261f7edb760eb3fe0726187c818b796dc7ea798 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 30 Jun 2023 15:43:14 -0700 Subject: [PATCH 13/35] Revert `fstream.seekp(0, ios::cur)` change (#3841) --- stl/inc/__msvc_filebuf.hpp | 3 +- tests/std/test.lst | 2 +- .../GH_003572_fstream_seekp_0_cur/test.cpp | 47 ----------------- .../env.lst | 2 +- .../test.cpp | 51 +++++++++++++++++++ 5 files changed, 55 insertions(+), 50 deletions(-) delete mode 100644 tests/std/tests/GH_003572_fstream_seekp_0_cur/test.cpp rename tests/std/tests/{GH_003572_fstream_seekp_0_cur => GH_003840_tellg_when_reading_lf_file_in_text_mode}/env.lst (70%) create mode 100644 tests/std/tests/GH_003840_tellg_when_reading_lf_file_in_text_mode/test.cpp diff --git a/stl/inc/__msvc_filebuf.hpp b/stl/inc/__msvc_filebuf.hpp index f06907a888c..7e420846cfa 100644 --- a/stl/inc/__msvc_filebuf.hpp +++ b/stl/inc/__msvc_filebuf.hpp @@ -651,7 +651,8 @@ class basic_filebuf : public basic_streambuf<_Elem, _Traits> { // stream buffer _Off -= static_cast(sizeof(_Elem)); // back up over _Elem bytes } - if (!_Myfile || !_Endwrite() || _CSTD _fseeki64(_Myfile, _Off, _Way) != 0 + if (!_Myfile || !_Endwrite() + || ((_Off != 0 || _Way != ios_base::cur) && _CSTD _fseeki64(_Myfile, _Off, _Way) != 0) || _CSTD fgetpos(_Myfile, &_Fileposition) != 0) { return pos_type{off_type{-1}}; // report failure } diff --git a/tests/std/test.lst b/tests/std/test.lst index 3059eef1402..5c0b3ca9533 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -223,10 +223,10 @@ tests\GH_003022_substr_allocator tests\GH_003105_piecewise_densities tests\GH_003119_error_category_ctor tests\GH_003246_cmath_narrowing -tests\GH_003572_fstream_seekp_0_cur tests\GH_003617_vectorized_meow_element tests\GH_003676_format_large_hh_mm_ss_values tests\GH_003735_char_traits_signatures +tests\GH_003840_tellg_when_reading_lf_file_in_text_mode tests\LWG2381_num_get_floating_point tests\LWG2597_complex_branch_cut tests\LWG3018_shared_ptr_function diff --git a/tests/std/tests/GH_003572_fstream_seekp_0_cur/test.cpp b/tests/std/tests/GH_003572_fstream_seekp_0_cur/test.cpp deleted file mode 100644 index 72d15f50bcb..00000000000 --- a/tests/std/tests/GH_003572_fstream_seekp_0_cur/test.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -#include -#include -#include -#include - -int main() { - using namespace std; - - fstream f("test.txt", ios::in | ios::out | ios::trunc); - - f << "123"; - - auto check = [&f](const char(&content)[4]) { - char buffer[4]{}; - f.seekg(0); - f.read(buffer, 3); - assert(f); - assert(memcmp(buffer, content, 4) == 0); - }; - - f.seekg(0); - (void) f.get(); - f.seekp(f.tellp()); - f << "*"; - check("1*3"); - - f.seekg(0); - (void) f.get(); - f.seekp(0, ios::cur); - f << "!"; - check("1!3"); - - f.seekg(0); - (void) f.get(); - f.seekp(1, ios::cur); - f << "!"; - check("1!!"); - - f.seekg(0); - (void) f.get(); - f.seekp(-1, ios::cur); - f << "!"; - check("!!!"); -} diff --git a/tests/std/tests/GH_003572_fstream_seekp_0_cur/env.lst b/tests/std/tests/GH_003840_tellg_when_reading_lf_file_in_text_mode/env.lst similarity index 70% rename from tests/std/tests/GH_003572_fstream_seekp_0_cur/env.lst rename to tests/std/tests/GH_003840_tellg_when_reading_lf_file_in_text_mode/env.lst index 19f025bd0e6..2de7aab2959 100644 --- a/tests/std/tests/GH_003572_fstream_seekp_0_cur/env.lst +++ b/tests/std/tests/GH_003840_tellg_when_reading_lf_file_in_text_mode/env.lst @@ -1,4 +1,4 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -RUNALL_INCLUDE ..\usual_matrix.lst +RUNALL_INCLUDE ..\usual_17_matrix.lst diff --git a/tests/std/tests/GH_003840_tellg_when_reading_lf_file_in_text_mode/test.cpp b/tests/std/tests/GH_003840_tellg_when_reading_lf_file_in_text_mode/test.cpp new file mode 100644 index 00000000000..2482c9c6a1f --- /dev/null +++ b/tests/std/tests/GH_003840_tellg_when_reading_lf_file_in_text_mode/test.cpp @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include + +#include "temp_file_name.hpp" + +using namespace std; + +void test(const string& temp_file_name_str, const ios_base::openmode mode) { + filesystem::remove(temp_file_name_str); + + { + ofstream out{temp_file_name_str, mode}; + out << "Line A\n"; + out << "Line B\n"; + out << "Line C\n"; + } + + { + ifstream in{temp_file_name_str}; + string line; + + assert(getline(in, line)); + assert(line == "Line A"); + (void) in.tellg(); + + assert(getline(in, line)); + assert(line == "Line B"); + (void) in.tellg(); + + assert(getline(in, line)); + assert(line == "Line C"); + (void) in.tellg(); + + assert(!getline(in, line)); + } + + filesystem::remove(temp_file_name_str); +} + +int main() { + const string temp_file_name_str = temp_file_name(); + + test(temp_file_name_str, ios_base::out); + test(temp_file_name_str, ios_base::binary); +} From 23a5a53143c2621eb07b26f93badecae8aca9269 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 13 Jul 2023 18:18:54 -0700 Subject: [PATCH 14/35] Toolset update: VS 2022 17.7 Preview 3, Clang 16.0.5 (#3866) --- .github/workflows/update-status-chart.yml | 2 +- README.md | 4 +- azure-devops/create-1es-hosted-pool.ps1 | 2 +- azure-devops/provision-image.ps1 | 2 +- azure-pipelines.yml | 2 +- stl/inc/__msvc_int128.hpp | 25 ++++---- stl/inc/complex | 2 +- stl/inc/memory | 5 -- stl/inc/stop_token | 4 +- stl/inc/tuple | 4 +- stl/inc/type_traits | 5 +- stl/inc/variant | 11 +--- stl/inc/xtree | 21 +++---- stl/inc/yvals_core.h | 4 -- stl/src/StlCompareStringA.cpp | 1 - stl/src/StlLCMapStringA.cpp | 1 - tests/libcxx/expected_results.txt | 6 +- .../tests/GH_000431_copy_move_family/test.cpp | 2 + .../std/tests/GH_000431_equal_family/test.cpp | 2 + .../test.compile.pass.cpp | 6 ++ .../test.compile.pass.cpp | 4 ++ .../test.cpp | 2 - tests/std/tests/P0067R5_charconv/test.cpp | 4 -- tests/std/tests/P0220R1_any/test.cpp | 14 +++++ .../test.cpp | 4 +- .../env.lst | 5 +- .../tests/P1208R6_source_location/header.h | 6 +- .../tests/P1208R6_source_location/test.cpp | 62 +++++++++++++------ .../test.compile.pass.cpp | 4 -- tests/std/tests/prefix.lst | 2 +- tests/tr1/prefix.lst | 2 +- 31 files changed, 116 insertions(+), 104 deletions(-) diff --git a/.github/workflows/update-status-chart.yml b/.github/workflows/update-status-chart.yml index 37e7f5db180..ec42d63e72d 100644 --- a/.github/workflows/update-status-chart.yml +++ b/.github/workflows/update-status-chart.yml @@ -18,7 +18,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v3 with: - node-version: ">=17.8.0" + node-version: ">=20.4.0" - name: Install Packages run: | npm ci diff --git a/README.md b/README.md index a4f9f458025..4f699bd9660 100644 --- a/README.md +++ b/README.md @@ -141,7 +141,7 @@ 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.7 Preview 2 or later. +1. Install Visual Studio 2022 17.7 Preview 3 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. @@ -157,7 +157,7 @@ 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.7 Preview 2 or later. +1. Install Visual Studio 2022 17.7 Preview 3 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. diff --git a/azure-devops/create-1es-hosted-pool.ps1 b/azure-devops/create-1es-hosted-pool.ps1 index a8afa4759a5..232464f305f 100644 --- a/azure-devops/create-1es-hosted-pool.ps1 +++ b/azure-devops/create-1es-hosted-pool.ps1 @@ -14,7 +14,7 @@ $ErrorActionPreference = 'Stop' $CurrentDate = Get-Date $Location = 'eastus' -$VMSize = 'Standard_D32ads_v5' +$VMSize = 'Standard_D32ds_v5' $ProtoVMName = 'PROTOTYPE' $ImagePublisher = 'MicrosoftWindowsServer' $ImageOffer = 'WindowsServer' diff --git a/azure-devops/provision-image.ps1 b/azure-devops/provision-image.ps1 index b97754cd955..d87f5b47491 100644 --- a/azure-devops/provision-image.ps1 +++ b/azure-devops/provision-image.ps1 @@ -91,7 +91,7 @@ if ([string]::IsNullOrEmpty($AdminUserPassword)) { $PsExecPath = Join-Path $ExtractedPsToolsPath 'PsExec64.exe' # https://github.com/PowerShell/PowerShell/releases/latest - $PowerShellZipUrl = 'https://github.com/PowerShell/PowerShell/releases/download/v7.3.4/PowerShell-7.3.4-win-x64.zip' + $PowerShellZipUrl = 'https://github.com/PowerShell/PowerShell/releases/download/v7.3.5/PowerShell-7.3.5-win-x64.zip' Write-Host "Downloading: $PowerShellZipUrl" $ExtractedPowerShellPath = DownloadAndExtractZip -Url $PowerShellZipUrl $PwshPath = Join-Path $ExtractedPowerShellPath 'pwsh.exe' diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 124da209a6f..4c306b0c311 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -9,7 +9,7 @@ variables: benchmarkBuildOutputLocation: 'D:\benchmark' pool: - name: 'StlBuild-2023-06-13T1913-Pool' + name: 'StlBuild-2023-07-11T1513-Pool' demands: EnableSpotVM -equals true pr: diff --git a/stl/inc/__msvc_int128.hpp b/stl/inc/__msvc_int128.hpp index 61ea8e29b16..31be4971b84 100644 --- a/stl/inc/__msvc_int128.hpp +++ b/stl/inc/__msvc_int128.hpp @@ -43,17 +43,14 @@ _STD_BEGIN #if defined(_M_X64) && !defined(_M_ARM64EC) && !defined(_M_CEE_PURE) && !defined(__CUDACC__) \ && !defined(__INTEL_COMPILER) #define _STL_128_INTRINSICS 1 -#ifdef __clang__ -#define _STL_128_ADD_SUB_INTRINSICS 0 // clang doesn't have _addcarry_u64 / _subborrow_u64 -#define _STL_128_DIV_INTRINSICS 0 // clang doesn't have _udiv128 / _div128 -#else // ^^^ Clang / other compilers vvv -#define _STL_128_ADD_SUB_INTRINSICS 1 -#define _STL_128_DIV_INTRINSICS 1 -#endif // ^^^ other compilers ^^^ +#ifdef __clang__ // clang doesn't have _udiv128 / _div128 +#define _STL_128_DIV_INTRINSICS 0 +#else // ^^^ Clang / other vvv +#define _STL_128_DIV_INTRINSICS 1 +#endif // ^^^ detect _udiv128 / _div128 ^^^ #else // ^^^ intrinsics available / intrinsics unavailable vvv -#define _STL_128_INTRINSICS 0 -#define _STL_128_ADD_SUB_INTRINSICS 0 -#define _STL_128_DIV_INTRINSICS 0 +#define _STL_128_INTRINSICS 0 +#define _STL_128_DIV_INTRINSICS 0 #endif // ^^^ intrinsics unavailable ^^^ template @@ -132,11 +129,11 @@ struct static constexpr unsigned char _AddCarry64( unsigned char _Carry, uint64_t _Left, uint64_t _Right, uint64_t& _Result) noexcept { // _STL_INTERNAL_CHECK(_Carry < 2); -#if _STL_128_ADD_SUB_INTRINSICS +#if _STL_128_INTRINSICS if (!_Is_constant_evaluated()) { return _addcarry_u64(_Carry, _Left, _Right, &_Result); } -#endif // _STL_128_ADD_SUB_INTRINSICS +#endif // _STL_128_INTRINSICS const uint64_t _Sum = _Left + _Right + _Carry; _Result = _Sum; @@ -146,11 +143,11 @@ struct static constexpr unsigned char _SubBorrow64( unsigned char _Carry, uint64_t _Left, uint64_t _Right, uint64_t& _Result) noexcept { // _STL_INTERNAL_CHECK(_Carry < 2); -#if _STL_128_ADD_SUB_INTRINSICS +#if _STL_128_INTRINSICS if (!_Is_constant_evaluated()) { return _subborrow_u64(_Carry, _Left, _Right, &_Result); } -#endif // _STL_128_ADD_SUB_INTRINSICS +#endif // _STL_128_INTRINSICS const auto _Difference = _Left - _Right - _Carry; _Result = _Difference; diff --git a/stl/inc/complex b/stl/inc/complex index 6420abadcec..ce60701b764 100644 --- a/stl/inc/complex +++ b/stl/inc/complex @@ -2037,7 +2037,7 @@ _NODISCARD complex<_Ty> tanh(const complex<_Ty>& _Left) { _Real = _Ty{1}; } - return complex<_Ty>(_Real, _Tv* _Ty{0}); + return complex<_Ty>(_Real, _Tv * _Ty{0}); } return complex<_Ty>((_Ctraits<_Ty>::sqrt(_Ty{1} + _Sv * _Sv)) * _Bv / _Dv, _Tv / _Dv); diff --git a/stl/inc/memory b/stl/inc/memory index 5ed5de5528f..8cc86b2ccb3 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1879,12 +1879,7 @@ _NODISCARD bool operator==(const shared_ptr<_Ty1>& _Left, const shared_ptr<_Ty2> #if _HAS_CXX20 _EXPORT_STD template _NODISCARD strong_ordering operator<=>(const shared_ptr<_Ty1>& _Left, const shared_ptr<_Ty2>& _Right) noexcept { -#if !defined(__EDG__) && !defined(__clang__) // TRANSITION, DevCom-10334808 - using _Common_ptr_t = decltype(false ? _Left.get() : _Right.get()); - return static_cast<_Common_ptr_t>(_Left.get()) <=> static_cast<_Common_ptr_t>(_Right.get()); -#else // ^^^ workaround / no workaround vvv return _Left.get() <=> _Right.get(); -#endif // ^^^ no workaround ^^^ } #else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv template diff --git a/stl/inc/stop_token b/stl/inc/stop_token index 3d65a48ddc6..ee14cc886a9 100644 --- a/stl/inc/stop_token +++ b/stl/inc/stop_token @@ -255,7 +255,7 @@ void _Stop_callback_base::_Do_attach( // fast path check if the state is already known auto _Local_sources = _State->_Stop_sources.load(); - if ((_Local_sources& uint32_t{1}) != 0) { + if ((_Local_sources & uint32_t{1}) != 0) { // stop already requested _Fn(this); return; @@ -269,7 +269,7 @@ void _Stop_callback_base::_Do_attach( auto _Head = _State->_Callbacks._Lock_and_load(); // recheck the state in case it changed while we were waiting to acquire the lock _Local_sources = _State->_Stop_sources.load(); - if ((_Local_sources& uint32_t{1}) != 0) { + if ((_Local_sources & uint32_t{1}) != 0) { // stop already requested _State->_Callbacks._Store_and_unlock(_Head); _Fn(this); diff --git a/stl/inc/tuple b/stl/inc/tuple index 6a04b92fd56..8059fbaed02 100644 --- a/stl/inc/tuple +++ b/stl/inc/tuple @@ -191,8 +191,8 @@ inline constexpr bool _Can_construct_values_from_tuple_like_v, template concept _Can_construct_from_tuple_like = _Different_from<_TupleLike, _Tuple> && _Tuple_like<_TupleLike> && !_Is_subrange_v> - && (tuple_size_v<_Tuple> - == tuple_size_v>) &&_Can_construct_values_from_tuple_like_v<_Tuple, _TupleLike> + && (tuple_size_v<_Tuple> == tuple_size_v>) // + &&_Can_construct_values_from_tuple_like_v<_Tuple, _TupleLike> && (tuple_size_v<_Tuple> != 1 || (!is_convertible_v<_TupleLike, tuple_element_t<0, _Tuple>> && !is_constructible_v, _TupleLike>) ); diff --git a/stl/inc/type_traits b/stl/inc/type_traits index e36e2e587b7..529563cccd2 100644 --- a/stl/inc/type_traits +++ b/stl/inc/type_traits @@ -732,8 +732,7 @@ 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, VSO-1690654 -#ifdef __EDG__ +#ifdef __EDG__ // TRANSITION, VSO-1690654 template struct _Is_aggregate_impl : bool_constant<__is_aggregate(_Ty)> {}; @@ -1934,7 +1933,6 @@ inline constexpr bool is_nothrow_invocable_r_v = #endif // _HAS_CXX17 #if _HAS_CXX20 -#ifndef __EDG__ // TRANSITION, VSO-1268984 #ifndef __clang__ // TRANSITION, LLVM-48860 _EXPORT_STD template struct is_layout_compatible : bool_constant<__is_layout_compatible(_Ty1, _Ty2)> {}; @@ -1958,7 +1956,6 @@ _NODISCARD constexpr bool is_corresponding_member(_MemberTy1 _ClassTy1::*_Pm1, _ return __is_corresponding_member(_ClassTy1, _ClassTy2, _Pm1, _Pm2); } #endif // __clang__ -#endif // __EDG__ #endif // _HAS_CXX20 template diff --git a/stl/inc/variant b/stl/inc/variant index 3808ea86bc4..2dc66b9b87c 100644 --- a/stl/inc/variant +++ b/stl/inc/variant @@ -1110,11 +1110,7 @@ public: [this, &_That, _My_ref](auto _That_ref) noexcept( conjunction_v..., is_nothrow_swappable<_Types>...>) { constexpr size_t _That_idx = decltype(_That_ref)::_Idx; -#ifdef __EDG__ // TRANSITION, VSO-657455 - constexpr size_t _My_idx = decltype(_My_ref)::_Idx + 0 * _That_idx; -#else // ^^^ workaround / no workaround vvv - constexpr size_t _My_idx = decltype(_My_ref)::_Idx; -#endif // TRANSITION, VSO-657455 + constexpr size_t _My_idx = decltype(_My_ref)::_Idx; if constexpr (_My_idx == _That_idx) { // Same alternatives... if constexpr (_My_idx != variant_npos) { // ...and not valueless, swap directly using _STD swap; @@ -1127,12 +1123,7 @@ public: _That._Emplace_valueless<_My_idx>(_STD move(_My_ref._Val)); this->template _Reset<_My_idx>(); } else { // different non-valueless alternatives -#ifdef __EDG__ // TRANSITION, VSO-657455 - using _Workaround = enable_if_t<_That_idx != variant_npos, decltype(_My_ref._Val)>; - auto _Tmp = _STD move(static_cast<_Workaround>(_My_ref._Val)); -#else // ^^^ workaround / no workaround vvv auto _Tmp = _STD move(_My_ref._Val); -#endif // TRANSITION, VSO-657455 this->template _Reset<_My_idx>(); this->_Emplace_valueless<_That_idx>(_STD move(_That_ref._Val)); _That.template _Reset<_That_idx>(); diff --git a/stl/inc/xtree b/stl/inc/xtree index aec01557a7e..767027093f1 100644 --- a/stl/inc/xtree +++ b/stl/inc/xtree @@ -907,25 +907,18 @@ public: _Swap_val_excluding_comp(_Right); } -private: - void _Different_allocator_move_construct(_Tree&& _Right) { - // TRANSITION, VSO-761321 (inline into only caller when that is fixed) - auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alnode, _Getal()); - const auto _Scary = _Get_scary(); - _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, *_Scary); - _Tree_head_scoped_ptr<_Alnode, _Scary_val> _Sentinel(_Getal(), *_Scary); - _Copy<_Strategy::_Move>(_Right); - _Sentinel._Release(); - _Proxy._Release(); - } - -public: _Tree(_Tree&& _Right, const allocator_type& _Al) : _Mypair(_One_then_variadic_args_t{}, _Right.key_comp(), // intentionally copy comparator, see LWG-2227 _One_then_variadic_args_t{}, _Al) { if constexpr (!_Alnode_traits::is_always_equal::value) { if (_Getal() != _Right._Getal()) { - _Different_allocator_move_construct(_STD move(_Right)); + auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alnode, _Getal()); + const auto _Scary = _Get_scary(); + _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, *_Scary); + _Tree_head_scoped_ptr<_Alnode, _Scary_val> _Sentinel(_Getal(), *_Scary); + _Copy<_Strategy::_Move>(_Right); + _Sentinel._Release(); + _Proxy._Release(); return; } } diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index ceb2fce5ed8..7bae2e830b3 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1665,19 +1665,15 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #define __cpp_lib_interpolate 201902L #define __cpp_lib_is_constant_evaluated 201811L -#ifndef __EDG__ // TRANSITION, VSO-1268984 #ifndef __clang__ // TRANSITION, LLVM-48860 #define __cpp_lib_is_layout_compatible 201907L #endif // __clang__ -#endif // __EDG__ #define __cpp_lib_is_nothrow_convertible 201806L -#ifndef __EDG__ // TRANSITION, VSO-1268984 #ifndef __clang__ // TRANSITION, LLVM-48860 #define __cpp_lib_is_pointer_interconvertible 201907L #endif // __clang__ -#endif // __EDG__ #define __cpp_lib_jthread 201911L #define __cpp_lib_latch 201907L diff --git a/stl/src/StlCompareStringA.cpp b/stl/src/StlCompareStringA.cpp index 281ccdec63b..81eb6e41c57 100644 --- a/stl/src/StlCompareStringA.cpp +++ b/stl/src/StlCompareStringA.cpp @@ -133,7 +133,6 @@ extern "C" int __cdecl __crtCompareStringA(_In_z_ LPCWSTR LocaleName, _In_ DWORD } // allocate enough space for chars -#pragma warning(suppress : 6386) // TRANSITION, VSO-1152705 false buffer overrun report in _malloca_crt_t const __crt_scoped_stack_ptr wbuffer2(_malloca_crt_t(wchar_t, buff_size2)); if (wbuffer2.get() == nullptr) { return 0; diff --git a/stl/src/StlLCMapStringA.cpp b/stl/src/StlLCMapStringA.cpp index d176fcc4151..2ddf8258b5d 100644 --- a/stl/src/StlLCMapStringA.cpp +++ b/stl/src/StlLCMapStringA.cpp @@ -94,7 +94,6 @@ extern "C" int __cdecl __crtLCMapStringA(_In_opt_z_ LPCWSTR LocaleName, _In_ DWO int outbuff_size = retval; // allocate enough space for wide chars (includes null terminator if any) -#pragma warning(suppress : 6386) // TRANSITION, VSO-1152705 false buffer overrun report in _malloca_crt_t const __crt_scoped_stack_ptr outwbuffer(_malloca_crt_t(wchar_t, outbuff_size)); if (!outwbuffer) { return retval; diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index a815353ffd2..055288aaa6b 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -417,7 +417,7 @@ std/utilities/function.objects/func.wrap/func.wrap.func/noncopyable_return_type. # *** CLANG COMPILER BUGS *** # LLVM-46207 Clang's tgmath.h interferes with the UCRT's tgmath.h -std/depr/depr.c.headers/tgmath_h.pass.cpp:1 SKIPPED +std/depr/depr.c.headers/tgmath_h.pass.cpp:1 FAIL # *** CLANG ISSUES, NOT YET ANALYZED *** @@ -513,8 +513,8 @@ std/thread/thread.threads/thread.thread.class/thread.thread.assign/move2.pass.cp std/thread/thread.threads/thread.thread.class/thread.thread.member/join.pass.cpp SKIPPED # OS-29877133 "LDBL_DECIMAL_DIG missing from " -std/depr/depr.c.headers/float_h.pass.cpp FAIL -std/language.support/support.limits/c.limits/cfloat.pass.cpp FAIL +std/depr/depr.c.headers/float_h.pass.cpp:0 FAIL +std/language.support/support.limits/c.limits/cfloat.pass.cpp:0 FAIL # *** LIKELY BOGUS TESTS *** diff --git a/tests/std/tests/GH_000431_copy_move_family/test.cpp b/tests/std/tests/GH_000431_copy_move_family/test.cpp index 9486d75d7f6..9b7cf5ab6e1 100644 --- a/tests/std/tests/GH_000431_copy_move_family/test.cpp +++ b/tests/std/tests/GH_000431_copy_move_family/test.cpp @@ -105,7 +105,9 @@ struct StatefulDerived2 : EmptyBase, StatefulBase {}; #ifdef __cpp_lib_is_pointer_interconvertible STATIC_ASSERT(is_pointer_interconvertible_base_of_v); STATIC_ASSERT(is_pointer_interconvertible_base_of_v); +#ifndef __EDG__ // TRANSITION, VSO-1849453 STATIC_ASSERT(!is_pointer_interconvertible_base_of_v); +#endif // ^^^ no workaround ^^^ STATIC_ASSERT(is_pointer_interconvertible_base_of_v); STATIC_ASSERT(is_pointer_interconvertible_base_of_v); #endif // __cpp_lib_is_pointer_interconvertible diff --git a/tests/std/tests/GH_000431_equal_family/test.cpp b/tests/std/tests/GH_000431_equal_family/test.cpp index 5461fbc81ad..9bd78f6bb3f 100644 --- a/tests/std/tests/GH_000431_equal_family/test.cpp +++ b/tests/std/tests/GH_000431_equal_family/test.cpp @@ -133,7 +133,9 @@ struct StatefulDerived2 : EmptyBase, StatefulBase {}; #ifdef __cpp_lib_is_pointer_interconvertible STATIC_ASSERT(is_pointer_interconvertible_base_of_v); STATIC_ASSERT(is_pointer_interconvertible_base_of_v); +#ifndef __EDG__ // TRANSITION, VSO-1849453 STATIC_ASSERT(!is_pointer_interconvertible_base_of_v); +#endif // ^^^ no workaround ^^^ STATIC_ASSERT(is_pointer_interconvertible_base_of_v); STATIC_ASSERT(is_pointer_interconvertible_base_of_v); #endif // __cpp_lib_is_pointer_interconvertible diff --git a/tests/std/tests/GH_000431_equal_memcmp_is_safe/test.compile.pass.cpp b/tests/std/tests/GH_000431_equal_memcmp_is_safe/test.compile.pass.cpp index 5159486e50b..560f081613f 100644 --- a/tests/std/tests/GH_000431_equal_memcmp_is_safe/test.compile.pass.cpp +++ b/tests/std/tests/GH_000431_equal_memcmp_is_safe/test.compile.pass.cpp @@ -141,9 +141,13 @@ struct StatefulPrivatelyDerived2 : private EmptyBase, private StatefulBase {}; STATIC_ASSERT(is_pointer_interconvertible_base_of_v); STATIC_ASSERT(is_pointer_interconvertible_base_of_v); STATIC_ASSERT(is_pointer_interconvertible_base_of_v); +#ifndef __EDG__ // TRANSITION, VSO-1849453 STATIC_ASSERT(!is_pointer_interconvertible_base_of_v); +#endif // ^^^ no workaround ^^^ STATIC_ASSERT(is_pointer_interconvertible_base_of_v); +#ifndef __EDG__ // TRANSITION, VSO-1849453 STATIC_ASSERT(!is_pointer_interconvertible_base_of_v); +#endif // ^^^ no workaround ^^^ STATIC_ASSERT(is_pointer_interconvertible_base_of_v); STATIC_ASSERT(is_pointer_interconvertible_base_of_v); STATIC_ASSERT(is_pointer_interconvertible_base_of_v); @@ -453,8 +457,10 @@ STATIC_ASSERT(test_equal_memcmp_is_safe_for_pointers()); STATIC_ASSERT(test_equal_memcmp_is_safe_for_pointers()); STATIC_ASSERT(test_equal_memcmp_is_safe_for_pointers()); +#ifndef __EDG__ // TRANSITION, VSO-1849453 STATIC_ASSERT(test_equal_memcmp_is_safe_for_pointers()); STATIC_ASSERT(test_equal_memcmp_is_safe_for_pointers()); +#endif // ^^^ no workaround ^^^ STATIC_ASSERT(test_equal_memcmp_is_safe_for_pointers()); STATIC_ASSERT(test_equal_memcmp_is_safe_for_pointers()); STATIC_ASSERT(test_equal_memcmp_is_safe_for_pointers()); diff --git a/tests/std/tests/GH_000431_iter_copy_move_cat/test.compile.pass.cpp b/tests/std/tests/GH_000431_iter_copy_move_cat/test.compile.pass.cpp index 682d00de985..e82adc5789f 100644 --- a/tests/std/tests/GH_000431_iter_copy_move_cat/test.compile.pass.cpp +++ b/tests/std/tests/GH_000431_iter_copy_move_cat/test.compile.pass.cpp @@ -309,9 +309,13 @@ struct StatefulPrivatelyDerived2 : private EmptyBase, private StatefulBase {}; STATIC_ASSERT(is_pointer_interconvertible_base_of_v); STATIC_ASSERT(is_pointer_interconvertible_base_of_v); STATIC_ASSERT(is_pointer_interconvertible_base_of_v); +#ifndef __EDG__ // TRANSITION, VSO-1849453 STATIC_ASSERT(!is_pointer_interconvertible_base_of_v); +#endif // ^^^ no workaround ^^^ STATIC_ASSERT(is_pointer_interconvertible_base_of_v); +#ifndef __EDG__ // TRANSITION, VSO-1849453 STATIC_ASSERT(!is_pointer_interconvertible_base_of_v); +#endif // ^^^ no workaround ^^^ STATIC_ASSERT(is_pointer_interconvertible_base_of_v); STATIC_ASSERT(is_pointer_interconvertible_base_of_v); STATIC_ASSERT(is_pointer_interconvertible_base_of_v); diff --git a/tests/std/tests/P0040R3_parallel_memory_algorithms/test.cpp b/tests/std/tests/P0040R3_parallel_memory_algorithms/test.cpp index abeb44503aa..e040f958564 100644 --- a/tests/std/tests/P0040R3_parallel_memory_algorithms/test.cpp +++ b/tests/std/tests/P0040R3_parallel_memory_algorithms/test.cpp @@ -399,7 +399,6 @@ struct test_case_uninitialized_fill_n_parallel { }; int main() { -#ifndef _M_CEE // TRANSITION, VSO-1664463 parallel_test_case(test_case_uninitialized_default_construct_parallel{}, par); parallel_test_case(test_case_uninitialized_default_construct_n_parallel{}, par); parallel_test_case(test_case_uninitialized_default_construct_trivial_parallel{}, par); @@ -446,5 +445,4 @@ int main() { parallel_test_case(test_case_uninitialized_fill_parallel{}, unseq); parallel_test_case(test_case_uninitialized_fill_n_parallel{}, unseq); #endif // _HAS_CXX20 -#endif // _M_CEE } diff --git a/tests/std/tests/P0067R5_charconv/test.cpp b/tests/std/tests/P0067R5_charconv/test.cpp index b898d1902d4..c06b8444798 100644 --- a/tests/std/tests/P0067R5_charconv/test.cpp +++ b/tests/std/tests/P0067R5_charconv/test.cpp @@ -1170,9 +1170,6 @@ template pair std::__to_chars( wchar_t* const, wchar_t* const, const __floating_decimal_64, chars_format, const double); template pair std::__d2fixed_buffered_n(wchar_t*, wchar_t* const, const double, const uint32_t); -#if defined(__clang__) && defined(_M_IX86) // TRANSITION, LLVM-62762, fixed in Clang 16.0.3 -int main() {} -#else // ^^^ workaround / no workaround vvv int main(int argc, char** argv) { const auto start = chrono::steady_clock::now(); @@ -1201,4 +1198,3 @@ int main(int argc, char** argv) { puts("That was slow. Consider tuning PrefixesToTest and FractionBits to test fewer cases."); } } -#endif // ^^^ no workaround ^^^ diff --git a/tests/std/tests/P0220R1_any/test.cpp b/tests/std/tests/P0220R1_any/test.cpp index cd69a914de5..6d3d25e3552 100644 --- a/tests/std/tests/P0220R1_any/test.cpp +++ b/tests/std/tests/P0220R1_any/test.cpp @@ -2604,6 +2604,11 @@ namespace msvc { } // namespace swap_ } // namespace modifiers +#ifdef _M_CEE // TRANSITION, VSO-1846195 +#pragma warning(push) +#pragma warning(disable : 5267) // definition of implicit copy constructor for 'X' is deprecated + // because it has a user-provided destructor +#endif // ^^^ workaround ^^^ namespace overaligned { template void test_one_alignment() { @@ -2612,6 +2617,12 @@ namespace msvc { struct aligned_type { alignas(align) unsigned char space[align]; +#ifndef _M_CEE // TRANSITION, VSO-1846195 + aligned_type() = default; + aligned_type(const aligned_type&) = default; + aligned_type& operator=(const aligned_type&) = default; +#endif // ^^^ no workaround ^^^ + ~aligned_type() noexcept { assert(reinterpret_cast(this) % align == 0); } @@ -2644,6 +2655,9 @@ namespace msvc { test_one_alignment<3>(); } } // namespace overaligned +#ifdef _M_CEE // TRANSITION, VSO-1846195 +#pragma warning(pop) +#endif // ^^^ workaround ^^^ namespace size_and_alignment { void run_test() { diff --git a/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp b/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp index 943f0220786..ac110e8d1ed 100644 --- a/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp +++ b/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp @@ -14,7 +14,6 @@ struct S { // Must be declared at namespace scope due to static data member }; constexpr bool test() { -#ifndef __EDG__ // TRANSITION, VSO-1268984 #ifndef __clang__ // TRANSITION, LLVM-48860 // is_layout_compatible tests { @@ -73,9 +72,11 @@ constexpr bool test() { ASSERT(is_layout_compatible_v); ASSERT(is_layout_compatible_v); +#ifndef __EDG__ // TRANSITION, VSO-1849458 ASSERT(is_layout_compatible_v); ASSERT(is_layout_compatible_v); ASSERT(is_layout_compatible_v); +#endif // ^^^ no workaround ^^^ ASSERT(!is_layout_compatible_v); ASSERT(!is_layout_compatible_v); @@ -246,7 +247,6 @@ constexpr bool test() { ASSERT(!is_pointer_interconvertible_with_class(static_cast(nullptr))); } #endif // __clang__ -#endif // __EDG__ return true; } diff --git a/tests/std/tests/P0645R10_text_formatting_legacy_text_encoding/env.lst b/tests/std/tests/P0645R10_text_formatting_legacy_text_encoding/env.lst index fee12cbc26a..adb6a326162 100644 --- a/tests/std/tests/P0645R10_text_formatting_legacy_text_encoding/env.lst +++ b/tests/std/tests/P0645R10_text_formatting_legacy_text_encoding/env.lst @@ -21,9 +21,8 @@ PM_CL="/EHsc /MTd /D_ITERATOR_DEBUG_LEVEL=0 /std:c++latest /permissive- /fp:stri PM_CL="/EHsc /MTd /D_ITERATOR_DEBUG_LEVEL=1 /std:c++latest /permissive-" PM_CL="/EHsc /MTd /D_ITERATOR_DEBUG_LEVEL=2 /std:c++latest /permissive" PM_CL="/EHsc /MTd /D_ITERATOR_DEBUG_LEVEL=2 /std:c++latest /permissive- /analyze:only /analyze:autolog-" -# TRANSITION, VSO-1664463 -# PM_CL="/clr /MD /std:c++20" -# PM_CL="/clr /MDd /std:c++20" +PM_CL="/clr /MD /std:c++20" +PM_CL="/clr /MDd /std:c++20" # PM_CL="/std:c++20 /permissive- /BE /c /EHsc /MD" # PM_CL="/std:c++latest /permissive- /BE /c /EHsc /MTd" # PM_COMPILER="clang-cl" PM_CL="-fno-ms-compatibility -fno-delayed-template-parsing -Wno-unqualified-std-cast-call /EHsc /std:c++20 /permissive- /MD" diff --git a/tests/std/tests/P1208R6_source_location/header.h b/tests/std/tests/P1208R6_source_location/header.h index 2bf8cdf2b31..e9c8b48bbb7 100644 --- a/tests/std/tests/P1208R6_source_location/header.h +++ b/tests/std/tests/P1208R6_source_location/header.h @@ -12,9 +12,11 @@ constexpr void header_test() { assert(x.line() == __LINE__ - 1); #ifdef __clang__ assert(x.column() == 20); -#else // ^^^ defined(__clang__) / !defined(__clang__) vvv +#elif defined(__EDG__) + assert(x.column() == 45); +#else // ^^^ EDG / C1XX vvv assert(x.column() == 37); -#endif // ^^^ !defined(__clang__) ^^^ +#endif // ^^^ C1XX ^^^ #if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-10199227 and LLVM-58951 assert(x.function_name() == "header_test"sv); #else // ^^^ workaround / no workaround vvv diff --git a/tests/std/tests/P1208R6_source_location/test.cpp b/tests/std/tests/P1208R6_source_location/test.cpp index d41dc8d3194..4640ca5c131 100644 --- a/tests/std/tests/P1208R6_source_location/test.cpp +++ b/tests/std/tests/P1208R6_source_location/test.cpp @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#ifndef __EDG__ // TRANSITION, VSO-1285779 #include "header.h" #include #include @@ -21,9 +20,11 @@ constexpr auto g = source_location::current(); static_assert(g.line() == __LINE__ - 1); #ifdef __clang__ static_assert(g.column() == 20); -#else // ^^^ defined(__clang__) / !defined(__clang__) vvv +#elif defined(__EDG__) +static_assert(g.column() == 45); +#else // ^^^ EDG / C1XX vvv static_assert(g.column() == 37); -#endif // ^^^ !defined(__clang__) ^^^ +#endif // ^^^ C1XX ^^^ static_assert(g.function_name() == ""sv); static_assert(string_view{g.file_name()}.ends_with(test_cpp)); @@ -55,9 +56,11 @@ constexpr void local_test() { assert(x.line() == __LINE__ - 1); #ifdef __clang__ assert(x.column() == 20); -#else // ^^^ defined(__clang__) / !defined(__clang__) vvv +#elif defined(__EDG__) + assert(x.column() == 45); +#else // ^^^ EDG / C1XX vvv assert(x.column() == 37); -#endif // ^^^ !defined(__clang__) ^^^ +#endif // ^^^ C1XX ^^^ #if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-10199227 and LLVM-58951 assert(x.function_name() == "local_test"sv); #else // ^^^ workaround / no workaround vvv @@ -81,7 +84,11 @@ constexpr void argument_test( constexpr void sloc_constructor_test() { const s x; assert(x.loc.line() == __LINE__ - 1); +#ifdef __EDG__ + assert(x.loc.column() == 14); +#else // ^^^ defined(__EDG__) / !defined(__EDG__) vvv assert(x.loc.column() == 13); +#endif // ^^^ !defined(__EDG__) ^^^ #if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-10199227 and LLVM-58951 assert(x.loc.function_name() == "sloc_constructor_test"sv); #else // ^^^ workaround / no workaround vvv @@ -99,9 +106,11 @@ constexpr void different_constructor_test() { assert(x.loc.line() == s_int_line); #ifdef __clang__ assert(x.loc.column() == 15); -#else // ^^^ defined(__clang__) / !defined(__clang__) vvv +#elif defined(__EDG__) + assert(x.loc.column() == 22); +#else // ^^^ EDG / C1XX vvv assert(x.loc.column() == 5); -#endif // ^^^ !defined(__clang__) ^^^ +#endif // ^^^ C1XX ^^^ #if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-10199227 and LLVM-58951 assert(x.loc.function_name() == "s"sv); #elif defined(_M_IX86) // ^^^ workaround / no workaround vvv @@ -115,7 +124,11 @@ constexpr void different_constructor_test() { constexpr void sub_member_test() { const s2 s; assert(s.x.loc.line() == __LINE__ - 1); +#ifdef __EDG__ + assert(s.x.loc.column() == 15); +#else // ^^^ defined(__EDG__) / !defined(__EDG__) vvv assert(s.x.loc.column() == 14); +#endif // ^^^ !defined(__EDG__) ^^^ #if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-10199227 and LLVM-58951 assert(s.x.loc.function_name() == "sub_member_test"sv); #else // ^^^ workaround / no workaround vvv @@ -131,9 +144,11 @@ constexpr void sub_member_test() { assert(s_i.x.loc.line() == s2_int_line); #ifdef __clang__ assert(s_i.x.loc.column() == 15); -#else // ^^^ defined(__clang__) / !defined(__clang__) vvv +#elif defined(__EDG__) + assert(s_i.x.loc.column() == 23); +#else // ^^^ EDG / C1XX vvv assert(s_i.x.loc.column() == 5); -#endif // ^^^ !defined(__clang__) ^^^ +#endif // ^^^ C1XX ^^^ #if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-10199227 and LLVM-58951 assert(s_i.x.loc.function_name() == "s2"sv); #elif defined(_M_IX86) // ^^^ workaround / no workaround vvv @@ -154,10 +169,13 @@ constexpr void lambda_test() { #ifdef __clang__ assert(x1.column() == 28); assert(x2.column() == 33); -#else // ^^^ defined(__clang__) / !defined(__clang__) vvv +#elif defined(__EDG__) + assert(x1.column() == 53); + assert(x2.column() == 58); +#else // ^^^ EDG / C1XX vvv assert(x1.column() == 52); assert(x2.column() == 50); -#endif // ^^^ !defined(__clang__) ^^^ +#endif // ^^^ C1XX ^^^ #if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-10199227 and LLVM-58951 assert(x1.function_name() == "lambda_test"sv); assert(x2.function_name() == "operator()"sv); @@ -185,9 +203,11 @@ constexpr void function_template_test() { assert(x1.line() == __LINE__ - 5); #ifdef __clang__ assert(x1.column() == 12); -#else // ^^^ defined(__clang__) / !defined(__clang__) vvv +#elif defined(__EDG__) + assert(x1.column() == 37); +#else // ^^^ EDG / C1XX vvv assert(x1.column() == 29); -#endif // ^^^ !defined(__clang__) ^^^ +#endif // ^^^ C1XX ^^^ #if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-10199227 and LLVM-58951 assert(x1.function_name() == "function_template"sv); #else // ^^^ workaround / no workaround vvv @@ -209,14 +229,21 @@ constexpr void function_template_test() { constexpr bool test() { copy_test(); local_test(); +#ifdef __EDG__ + argument_test(__LINE__, 31); +#else // ^^^ defined(__EDG__) / !defined(__EDG__) vvv argument_test(__LINE__, 5); +#endif // ^^^ !defined(__EDG__) ^^^ #ifdef __clang__ const auto loc = source_location::current(); argument_test(__LINE__ - 1, 22, loc); -#else // ^^^ defined(__clang__) / !defined(__clang__) vvv +#elif defined(__EDG__) + const auto loc = source_location::current(); + argument_test(__LINE__ - 1, 47, loc); +#else // ^^^ EDG / C1XX vvv const auto loc = source_location::current(); argument_test(__LINE__ - 1, 39, loc); -#endif // ^^^ !defined(__clang__) ^^^ +#endif // ^^^ C1XX ^^^ sloc_constructor_test(); different_constructor_test(); sub_member_test(); @@ -226,17 +253,16 @@ constexpr bool test() { return true; } +#ifndef __EDG__ // TRANSITION, VSO-1849463 // Also test GH-2822 Failed to specialize std::invoke on operator() with default argument // std::source_location::current() void test_gh_2822() { // COMPILE-ONLY invoke([](source_location = source_location::current()) {}); } +#endif // ^^^ no workaround ^^^ int main() { test(); static_assert(test()); return 0; } -#else // ^^^ !defined(__EDG__) / defined(__EDG__) vvv -int main() {} -#endif // ^^^ defined(__EDG__) ^^^ 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 276dd6fdd8d..e523756c01c 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 @@ -1135,7 +1135,6 @@ STATIC_ASSERT(__cpp_lib_is_invocable == 201703L); #endif #if _HAS_CXX20 -#ifndef __EDG__ // TRANSITION, VSO-1268984 #ifndef __clang__ // TRANSITION, LLVM-48860 #ifndef __cpp_lib_is_layout_compatible #error __cpp_lib_is_layout_compatible is not defined @@ -1150,7 +1149,6 @@ STATIC_ASSERT(__cpp_lib_is_layout_compatible == 201907L); #endif #endif #endif -#endif #if _HAS_CXX20 #ifndef __cpp_lib_is_nothrow_convertible @@ -1175,7 +1173,6 @@ STATIC_ASSERT(__cpp_lib_is_null_pointer == 201309L); #endif #if _HAS_CXX20 -#ifndef __EDG__ // TRANSITION, VSO-1268984 #ifndef __clang__ // TRANSITION, LLVM-48860 #ifndef __cpp_lib_is_pointer_interconvertible #error __cpp_lib_is_pointer_interconvertible is not defined @@ -1190,7 +1187,6 @@ STATIC_ASSERT(__cpp_lib_is_pointer_interconvertible == 201907L); #endif #endif #endif -#endif #if _HAS_CXX23 #ifndef __cpp_lib_is_scoped_enum diff --git a/tests/std/tests/prefix.lst b/tests/std/tests/prefix.lst index bcecff6486a..0489944b713 100644 --- a/tests/std/tests/prefix.lst +++ b/tests/std/tests/prefix.lst @@ -3,4 +3,4 @@ RUNALL_INCLUDE ..\..\universal_prefix.lst RUNALL_CROSSLIST -PM_CL="/FIforce_include.hpp /w14365 /D_ENFORCE_FACET_SPECIALIZATIONS=1 /D_STL_CALL_ABORT_INSTEAD_OF_INVALID_PARAMETER" +PM_CL="/FIforce_include.hpp /w14365 /w15267 /D_ENFORCE_FACET_SPECIALIZATIONS=1 /D_STL_CALL_ABORT_INSTEAD_OF_INVALID_PARAMETER" diff --git a/tests/tr1/prefix.lst b/tests/tr1/prefix.lst index faad49566d5..03a2c4e6803 100644 --- a/tests/tr1/prefix.lst +++ b/tests/tr1/prefix.lst @@ -3,4 +3,4 @@ RUNALL_INCLUDE ..\universal_prefix.lst RUNALL_CROSSLIST -PM_CL="/FIforce_include.hpp /D_ENFORCE_FACET_SPECIALIZATIONS=1 /D_CRT_SECURE_NO_WARNINGS /D_STL_CALL_ABORT_INSTEAD_OF_INVALID_PARAMETER" +PM_CL="/FIforce_include.hpp /w15267 /D_ENFORCE_FACET_SPECIALIZATIONS=1 /D_CRT_SECURE_NO_WARNINGS /D_STL_CALL_ABORT_INSTEAD_OF_INVALID_PARAMETER" From 90dcf2672a5062f4be144b27a7232720d4d2c744 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Fri, 14 Jul 2023 09:26:47 +0800 Subject: [PATCH 15/35] ``: Modernize and deprecate `(un)checked_array_iterator` (#3818) Co-authored-by: Stephan T. Lavavej --- stl/inc/iterator | 95 +++++++++--- stl/inc/yvals_core.h | 14 +- .../test.cpp | 1 + .../test.cpp | 138 +++++++++++++----- .../test.compile.pass.cpp | 2 + .../test.cpp | 1 + .../test.cpp | 2 + tests/std/tests/P1614R2_spaceship/test.cpp | 2 + .../test.compile.pass.cpp | 1 + .../test.cpp | 2 + 10 files changed, 193 insertions(+), 65 deletions(-) diff --git a/stl/inc/iterator b/stl/inc/iterator index 180abaa4c2f..48089f6d0a9 100644 --- a/stl/inc/iterator +++ b/stl/inc/iterator @@ -1467,27 +1467,39 @@ struct iterator_traits> : iterator_traits<_Iter> { _STD_END _STDEXT_BEGIN -using _STD iterator_traits; using _STD size_t; template -class checked_array_iterator { // wrap a pointer with checking - static_assert(_STD is_pointer_v<_Ptr>, "checked_array_iterator requires pointers"); +class _DEPRECATE_STDEXT_ARR_ITERS checked_array_iterator { // wrap a pointer with checking +private: + using _Pointee_type = _STD remove_pointer_t<_Ptr>; + static_assert(_STD is_pointer_v<_Ptr> && _STD is_object_v<_Pointee_type>, + "checked_array_iterator requires pointers to objects"); public: - using iterator_category = typename iterator_traits<_Ptr>::iterator_category; - using value_type = typename iterator_traits<_Ptr>::value_type; - using difference_type = typename iterator_traits<_Ptr>::difference_type; - using pointer = typename iterator_traits<_Ptr>::pointer; - using reference = typename iterator_traits<_Ptr>::reference; + using iterator_category = _STD random_access_iterator_tag; + using value_type = _STD remove_cv_t<_Pointee_type>; + using difference_type = _STD ptrdiff_t; + using pointer = _Ptr; + using reference = _Pointee_type&; +#ifdef __cpp_lib_concepts + using iterator_concept = _STD contiguous_iterator_tag; +#endif // __cpp_lib_concepts - constexpr checked_array_iterator() noexcept : _Myarray(nullptr), _Mysize(0), _Myindex(0) {} + constexpr checked_array_iterator() = default; constexpr checked_array_iterator(const _Ptr _Array, const size_t _Size, const size_t _Index = 0) noexcept : _Myarray(_Array), _Mysize(_Size), _Myindex(_Index) { _STL_VERIFY(_Index <= _Size, "checked_array_iterator construction index out of range"); } + _STL_DISABLE_DEPRECATED_WARNING + template , int> = 0> + constexpr operator checked_array_iterator() const noexcept { + return checked_array_iterator{_Myarray, _Mysize, _Myindex}; + } + _STL_RESTORE_DEPRECATED_WARNING + _NODISCARD constexpr _Ptr base() const noexcept { return _Myarray + _Myindex; } @@ -1658,32 +1670,47 @@ public: } private: - _Ptr _Myarray; // beginning of array - size_t _Mysize; // size of array - size_t _Myindex; // offset into array + _Ptr _Myarray = nullptr; // beginning of array + size_t _Mysize = 0; // size of array + size_t _Myindex = 0; // offset into array }; +_STL_DISABLE_DEPRECATED_WARNING template -_NODISCARD constexpr checked_array_iterator<_Ptr> make_checked_array_iterator( - const _Ptr _Array, const size_t _Size, const size_t _Index = 0) { +_DEPRECATE_STDEXT_ARR_ITERS _NODISCARD constexpr checked_array_iterator<_Ptr> make_checked_array_iterator( + const _Ptr _Array, const size_t _Size, const size_t _Index = 0) noexcept { return checked_array_iterator<_Ptr>(_Array, _Size, _Index); } +_STL_RESTORE_DEPRECATED_WARNING template -class unchecked_array_iterator { // wrap a pointer without checking, to silence warnings - static_assert(_STD is_pointer_v<_Ptr>, "unchecked_array_iterator requires pointers"); +class _DEPRECATE_STDEXT_ARR_ITERS unchecked_array_iterator { // wrap a pointer without checking, to silence warnings +private: + using _Pointee_type = _STD remove_pointer_t<_Ptr>; + static_assert(_STD is_pointer_v<_Ptr> && _STD is_object_v<_Pointee_type>, + "unchecked_array_iterator requires pointers to objects"); public: - using iterator_category = typename iterator_traits<_Ptr>::iterator_category; - using value_type = typename iterator_traits<_Ptr>::value_type; - using difference_type = typename iterator_traits<_Ptr>::difference_type; - using pointer = typename iterator_traits<_Ptr>::pointer; - using reference = typename iterator_traits<_Ptr>::reference; + using iterator_category = _STD random_access_iterator_tag; + using value_type = _STD remove_cv_t<_Pointee_type>; + using difference_type = _STD ptrdiff_t; + using pointer = _Ptr; + using reference = _Pointee_type&; +#ifdef __cpp_lib_concepts + using iterator_concept = _STD contiguous_iterator_tag; +#endif // __cpp_lib_concepts - constexpr unchecked_array_iterator() noexcept : _Myptr(nullptr) {} + constexpr unchecked_array_iterator() = default; constexpr explicit unchecked_array_iterator(const _Ptr _Src) noexcept : _Myptr(_Src) {} + _STL_DISABLE_DEPRECATED_WARNING + template , int> = 0> + constexpr operator unchecked_array_iterator() const noexcept { + return unchecked_array_iterator{_Myptr}; + } + _STL_RESTORE_DEPRECATED_WARNING + _NODISCARD constexpr _Ptr base() const noexcept { return _Myptr; } @@ -1802,15 +1829,35 @@ public: } private: - _Ptr _Myptr; // underlying pointer + _Ptr _Myptr = nullptr; // underlying pointer }; +_STL_DISABLE_DEPRECATED_WARNING template -_NODISCARD unchecked_array_iterator<_Ptr> make_unchecked_array_iterator(const _Ptr _It) noexcept { +_DEPRECATE_STDEXT_ARR_ITERS _NODISCARD unchecked_array_iterator<_Ptr> make_unchecked_array_iterator( + const _Ptr _It) noexcept { return unchecked_array_iterator<_Ptr>(_It); } +_STL_RESTORE_DEPRECATED_WARNING _STDEXT_END +#if _HAS_CXX20 +_STD_BEGIN +_STL_DISABLE_DEPRECATED_WARNING +template +struct pointer_traits<_STDEXT checked_array_iterator<_Ty*>> { + using pointer = _STDEXT checked_array_iterator<_Ty*>; + using element_type = _Ty; + using difference_type = ptrdiff_t; + + _NODISCARD static constexpr element_type* to_address(const pointer _Iter) noexcept { + return _Iter._Unwrapped(); + } +}; +_STL_RESTORE_DEPRECATED_WARNING +_STD_END +#endif // _HAS_CXX20 + #pragma pop_macro("new") _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 7bae2e830b3..2b84d713f45 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1445,7 +1445,19 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #define _CXX23_DEPRECATE_DENORM #endif // ^^^ warning disabled ^^^ -// next warning number: STL4043 +#if _HAS_CXX17 && !defined(_SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _DEPRECATE_STDEXT_ARR_ITERS \ + [[deprecated( \ + "warning STL4043: stdext::checked_array_iterator, stdext::unchecked_array_iterator, and related factory " \ + "functions are non-Standard extensions and will be removed in the future. std::span (since C++20) " \ + "and gsl::span can be used instead. You can define _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING or " \ + "_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to suppress this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _DEPRECATE_STDEXT_ARR_ITERS +#endif // ^^^ warning disabled ^^^ + +// next warning number: STL4044 // next error number: STL1006 diff --git a/tests/std/tests/Dev10_500860_overloaded_address_of/test.cpp b/tests/std/tests/Dev10_500860_overloaded_address_of/test.cpp index 93b4ead540d..5718201bf03 100644 --- a/tests/std/tests/Dev10_500860_overloaded_address_of/test.cpp +++ b/tests/std/tests/Dev10_500860_overloaded_address_of/test.cpp @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#define _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING #define _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS #include diff --git a/tests/std/tests/Dev10_709166_checked_and_unchecked_array_iterator/test.cpp b/tests/std/tests/Dev10_709166_checked_and_unchecked_array_iterator/test.cpp index 5addf960bdc..a1f8f5b611f 100644 --- a/tests/std/tests/Dev10_709166_checked_and_unchecked_array_iterator/test.cpp +++ b/tests/std/tests/Dev10_709166_checked_and_unchecked_array_iterator/test.cpp @@ -1,15 +1,74 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#define _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING + #include #include +#include #include +#include +#include #include #include #include +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +template +void check_checked_array_iterator_category_and_convertibility() { + STATIC_ASSERT(std::is_same_v::iterator_category, + std::random_access_iterator_tag>); + + STATIC_ASSERT(std::is_same_v::value_type, std::remove_cv_t>); + + STATIC_ASSERT(std::is_same_v::difference_type, std::ptrdiff_t>); + + STATIC_ASSERT(std::is_same_v::pointer, T*>); + + STATIC_ASSERT(std::is_same_v::reference, T&>); + + STATIC_ASSERT(std::is_convertible_v, stdext::checked_array_iterator>); + +#ifdef __cpp_lib_concepts + STATIC_ASSERT( + std::is_same_v::iterator_concept, std::contiguous_iterator_tag>); + + STATIC_ASSERT(std::contiguous_iterator>); +#endif // __cpp_lib_concepts +} + +template +void check_unchecked_array_iterator_category_and_convertibility() { + STATIC_ASSERT(std::is_same_v::iterator_category, + std::random_access_iterator_tag>); + + STATIC_ASSERT(std::is_same_v::value_type, std::remove_cv_t>); + + STATIC_ASSERT(std::is_same_v::difference_type, std::ptrdiff_t>); + + STATIC_ASSERT(std::is_same_v::pointer, T*>); + + STATIC_ASSERT(std::is_same_v::reference, T&>); + + STATIC_ASSERT( + std::is_convertible_v, stdext::unchecked_array_iterator>); + +#ifdef __cpp_lib_concepts + STATIC_ASSERT( + std::is_same_v::iterator_concept, std::contiguous_iterator_tag>); + + STATIC_ASSERT(std::contiguous_iterator>); +#endif // __cpp_lib_concepts +} + int main() { { + check_checked_array_iterator_category_and_convertibility(); + check_checked_array_iterator_category_and_convertibility(); + check_checked_array_iterator_category_and_convertibility>(); + + int* const p = new int[9]; for (int i = 0; i < 9; ++i) { @@ -19,31 +78,28 @@ int main() { auto cat = stdext::make_checked_array_iterator(p, 9); - static_assert(std::is_same_v>, - "stdext::make_checked_array_iterator(p, 9)'s return type is wrong!"); - - - auto dog = stdext::make_checked_array_iterator(p, 9, 3); - - static_assert(std::is_same_v>, - "stdext::make_checked_array_iterator(p, 9, 3)'s return type is wrong!"); - + STATIC_ASSERT(std::is_same_v>); - static_assert( - std::is_same_v::iterator_category, std::random_access_iterator_tag>, - "stdext::checked_array_iterator::iterator_category is wrong!"); +#if _HAS_CXX20 + assert(std::to_address(cat) == &*cat); + assert(std::to_address(cat + 8) == &*cat + 8); + assert(std::to_address(cat + 8) == std::to_address(cat) + 8); + assert(std::to_address(cat + 9) == std::to_address(cat) + 9); +#endif // _HAS_CXX20 - static_assert(std::is_same_v::value_type, int>, - "stdext::checked_array_iterator::value_type is wrong!"); - static_assert(std::is_same_v::difference_type, ptrdiff_t>, - "stdext::checked_array_iterator::difference_type is wrong!"); + auto dog = stdext::make_checked_array_iterator(p, 9, 3); - static_assert(std::is_same_v::pointer, int*>, - "stdext::checked_array_iterator::pointer is wrong!"); + STATIC_ASSERT(std::is_same_v>); - static_assert(std::is_same_v::reference, int&>, - "stdext::checked_array_iterator::reference is wrong!"); +#if _HAS_CXX20 + assert(std::to_address(dog) == &*dog); + assert(std::to_address(dog + 5) == &*dog + 5); + assert(std::to_address(dog + 5) == std::to_address(dog) + 5); + assert(std::to_address(dog - 3) == &*dog - 3); + assert(std::to_address(dog - 3) == std::to_address(dog) - 3); + assert(std::to_address(dog + 6) == std::to_address(dog) + 6); +#endif // _HAS_CXX20 { @@ -184,6 +240,11 @@ int main() { } { + check_unchecked_array_iterator_category_and_convertibility(); + check_unchecked_array_iterator_category_and_convertibility(); + check_unchecked_array_iterator_category_and_convertibility>(); + + int* const p = new int[9]; for (int i = 0; i < 9; ++i) { @@ -193,31 +254,28 @@ int main() { auto cat = stdext::make_unchecked_array_iterator(p); - static_assert(std::is_same_v>, - "stdext::make_unchecked_array_iterator(p)'s return type is wrong!"); + STATIC_ASSERT(std::is_same_v>); +#if _HAS_CXX20 + assert(std::to_address(cat) == &*cat); + assert(std::to_address(cat + 8) == &*cat + 8); + assert(std::to_address(cat + 8) == std::to_address(cat) + 8); + assert(std::to_address(cat + 9) == std::to_address(cat) + 9); +#endif // _HAS_CXX20 - auto dog = stdext::make_unchecked_array_iterator(p + 3); - - static_assert(std::is_same_v>, - "stdext::make_unchecked_array_iterator(p + 3)'s return type is wrong!"); + auto dog = stdext::make_unchecked_array_iterator(p + 3); - static_assert( - std::is_same_v::iterator_category, std::random_access_iterator_tag>, - "stdext::unchecked_array_iterator::iterator_category is wrong!"); - - static_assert(std::is_same_v::value_type, int>, - "stdext::unchecked_array_iterator::value_type is wrong!"); - - static_assert(std::is_same_v::difference_type, ptrdiff_t>, - "stdext::unchecked_array_iterator::difference_type is wrong!"); - - static_assert(std::is_same_v::pointer, int*>, - "stdext::unchecked_array_iterator::pointer is wrong!"); + STATIC_ASSERT(std::is_same_v>); - static_assert(std::is_same_v::reference, int&>, - "stdext::unchecked_array_iterator::reference is wrong!"); +#if _HAS_CXX20 + assert(std::to_address(dog) == &*dog); + assert(std::to_address(dog + 5) == &*dog + 5); + assert(std::to_address(dog + 5) == std::to_address(dog) + 5); + assert(std::to_address(dog - 3) == &*dog - 3); + assert(std::to_address(dog - 3) == std::to_address(dog) - 3); + assert(std::to_address(dog + 6) == std::to_address(dog) + 6); +#endif // _HAS_CXX20 { diff --git a/tests/std/tests/Dev10_709168_marking_iterators_as_checked/test.compile.pass.cpp b/tests/std/tests/Dev10_709168_marking_iterators_as_checked/test.compile.pass.cpp index 4e7f0833bce..754b6a632f2 100644 --- a/tests/std/tests/Dev10_709168_marking_iterators_as_checked/test.compile.pass.cpp +++ b/tests/std/tests/Dev10_709168_marking_iterators_as_checked/test.compile.pass.cpp @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#define _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING + #include #include #include diff --git a/tests/std/tests/Dev11_0000000_null_forward_iterators/test.cpp b/tests/std/tests/Dev11_0000000_null_forward_iterators/test.cpp index f9ea851fcc1..64e3e9d2cf4 100644 --- a/tests/std/tests/Dev11_0000000_null_forward_iterators/test.cpp +++ b/tests/std/tests/Dev11_0000000_null_forward_iterators/test.cpp @@ -3,6 +3,7 @@ #define _SILENCE_CXX23_ALIGNED_UNION_DEPRECATION_WARNING #define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING +#define _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING #include #include diff --git a/tests/std/tests/P0040R3_extending_memory_management_tools/test.cpp b/tests/std/tests/P0040R3_extending_memory_management_tools/test.cpp index 771425af7e0..dce64b84442 100644 --- a/tests/std/tests/P0040R3_extending_memory_management_tools/test.cpp +++ b/tests/std/tests/P0040R3_extending_memory_management_tools/test.cpp @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#define _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING + #include #include #include diff --git a/tests/std/tests/P1614R2_spaceship/test.cpp b/tests/std/tests/P1614R2_spaceship/test.cpp index aee2e256ee3..45b77573ce6 100644 --- a/tests/std/tests/P1614R2_spaceship/test.cpp +++ b/tests/std/tests/P1614R2_spaceship/test.cpp @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#define _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING + #include #include #include diff --git a/tests/std/tests/VSO_0000000_instantiate_iterators_misc/test.compile.pass.cpp b/tests/std/tests/VSO_0000000_instantiate_iterators_misc/test.compile.pass.cpp index 7ade4b41b17..690dd4be34a 100644 --- a/tests/std/tests/VSO_0000000_instantiate_iterators_misc/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0000000_instantiate_iterators_misc/test.compile.pass.cpp @@ -18,6 +18,7 @@ #define _SILENCE_CXX20_REL_OPS_DEPRECATION_WARNING #define _SILENCE_CXX20_U8PATH_DEPRECATION_WARNING #define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING +#define _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING #define _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING #define _USE_NAMED_IDL_NAMESPACE 1 diff --git a/tests/std/tests/VSO_0299624_checked_array_iterator_idl/test.cpp b/tests/std/tests/VSO_0299624_checked_array_iterator_idl/test.cpp index 91aee8682f3..f5da03d2735 100644 --- a/tests/std/tests/VSO_0299624_checked_array_iterator_idl/test.cpp +++ b/tests/std/tests/VSO_0299624_checked_array_iterator_idl/test.cpp @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#define _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING + #include #include From cc6533adbb7b317d2867887e32d547236f940fc1 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Fri, 14 Jul 2023 09:36:13 +0800 Subject: [PATCH 16/35] Implement P2538R1 ADL-Proof `projected` (#3822) Co-authored-by: Stephan T. Lavavej --- stl/inc/xutility | 40 ++++++++++---- stl/inc/yvals_core.h | 1 + tests/std/test.lst | 1 + .../P2538R1_adl_proof_std_projected/env.lst | 4 ++ .../test.compile.pass.cpp | 54 +++++++++++++++++++ .../env.lst | 2 +- 6 files changed, 90 insertions(+), 12 deletions(-) create mode 100644 tests/std/tests/P2538R1_adl_proof_std_projected/env.lst create mode 100644 tests/std/tests/P2538R1_adl_proof_std_projected/test.compile.pass.cpp diff --git a/stl/inc/xutility b/stl/inc/xutility index 681fb49c0bc..a4312e1ba25 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -864,22 +864,40 @@ _EXPORT_STD template requires (indirectly_readable<_Its> && ...) && invocable<_Fn, iter_reference_t<_Its>...> using indirect_result_t = invoke_result_t<_Fn, iter_reference_t<_Its>...>; -_EXPORT_STD template _Proj> -struct projected { - using value_type = remove_cvref_t>; - indirect_result_t<_Proj&, _It> operator*() const { - _CSTD abort(); - } +template +struct _Projected_difference_type_impl { + struct _Base {}; +}; + +template +struct _Projected_difference_type_impl<_It> { + struct _Base { + using difference_type = iter_difference_t<_It>; + }; }; template -struct _Indirect_value_impl> { - using type = invoke_result_t<_Proj&, _Indirect_value_t<_It>>; +struct _Projected_impl { + struct _Type : _Projected_difference_type_impl<_It>::_Base { + using _Iterator = _It; + using _Projection = _Proj; + + using value_type = remove_cvref_t>; + indirect_result_t<_Proj&, _It> operator*() const { + _CSTD abort(); + } + }; }; -template -struct incrementable_traits> { - using difference_type = iter_difference_t<_It>; +_EXPORT_STD template _Proj> +using projected = _Projected_impl<_It, _Proj>::_Type; + +template +concept _Projected_specialization = same_as<_Ty, projected>; + +template <_Projected_specialization _ProjTy> +struct _Indirect_value_impl<_ProjTy> { + using type = invoke_result_t>; }; _EXPORT_STD template diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 2b84d713f45..a33eb6a44c3 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -285,6 +285,7 @@ // P2432R1 Fix istream_view // P2508R1 basic_format_string, format_string, wformat_string // P2520R0 move_iterator Should Be A Random-Access Iterator +// P2538R1 ADL-Proof projected // P2572R1 std::format Fill Character Allowances // P2588R3 barrier's Phase Completion Guarantees // P2602R2 Poison Pills Are Too Toxic diff --git a/tests/std/test.lst b/tests/std/test.lst index 5c0b3ca9533..5ac86ab8aed 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -618,6 +618,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\P2538R1_adl_proof_std_projected tests\P2609R3_relaxing_ranges_just_a_smidge tests\VSO_0000000_allocator_propagation tests\VSO_0000000_any_calling_conventions diff --git a/tests/std/tests/P2538R1_adl_proof_std_projected/env.lst b/tests/std/tests/P2538R1_adl_proof_std_projected/env.lst new file mode 100644 index 00000000000..d6d824b5879 --- /dev/null +++ b/tests/std/tests/P2538R1_adl_proof_std_projected/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\concepts_20_matrix.lst diff --git a/tests/std/tests/P2538R1_adl_proof_std_projected/test.compile.pass.cpp b/tests/std/tests/P2538R1_adl_proof_std_projected/test.compile.pass.cpp new file mode 100644 index 00000000000..c1a405fc864 --- /dev/null +++ b/tests/std/tests/P2538R1_adl_proof_std_projected/test.compile.pass.cpp @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef _M_CEE // TRANSITION, VSO-1659496 +#include +#include +#include +#include +#include + +using namespace std; + +// TRANSITION, GH-1596, should use ranges::count +struct my_count_fn { + template S, class T, class Proj = identity> + requires indirect_binary_predicate, const T*> + constexpr iter_difference_t operator()(I first, S last, const T& value, Proj proj = {}) const { + iter_difference_t counter = 0; + for (; first != last; ++first) { + if (std::invoke(proj, *first) == value) { // intentionally qualified to avoid ADL + ++counter; + } + } + return counter; + } + + template + requires indirect_binary_predicate, Proj>, const T*> + constexpr ranges::range_difference_t operator()(R&& r, const T& value, Proj proj = {}) const { + return (*this)(ranges::begin(r), ranges::end(r), value, ref(proj)); + } +}; + +inline constexpr my_count_fn my_count; + +template +struct Holder { + T t; +}; +struct Incomplete; + +static_assert(equality_comparable*>); +static_assert(indirectly_comparable**, Holder**, equal_to<>>); +static_assert(sortable**>); + +constexpr bool test() { + Holder* a[10] = {}; + assert(my_count(a, a + 10, nullptr) == 10); + assert(my_count(a, nullptr) == 10); + return true; +} + +static_assert(test()); +#endif // _M_CEE 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 index 18e2d7c71ec..d6d824b5879 100644 --- a/tests/std/tests/P2609R3_relaxing_ranges_just_a_smidge/env.lst +++ b/tests/std/tests/P2609R3_relaxing_ranges_just_a_smidge/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 ..\concepts_20_matrix.lst From f155b411f26ca0c551d42bd438c533af999bc6ac Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Fri, 14 Jul 2023 09:40:12 +0800 Subject: [PATCH 17/35] Test coverage for LWG-2682 `filesystem::copy()` won't create a symlink to a directory (#3827) --- tests/std/tests/P0218R1_filesystem/test.cpp | 22 +++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/std/tests/P0218R1_filesystem/test.cpp b/tests/std/tests/P0218R1_filesystem/test.cpp index 1f53756d979..9dccd939413 100644 --- a/tests/std/tests/P0218R1_filesystem/test.cpp +++ b/tests/std/tests/P0218R1_filesystem/test.cpp @@ -2248,6 +2248,26 @@ void test_copy_symlink() { } } +void test_copy_directory_as_symlink() { + const path dirpath{L"./test-lwg2682-dir"sv}; + error_code ec; + create_directory(dirpath, ec); + EXPECT(good(ec)); + try { + copy(dirpath, L"./symlink"sv, copy_options::create_symlinks); + EXPECT(false); + } catch (filesystem_error& e) { + EXPECT(e.code().value() == static_cast(errc::is_a_directory)); + } + { + error_code copy_ec; + copy(dirpath, L"./symlink"sv, copy_options::create_symlinks, copy_ec); + EXPECT(copy_ec.value() == static_cast(errc::is_a_directory)); + } + remove_all(dirpath, ec); + EXPECT(good(ec)); +} + void equivalent_failure_test_case(const path& left, const path& right) { EXPECT(throws_filesystem_error([&] { EXPECT(!equivalent(left, right)); }, "equivalent", left, right)); @@ -3997,6 +4017,8 @@ int wmain(int argc, wchar_t* argv[]) { test_copy_symlink(); + test_copy_directory_as_symlink(); // per LWG-2682 + test_conversions(); test_file_size(); From 7c7cc0c13dd75957b2d23952cb9b99a17193004b Mon Sep 17 00:00:00 2001 From: statementreply Date: Fri, 14 Jul 2023 09:43:51 +0800 Subject: [PATCH 18/35] Add `[[msvc::lifetimebound]]` to `minmax` (#3831) Co-authored-by: Stephan T. Lavavej --- stl/inc/algorithm | 24 ++++++++++++++----- stl/inc/yvals_core.h | 14 +++++++++++ tests/std/lit.site.cfg.in | 2 ++ tests/std/rulesets/stl.ruleset | 11 +++++++++ tests/std/test.lst | 2 ++ .../GH_002094_cpp_core_guidelines/env.lst | 16 +++++++++++++ .../test.compile.pass.cpp | 4 ++++ tests/utils/stl/test/format.py | 2 +- tests/utils/stl/test/tests.py | 14 +++++++++++ 9 files changed, 82 insertions(+), 7 deletions(-) create mode 100644 tests/std/rulesets/stl.ruleset create mode 100644 tests/std/tests/GH_002094_cpp_core_guidelines/env.lst create mode 100644 tests/std/tests/GH_002094_cpp_core_guidelines/test.compile.pass.cpp diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 7a8f91dc1aa..466fbf25731 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -21,6 +21,12 @@ _STL_DISABLE_CLANG_WARNINGS #pragma push_macro("new") #undef new +// TRANSITION, non-_Ugly attribute tokens +#pragma push_macro("msvc") +#pragma push_macro("lifetimebound") +#undef msvc +#undef lifetimebound + #if _USE_STD_VECTOR_ALGORITHMS _EXTERN_C @@ -10003,8 +10009,9 @@ namespace ranges { #endif // _HAS_CXX17 _EXPORT_STD template -_NODISCARD constexpr pair minmax(const _Ty& _Left, const _Ty& _Right, _Pr _Pred) noexcept( - noexcept(_DEBUG_LT_PRED(_Pred, _Right, _Left))) /* strengthened */ { +_NODISCARD constexpr pair minmax(const _Ty& _Left _MSVC_LIFETIMEBOUND, + const _Ty& _Right _MSVC_LIFETIMEBOUND, + _Pr _Pred) noexcept(noexcept(_DEBUG_LT_PRED(_Pred, _Right, _Left))) /* strengthened */ { // return pair(leftmost/smaller, rightmost/larger) of _Left and _Right if (_DEBUG_LT_PRED(_Pred, _Right, _Left)) { return {_Right, _Left}; @@ -10021,8 +10028,8 @@ _NODISCARD constexpr pair<_Ty, _Ty> minmax(initializer_list<_Ty> _Ilist, _Pr _Pr } _EXPORT_STD template -_NODISCARD constexpr pair minmax(const _Ty& _Left, const _Ty& _Right) noexcept( - noexcept(_Right < _Left)) /* strengthened */ { +_NODISCARD constexpr pair minmax(const _Ty& _Left _MSVC_LIFETIMEBOUND, + const _Ty& _Right _MSVC_LIFETIMEBOUND) noexcept(noexcept(_Right < _Left)) /* strengthened */ { // return pair(leftmost/smaller, rightmost/larger) of _Left and _Right if (_Right < _Left) { _STL_ASSERT(!(_Left < _Right), "invalid comparator"); @@ -10049,8 +10056,8 @@ namespace ranges { template > _Pr = ranges::less> - _NODISCARD constexpr minmax_result operator()( - const _Ty& _Left, const _Ty& _Right, _Pr _Pred = {}, _Pj _Proj = {}) const { + _NODISCARD constexpr minmax_result operator()(const _Ty& _Left _MSVC_LIFETIMEBOUND, + const _Ty& _Right _MSVC_LIFETIMEBOUND, _Pr _Pred = {}, _Pj _Proj = {}) const { if (_STD invoke(_Pred, _STD invoke(_Proj, _Right), _STD invoke(_Proj, _Left))) { return {_Right, _Left}; } else { @@ -10673,6 +10680,11 @@ namespace ranges { #endif // _HAS_CXX17 _STD_END + +// TRANSITION, non-_Ugly attribute tokens +#pragma pop_macro("lifetimebound") +#pragma pop_macro("msvc") + #pragma pop_macro("new") _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index a33eb6a44c3..394c40f10c1 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -664,10 +664,12 @@ #pragma push_macro("known_semantics") #pragma push_macro("noop_dtor") #pragma push_macro("intrinsic") +#pragma push_macro("lifetimebound") #undef msvc #undef known_semantics #undef noop_dtor #undef intrinsic +#undef lifetimebound #ifndef __has_cpp_attribute #define _HAS_MSVC_ATTRIBUTE(x) 0 @@ -701,7 +703,19 @@ #define _MSVC_INTRINSIC #endif +// Should we enable [[msvc::lifetimebound]] or [[clang::lifetimebound]] warnings? +#if !defined(__has_cpp_attribute) || defined(_SILENCE_LIFETIMEBOUND_WARNING) +#define _MSVC_LIFETIMEBOUND +#elif _HAS_MSVC_ATTRIBUTE(lifetimebound) +#define _MSVC_LIFETIMEBOUND [[msvc::lifetimebound]] +#elif __has_cpp_attribute(_Clang::__lifetimebound__) +#define _MSVC_LIFETIMEBOUND [[_Clang::__lifetimebound__]] +#else +#define _MSVC_LIFETIMEBOUND +#endif + #undef _HAS_MSVC_ATTRIBUTE +#pragma pop_macro("lifetimebound") #pragma pop_macro("intrinsic") #pragma pop_macro("noop_dtor") #pragma pop_macro("known_semantics") diff --git a/tests/std/lit.site.cfg.in b/tests/std/lit.site.cfg.in index 78cdb1a7130..9941c44e79c 100644 --- a/tests/std/lit.site.cfg.in +++ b/tests/std/lit.site.cfg.in @@ -19,12 +19,14 @@ config.test_format = stl.test.format.STLTestFormat() lit_config.expected_results = getattr(lit_config, 'expected_results', dict()) lit_config.include_dirs = getattr(lit_config, 'include_dirs', dict()) lit_config.library_dirs = getattr(lit_config, 'library_dirs', dict()) +lit_config.ruleset_dirs = getattr(lit_config, 'ruleset_dirs', dict()) lit_config.test_subdirs = getattr(lit_config, 'test_subdirs', dict()) lit_config.expected_results[config.name] = stl.test.file_parsing.parse_result_file('@STD_EXPECTED_RESULTS@') lit_config.include_dirs[config.name] = \ ['@STL_TESTED_HEADERS_DIR@', '@LIBCXX_SOURCE_DIR@/test/support', '@STL_SOURCE_DIR@/tests/std/include'] lit_config.library_dirs[config.name] = ['@STL_LIBRARY_OUTPUT_DIRECTORY@', '@TOOLSET_LIB@'] +lit_config.ruleset_dirs[config.name] = ['@STL_SOURCE_DIR@/tests/std/rulesets'] lit_config.test_subdirs[config.name] = ['@CMAKE_CURRENT_SOURCE_DIR@/tests'] lit_config.cxx_headers = '@STL_TESTED_HEADERS_DIR@' diff --git a/tests/std/rulesets/stl.ruleset b/tests/std/rulesets/stl.ruleset new file mode 100644 index 00000000000..7859a44da86 --- /dev/null +++ b/tests/std/rulesets/stl.ruleset @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tests/std/test.lst b/tests/std/test.lst index 5ac86ab8aed..1fd920dc5ec 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -200,6 +200,8 @@ tests\GH_002030_asan_annotate_vector tests\GH_002039_byte_is_not_trivially_swappable tests\GH_002045_put_time_changes_errno tests\GH_002058_debug_iterator_race +# Needs special machinery to work in the MSVC-internal test harness, not yet implemented: +# tests\GH_002094_cpp_core_guidelines tests\GH_002120_streambuf_seekpos_and_seekoff tests\GH_002168_regex_overflow tests\GH_002206_unreserved_names diff --git a/tests/std/tests/GH_002094_cpp_core_guidelines/env.lst b/tests/std/tests/GH_002094_cpp_core_guidelines/env.lst new file mode 100644 index 00000000000..56a4f87e0b0 --- /dev/null +++ b/tests/std/tests/GH_002094_cpp_core_guidelines/env.lst @@ -0,0 +1,16 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\prefix.lst +RUNALL_CROSSLIST +PM_CL="/EHsc /w14640 /Zc:threadSafeInit-" +RUNALL_CROSSLIST +PM_CL="/MD /D_ITERATOR_DEBUG_LEVEL=0 /std:c++14 /analyze:only /analyze:autolog- /analyze:plugin EspXEngine.dll /analyze:ruleset stl.ruleset" +PM_CL="/MDd /D_ITERATOR_DEBUG_LEVEL=2 /std:c++17 /permissive- /analyze:only /analyze:autolog- /analyze:plugin EspXEngine.dll /analyze:ruleset stl.ruleset" +PM_CL="/MDd /D_ITERATOR_DEBUG_LEVEL=2 /std:c++20 /permissive- /analyze:only /analyze:autolog- /analyze:plugin EspXEngine.dll /analyze:ruleset stl.ruleset" +PM_CL="/MT /D_ITERATOR_DEBUG_LEVEL=0 /std:c++latest /permissive- /analyze:only /analyze:autolog- /analyze:plugin EspXEngine.dll /analyze:ruleset stl.ruleset" +PM_CL="/MTd /D_ITERATOR_DEBUG_LEVEL=2 /std:c++latest /permissive- /analyze:only /analyze:autolog- /analyze:plugin EspXEngine.dll /analyze:ruleset stl.ruleset" +PM_COMPILER="clang-cl" PM_CL="-fno-ms-compatibility -fno-delayed-template-parsing -Wno-unqualified-std-cast-call /MD /std:c++14" +PM_COMPILER="clang-cl" PM_CL="-fno-ms-compatibility -fno-delayed-template-parsing -Wno-unqualified-std-cast-call /MDd /std:c++17" +PM_COMPILER="clang-cl" PM_CL="-fno-ms-compatibility -fno-delayed-template-parsing -Wno-unqualified-std-cast-call /MT /std:c++20 /permissive-" +PM_COMPILER="clang-cl" PM_CL="-fno-ms-compatibility -fno-delayed-template-parsing -Wno-unqualified-std-cast-call /MTd /std:c++latest /permissive-" diff --git a/tests/std/tests/GH_002094_cpp_core_guidelines/test.compile.pass.cpp b/tests/std/tests/GH_002094_cpp_core_guidelines/test.compile.pass.cpp new file mode 100644 index 00000000000..1132aa12357 --- /dev/null +++ b/tests/std/tests/GH_002094_cpp_core_guidelines/test.compile.pass.cpp @@ -0,0 +1,4 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include <__msvc_all_public_headers.hpp> diff --git a/tests/utils/stl/test/format.py b/tests/utils/stl/test/format.py index 7de5471eda7..096a0a7907c 100644 --- a/tests/utils/stl/test/format.py +++ b/tests/utils/stl/test/format.py @@ -145,7 +145,7 @@ class SharedState: env: Dict[str, str] = field(default_factory=dict) execDir, _ = test.getTempPaths() - shared = SharedState(None, execDir, copy.deepcopy(litConfig.test_env)) + shared = SharedState(None, execDir, _mergeEnvironments(litConfig.test_env, test.env)) shared.env['TMP'] = execDir shared.env['TEMP'] = execDir shared.env['TMPDIR'] = execDir diff --git a/tests/utils/stl/test/tests.py b/tests/utils/stl/test/tests.py index fc0b0e2fafe..21f0bb9921a 100644 --- a/tests/utils/stl/test/tests.py +++ b/tests/utils/stl/test/tests.py @@ -38,6 +38,7 @@ def __init__(self, suite, pathInSuite, litConfig, testConfig, envlstEntry, envNu def configureTest(self, litConfig): self.compileFlags = [] self.cxx = None + self.env = {} self.fileDependencies = [] self.flags = [] self.isenseRspPath = None @@ -234,7 +235,13 @@ def _addCustomFeature(self, name): def _parseFlags(self, litConfig): foundStd = False foundCRT = False + afterAnalyzePlugin = False for flag in chain(self.flags, self.compileFlags, self.linkFlags): + if afterAnalyzePlugin: + if 'EspXEngine.dll'.casefold() in flag.casefold(): + self._addCustomFeature('espxengine') + afterAnalyzePlugin = False + if flag[1:5] == 'std:': foundStd = True if flag[5:] == 'c++latest': @@ -279,6 +286,8 @@ def _parseFlags(self, litConfig): self._addCustomFeature('MT') self._addCustomFeature('static_CRT') foundCRT = True + elif flag[1:] == 'analyze:plugin': + afterAnalyzePlugin = True if not foundStd: self._addCustomFeature('c++14') @@ -294,6 +303,11 @@ def _parseFlags(self, litConfig): if 'asan' in self.config.available_features and 'clang' in self.config.available_features: self.linkFlags.append("/INFERASANLIBS") + # code analysis settings + if 'espxengine' in self.config.available_features: + self.compileFlags.extend(["/analyze:rulesetdirectory", ';'.join(litConfig.ruleset_dirs[self.config.name])]) + self.env['Esp.Extensions'] = 'CppCoreCheck.dll' + self.env['Esp.AnnotationBuildLevel'] = 'Ignore' class LibcxxTest(STLTest): def getTestName(self): From ab57910040a0ccd9fa36e22536f3fc25a8225ef3 Mon Sep 17 00:00:00 2001 From: Igor Zhukov Date: Fri, 14 Jul 2023 08:48:49 +0700 Subject: [PATCH 19/35] add specialization for 24MHz QueryPerformanceFrequency (#3832) Co-authored-by: Steven Noonan Co-authored-by: Stephan T. Lavavej --- stl/inc/__msvc_chrono.hpp | 32 +++++++++++++++++++++++++++----- stl/inc/yvals_core.h | 14 ++++++++++++++ 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/stl/inc/__msvc_chrono.hpp b/stl/inc/__msvc_chrono.hpp index 45b9f75f782..581d2e74f0d 100644 --- a/stl/inc/__msvc_chrono.hpp +++ b/stl/inc/__msvc_chrono.hpp @@ -666,18 +666,37 @@ namespace chrono { using time_point = _CHRONO time_point; static constexpr bool is_steady = true; +#if defined(_M_ARM) || defined(_M_ARM64) // vvv ARM or ARM64 arch vvv +#define _LIKELY_ARM_ARM64 _LIKELY +#define _LIKELY_X86_X64 +#elif defined(_M_IX86) || defined(_M_X64) // ^^^ ARM or ARM64 arch / x86 or x64 arch vvv +#define _LIKELY_ARM_ARM64 +#define _LIKELY_X86_X64 _LIKELY +#else // ^^^ x86 or x64 arch / other arch vvv +#define _LIKELY_ARM_ARM64 +#define _LIKELY_X86_X64 +#endif // ^^^ other arch ^^^ _NODISCARD static time_point now() noexcept { // get current time const long long _Freq = _Query_perf_frequency(); // doesn't change after system boot const long long _Ctr = _Query_perf_counter(); static_assert(period::num == 1, "This assumes period::num == 1."); - // 10 MHz is a very common QPC frequency on modern PCs. Optimizing for - // this specific frequency can double the performance of this function by - // avoiding the expensive frequency conversion path. - constexpr long long _TenMHz = 10'000'000; - if (_Freq == _TenMHz) { + // The compiler recognizes the constants for frequency and time period and uses shifts and + // multiplies instead of divides to calculate the nanosecond value. + constexpr long long _TenMHz = 10'000'000; + constexpr long long _TwentyFourMHz = 24'000'000; + // clang-format off + if (_Freq == _TenMHz) _LIKELY_X86_X64 { + // 10 MHz is a very common QPC frequency on modern x86/x64 PCs. Optimizing for + // this specific frequency can double the performance of this function by + // avoiding the expensive frequency conversion path. static_assert(period::den % _TenMHz == 0, "It should never fail."); constexpr long long _Multiplier = period::den / _TenMHz; return time_point(duration(_Ctr * _Multiplier)); + } else if (_Freq == _TwentyFourMHz) _LIKELY_ARM_ARM64 { + // 24 MHz is a common frequency on ARM/ARM64, including cases where it emulates x86/x64. + const long long _Whole = (_Ctr / _TwentyFourMHz) * period::den; + const long long _Part = (_Ctr % _TwentyFourMHz) * period::den / _TwentyFourMHz; + return time_point(duration(_Whole + _Part)); } else { // Instead of just having "(_Ctr * period::den) / _Freq", // the algorithm below prevents overflow when _Ctr is sufficiently large. @@ -688,7 +707,10 @@ namespace chrono { const long long _Part = (_Ctr % _Freq) * period::den / _Freq; return time_point(duration(_Whole + _Part)); } + // clang-format on } +#undef _LIKELY_ARM_ARM64 +#undef _LIKELY_X86_X64 }; _EXPORT_STD using high_resolution_clock = steady_clock; diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 394c40f10c1..c8a8bc5e2cf 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -526,6 +526,20 @@ #define _FALLTHROUGH #endif +#ifndef __has_cpp_attribute // vvv no attributes vvv +#define _LIKELY +#define _UNLIKELY +#elif __has_cpp_attribute(likely) >= 201803L && __has_cpp_attribute(unlikely) >= 201803L // ^^^ no attr / C++20 attr vvv +#define _LIKELY [[likely]] +#define _UNLIKELY [[unlikely]] +#elif defined(__clang__) // ^^^ C++20 attributes / clang attributes and C++17 or C++14 vvv +#define _LIKELY [[__likely__]] +#define _UNLIKELY [[__unlikely__]] +#else // ^^^ clang attributes and C++17 or C++14 / C1XX attributes and C++17 or C++14 vvv +#define _LIKELY +#define _UNLIKELY +#endif // ^^^ C1XX attributes and C++17 or C++14 ^^^ + // _HAS_NODISCARD (in vcruntime.h) controls: // [[nodiscard]] attributes on STL functions From 068ce67f8aebef92f2aa522519a38a10ef05c262 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Fri, 14 Jul 2023 09:51:58 +0800 Subject: [PATCH 20/35] C++26 freestanding feature-test macros (#3837) Co-authored-by: Stephan T. Lavavej --- stl/inc/yvals_core.h | 55 ++++++-- .../test.compile.pass.cpp | 132 ++++++++++++++++++ 2 files changed, 172 insertions(+), 15 deletions(-) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index c8a8bc5e2cf..a1e9235da38 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -72,6 +72,12 @@ // P1164R1 Making create_directory() Intuitive // P1165R1 Consistently Propagating Stateful Allocators In basic_string's operator+() // P1902R1 Missing Feature-Test Macros 2017-2019 +// P2013R5 Freestanding Language: Optional ::operator new +// (no change is needed for our hosted implementation) +// P2198R7 Freestanding Feature-Test Macros And Implementation-Defined Extensions +// (except for __cpp_lib_freestanding_ranges) +// P2338R4 Freestanding Library: Character Primitives And The C Library +// (except for __cpp_lib_freestanding_charconv) // P2401R0 Conditional noexcept For exchange() // _HAS_CXX17 directly controls: @@ -127,6 +133,8 @@ // P2162R2 Inheriting From variant // P2251R1 Require span And basic_string_view To Be Trivially Copyable // (basic_string_view always provides this behavior) +// P2338R4 Freestanding Library: Character Primitives And The C Library +// (including __cpp_lib_freestanding_charconv) // P2517R1 Conditional noexcept For apply() // _HAS_CXX17 indirectly controls: @@ -266,6 +274,8 @@ // P2106R0 Range Algorithm Result Types // P2116R0 Removing tuple-Like Protocol Support From Fixed-Extent span // P2167R3 Improving boolean-testable Usage +// P2198R7 Freestanding Feature-Test Macros And Implementation-Defined Extensions +// (including __cpp_lib_freestanding_ranges) // P2210R2 Superior String Splitting // P2216R3 std::format Improvements // P2231R1 Completing constexpr In optional And variant @@ -1563,20 +1573,33 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #endif // _HAS_GARBAGE_COLLECTION_SUPPORT_DELETED_IN_CXX23 // C++14 -#define __cpp_lib_chrono_udls 201304L -#define __cpp_lib_complex_udls 201309L -#define __cpp_lib_exchange_function 201304L -#define __cpp_lib_generic_associative_lookup 201304L -#define __cpp_lib_integer_sequence 201304L -#define __cpp_lib_integral_constant_callable 201304L -#define __cpp_lib_is_final 201402L -#define __cpp_lib_is_null_pointer 201309L -#define __cpp_lib_make_reverse_iterator 201402L -#define __cpp_lib_make_unique 201304L -#define __cpp_lib_null_iterators 201304L -#define __cpp_lib_quoted_string_io 201304L -#define __cpp_lib_result_of_sfinae 201210L -#define __cpp_lib_robust_nonmodifying_seq_ops 201304L +#define __cpp_lib_chrono_udls 201304L +#define __cpp_lib_complex_udls 201309L +#define __cpp_lib_exchange_function 201304L +#define __cpp_lib_freestanding_char_traits 202306L +#define __cpp_lib_freestanding_cstdlib 202306L +#define __cpp_lib_freestanding_cstring 202306L +#define __cpp_lib_freestanding_cwchar 202306L +#define __cpp_lib_freestanding_errc 202306L +#define __cpp_lib_freestanding_feature_test_macros 202306L +#define __cpp_lib_freestanding_functional 202306L +#define __cpp_lib_freestanding_iterator 202306L +#define __cpp_lib_freestanding_memory 202306L +#define __cpp_lib_freestanding_operator_new 202306L +#define __cpp_lib_freestanding_ratio 202306L +#define __cpp_lib_freestanding_tuple 202306L +#define __cpp_lib_freestanding_utility 202306L +#define __cpp_lib_generic_associative_lookup 201304L +#define __cpp_lib_integer_sequence 201304L +#define __cpp_lib_integral_constant_callable 201304L +#define __cpp_lib_is_final 201402L +#define __cpp_lib_is_null_pointer 201309L +#define __cpp_lib_make_reverse_iterator 201402L +#define __cpp_lib_make_unique 201304L +#define __cpp_lib_null_iterators 201304L +#define __cpp_lib_quoted_string_io 201304L +#define __cpp_lib_result_of_sfinae 201210L +#define __cpp_lib_robust_nonmodifying_seq_ops 201304L #ifndef _M_CEE_PURE #define __cpp_lib_shared_timed_mutex 201402L #endif // _M_CEE_PURE @@ -1615,6 +1638,7 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #endif // _HAS_STD_BYTE #define __cpp_lib_clamp 201603L #define __cpp_lib_filesystem 201703L +#define __cpp_lib_freestanding_charconv 202306L #define __cpp_lib_gcd_lcm 201606L #define __cpp_lib_hardware_interference_size 201703L #define __cpp_lib_has_unique_object_representations 201606L @@ -1697,7 +1721,8 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #define __cpp_lib_erase_if 202002L #ifdef __cpp_lib_concepts -#define __cpp_lib_format 202207L +#define __cpp_lib_format 202207L +#define __cpp_lib_freestanding_ranges 202306L #endif // __cpp_lib_concepts #define __cpp_lib_generic_unordered_lookup 201811L 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 e523756c01c..ac0a21ce6aa 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 @@ -904,6 +904,138 @@ STATIC_ASSERT(__cpp_lib_forward_like == 202207L); #endif #endif +#ifndef __cpp_lib_freestanding_char_traits +#error __cpp_lib_freestanding_char_traits is not defined +#elif __cpp_lib_freestanding_char_traits != 202306L +#error __cpp_lib_freestanding_char_traits is not 202306L +#else +STATIC_ASSERT(__cpp_lib_freestanding_char_traits == 202306L); +#endif + +#if _HAS_CXX17 +#ifndef __cpp_lib_freestanding_charconv +#error __cpp_lib_freestanding_charconv is not defined +#elif __cpp_lib_freestanding_charconv != 202306L +#error __cpp_lib_freestanding_charconv is not 202306L +#else +STATIC_ASSERT(__cpp_lib_freestanding_charconv == 202306L); +#endif +#else +#ifdef __cpp_lib_freestanding_charconv +#error __cpp_lib_freestanding_charconv is defined +#endif +#endif + +#ifndef __cpp_lib_freestanding_cstdlib +#error __cpp_lib_freestanding_cstdlib is not defined +#elif __cpp_lib_freestanding_cstdlib != 202306L +#error __cpp_lib_freestanding_cstdlib is not 202306L +#else +STATIC_ASSERT(__cpp_lib_freestanding_cstdlib == 202306L); +#endif + +#ifndef __cpp_lib_freestanding_cstring +#error __cpp_lib_freestanding_cstring is not defined +#elif __cpp_lib_freestanding_cstring != 202306L +#error __cpp_lib_freestanding_cstring is not 202306L +#else +STATIC_ASSERT(__cpp_lib_freestanding_cstring == 202306L); +#endif + +#ifndef __cpp_lib_freestanding_cwchar +#error __cpp_lib_freestanding_cwchar is not defined +#elif __cpp_lib_freestanding_cwchar != 202306L +#error __cpp_lib_freestanding_cwchar is not 202306L +#else +STATIC_ASSERT(__cpp_lib_freestanding_cwchar == 202306L); +#endif + +#ifndef __cpp_lib_freestanding_errc +#error __cpp_lib_freestanding_errc is not defined +#elif __cpp_lib_freestanding_errc != 202306L +#error __cpp_lib_freestanding_errc is not 202306L +#else +STATIC_ASSERT(__cpp_lib_freestanding_errc == 202306L); +#endif + +#ifndef __cpp_lib_freestanding_feature_test_macros +#error __cpp_lib_freestanding_feature_test_macros is not defined +#elif __cpp_lib_freestanding_feature_test_macros != 202306L +#error __cpp_lib_freestanding_feature_test_macros is not 202306L +#else +STATIC_ASSERT(__cpp_lib_freestanding_feature_test_macros == 202306L); +#endif + +#ifndef __cpp_lib_freestanding_functional +#error __cpp_lib_freestanding_functional is not defined +#elif __cpp_lib_freestanding_functional != 202306L +#error __cpp_lib_freestanding_functional is not 202306L +#else +STATIC_ASSERT(__cpp_lib_freestanding_functional == 202306L); +#endif + +#ifndef __cpp_lib_freestanding_iterator +#error __cpp_lib_freestanding_iterator is not defined +#elif __cpp_lib_freestanding_iterator != 202306L +#error __cpp_lib_freestanding_iterator is not 202306L +#else +STATIC_ASSERT(__cpp_lib_freestanding_iterator == 202306L); +#endif + +#ifndef __cpp_lib_freestanding_memory +#error __cpp_lib_freestanding_memory is not defined +#elif __cpp_lib_freestanding_memory != 202306L +#error __cpp_lib_freestanding_memory is not 202306L +#else +STATIC_ASSERT(__cpp_lib_freestanding_memory == 202306L); +#endif + +#ifndef __cpp_lib_freestanding_operator_new +#error __cpp_lib_freestanding_operator_new is not defined +#elif __cpp_lib_freestanding_operator_new != 202306L +#error __cpp_lib_freestanding_operator_new is not 202306L +#else +STATIC_ASSERT(__cpp_lib_freestanding_operator_new == 202306L); +#endif + +#ifdef __cpp_lib_concepts +#ifndef __cpp_lib_freestanding_ranges +#error __cpp_lib_freestanding_ranges is not defined +#elif __cpp_lib_freestanding_ranges != 202306L +#error __cpp_lib_freestanding_ranges is not 202306L +#else +STATIC_ASSERT(__cpp_lib_freestanding_ranges == 202306L); +#endif +#else +#ifdef __cpp_lib_freestanding_ranges +#error __cpp_lib_freestanding_ranges is defined +#endif +#endif + +#ifndef __cpp_lib_freestanding_ratio +#error __cpp_lib_freestanding_ratio is not defined +#elif __cpp_lib_freestanding_ratio != 202306L +#error __cpp_lib_freestanding_ratio is not 202306L +#else +STATIC_ASSERT(__cpp_lib_freestanding_ratio == 202306L); +#endif + +#ifndef __cpp_lib_freestanding_tuple +#error __cpp_lib_freestanding_tuple is not defined +#elif __cpp_lib_freestanding_tuple != 202306L +#error __cpp_lib_freestanding_tuple is not 202306L +#else +STATIC_ASSERT(__cpp_lib_freestanding_tuple == 202306L); +#endif + +#ifndef __cpp_lib_freestanding_utility +#error __cpp_lib_freestanding_utility is not defined +#elif __cpp_lib_freestanding_utility != 202306L +#error __cpp_lib_freestanding_utility is not 202306L +#else +STATIC_ASSERT(__cpp_lib_freestanding_utility == 202306L); +#endif + #if _HAS_CXX17 #ifndef __cpp_lib_gcd_lcm #error __cpp_lib_gcd_lcm is not defined From b32f3b48de950c3aed4a90972abfc378e4e35652 Mon Sep 17 00:00:00 2001 From: Jakub Mazurkiewicz Date: Fri, 14 Jul 2023 03:56:03 +0200 Subject: [PATCH 21/35] ``: Improve implementation of recommended practices in `views::cartesian_product` (#3839) --- stl/inc/ranges | 384 ++++++++++++-- tests/std/test.lst | 1 + .../P2374R4_views_cartesian_product/test.cpp | 51 -- .../env.lst | 4 + .../test.compile.pass.cpp | 497 ++++++++++++++++++ 5 files changed, 829 insertions(+), 108 deletions(-) create mode 100644 tests/std/tests/P2374R4_views_cartesian_product_recommended_practices/env.lst create mode 100644 tests/std/tests/P2374R4_views_cartesian_product_recommended_practices/test.compile.pass.cpp diff --git a/stl/inc/ranges b/stl/inc/ranges index 76f11b526bd..fe82e889990 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -38,6 +38,9 @@ namespace ranges { template inline constexpr bool _Is_initializer_list = _Is_specialization_v, initializer_list>; + template // _Require_constant is a valid template-id iff E is a constant expression of structural type + struct _Require_constant; + #if _HAS_CXX23 _EXPORT_STD template using const_iterator_t = const_iterator>; @@ -47,6 +50,34 @@ namespace ranges { _EXPORT_STD template using range_const_reference_t = iter_const_reference_t>; + + template + inline constexpr auto _Compile_time_max_size = + (numeric_limits<_Make_unsigned_like_t>>::max)(); + + template + inline constexpr auto _Compile_time_max_size<_Ty> = (numeric_limits>::max)(); + + template + requires requires { typename _Require_constant<_Ty::size()>; } + inline constexpr auto _Compile_time_max_size<_Ty> = _Ty::size(); + + template + inline constexpr auto _Compile_time_max_size<_Ty[_Size]> = _Size; + + template + inline constexpr auto _Compile_time_max_size> = _Size; + + template + inline constexpr auto _Compile_time_max_size> = _Size; + + template + requires (_Extent != dynamic_extent) + inline constexpr auto _Compile_time_max_size> = _Extent; + + template + requires (_Extent != dynamic_extent) + inline constexpr auto _Compile_time_max_size> = _Extent; #endif // _HAS_CXX23 // clang-format off @@ -1828,6 +1859,14 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = true; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; +#endif // _HAS_CXX23 + _EXPORT_STD template requires (movable<_Rng> && !_Is_initializer_list<_Rng>) class owning_view : public view_interface> { @@ -1915,6 +1954,14 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { template concept _Can_ref_view = requires(_Rng&& __r) { ref_view{static_cast<_Rng&&>(__r)}; }; @@ -2050,6 +2097,14 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { template concept _Can_as_rvalue = requires(_Rng&& __r) { as_rvalue_view{static_cast<_Rng&&>(__r)}; }; @@ -2327,6 +2382,11 @@ namespace ranges { template filter_view(_Rng&&, _Pr) -> filter_view, _Pr>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; +#endif // _HAS_CXX23 + namespace views { struct _Filter_fn { // clang-format off @@ -2757,6 +2817,14 @@ namespace ranges { template transform_view(_Rng&&, _Fn) -> transform_view, _Fn>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { struct _Transform_fn { // clang-format off @@ -2970,6 +3038,14 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { template concept _Random_sized_range = random_access_range<_Rng> && sized_range<_Rng>; @@ -3211,6 +3287,14 @@ namespace ranges { template take_while_view(_Rng&&, _Pr) -> take_while_view, _Pr>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { struct _Take_while_fn { template @@ -3360,6 +3444,14 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { class _Drop_fn { private: @@ -3525,6 +3617,11 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; +#endif // _HAS_CXX23 + namespace views { struct _Drop_while_fn { template @@ -3940,6 +4037,30 @@ namespace ranges { template explicit join_view(_Rng&&) -> join_view>; +#if _HAS_CXX23 + template + _NODISCARD consteval auto _Join_view_compile_time_max_size() { + using _Inner = remove_reference_t>; + using _Size_type = + common_type_t), decltype(_Compile_time_max_size<_Inner>)>; + _Size_type _Result{}; + const bool _Overflow = _Mul_overflow(static_cast<_Size_type>(_Compile_time_max_size<_Rng>), + static_cast<_Size_type>(_Compile_time_max_size<_Inner>), _Result); + if (_Overflow) { + return (numeric_limits<_Size_type>::max)(); + } else { + return _Result; + } + } + + template + inline constexpr auto _Compile_time_max_size> = _Join_view_compile_time_max_size<_Rng>(); + + template + inline constexpr auto _Compile_time_max_size> = + _Join_view_compile_time_max_size(); +#endif // _HAS_CXX23 + namespace views { class _Join_fn : public _Pipe::_Base<_Join_fn> { public: @@ -4447,6 +4568,37 @@ namespace ranges { join_with_view(_Rng&&, range_value_t>) -> join_with_view, single_view>>>; +#if _HAS_CXX23 + template + _NODISCARD consteval auto _Join_with_view_compile_time_max_size() { + using _Inner = remove_reference_t>; + using _Size_type = common_type_t), + decltype(_Compile_time_max_size<_Inner>), decltype(_Compile_time_max_size<_Pat>)>; + _Size_type _Joined_max_size{}; + _Size_type _Pattern_max_size{}; + _Size_type _Result{}; + const bool _Overflow = + _Mul_overflow(static_cast<_Size_type>(_Compile_time_max_size<_Rng>), + static_cast<_Size_type>(_Compile_time_max_size<_Inner>), _Joined_max_size) + || _Mul_overflow((_STD max)(static_cast<_Size_type>(_Compile_time_max_size<_Rng>), _Size_type{1}) - 1, + static_cast<_Size_type>(_Compile_time_max_size<_Pat>), _Pattern_max_size) + || _Add_overflow(_Joined_max_size, _Pattern_max_size, _Result); + if (_Overflow) { + return (numeric_limits<_Size_type>::max)(); + } else { + return _Result; + } + } + + template + inline constexpr auto _Compile_time_max_size> = + _Join_with_view_compile_time_max_size<_Rng, _Pat>(); + + template + inline constexpr auto _Compile_time_max_size> = + _Join_with_view_compile_time_max_size(); +#endif // _HAS_CXX23 + namespace views { struct _Join_with_fn { // clang-format off @@ -4471,9 +4623,6 @@ namespace ranges { } // namespace views #endif // _HAS_CXX23 - template // _Require_constant is a valid template-id iff E is a constant expression of structural type - struct _Require_constant; - // clang-format off template concept _Tiny_range = sized_range<_Ty> @@ -4868,6 +5017,15 @@ namespace ranges { lazy_split_view(_Rng&&, range_value_t<_Rng>) -> lazy_split_view, single_view>>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = + _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { struct _Lazy_split_fn { // clang-format off @@ -5064,6 +5222,11 @@ namespace ranges { template split_view(_Rng&&, range_value_t<_Rng>) -> split_view, single_view>>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; +#endif // _HAS_CXX23 + namespace views { struct _Split_fn { // clang-format off @@ -5214,6 +5377,14 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { class _Common_fn : public _Pipe::_Base<_Common_fn> { private: @@ -5333,6 +5504,14 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { template concept _Can_extract_base = requires(_Rng&& __r) { static_cast<_Rng&&>(__r).base(); }; @@ -5470,6 +5649,14 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { template concept _Can_as_const = requires(_Rng&& __r) { as_const_view{static_cast<_Rng&&>(__r)}; }; @@ -5940,6 +6127,15 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = + _Compile_time_max_size; +#endif // _HAS_CXX23 + _EXPORT_STD template using keys_view = elements_view<_Rng, 0>; _EXPORT_STD template @@ -6282,6 +6478,14 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { class _Enumerate_fn : public _Pipe::_Base<_Enumerate_fn> { public: @@ -6876,6 +7080,15 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Vw> && forward_range<_Vw>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + requires forward_range<_Rng> + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { struct _Chunk_fn { // clang-format off @@ -7268,6 +7481,14 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Vw>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { struct _Slide_fn { // clang-format off @@ -7467,6 +7688,11 @@ namespace ranges { template chunk_by_view(_Rng&&, _Pr) -> chunk_by_view, _Pr>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; +#endif // _HAS_CXX23 + namespace views { struct _Chunk_by_fn { // clang-format off @@ -7856,6 +8082,14 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Vw>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { struct _Stride_fn { // clang-format off @@ -8349,6 +8583,21 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = (enable_borrowed_range<_ViewTypes> && ...); +#if _HAS_CXX23 + template + _NODISCARD consteval auto _Zip_view_compile_time_max_size() { + using _Size_type = common_type_t)...>; + return (_STD min)({static_cast<_Size_type>(_Compile_time_max_size<_Rngs>)...}); + } + + template + inline constexpr auto _Compile_time_max_size> = _Zip_view_compile_time_max_size<_Rngs...>(); + + template + inline constexpr auto _Compile_time_max_size> = + _Zip_view_compile_time_max_size(); +#endif // _HAS_CXX23 + namespace views { struct _Zip_fn { private: @@ -8687,6 +8936,16 @@ namespace ranges { template zip_transform_view(_Func, _Ranges&&...) -> zip_transform_view<_Func, views::all_t<_Ranges>...>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = + _Compile_time_max_size>; + + template + inline constexpr auto _Compile_time_max_size> = + _Compile_time_max_size>; +#endif // _HAS_CXX23 + namespace views { struct _Zip_transform_fn { private: @@ -9143,6 +9402,24 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; +#if _HAS_CXX23 + template + _NODISCARD consteval auto _Adjacent_view_compile_time_max_size() { + using _Size_type = common_type_t), size_t>; + auto _Size = static_cast<_Size_type>(_Compile_time_max_size<_Rng>); + _Size -= (_STD min)(_Size, static_cast<_Size_type>(_Nx - 1)); + return static_cast<_Size_type>(_Size); + } + + template + inline constexpr auto _Compile_time_max_size> = + _Adjacent_view_compile_time_max_size<_Rng, _Nx>(); + + template + inline constexpr auto _Compile_time_max_size> = + _Adjacent_view_compile_time_max_size(); +#endif // _HAS_CXX23 + namespace views { template class _Adjacent_fn : public _Pipe::_Base<_Adjacent_fn<_Nx>> { @@ -9478,6 +9755,16 @@ namespace ranges { } }; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = + _Compile_time_max_size>; + + template + inline constexpr auto _Compile_time_max_size> = + _Compile_time_max_size>; +#endif // _HAS_CXX23 + namespace views { template class _Adjacent_transform_fn { @@ -9551,69 +9838,28 @@ namespace ranges { } } - template - inline constexpr auto _Compile_time_max_size = (numeric_limits>::max)(); - - template - concept _Constant_sized_range = - sized_range<_Ty> && requires { typename _Require_constant::size()>; }; - - template <_Constant_sized_range _Ty> - inline constexpr auto _Compile_time_max_size<_Ty> = remove_reference_t<_Ty>::size(); - - template - inline constexpr auto _Compile_time_max_size> = _Size; - - template - inline constexpr auto _Compile_time_max_size> = _Size; - - template - requires (_Extent != dynamic_extent) - inline constexpr auto _Compile_time_max_size> = _Extent; - - template - requires (_Extent != dynamic_extent) - inline constexpr auto _Compile_time_max_size> = _Extent; - - template - inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Ty>; - - template - requires sized_range - inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; - - template - inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Ty>; - - template - requires sized_range - inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; - - template - _NODISCARD consteval int _Cartesian_product_max_size_bit_width() noexcept { - if constexpr (sized_range<_Rng>) { - if constexpr (requires(range_size_t<_Rng> _Val) { _STD bit_width(_Val); }) { - return _STD bit_width(_Compile_time_max_size<_Rng>); - } else { - return numeric_limits>::digits; - } + template + _NODISCARD consteval int _Cartesian_product_max_size_bit_width() { + using _Size_type = decltype(_Compile_time_max_size<_Rng>); + if constexpr (requires(_Size_type _Val) { _STD bit_width(_Val); }) { + return _STD bit_width(_Compile_time_max_size<_Rng>); } else { - return numeric_limits<_Make_unsigned_like_t>>::digits; + return numeric_limits<_Size_type>::digits; } } - template + template + requires (sizeof...(_Rngs) > 0) _NODISCARD consteval auto _Cartesian_product_optimal_size_type() noexcept { - constexpr int _Optimal_size_type_bit_width = - (_Cartesian_product_max_size_bit_width<_First>() + ... + _Cartesian_product_max_size_bit_width<_Rest>()); + constexpr int _Optimal_size_type_bit_width = (_Cartesian_product_max_size_bit_width<_Rngs>() + ...); if constexpr (_Optimal_size_type_bit_width <= 8) { - return uint_least8_t{}; + return uint8_t{}; } else if constexpr (_Optimal_size_type_bit_width <= 16) { - return uint_least16_t{}; + return uint16_t{}; } else if constexpr (_Optimal_size_type_bit_width <= 32) { - return uint_least32_t{}; + return uint32_t{}; } else if constexpr (_Optimal_size_type_bit_width <= 64) { - return uint_least64_t{}; + return uint64_t{}; } else { return _Unsigned128{}; } @@ -10037,6 +10283,30 @@ namespace ranges { template cartesian_product_view(_Rngs&&...) -> cartesian_product_view...>; +#if _HAS_CXX23 + template + _NODISCARD consteval auto _Cartesian_product_view_compile_time_max_size() { + using _Size_type = common_type_t()), + decltype(_Compile_time_max_size<_Rngs>)...>; + _Size_type _Result{1}; + const bool _Overflow = + (_Mul_overflow(static_cast<_Size_type>(_Compile_time_max_size<_Rngs>), _Result, _Result) || ...); + if (_Overflow) { + return (numeric_limits<_Size_type>::max)(); + } else { + return _Result; + } + } + + template + inline constexpr auto _Compile_time_max_size> = + _Cartesian_product_view_compile_time_max_size<_Rngs...>(); + + template + inline constexpr auto _Compile_time_max_size> = + _Cartesian_product_view_compile_time_max_size(); +#endif // _HAS_CXX23 + namespace views { class _Cartesian_product_fn { public: diff --git a/tests/std/test.lst b/tests/std/test.lst index 1fd920dc5ec..5eb06eab1a3 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -593,6 +593,7 @@ tests\P2322R6_ranges_alg_fold tests\P2374R4_checked_arithmetic_operations tests\P2374R4_views_cartesian_product tests\P2374R4_views_cartesian_product_death +tests\P2374R4_views_cartesian_product_recommended_practices tests\P2387R3_bind_back tests\P2387R3_pipe_support_for_user_defined_range_adaptors tests\P2401R0_conditional_noexcept_for_exchange diff --git a/tests/std/tests/P2374R4_views_cartesian_product/test.cpp b/tests/std/tests/P2374R4_views_cartesian_product/test.cpp index eedcde49eea..b38606f23db 100644 --- a/tests/std/tests/P2374R4_views_cartesian_product/test.cpp +++ b/tests/std/tests/P2374R4_views_cartesian_product/test.cpp @@ -922,57 +922,6 @@ using move_only_view = test::range}, test::ProxyRef{!derived_from}, test::CanView::yes, test::Copyability::move_only>; -namespace check_recommended_practice_implementation { // MSVC STL specific behavior - using ranges::cartesian_product_view, ranges::empty_view, ranges::single_view, views::all_t, ranges::range_size_t, - ranges::range_difference_t, ranges::ref_view, ranges::owning_view; - using Arr = array; - using Vec = vector; - using Span = span; - - // Computing product for such small array does not require big range_size_t - STATIC_ASSERT(sizeof(range_size_t>>) <= sizeof(size_t)); - STATIC_ASSERT(sizeof(range_size_t, all_t>>) <= sizeof(size_t)); - STATIC_ASSERT(sizeof(range_size_t, all_t, all_t>>) <= sizeof(size_t)); - - // Same thing with range_difference_t - STATIC_ASSERT(sizeof(range_difference_t>>) <= sizeof(ptrdiff_t)); - STATIC_ASSERT(sizeof(range_difference_t, all_t>>) <= sizeof(ptrdiff_t)); - STATIC_ASSERT( - sizeof(range_difference_t, all_t, all_t>>) <= sizeof(ptrdiff_t)); - - // Computing product for such small span does not require big range_size_t - STATIC_ASSERT(sizeof(range_size_t>>) <= sizeof(size_t)); - STATIC_ASSERT(sizeof(range_size_t, all_t>>) <= sizeof(size_t)); - STATIC_ASSERT( - sizeof(range_size_t, all_t, all_t>>) <= sizeof(size_t)); - - // Same thing with range_difference_t - STATIC_ASSERT(sizeof(range_difference_t>>) <= sizeof(ptrdiff_t)); - STATIC_ASSERT(sizeof(range_difference_t, all_t>>) <= sizeof(ptrdiff_t)); - STATIC_ASSERT( - sizeof(range_difference_t, all_t, all_t>>) <= sizeof(ptrdiff_t)); - - // Check 'single_view' and 'empty_view' - STATIC_ASSERT(sizeof(range_size_t, single_view>>) <= sizeof(size_t)); - STATIC_ASSERT( - sizeof(range_difference_t, single_view>>) <= sizeof(ptrdiff_t)); - - // Check 'ref_view<(const) V>' and 'owning_view' - STATIC_ASSERT(sizeof(range_size_t, ref_view, owning_view>>) - <= sizeof(size_t)); - STATIC_ASSERT( - sizeof(range_difference_t, ref_view, owning_view>>) - <= sizeof(ptrdiff_t)); - - // One vector should not use big integer-class type... - STATIC_ASSERT(sizeof(range_size_t>>) <= sizeof(size_t)); - STATIC_ASSERT(sizeof(range_difference_t>>) <= sizeof(ptrdiff_t)); - - // ... but two vectors will - STATIC_ASSERT(sizeof(range_size_t, all_t>>) > sizeof(size_t)); - STATIC_ASSERT(sizeof(range_difference_t, all_t>>) > sizeof(ptrdiff_t)); -} // namespace check_recommended_practice_implementation - // GH-3733: cartesian_product_view would incorrectly reject a call to size() claiming that big*big*big*0 is not // representable as range_size_t because big*big*big is not. constexpr void test_gh_3733() { diff --git a/tests/std/tests/P2374R4_views_cartesian_product_recommended_practices/env.lst b/tests/std/tests/P2374R4_views_cartesian_product_recommended_practices/env.lst new file mode 100644 index 00000000000..8ac7033b206 --- /dev/null +++ b/tests/std/tests/P2374R4_views_cartesian_product_recommended_practices/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\strict_concepts_latest_matrix.lst diff --git a/tests/std/tests/P2374R4_views_cartesian_product_recommended_practices/test.compile.pass.cpp b/tests/std/tests/P2374R4_views_cartesian_product_recommended_practices/test.compile.pass.cpp new file mode 100644 index 00000000000..42f982da641 --- /dev/null +++ b/tests/std/tests/P2374R4_views_cartesian_product_recommended_practices/test.compile.pass.cpp @@ -0,0 +1,497 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// Check MSVC-STL internal machinery + +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using ranges::_Compile_time_max_size, ranges::cartesian_product_view, ranges::sized_range, ranges::range_difference_t, + ranges::range_size_t, views::all_t; + +template +using cpv_size_t = range_size_t>; + +template +using cpv_difference_t = range_difference_t>; + +template +using cpv_const_size_t = range_size_t>; + +template +using cpv_const_difference_t = range_difference_t>; + +#ifdef _WIN64 +constexpr bool is_64_bit = true; +#else // ^^^ 64 bit ^^^ / vvv 32 bit vvv +constexpr bool is_64_bit = false; +#endif // ^^^ 32 bit ^^^ + +constexpr void check_array() { + // Check '_Compile_time_max_size' type trait + static_assert(_Compile_time_max_size == 3); + static_assert(_Compile_time_max_size == 9); + + // Check '_Compile_time_max_size' type trait for const arrays + static_assert(_Compile_time_max_size == 3); + static_assert(_Compile_time_max_size == 9); + + // Computing cartesian product for small arrays does not require big range_size_t + using A1 = all_t; + static_assert(sizeof(cpv_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_size_t) <= sizeof(size_t)); + + // Same thing with range_difference_t + static_assert(sizeof(cpv_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_difference_t) <= sizeof(ptrdiff_t)); + +#ifndef __clang__ // TRANSITION, Clang 17 + // Computing cartesian product for big arrays requires bigger types + using A2 = all_t; + static_assert(sizeof(cpv_size_t) > sizeof(size_t)); + static_assert(sizeof(cpv_difference_t) > sizeof(ptrdiff_t)); +#endif // __clang__ +} + +constexpr void check_std_array() { + // Check '_Compile_time_max_size' type trait + static_assert(_Compile_time_max_size> == 0); + static_assert(_Compile_time_max_size> == 3); + static_assert(_Compile_time_max_size> == 9); + + // Check '_Compile_time_max_size' type trait for const arrays + static_assert(_Compile_time_max_size> == 0); + static_assert(_Compile_time_max_size> == 3); + static_assert(_Compile_time_max_size> == 9); + + // Computing cartesian product for small arrays does not require big range_size_t + using A1 = all_t>; + static_assert(sizeof(cpv_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_const_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_const_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_const_size_t) <= sizeof(size_t)); + + // Same thing with range_difference_t + static_assert(sizeof(cpv_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_const_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_const_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_const_difference_t) <= sizeof(ptrdiff_t)); + + // Computing cartesian product for big arrays requires bigger types + using A2 = all_t&>; + static_assert(sizeof(cpv_size_t) > sizeof(size_t)); + static_assert(sizeof(cpv_difference_t) > sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_const_size_t) > sizeof(size_t)); + static_assert(sizeof(cpv_const_difference_t) > sizeof(ptrdiff_t)); +} + +constexpr void check_span() { + // Check '_Compile_time_max_size' type trait + static_assert(_Compile_time_max_size> == 0); + static_assert(_Compile_time_max_size> == 3); + static_assert(_Compile_time_max_size> == 9); + static_assert(_Compile_time_max_size> == (numeric_limits::size_type>::max)()); + + // Check '_Compile_time_max_size' type trait for const spans + static_assert(_Compile_time_max_size> == 0); + static_assert(_Compile_time_max_size> == 3); + static_assert(_Compile_time_max_size> == 9); + static_assert(_Compile_time_max_size> == (numeric_limits::size_type>::max)()); + + // Computing cartesian product for small spans does not require big range_size_t + using S1 = all_t>; + static_assert(sizeof(cpv_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_const_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_const_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_const_size_t) <= sizeof(size_t)); + + // Same thing with range_difference_t + static_assert(sizeof(cpv_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_const_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_const_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_const_difference_t) <= sizeof(ptrdiff_t)); + + // Computing cartesian product for big spans requires bigger types + using S2 = span; + static_assert(sizeof(cpv_size_t) > sizeof(size_t)); + static_assert(sizeof(cpv_difference_t) > sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_const_size_t) > sizeof(size_t)); + static_assert(sizeof(cpv_const_difference_t) > sizeof(ptrdiff_t)); +} + +constexpr void check_empty_view() { + using ranges::empty_view; + + // Check '_Compile_time_max_size' type trait + static_assert(_Compile_time_max_size> == 0); + static_assert(_Compile_time_max_size> == 0); + static_assert(_Compile_time_max_size> == 0); + static_assert(_Compile_time_max_size> == 0); + + using E = empty_view; + static_assert(sizeof(cpv_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_const_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_const_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_const_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_const_difference_t) <= sizeof(ptrdiff_t)); +} + +constexpr void check_single_view() { + using ranges::single_view; + + // Check '_Compile_time_max_size' type trait + static_assert(_Compile_time_max_size> == 1); + static_assert(_Compile_time_max_size> == 1); + static_assert(_Compile_time_max_size> == 1); + static_assert(_Compile_time_max_size> == 1); + + using S = single_view; + static_assert(sizeof(cpv_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_const_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_const_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_const_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_const_difference_t) <= sizeof(ptrdiff_t)); +} + +enum class CheckConstAdaptor : bool { no, yes }; + +template