diff --git a/README.md b/README.md index 27fc8769080..8cc98b808cf 100644 --- a/README.md +++ b/README.md @@ -143,7 +143,7 @@ Just try to follow these rules, so we can spend more time fixing bugs and implem The STL uses boost-math headers to provide P0226R1 Mathematical Special Functions. We recommend using [vcpkg][] to acquire this dependency. -1. Install Visual Studio 2019 16.9 Preview 3 or later. +1. Install Visual Studio 2019 16.9 Preview 4 or later. * We recommend selecting "C++ CMake tools for Windows" in the VS Installer. This will ensure that you're using supported versions of CMake and Ninja. * Otherwise, install [CMake][] 3.19 or later, and [Ninja][] 1.10.2 or later. @@ -158,7 +158,7 @@ acquire this dependency. # How To Build With A Native Tools Command Prompt -1. Install Visual Studio 2019 16.9 Preview 3 or later. +1. Install Visual Studio 2019 16.9 Preview 4 or later. * We recommend selecting "C++ CMake tools for Windows" in the VS Installer. This will ensure that you're using supported versions of CMake and Ninja. * Otherwise, install [CMake][] 3.19 or later, and [Ninja][] 1.10.2 or later. diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 1451cb51321..481db224222 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -8,7 +8,7 @@ variables: buildOutputLocation: 'D:\build' vcpkgLocation: '$(Build.SourcesDirectory)/vcpkg' -pool: 'StlBuild-2021-01-20-2' +pool: 'StlBuild-2021-02-09' stages: - stage: Code_Format @@ -69,7 +69,7 @@ stages: vsDevCmdArch: x86 - stage: Build_And_Test_x64 - dependsOn: Code_Format + dependsOn: Build_And_Test_x86 displayName: 'Build and Test' jobs: - template: azure-devops/native-build-test.yml @@ -78,7 +78,7 @@ stages: vsDevCmdArch: amd64 - stage: Build_ARM - dependsOn: Code_Format + dependsOn: Build_And_Test_x86 displayName: 'Build' jobs: - template: azure-devops/cross-build.yml @@ -87,7 +87,7 @@ stages: vsDevCmdArch: arm - stage: Build_ARM64 - dependsOn: Code_Format + dependsOn: Build_And_Test_x86 displayName: 'Build' jobs: - template: azure-devops/cross-build.yml diff --git a/stl/inc/charconv b/stl/inc/charconv index 20d8342c41b..9ab5d01ec81 100644 --- a/stl/inc/charconv +++ b/stl/inc/charconv @@ -127,6 +127,17 @@ _NODISCARD to_chars_result _Integer_to_chars( } while (_Value != 0); break; + case 3: + case 5: + case 6: + case 7: + case 9: + do { + *--_RNext = static_cast('0' + _Value % _Base); + _Value = static_cast<_Unsigned>(_Value / _Base); + } while (_Value != 0); + break; + default: do { *--_RNext = _Charconv_digits[_Value % _Base]; diff --git a/stl/inc/chrono b/stl/inc/chrono index 7927b883277..25d3b2ac196 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -1394,35 +1394,31 @@ namespace chrono { // courtesy of Howard Hinnant // https://howardhinnant.github.io/date_algorithms.html#civil_from_days _NODISCARD static constexpr year_month_day _Civil_from_days(int _Tp) noexcept { - static_assert(numeric_limits::digits >= 18); - static_assert(numeric_limits::digits >= 20); - const int _Zx = _Tp + 719468; // Shift epoch to 0000-03-01 - const int _Era = (_Zx >= 0 ? _Zx : _Zx - 146096) / 146097; - const unsigned int _Day_of_era = static_cast(_Zx - _Era * 146097); // [0, 146096] - const unsigned int _Year_of_era = - (_Day_of_era - _Day_of_era / 1460 + _Day_of_era / 36524 - _Day_of_era / 146096) / 365; // [0, 399] - const int _Year = static_cast(_Year_of_era) + _Era * 400; // Where March is the first month - const unsigned int _Day_of_year = - _Day_of_era - (365 * _Year_of_era + _Year_of_era / 4 - _Year_of_era / 100); // [0, 365] - const unsigned int _Mp = (5 * _Day_of_year + 2) / 153; // [0, 11] - const unsigned int _Day = _Day_of_year - (153 * _Mp + 2) / 5 + 1; // [1, 31] - const unsigned int _Month = _Mp + (_Mp < 10 ? 3 : static_cast(-9)); // [1, 12] + static_assert(numeric_limits::digits >= 32); + static_assert(numeric_limits::digits >= 26); + const int _Zx = _Tp + 719468; // Shift epoch to 0000-03-01 + const int _Century = (_Zx >= 0 ? 4 * _Zx + 3 : 4 * _Zx - 146093) / 146097; + const unsigned int _Day_of_century = + static_cast(_Zx - ((146097 * _Century) >> 2)); // [0, 36524] + const unsigned int _Year_of_century = (91867 * (_Day_of_century + 1)) >> 25; // [0, 99] + const int _Year = static_cast(_Year_of_century) + _Century * 100; // Where March is the first month + const unsigned int _Day_of_year = _Day_of_century - ((1461 * _Year_of_century) >> 2); // [0, 365] + const unsigned int _Mp = (535 * _Day_of_year + 333) >> 14; // [0, 11] + const unsigned int _Day = _Day_of_year - ((979 * _Mp + 19) >> 5) + 1; // [1, 31] + const unsigned int _Month = _Mp + (_Mp < 10 ? 3 : static_cast(-9)); // [1, 12] return year_month_day{_CHRONO year{_Year + (_Month <= 2)}, _CHRONO month{_Month}, _CHRONO day{_Day}}; } // courtesy of Howard Hinnant // https://howardhinnant.github.io/date_algorithms.html#days_from_civil _NODISCARD constexpr days _Days_from_civil() const noexcept { static_assert(numeric_limits::digits >= 18); - static_assert(numeric_limits::digits >= 20); - const int _Ye = static_cast(_Year) - (_Month <= _CHRONO month{2}); - const unsigned int _Mo = static_cast(_Month); - const int _Era = (_Ye >= 0 ? _Ye : _Ye - 399) / 400; - const unsigned int _Year_of_era = static_cast(_Ye - _Era * 400); // [0, 399] - const unsigned int _Day_of_year = (153 * (_Mo + (_Mo > 2 ? static_cast(-3) : 9)) + 2) / 5 - + static_cast(_Day) - 1; // [0, 365] - const unsigned int _Day_of_era = - _Year_of_era * 365 + _Year_of_era / 4 - _Year_of_era / 100 + _Day_of_year; // [0, 146096] - return days{_Era * 146097 + static_cast(_Day_of_era) - 719468}; + static_assert(numeric_limits::digits >= 26); + const unsigned int _Mo = static_cast(_Month); // [1, 12] + const int _Ye = static_cast(_Year) - (_Mo <= 2); + const int _Century = (_Ye >= 0 ? _Ye : _Ye - 99) / 100; + const unsigned int _Mp = _Mo + (_Mo > 2 ? static_cast(-3) : 9); // [0, 11] + const int _Day_of_year = static_cast(((979 * _Mp + 19) >> 5) + static_cast(_Day)) - 1; + return days{((_Ye * 1461) >> 2) - _Century + (_Century >> 2) + _Day_of_year - 719468}; } }; diff --git a/stl/inc/random b/stl/inc/random index 405f47898a4..4bef1ed35fa 100644 --- a/stl/inc/random +++ b/stl/inc/random @@ -2428,7 +2428,7 @@ public: _Ty1 _Logp; _Ty1 _Logp1; - _Small_poisson_distribution<_Ty> _Small; + _Small_poisson_distribution<_Ty> _Small; // TRANSITION, ABI: unused }; binomial_distribution() : _Par(1, _Ty1(0.5)) {} @@ -2505,8 +2505,26 @@ private: return _Res; } else if (_Par0._Mean < 1.0) { - // events are rare, use Poisson distribution - _Res = _Par0._Small(_Eng); + // Events are rare, use waiting time method (Luc Devroye, Non-Uniform Random Variate Generation, p. 525). + const _Ty1 _Rand = _NRAND(_Eng, _Ty1); + + // The exit condition is log(1 - _Rand)/t < log(1-p), which is equivalent to _Rand > 1 - (1-p)^t. If + // we have a cheap upper bound for 1-(1-p)^t, we can exit early without having to call log. We use two + // such bounds, one that is tight for mean ~0 and another for mean ~1. In the first case, Bernoulli's + // inequality gives -1+p*t >= -(1-p)^t, so 1 - (1-p)^t <= p*t = mean. For the other bound, 1-(1-p)^t = + // 1-(1-p)(1-mean/t)^(t-1) <= 1-(1-p)(1-1/t)^(t-1) <= 1-(1-p)/e. + const _Ty1 _Ub = + (_STD min)(_Par0._Mean, _Ty1{3.678794411714423216e-1} * _Par0._Pp + _Ty1{6.32120558828557678e-1}); + if (_Rand > _Ub) { + _Res = _Ty{0}; + } else { + _Ty _Denom = _Par0._Tx; + _Ty1 _Sum = _CSTD log(_Ty1{1.0} - _Rand) / _Denom; + while (_Sum >= _Par0._Logp1 && --_Denom != 0) { + _Sum += _CSTD log(_Ty1{1.0} - _NRAND(_Eng, _Ty1)) / _Denom; + } + _Res = static_cast<_Ty>(_Par0._Tx - _Denom); + } } else { // no shortcuts using _Uty = make_unsigned_t<_Ty>; const auto _Ty1_Tx{_Float_upper_bound<_Ty1>(static_cast<_Uty>(_Par0._Tx))}; @@ -2780,7 +2798,7 @@ public: } _NODISCARD result_type(max)() const { // get largest possible result - return (numeric_limits::max)(); + return numeric_limits::infinity(); } void reset() {} // clear internal state @@ -2917,11 +2935,11 @@ public: } _NODISCARD result_type(min)() const { // get smallest possible result - return numeric_limits::denorm_min(); + return -numeric_limits::infinity(); } _NODISCARD result_type(max)() const { // get largest possible result - return (numeric_limits::max)(); + return numeric_limits::infinity(); } void reset() { // clear internal state @@ -3057,7 +3075,7 @@ public: } _NODISCARD bool operator==(const param_type& _Right) const { - return _Px == _Right._Px; + return _Alpha == _Right._Alpha && _Beta == _Right._Beta; } _NODISCARD bool operator!=(const param_type& _Right) const { @@ -3111,11 +3129,11 @@ public: } _NODISCARD result_type(min)() const { // get smallest possible result - return numeric_limits::denorm_min(); + return result_type{0.0}; } _NODISCARD result_type(max)() const { // get largest possible result - return (numeric_limits::max)(); + return numeric_limits::infinity(); } void reset() {} // clear internal state @@ -3306,7 +3324,7 @@ public: } _NODISCARD result_type(max)() const { // get largest possible result - return (numeric_limits::max)(); + return numeric_limits::infinity(); } void reset() {} // clear internal state @@ -3438,11 +3456,11 @@ public: } _NODISCARD result_type(min)() const { // get smallest possible result - return (numeric_limits::min)(); + return -numeric_limits::infinity(); } _NODISCARD result_type(max)() const { // get largest possible result - return (numeric_limits::max)(); + return numeric_limits::infinity(); } void reset() {} // clear internal state @@ -3576,11 +3594,11 @@ public: } _NODISCARD result_type(min)() const { // get smallest possible result - return -(numeric_limits::max)(); + return result_type{0.0}; } _NODISCARD result_type(max)() const { // get largest possible result - return (numeric_limits::max)(); + return numeric_limits::infinity(); } void reset() {} // clear internal state @@ -3702,11 +3720,11 @@ public: } _NODISCARD result_type(min)() const { // get smallest possible result - return numeric_limits::denorm_min(); + return result_type{0.0}; } _NODISCARD result_type(max)() const { // get largest possible result - return (numeric_limits::max)(); + return numeric_limits::infinity(); } void reset() {} // clear internal state @@ -3834,11 +3852,11 @@ public: } _NODISCARD result_type(min)() const { // get smallest possible result - return -(numeric_limits::max)(); + return -numeric_limits::infinity(); } _NODISCARD result_type(max)() const { // get largest possible result - return (numeric_limits::max)(); + return numeric_limits::infinity(); } void reset() {} // clear internal state @@ -4035,7 +4053,7 @@ public: } _NODISCARD result_type(max)() const { // get largest possible result - return (numeric_limits::max)(); + return numeric_limits::infinity(); } void reset() {} // clear internal state @@ -4168,11 +4186,11 @@ public: } _NODISCARD result_type(min)() const { // get smallest possible result - return -(numeric_limits::max)(); + return -numeric_limits::infinity(); } _NODISCARD result_type(max)() const { // get largest possible result - return (numeric_limits::max)(); + return numeric_limits::infinity(); } void reset() {} // clear internal state diff --git a/stl/inc/regex b/stl/inc/regex index 5b748309cb6..84ff2ce169d 100644 --- a/stl/inc/regex +++ b/stl/inc/regex @@ -2749,7 +2749,7 @@ public: _MyRe = nullptr; #if _ITERATOR_DEBUG_LEVEL == 2 - this->_Orphan_me(); + this->_Orphan_me_v2(); #endif // _ITERATOR_DEBUG_LEVEL return *this; diff --git a/stl/inc/xhash b/stl/inc/xhash index 21f0901e804..3c8a7bbaba2 100644 --- a/stl/inc/xhash +++ b/stl/inc/xhash @@ -1841,6 +1841,7 @@ protected: } } + template = 0> _NODISCARD bool _Multi_equal(const _Hash& _Right) const { static_assert(_Traits::_Multi, "This function only works with multi containers"); _STL_INTERNAL_CHECK(this->size() == _Right.size()); diff --git a/stl/inc/xmemory b/stl/inc/xmemory index 6c54d796390..9550df6676a 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -27,7 +27,7 @@ _STD_BEGIN template struct _NODISCARD _Tidy_guard { // class with destructor that calls _Tidy _Ty* _Target; - ~_Tidy_guard() { + _CONSTEXPR20_DYNALLOC ~_Tidy_guard() { if (_Target) { _Target->_Tidy(); } @@ -38,7 +38,7 @@ struct _NODISCARD _Tidy_guard { // class with destructor that calls _Tidy template struct _NODISCARD _Tidy_deallocate_guard { // class with destructor that calls _Tidy_deallocate _Ty* _Target; - ~_Tidy_deallocate_guard() { + _CONSTEXPR20_DYNALLOC ~_Tidy_deallocate_guard() { if (_Target) { _Target->_Tidy_deallocate(); } @@ -286,12 +286,12 @@ using _Rebind_pointer_t = typename pointer_traits<_Ptr>::template rebind<_Ty>; // FUNCTION TEMPLATE _Refancy template , int> = 0> -_Pointer _Refancy(typename pointer_traits<_Pointer>::element_type* _Ptr) noexcept { +_CONSTEXPR20 _Pointer _Refancy(typename pointer_traits<_Pointer>::element_type* _Ptr) noexcept { return pointer_traits<_Pointer>::pointer_to(*_Ptr); } template , int> = 0> -_Pointer _Refancy(_Pointer _Ptr) noexcept { +_CONSTEXPR20 _Pointer _Refancy(_Pointer _Ptr) noexcept { return _Ptr; } @@ -843,7 +843,7 @@ public: template _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS void construct(_Objty* const _Ptr, _Types&&... _Args) { - ::new (const_cast(static_cast(_Ptr))) _Objty(_STD forward<_Types>(_Args)...); + ::new (_Voidify_iter(_Ptr)) _Objty(_STD forward<_Types>(_Args)...); } template @@ -909,7 +909,7 @@ using _Alloc_size_t = typename allocator_traits<_Alloc>::size_type; // FUNCTION TEMPLATE _Pocca template -void _Pocca(_Alloc& _Left, const _Alloc& _Right) noexcept { +_CONSTEXPR20 void _Pocca(_Alloc& _Left, const _Alloc& _Right) noexcept { if constexpr (allocator_traits<_Alloc>::propagate_on_container_copy_assignment::value) { _Left = _Right; } @@ -917,7 +917,7 @@ void _Pocca(_Alloc& _Left, const _Alloc& _Right) noexcept { // FUNCTION TEMPLATE _Pocma template -void _Pocma(_Alloc& _Left, _Alloc& _Right) noexcept { // (maybe) propagate on container move assignment +_CONSTEXPR20 void _Pocma(_Alloc& _Left, _Alloc& _Right) noexcept { // (maybe) propagate on container move assignment if constexpr (allocator_traits<_Alloc>::propagate_on_container_move_assignment::value) { _Left = _STD move(_Right); } @@ -925,7 +925,7 @@ void _Pocma(_Alloc& _Left, _Alloc& _Right) noexcept { // (maybe) propagate on co // FUNCTION TEMPLATE _Pocs template -void _Pocs(_Alloc& _Left, _Alloc& _Right) noexcept { +_CONSTEXPR20 void _Pocs(_Alloc& _Left, _Alloc& _Right) noexcept { if constexpr (allocator_traits<_Alloc>::propagate_on_container_swap::value) { _Swap_adl(_Left, _Right); } else { @@ -935,7 +935,8 @@ void _Pocs(_Alloc& _Left, _Alloc& _Right) noexcept { // FUNCTION TEMPLATE _Destroy_range WITH ALLOC template -void _Destroy_range(_Alloc_ptr_t<_Alloc> _First, const _Alloc_ptr_t<_Alloc> _Last, _Alloc& _Al) noexcept { +_CONSTEXPR20_DYNALLOC void _Destroy_range( + _Alloc_ptr_t<_Alloc> _First, const _Alloc_ptr_t<_Alloc> _Last, _Alloc& _Al) noexcept { // note that this is an optimization for debug mode codegen; in release mode the BE removes all of this using _Ty = typename _Alloc::value_type; if constexpr (!conjunction_v, _Uses_default_destroy<_Alloc, _Ty*>>) { @@ -975,7 +976,7 @@ _NODISCARD constexpr size_t _Convert_size(const size_t _Len) noexcept { // FUNCTION TEMPLATE _Deallocate_plain template -void _Deallocate_plain(_Alloc& _Al, typename _Alloc::value_type* const _Ptr) noexcept { +_CONSTEXPR20_DYNALLOC void _Deallocate_plain(_Alloc& _Al, typename _Alloc::value_type* const _Ptr) noexcept { // deallocate a plain pointer using an allocator using _Alloc_traits = allocator_traits<_Alloc>; if constexpr (is_same_v<_Alloc_ptr_t<_Alloc>, typename _Alloc::value_type*>) { @@ -988,7 +989,7 @@ void _Deallocate_plain(_Alloc& _Al, typename _Alloc::value_type* const _Ptr) noe // FUNCTION TEMPLATE _Delete_plain_internal template -void _Delete_plain_internal(_Alloc& _Al, typename _Alloc::value_type* const _Ptr) noexcept { +_CONSTEXPR20_DYNALLOC void _Delete_plain_internal(_Alloc& _Al, typename _Alloc::value_type* const _Ptr) noexcept { // destroy *_Ptr in place, then deallocate _Ptr using _Al; used for internal container types the user didn't name using _Ty = typename _Alloc::value_type; _Ptr->~_Ty(); @@ -1002,18 +1003,18 @@ struct _Alloc_construct_ptr { // pointer used to help construct 1 _Alloc::value_ _Alloc& _Al; pointer _Ptr; - explicit _Alloc_construct_ptr(_Alloc& _Al_) : _Al(_Al_), _Ptr(nullptr) {} + _CONSTEXPR20_DYNALLOC explicit _Alloc_construct_ptr(_Alloc& _Al_) : _Al(_Al_), _Ptr(nullptr) {} - _NODISCARD pointer _Release() noexcept { // disengage *this and return contained pointer + _NODISCARD _CONSTEXPR20_DYNALLOC pointer _Release() noexcept { // disengage *this and return contained pointer return _STD exchange(_Ptr, nullptr); } - void _Allocate() { // disengage *this, then allocate a new memory block + _CONSTEXPR20_DYNALLOC void _Allocate() { // disengage *this, then allocate a new memory block _Ptr = nullptr; // if allocate throws, prevents double-free _Ptr = _Al.allocate(1); } - ~_Alloc_construct_ptr() { // if this instance is engaged, deallocate storage + _CONSTEXPR20_DYNALLOC ~_Alloc_construct_ptr() { // if this instance is engaged, deallocate storage if (_Ptr) { _Al.deallocate(_Ptr, 1); } @@ -1027,15 +1028,15 @@ struct _Alloc_construct_ptr { // pointer used to help construct 1 _Alloc::value_ struct _Fake_allocator {}; struct _Container_base0 { - void _Orphan_all() noexcept {} - void _Swap_proxy_and_iterators(_Container_base0&) noexcept {} - void _Alloc_proxy(const _Fake_allocator&) noexcept {} - void _Reload_proxy(const _Fake_allocator&, const _Fake_allocator&) noexcept {} + _CONSTEXPR20_CONTAINER void _Orphan_all() noexcept {} + _CONSTEXPR20_CONTAINER void _Swap_proxy_and_iterators(_Container_base0&) noexcept {} + _CONSTEXPR20_CONTAINER void _Alloc_proxy(const _Fake_allocator&) noexcept {} + _CONSTEXPR20_CONTAINER void _Reload_proxy(const _Fake_allocator&, const _Fake_allocator&) noexcept {} }; struct _Iterator_base0 { - void _Adopt(const void*) noexcept {} - const _Container_base0* _Getcont() const noexcept { + _CONSTEXPR20_CONTAINER void _Adopt(const void*) noexcept {} + _CONSTEXPR20_CONTAINER const _Container_base0* _Getcont() const noexcept { return nullptr; } @@ -1045,25 +1046,25 @@ struct _Iterator_base0 { // CLASS _Container_proxy struct _Container_base12; struct _Container_proxy { // store head of iterator chain and back pointer - _Container_proxy() noexcept : _Mycont(nullptr), _Myfirstiter(nullptr) {} - _Container_proxy(_Container_base12* _Mycont_) noexcept : _Mycont(_Mycont_), _Myfirstiter(nullptr) {} + _CONSTEXPR20_CONTAINER _Container_proxy() noexcept = default; + _CONSTEXPR20_CONTAINER _Container_proxy(_Container_base12* _Mycont_) noexcept : _Mycont(_Mycont_) {} - const _Container_base12* _Mycont; - _Iterator_base12* _Myfirstiter; + const _Container_base12* _Mycont = nullptr; + mutable _Iterator_base12* _Myfirstiter = nullptr; }; struct _Container_base12 { public: - _Container_base12() noexcept : _Myproxy(nullptr) {} + _CONSTEXPR20_CONTAINER _Container_base12() noexcept = default; _Container_base12(const _Container_base12&) = delete; _Container_base12& operator=(const _Container_base12&) = delete; - void _Orphan_all() noexcept; - void _Swap_proxy_and_iterators(_Container_base12&) noexcept; + _CONSTEXPR20_CONTAINER void _Orphan_all() noexcept; + _CONSTEXPR20_CONTAINER void _Swap_proxy_and_iterators(_Container_base12&) noexcept; template - void _Alloc_proxy(_Alloc&& _Al) { + _CONSTEXPR20_CONTAINER void _Alloc_proxy(_Alloc&& _Al) { _Container_proxy* const _New_proxy = _Unfancy(_Al.allocate(1)); _Construct_in_place(*_New_proxy, this); _Myproxy = _New_proxy; @@ -1071,7 +1072,7 @@ public: } template - void _Reload_proxy(_Alloc&& _Old_alloc, _Alloc&& _New_alloc) { + _CONSTEXPR20_CONTAINER void _Reload_proxy(_Alloc&& _Old_alloc, _Alloc&& _New_alloc) { // pre: no iterators refer to the existing proxy _Container_proxy* const _New_proxy = _Unfancy(_New_alloc.allocate(1)); _Construct_in_place(*_New_proxy, this); @@ -1079,113 +1080,160 @@ public: _Delete_plain_internal(_Old_alloc, _STD exchange(_Myproxy, _New_proxy)); } - _Container_proxy* _Myproxy; + _Container_proxy* _Myproxy = nullptr; + +private: + _CONSTEXPR20_CONTAINER void _Orphan_all_unlocked() noexcept; + _CONSTEXPR20_CONTAINER void _Swap_proxy_and_iterators_unlocked(_Container_base12&) noexcept; + + void _Orphan_all_locked() noexcept { + _Lockit _Lock(_LOCK_DEBUG); + _Orphan_all_unlocked(); + } + + void _Swap_proxy_and_iterators_locked(_Container_base12& _Right) noexcept { + _Lockit _Lock(_LOCK_DEBUG); + _Swap_proxy_and_iterators_unlocked(_Right); + } }; struct _Iterator_base12 { // store links to container proxy, next iterator - _Iterator_base12() noexcept : _Myproxy(nullptr), _Mynextiter(nullptr) {} // construct orphaned iterator +public: + _CONSTEXPR20_CONTAINER _Iterator_base12() noexcept = default; // construct orphaned iterator - _Iterator_base12(const _Iterator_base12& _Right) noexcept : _Myproxy(nullptr), _Mynextiter(nullptr) { + _CONSTEXPR20_CONTAINER _Iterator_base12(const _Iterator_base12& _Right) noexcept { *this = _Right; } - _Iterator_base12& operator=(const _Iterator_base12& _Right) noexcept { + _CONSTEXPR20_CONTAINER _Iterator_base12& operator=(const _Iterator_base12& _Right) noexcept { if (_Myproxy != _Right._Myproxy) { if (_Right._Myproxy) { _Adopt(_Right._Myproxy->_Mycont); } else { // becoming invalid, disown current parent #if _ITERATOR_DEBUG_LEVEL == 2 - _Lockit _Lock(_LOCK_DEBUG); - _Orphan_me(); + _Orphan_me_v2(); #else // _ITERATOR_DEBUG_LEVEL == 2 _Myproxy = nullptr; #endif // _ITERATOR_DEBUG_LEVEL == 2 } } - return *this; } - ~_Iterator_base12() noexcept { #if _ITERATOR_DEBUG_LEVEL == 2 - _Lockit _Lock(_LOCK_DEBUG); - _Orphan_me(); -#endif // _ITERATOR_DEBUG_LEVEL == 2 + _CONSTEXPR20_CONTAINER ~_Iterator_base12() noexcept { + _Orphan_me_v2(); } - void _Adopt(const _Container_base12* _Parent) noexcept { - if (_Parent) { - // have a parent, do adoption + _CONSTEXPR20_CONTAINER void _Adopt(const _Container_base12* _Parent) noexcept { + if (_Parent) { // have a parent, do adoption _Container_proxy* _Parent_proxy = _Parent->_Myproxy; - -#if _ITERATOR_DEBUG_LEVEL == 2 if (_Myproxy != _Parent_proxy) { // change parentage - _Lockit _Lock(_LOCK_DEBUG); - _Orphan_me(); - _Mynextiter = _Parent_proxy->_Myfirstiter; - _Parent_proxy->_Myfirstiter = this; - _Myproxy = _Parent_proxy; +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (_STD is_constant_evaluated()) { + _Adopt_unlocked(_Parent_proxy); + } else +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _Adopt_locked(_Parent_proxy); + } } - -#else // _ITERATOR_DEBUG_LEVEL == 2 - _Myproxy = _Parent_proxy; -#endif // _ITERATOR_DEBUG_LEVEL == 2 - } else { - // no future parent, just disown current parent -#if _ITERATOR_DEBUG_LEVEL == 2 - _Lockit _Lock(_LOCK_DEBUG); - _Orphan_me(); -#else // _ITERATOR_DEBUG_LEVEL == 2 - _Myproxy = nullptr; -#endif // _ITERATOR_DEBUG_LEVEL == 2 + } else { // no future parent, just disown current parent + _Orphan_me_v2(); } } - const _Container_base12* _Getcont() const noexcept { - return _Myproxy ? _Myproxy->_Mycont : nullptr; - } - -#if _ITERATOR_DEBUG_LEVEL == 2 - void _Orphan_me() noexcept { + _CONSTEXPR20_CONTAINER void _Orphan_me_v2() noexcept { if (_Myproxy) { // adopted, remove self from list - _Iterator_base12** _Pnext = &_Myproxy->_Myfirstiter; - while (*_Pnext && *_Pnext != this) { - _Pnext = &(*_Pnext)->_Mynextiter; +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (_STD is_constant_evaluated()) { + _Orphan_me_unlocked(); + } else +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _Orphan_me_locked(); } + } + } - _STL_VERIFY(*_Pnext, "ITERATOR LIST CORRUPTED!"); - *_Pnext = _Mynextiter; +#else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 ^^^ / vvv _ITERATOR_DEBUG_LEVEL != 2 vvv + _CONSTEXPR20_CONTAINER void _Adopt(const _Container_base12* _Parent) noexcept { + if (_Parent) { // have a parent, do adoption + _Myproxy = _Parent->_Myproxy; + } else { // no future parent, just disown current parent _Myproxy = nullptr; } } -#endif // _ITERATOR_DEBUG_LEVEL == 2 +#endif // _ITERATOR_DEBUG_LEVEL != 2 + + _CONSTEXPR20_CONTAINER const _Container_base12* _Getcont() const noexcept { + return _Myproxy ? _Myproxy->_Mycont : nullptr; + } static constexpr bool _Unwrap_when_unverified = _ITERATOR_DEBUG_LEVEL == 0; - _Container_proxy* _Myproxy; - _Iterator_base12* _Mynextiter; -}; + _Container_proxy* _Myproxy = nullptr; + _Iterator_base12* _Mynextiter = nullptr; -// MEMBER FUNCTIONS FOR _Container_base12 -inline void _Container_base12::_Orphan_all() noexcept { #if _ITERATOR_DEBUG_LEVEL == 2 - if (_Myproxy) { // proxy allocated, drain it +private: + _CONSTEXPR20_CONTAINER void _Adopt_unlocked(_Container_proxy* _Parent_proxy) noexcept { + if (_Myproxy) { // adopted, remove self from list + _Orphan_me_unlocked(); + } + _Mynextiter = _Parent_proxy->_Myfirstiter; + _Parent_proxy->_Myfirstiter = this; + _Myproxy = _Parent_proxy; + } + + void _Adopt_locked(_Container_proxy* _Parent_proxy) noexcept { _Lockit _Lock(_LOCK_DEBUG); + _Adopt_unlocked(_Parent_proxy); + } - for (auto _Pnext = &_Myproxy->_Myfirstiter; *_Pnext; *_Pnext = (*_Pnext)->_Mynextiter) { - (*_Pnext)->_Myproxy = nullptr; + _CONSTEXPR20_CONTAINER void _Orphan_me_unlocked() noexcept { + _Iterator_base12** _Pnext = &_Myproxy->_Myfirstiter; + while (*_Pnext && *_Pnext != this) { + const auto _Temp = *_Pnext; // TRANSITION, VSO-1269037 + _Pnext = &_Temp->_Mynextiter; } - _Myproxy->_Myfirstiter = nullptr; + _STL_VERIFY(*_Pnext, "ITERATOR LIST CORRUPTED!"); + *_Pnext = _Mynextiter; + _Myproxy = nullptr; + } + + void _Orphan_me_locked() noexcept { + _Lockit _Lock(_LOCK_DEBUG); + _Orphan_me_unlocked(); } #endif // _ITERATOR_DEBUG_LEVEL == 2 +}; + +// MEMBER FUNCTIONS FOR _Container_base12 +_CONSTEXPR20_CONTAINER void _Container_base12::_Orphan_all_unlocked() noexcept { + for (auto _Pnext = &_Myproxy->_Myfirstiter; *_Pnext; *_Pnext = (*_Pnext)->_Mynextiter) { + (*_Pnext)->_Myproxy = nullptr; + } + _Myproxy->_Myfirstiter = nullptr; } -inline void _Container_base12::_Swap_proxy_and_iterators(_Container_base12& _Right) noexcept { +_CONSTEXPR20_CONTAINER void _Container_base12::_Orphan_all() noexcept { #if _ITERATOR_DEBUG_LEVEL == 2 - _Lockit _Lock(_LOCK_DEBUG); + if (_Myproxy) { // proxy allocated, drain it +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (_STD is_constant_evaluated()) { + _Orphan_all_unlocked(); + } else +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _Orphan_all_locked(); + } + } #endif // _ITERATOR_DEBUG_LEVEL == 2 +} +_CONSTEXPR20_CONTAINER void _Container_base12::_Swap_proxy_and_iterators_unlocked(_Container_base12& _Right) noexcept { _Container_proxy* _Temp = _Myproxy; _Myproxy = _Right._Myproxy; _Right._Myproxy = _Temp; @@ -1199,6 +1247,21 @@ inline void _Container_base12::_Swap_proxy_and_iterators(_Container_base12& _Rig } } +_CONSTEXPR20_CONTAINER void _Container_base12::_Swap_proxy_and_iterators(_Container_base12& _Right) noexcept { +#if _ITERATOR_DEBUG_LEVEL == 2 +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (_STD is_constant_evaluated()) { + _Swap_proxy_and_iterators_unlocked(_Right); + } else +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _Swap_proxy_and_iterators_locked(_Right); + } +#else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 ^^^ / vvv _ITERATOR_DEBUG_LEVEL != 2 vvv + _Swap_proxy_and_iterators_unlocked(_Right); +#endif // _ITERATOR_DEBUG_LEVEL != 2 +} + #if _ITERATOR_DEBUG_LEVEL == 0 using _Container_base = _Container_base0; using _Iterator_base = _Iterator_base0; @@ -1215,23 +1278,23 @@ struct _Leave_proxy_unbound { struct _Fake_proxy_ptr_impl { // fake replacement for a container proxy smart pointer when no container proxy is in use _Fake_proxy_ptr_impl(const _Fake_proxy_ptr_impl&) = delete; _Fake_proxy_ptr_impl& operator=(const _Fake_proxy_ptr_impl&) = delete; - _Fake_proxy_ptr_impl(const _Fake_allocator&, _Leave_proxy_unbound) noexcept {} - _Fake_proxy_ptr_impl(const _Fake_allocator&, const _Container_base0&) noexcept {} + _CONSTEXPR20_CONTAINER _Fake_proxy_ptr_impl(const _Fake_allocator&, _Leave_proxy_unbound) noexcept {} + _CONSTEXPR20_CONTAINER _Fake_proxy_ptr_impl(const _Fake_allocator&, const _Container_base0&) noexcept {} - void _Bind(const _Fake_allocator&, _Container_base0*) noexcept {} - void _Release() noexcept {} + _CONSTEXPR20_CONTAINER void _Bind(const _Fake_allocator&, _Container_base0*) noexcept {} + _CONSTEXPR20_CONTAINER void _Release() noexcept {} }; struct _Basic_container_proxy_ptr12 { // smart pointer components for a _Container_proxy * that don't depend on the allocator - _Container_proxy* _Ptr; + _Container_proxy* _Ptr = nullptr; - void _Release() noexcept { // disengage this _Basic_container_proxy_ptr12 + constexpr void _Release() noexcept { // disengage this _Basic_container_proxy_ptr12 _Ptr = nullptr; } protected: - _Basic_container_proxy_ptr12() = default; + _CONSTEXPR20_CONTAINER _Basic_container_proxy_ptr12() = default; _Basic_container_proxy_ptr12(const _Basic_container_proxy_ptr12&) = delete; _Basic_container_proxy_ptr12(_Basic_container_proxy_ptr12&&) = delete; }; @@ -1241,26 +1304,27 @@ struct _Container_proxy_ptr12 : _Basic_container_proxy_ptr12 { // smart pointer components for a _Container_proxy * for an allocator family _Alloc& _Al; - _Container_proxy_ptr12(_Alloc& _Al_, _Leave_proxy_unbound) : _Al(_Al_) { // create a new unbound _Container_proxy + _CONSTEXPR20_CONTAINER _Container_proxy_ptr12(_Alloc& _Al_, _Leave_proxy_unbound) : _Al(_Al_) { + // create a new unbound _Container_proxy _Ptr = _Unfancy(_Al_.allocate(1)); _Construct_in_place(*_Ptr); } - _Container_proxy_ptr12(_Alloc& _Al_, _Container_base12& _Mycont) - : _Al(_Al_) { // create a new _Container_proxy pointing at _Mycont + _CONSTEXPR20_CONTAINER _Container_proxy_ptr12(_Alloc& _Al_, _Container_base12& _Mycont) : _Al(_Al_) { + // create a new _Container_proxy pointing at _Mycont _Ptr = _Unfancy(_Al_.allocate(1)); _Construct_in_place(*_Ptr, _STD addressof(_Mycont)); _Mycont._Myproxy = _Ptr; } - void _Bind(_Alloc& _Old_alloc, _Container_base12* _Mycont) noexcept { + _CONSTEXPR20_CONTAINER void _Bind(_Alloc& _Old_alloc, _Container_base12* _Mycont) noexcept { // Attach the proxy stored in *this to _Mycont, and destroy _Mycont's existing proxy // with _Old_alloc. Requires that no iterators are alive referring to _Mycont. _Ptr->_Mycont = _Mycont; _Delete_plain_internal(_Old_alloc, _STD exchange(_Mycont->_Myproxy, _STD exchange(_Ptr, nullptr))); } - ~_Container_proxy_ptr12() { + _CONSTEXPR20_CONTAINER ~_Container_proxy_ptr12() { if (_Ptr) { _Delete_plain_internal(_Al, _Ptr); } @@ -1393,18 +1457,18 @@ struct _NODISCARD _Uninitialized_backout { _Uninitialized_backout(const _Uninitialized_backout&) = delete; _Uninitialized_backout& operator=(const _Uninitialized_backout&) = delete; - ~_Uninitialized_backout() { + _CONSTEXPR20_DYNALLOC ~_Uninitialized_backout() { _Destroy_range(_First, _Last); } template - void _Emplace_back(_Types&&... _Vals) { + _CONSTEXPR20_DYNALLOC void _Emplace_back(_Types&&... _Vals) { // construct a new element at *_Last and increment _Construct_in_place(*_Last, _STD forward<_Types>(_Vals)...); ++_Last; } - _NoThrowFwdIt _Release() { // suppress any exception handling backout and return _Last + constexpr _NoThrowFwdIt _Release() { // suppress any exception handling backout and return _Last _First = _Last; return _Last; } @@ -1437,18 +1501,23 @@ namespace ranges { // FUNCTION TEMPLATE _Uninitialized_move_unchecked template -_NoThrowFwdIt _Uninitialized_move_unchecked(_InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) { +_CONSTEXPR20_DYNALLOC _NoThrowFwdIt _Uninitialized_move_unchecked( + _InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) { // move [_First, _Last) to raw [_Dest, ...) if constexpr (_Ptr_move_cat<_InIt, _NoThrowFwdIt>::_Really_trivial) { - return _Copy_memmove(_First, _Last, _Dest); - } else { - _Uninitialized_backout<_NoThrowFwdIt> _Backout{_Dest}; - for (; _First != _Last; ++_First) { - _Backout._Emplace_back(_STD move(*_First)); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + return _Copy_memmove(_First, _Last, _Dest); } - - return _Backout._Release(); } + _Uninitialized_backout<_NoThrowFwdIt> _Backout{_Dest}; + for (; _First != _Last; ++_First) { + _Backout._Emplace_back(_STD move(*_First)); + } + + return _Backout._Release(); } #ifdef __cpp_lib_concepts @@ -1516,22 +1585,23 @@ class _NODISCARD _Uninitialized_backout_al { using pointer = _Alloc_ptr_t<_Alloc>; public: - _Uninitialized_backout_al(pointer _Dest, _Alloc& _Al_) : _First(_Dest), _Last(_Dest), _Al(_Al_) {} + _CONSTEXPR20_DYNALLOC _Uninitialized_backout_al(pointer _Dest, _Alloc& _Al_) + : _First(_Dest), _Last(_Dest), _Al(_Al_) {} _Uninitialized_backout_al(const _Uninitialized_backout_al&) = delete; _Uninitialized_backout_al& operator=(const _Uninitialized_backout_al&) = delete; - ~_Uninitialized_backout_al() { + _CONSTEXPR20_DYNALLOC ~_Uninitialized_backout_al() { _Destroy_range(_First, _Last, _Al); } template - void _Emplace_back(_Types&&... _Vals) { // construct a new element at *_Last and increment + _CONSTEXPR20_DYNALLOC void _Emplace_back(_Types&&... _Vals) { // construct a new element at *_Last and increment allocator_traits<_Alloc>::construct(_Al, _Unfancy(_Last), _STD forward<_Types>(_Vals)...); ++_Last; } - pointer _Release() { // suppress any exception handling backout and return _Last + constexpr pointer _Release() { // suppress any exception handling backout and return _Last _First = _Last; return _Last; } @@ -1544,7 +1614,7 @@ private: // FUNCTION TEMPLATE _Uninitialized_copy WITH ALLOCATOR template -_Alloc_ptr_t<_Alloc> _Uninitialized_copy( +_CONSTEXPR20_DYNALLOC _Alloc_ptr_t<_Alloc> _Uninitialized_copy( const _InIt _First, const _InIt _Last, _Alloc_ptr_t<_Alloc> _Dest, _Alloc& _Al) { // copy [_First, _Last) to raw _Dest, using _Al // note: only called internally from elsewhere in the STL @@ -1555,21 +1625,46 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_copy( if constexpr (conjunction_v::_Really_trivial>, _Uses_default_construct<_Alloc, _Ptrval, decltype(*_UFirst)>>) { - _Copy_memmove(_UFirst, _ULast, _Unfancy(_Dest)); - _Dest += _ULast - _UFirst; - } else { - _Uninitialized_backout_al<_Alloc> _Backout{_Dest, _Al}; - for (; _UFirst != _ULast; ++_UFirst) { - _Backout._Emplace_back(*_UFirst); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _Copy_memmove(_UFirst, _ULast, _Unfancy(_Dest)); + _Dest += _ULast - _UFirst; + return _Dest; } + } - _Dest = _Backout._Release(); + _Uninitialized_backout_al<_Alloc> _Backout{_Dest, _Al}; + for (; _UFirst != _ULast; ++_UFirst) { + _Backout._Emplace_back(*_UFirst); } - return _Dest; + return _Backout._Release(); } // FUNCTION TEMPLATE uninitialized_copy +template +_CONSTEXPR20_DYNALLOC _NoThrowFwdIt _Uninitialized_copy_unchecked( + _InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) { + // copy [_First, _Last) to raw [_Dest, ...) + if constexpr (_Ptr_copy_cat<_InIt, _NoThrowFwdIt>::_Really_trivial) { +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + return _Copy_memmove(_First, _Last, _Dest); + } + } + + _Uninitialized_backout<_NoThrowFwdIt> _Backout{_Dest}; + for (; _First != _Last; ++_First) { + _Backout._Emplace_back(*_First); + } + + return _Backout._Release(); +} + template _NoThrowFwdIt uninitialized_copy(const _InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) { // copy [_First, _Last) to raw [_Dest, ...) @@ -1577,24 +1672,13 @@ _NoThrowFwdIt uninitialized_copy(const _InIt _First, const _InIt _Last, _NoThrow auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); auto _UDest = _Get_unwrapped_n(_Dest, _Idl_distance<_InIt>(_UFirst, _ULast)); - if constexpr (_Ptr_copy_cat::_Really_trivial) { - _UDest = _Copy_memmove(_UFirst, _ULast, _UDest); - } else { - _Uninitialized_backout _Backout{_UDest}; - for (; _UFirst != _ULast; ++_UFirst) { - _Backout._Emplace_back(*_UFirst); - } - - _UDest = _Backout._Release(); - } - - _Seek_wrapped(_Dest, _UDest); + _Seek_wrapped(_Dest, _Uninitialized_copy_unchecked(_UFirst, _ULast, _UDest)); return _Dest; } // FUNCTION TEMPLATE _Uninitialized_move WITH ALLOCATOR template -_Alloc_ptr_t<_Alloc> _Uninitialized_move( +_CONSTEXPR20_DYNALLOC _Alloc_ptr_t<_Alloc> _Uninitialized_move( const _InIt _First, const _InIt _Last, _Alloc_ptr_t<_Alloc> _Dest, _Alloc& _Al) { // move [_First, _Last) to raw _Dest, using _Al // note: only called internally from elsewhere in the STL @@ -1603,41 +1687,55 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_move( const auto _ULast = _Get_unwrapped(_Last); if constexpr (conjunction_v::_Really_trivial>, _Uses_default_construct<_Alloc, _Ptrval, decltype(_STD move(*_UFirst))>>) { - _Copy_memmove(_UFirst, _ULast, _Unfancy(_Dest)); - return _Dest + (_ULast - _UFirst); - } else { - _Uninitialized_backout_al<_Alloc> _Backout{_Dest, _Al}; - for (; _UFirst != _ULast; ++_UFirst) { - _Backout._Emplace_back(_STD move(*_UFirst)); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _Copy_memmove(_UFirst, _ULast, _Unfancy(_Dest)); + return _Dest + (_ULast - _UFirst); } + } - return _Backout._Release(); + _Uninitialized_backout_al<_Alloc> _Backout{_Dest, _Al}; + for (; _UFirst != _ULast; ++_UFirst) { + _Backout._Emplace_back(_STD move(*_UFirst)); } + + return _Backout._Release(); } // FUNCTION TEMPLATE _Uninitialized_fill_n WITH ALLOCATOR template -_Alloc_ptr_t<_Alloc> _Uninitialized_fill_n( +_CONSTEXPR20_DYNALLOC _Alloc_ptr_t<_Alloc> _Uninitialized_fill_n( _Alloc_ptr_t<_Alloc> _First, _Alloc_size_t<_Alloc> _Count, const typename _Alloc::value_type& _Val, _Alloc& _Al) { // copy _Count copies of _Val to raw _First, using _Al using _Ty = typename _Alloc::value_type; if constexpr (_Fill_memset_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value) { - _Fill_memset(_Unfancy(_First), _Val, static_cast(_Count)); - return _First + _Count; - } else { - if constexpr (_Fill_zero_memset_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value) { +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _Fill_memset(_Unfancy(_First), _Val, static_cast(_Count)); + return _First + _Count; + } + } else if constexpr (_Fill_zero_memset_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value) { +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { if (_Is_all_bits_zero(_Val)) { _Fill_zero_memset(_Unfancy(_First), static_cast(_Count)); return _First + _Count; } } - _Uninitialized_backout_al<_Alloc> _Backout{_First, _Al}; - for (; 0 < _Count; --_Count) { - _Backout._Emplace_back(_Val); - } + } - return _Backout._Release(); + _Uninitialized_backout_al<_Alloc> _Backout{_First, _Al}; + for (; 0 < _Count; --_Count) { + _Backout._Emplace_back(_Val); } + + return _Backout._Release(); } // FUNCTION TEMPLATE uninitialized_fill @@ -1656,6 +1754,7 @@ void uninitialized_fill(const _NoThrowFwdIt _First, const _NoThrowFwdIt _Last, c return; } } + _Uninitialized_backout<_Unwrapped_t> _Backout{_UFirst}; while (_Backout._Last != _ULast) { _Backout._Emplace_back(_Val); @@ -1680,22 +1779,27 @@ _Ptr _Zero_range(const _Ptr _First, const _Ptr _Last) { // fill [_First, _Last) } template -_Alloc_ptr_t<_Alloc> _Uninitialized_value_construct_n( +_CONSTEXPR20_DYNALLOC _Alloc_ptr_t<_Alloc> _Uninitialized_value_construct_n( _Alloc_ptr_t<_Alloc> _First, _Alloc_size_t<_Alloc> _Count, _Alloc& _Al) { // value-initialize _Count objects to raw _First, using _Al using _Ptrty = typename _Alloc::value_type*; if constexpr (_Use_memset_value_construct_v<_Ptrty> && _Uses_default_construct<_Alloc, _Ptrty>::value) { - auto _PFirst = _Unfancy(_First); - _Zero_range(_PFirst, _PFirst + _Count); - return _First + _Count; - } else { - _Uninitialized_backout_al<_Alloc> _Backout{_First, _Al}; - for (; 0 < _Count; --_Count) { - _Backout._Emplace_back(); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + auto _PFirst = _Unfancy(_First); + _Zero_range(_PFirst, _PFirst + _Count); + return _First + _Count; } + } - return _Backout._Release(); + _Uninitialized_backout_al<_Alloc> _Backout{_First, _Al}; + for (; 0 < _Count; --_Count) { + _Backout._Emplace_back(); } + + return _Backout._Release(); } template @@ -1861,7 +1965,8 @@ _NODISCARD _CONSTEXPR20 _FwdIt remove_if(_FwdIt _First, const _FwdIt _Last, _Pr // FUNCTION TEMPLATE _Erase_remove template -typename _Container::size_type _Erase_remove(_Container& _Cont, const _Uty& _Val) { // erase each element matching _Val +_CONSTEXPR20_DYNALLOC typename _Container::size_type _Erase_remove(_Container& _Cont, const _Uty& _Val) { + // erase each element matching _Val auto _First = _Cont.begin(); const auto _Last = _Cont.end(); const auto _Old_size = _Cont.size(); @@ -1872,7 +1977,8 @@ typename _Container::size_type _Erase_remove(_Container& _Cont, const _Uty& _Val // FUNCTION TEMPLATE _Erase_remove_if template -typename _Container::size_type _Erase_remove_if(_Container& _Cont, _Pr _Pred) { // erase each element satisfying _Pred +_CONSTEXPR20_DYNALLOC typename _Container::size_type _Erase_remove_if(_Container& _Cont, _Pr _Pred) { + // erase each element satisfying _Pred auto _First = _Cont.begin(); const auto _Last = _Cont.end(); const auto _Old_size = _Cont.size(); @@ -1883,7 +1989,8 @@ typename _Container::size_type _Erase_remove_if(_Container& _Cont, _Pr _Pred) { // FUNCTION TEMPLATE _Erase_nodes_if template -typename _Container::size_type _Erase_nodes_if(_Container& _Cont, _Pr _Pred) { // erase each element satisfying _Pred +typename _Container::size_type _Erase_nodes_if(_Container& _Cont, _Pr _Pred) { + // erase each element satisfying _Pred auto _First = _Cont.begin(); const auto _Last = _Cont.end(); const auto _Old_size = _Cont.size(); diff --git a/stl/inc/xutility b/stl/inc/xutility index 9f1c687ad01..eb2a04cadf3 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -131,18 +131,26 @@ _NODISCARD constexpr void* _Voidify_iter(_Iter _It) noexcept { // FUNCTION TEMPLATE construct_at #if _HAS_CXX20 -template -_CONSTEXPR20_DYNALLOC auto construct_at(_Ty* const _Location, _Types&&... _Args) noexcept( - noexcept(::new (_Voidify_iter(_Location)) _Ty(_STD forward<_Types>(_Args)...))) // strengthened - -> decltype(::new (_Voidify_iter(_Location)) _Ty(_STD forward<_Types>(_Args)...)) { +template ()) _Ty(_STD declval<_Types>()...))>> +_CONSTEXPR20_DYNALLOC _Ty* construct_at(_Ty* const _Location, _Types&&... _Args) noexcept( + noexcept(::new (_Voidify_iter(_Location)) _Ty(_STD forward<_Types>(_Args)...))) /* strengthened */ { return ::new (_Voidify_iter(_Location)) _Ty(_STD forward<_Types>(_Args)...); } #endif // _HAS_CXX20 // FUNCTION TEMPLATE _Construct_in_place template -void _Construct_in_place(_Ty& _Obj, _Types&&... _Args) noexcept(is_nothrow_constructible_v<_Ty, _Types...>) { - ::new (_Voidify_iter(_STD addressof(_Obj))) _Ty(_STD forward<_Types>(_Args)...); +_CONSTEXPR20_DYNALLOC void _Construct_in_place(_Ty& _Obj, _Types&&... _Args) noexcept( + is_nothrow_constructible_v<_Ty, _Types...>) { +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (_STD is_constant_evaluated()) { + _STD construct_at(_STD addressof(_Obj), _STD forward<_Types>(_Args)...); + } else +#endif // __cpp_lib_constexpr_dynamic_alloc + { + ::new (_Voidify_iter(_STD addressof(_Obj))) _Ty(_STD forward<_Types>(_Args)...); + } } // FUNCTION TEMPLATE _Default_construct_in_place diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index ce9b36d67aa..b9638ec3192 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -506,7 +506,7 @@ #define _CPPLIB_VER 650 #define _MSVC_STL_VERSION 142 -#define _MSVC_STL_UPDATE 202101L +#define _MSVC_STL_UPDATE 202102L #ifndef _ALLOW_COMPILER_AND_STL_VERSION_MISMATCH #ifdef __CUDACC__ @@ -1190,10 +1190,9 @@ #define __cpp_lib_constexpr_algorithms 201806L #define __cpp_lib_constexpr_complex 201711L -#if defined(__cpp_constexpr_dynamic_alloc) \ - && defined(__clang__) // TRANSITION, MSVC support for constexpr dynamic allocation +#ifdef __cpp_constexpr_dynamic_alloc #define __cpp_lib_constexpr_dynamic_alloc 201907L -#endif // defined(__cpp_constexpr_dynamic_alloc) && defined(__clang__) +#endif // __cpp_constexpr_dynamic_alloc #define __cpp_lib_constexpr_functional 201907L #define __cpp_lib_constexpr_iterator 201811L @@ -1284,6 +1283,13 @@ #define _CONSTEXPR20_DYNALLOC inline #endif +// Functions that became constexpr in C++20 via P0980R1 or P1004R2 +#if defined(__cpp_lib_constexpr_dynamic_alloc) && !defined(__clang__) // TRANSITION:LLVM-48606 +#define _CONSTEXPR20_CONTAINER constexpr +#else +#define _CONSTEXPR20_CONTAINER inline +#endif + #ifdef _RTC_CONVERSION_CHECKS_ENABLED #ifndef _ALLOW_RTCc_IN_STL #error /RTCc rejects conformant code, so it is not supported by the C++ Standard Library. Either remove this \ diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index ed1d3397670..bce3485d95b 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -310,18 +310,9 @@ std/language.support/support.limits/support.limits.general/format.version.pass.c std/utilities/format/format.error/format.error.pass.cpp FAIL # C++20 P0784R7 "More constexpr containers" -std/utilities/memory/allocator.traits/allocator.traits.members/allocate.pass.cpp:0 FAIL -std/utilities/memory/allocator.traits/allocator.traits.members/allocate_hint.pass.cpp:0 FAIL std/utilities/memory/allocator.traits/allocator.traits.members/construct.pass.cpp FAIL -std/utilities/memory/allocator.traits/allocator.traits.members/deallocate.pass.cpp:0 FAIL std/utilities/memory/allocator.traits/allocator.traits.members/destroy.pass.cpp FAIL -std/utilities/memory/allocator.traits/allocator.traits.members/max_size.pass.cpp:0 FAIL -std/utilities/memory/allocator.traits/allocator.traits.members/select_on_container_copy_construction.pass.cpp:0 FAIL -std/utilities/memory/default.allocator/allocator.globals/eq.pass.cpp:0 FAIL std/utilities/memory/specialized.algorithms/specialized.construct/construct_at.pass.cpp FAIL -std/utilities/memory/specialized.algorithms/specialized.destroy/destroy.pass.cpp:0 FAIL -std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_at.pass.cpp:0 FAIL -std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_n.pass.cpp:0 FAIL # C++20 P0896R4 "" std/language.support/support.limits/support.limits.general/algorithm.version.pass.cpp FAIL @@ -492,9 +483,6 @@ std/algorithms/robust_against_adl.pass.cpp FAIL # GH-1595: : bit_ceil(T(-1)) should not be a constant expression std/numerics/bit/bit.pow.two/bit_ceil.fail.cpp:0 FAIL -# GH-1530: : Poisson approximation for binomial_distribution is not accurate -std/numerics/rand/rand.dis/rand.dist.bern/rand.dist.bern.bin/eval.PR44847.pass.cpp FAIL - # *** CRT BUGS *** # We're permanently missing aligned_alloc(). @@ -678,38 +666,21 @@ std/input.output/filesystems/fs.filesystem.synopsis/file_time_type_resolution.co # Not yet analyzed, likely STL bugs. Assertions and other runtime failures. std/numerics/rand/rand.dis/rand.dist.bern/rand.dist.bern.bin/eval_param.pass.cpp FAIL std/numerics/rand/rand.dis/rand.dist.bern/rand.dist.bern.bin/eval.pass.cpp FAIL +std/numerics/rand/rand.dis/rand.dist.bern/rand.dist.bern.bin/eval.PR44847.pass.cpp FAIL std/numerics/rand/rand.dis/rand.dist.bern/rand.dist.bern.geo/eval_param.pass.cpp FAIL std/numerics/rand/rand.dis/rand.dist.bern/rand.dist.bern.geo/eval.pass.cpp FAIL std/numerics/rand/rand.dis/rand.dist.bern/rand.dist.bern.negbin/eval_param.pass.cpp FAIL std/numerics/rand/rand.dis/rand.dist.bern/rand.dist.bern.negbin/eval.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.norm/rand.dist.norm.cauchy/max.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.norm/rand.dist.norm.cauchy/min.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.norm/rand.dist.norm.chisq/max.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.norm/rand.dist.norm.chisq/min.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.norm/rand.dist.norm.f/max.pass.cpp FAIL std/numerics/rand/rand.dis/rand.dist.norm/rand.dist.norm.lognormal/eval_param.pass.cpp FAIL std/numerics/rand/rand.dis/rand.dist.norm/rand.dist.norm.lognormal/eval.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.norm/rand.dist.norm.lognormal/max.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.norm/rand.dist.norm.lognormal/min.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.norm/rand.dist.norm.normal/max.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.norm/rand.dist.norm.normal/min.pass.cpp FAIL std/numerics/rand/rand.dis/rand.dist.norm/rand.dist.norm.t/eval_param.pass.cpp FAIL std/numerics/rand/rand.dis/rand.dist.norm/rand.dist.norm.t/eval.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.norm/rand.dist.norm.t/max.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.norm/rand.dist.norm.t/min.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.pois/rand.dist.pois.exp/max.pass.cpp FAIL std/numerics/rand/rand.dis/rand.dist.pois/rand.dist.pois.extreme/eval_param.pass.cpp FAIL std/numerics/rand/rand.dis/rand.dist.pois/rand.dist.pois.extreme/eval.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.pois/rand.dist.pois.extreme/max.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.pois/rand.dist.pois.extreme/min.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.pois/rand.dist.pois.gamma/eq.pass.cpp FAIL std/numerics/rand/rand.dis/rand.dist.pois/rand.dist.pois.gamma/eval_param.pass.cpp FAIL std/numerics/rand/rand.dis/rand.dist.pois/rand.dist.pois.gamma/eval.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.pois/rand.dist.pois.gamma/max.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.pois/rand.dist.pois.gamma/min.pass.cpp FAIL std/numerics/rand/rand.dis/rand.dist.pois/rand.dist.pois.poisson/eval_param.pass.cpp FAIL std/numerics/rand/rand.dis/rand.dist.pois/rand.dist.pois.poisson/eval.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.pois/rand.dist.pois.weibull/max.pass.cpp FAIL std/numerics/rand/rand.dis/rand.dist.uni/rand.dist.uni.real/param_ctor.pass.cpp FAIL # Not yet analyzed, likely STL bugs. Various assertions. diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index d50700aaccf..29a4d817295 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -310,18 +310,9 @@ language.support\support.limits\support.limits.general\format.version.pass.cpp utilities\format\format.error\format.error.pass.cpp # C++20 P0784R7 "More constexpr containers" -utilities\memory\allocator.traits\allocator.traits.members\allocate.pass.cpp -utilities\memory\allocator.traits\allocator.traits.members\allocate_hint.pass.cpp utilities\memory\allocator.traits\allocator.traits.members\construct.pass.cpp -utilities\memory\allocator.traits\allocator.traits.members\deallocate.pass.cpp utilities\memory\allocator.traits\allocator.traits.members\destroy.pass.cpp -utilities\memory\allocator.traits\allocator.traits.members\max_size.pass.cpp -utilities\memory\allocator.traits\allocator.traits.members\select_on_container_copy_construction.pass.cpp -utilities\memory\default.allocator\allocator.globals\eq.pass.cpp utilities\memory\specialized.algorithms\specialized.construct\construct_at.pass.cpp -utilities\memory\specialized.algorithms\specialized.destroy\destroy.pass.cpp -utilities\memory\specialized.algorithms\specialized.destroy\destroy_at.pass.cpp -utilities\memory\specialized.algorithms\specialized.destroy\destroy_n.pass.cpp # C++20 P0896R4 "" language.support\support.limits\support.limits.general\algorithm.version.pass.cpp @@ -492,9 +483,6 @@ algorithms\robust_against_adl.pass.cpp # GH-1595: : bit_ceil(T(-1)) should not be a constant expression numerics\bit\bit.pow.two\bit_ceil.fail.cpp -# GH-1530: : Poisson approximation for binomial_distribution is not accurate -numerics\rand\rand.dis\rand.dist.bern\rand.dist.bern.bin\eval.PR44847.pass.cpp - # *** CRT BUGS *** # We're permanently missing aligned_alloc(). @@ -678,38 +666,21 @@ input.output\filesystems\fs.filesystem.synopsis\file_time_type_resolution.compil # Not yet analyzed, likely STL bugs. Assertions and other runtime failures. numerics\rand\rand.dis\rand.dist.bern\rand.dist.bern.bin\eval_param.pass.cpp numerics\rand\rand.dis\rand.dist.bern\rand.dist.bern.bin\eval.pass.cpp +numerics\rand\rand.dis\rand.dist.bern\rand.dist.bern.bin\eval.PR44847.pass.cpp numerics\rand\rand.dis\rand.dist.bern\rand.dist.bern.geo\eval_param.pass.cpp numerics\rand\rand.dis\rand.dist.bern\rand.dist.bern.geo\eval.pass.cpp numerics\rand\rand.dis\rand.dist.bern\rand.dist.bern.negbin\eval_param.pass.cpp numerics\rand\rand.dis\rand.dist.bern\rand.dist.bern.negbin\eval.pass.cpp -numerics\rand\rand.dis\rand.dist.norm\rand.dist.norm.cauchy\max.pass.cpp -numerics\rand\rand.dis\rand.dist.norm\rand.dist.norm.cauchy\min.pass.cpp -numerics\rand\rand.dis\rand.dist.norm\rand.dist.norm.chisq\max.pass.cpp -numerics\rand\rand.dis\rand.dist.norm\rand.dist.norm.chisq\min.pass.cpp -numerics\rand\rand.dis\rand.dist.norm\rand.dist.norm.f\max.pass.cpp numerics\rand\rand.dis\rand.dist.norm\rand.dist.norm.lognormal\eval_param.pass.cpp numerics\rand\rand.dis\rand.dist.norm\rand.dist.norm.lognormal\eval.pass.cpp -numerics\rand\rand.dis\rand.dist.norm\rand.dist.norm.lognormal\max.pass.cpp -numerics\rand\rand.dis\rand.dist.norm\rand.dist.norm.lognormal\min.pass.cpp -numerics\rand\rand.dis\rand.dist.norm\rand.dist.norm.normal\max.pass.cpp -numerics\rand\rand.dis\rand.dist.norm\rand.dist.norm.normal\min.pass.cpp numerics\rand\rand.dis\rand.dist.norm\rand.dist.norm.t\eval_param.pass.cpp numerics\rand\rand.dis\rand.dist.norm\rand.dist.norm.t\eval.pass.cpp -numerics\rand\rand.dis\rand.dist.norm\rand.dist.norm.t\max.pass.cpp -numerics\rand\rand.dis\rand.dist.norm\rand.dist.norm.t\min.pass.cpp -numerics\rand\rand.dis\rand.dist.pois\rand.dist.pois.exp\max.pass.cpp numerics\rand\rand.dis\rand.dist.pois\rand.dist.pois.extreme\eval_param.pass.cpp numerics\rand\rand.dis\rand.dist.pois\rand.dist.pois.extreme\eval.pass.cpp -numerics\rand\rand.dis\rand.dist.pois\rand.dist.pois.extreme\max.pass.cpp -numerics\rand\rand.dis\rand.dist.pois\rand.dist.pois.extreme\min.pass.cpp -numerics\rand\rand.dis\rand.dist.pois\rand.dist.pois.gamma\eq.pass.cpp numerics\rand\rand.dis\rand.dist.pois\rand.dist.pois.gamma\eval_param.pass.cpp numerics\rand\rand.dis\rand.dist.pois\rand.dist.pois.gamma\eval.pass.cpp -numerics\rand\rand.dis\rand.dist.pois\rand.dist.pois.gamma\max.pass.cpp -numerics\rand\rand.dis\rand.dist.pois\rand.dist.pois.gamma\min.pass.cpp numerics\rand\rand.dis\rand.dist.pois\rand.dist.pois.poisson\eval_param.pass.cpp numerics\rand\rand.dis\rand.dist.pois\rand.dist.pois.poisson\eval.pass.cpp -numerics\rand\rand.dis\rand.dist.pois\rand.dist.pois.weibull\max.pass.cpp numerics\rand\rand.dis\rand.dist.uni\rand.dist.uni.real\param_ctor.pass.cpp # Not yet analyzed, likely STL bugs. Various assertions. diff --git a/tests/std/test.lst b/tests/std/test.lst index 4147920dacb..52b1407f174 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -172,7 +172,9 @@ tests\GH_001103_countl_zero_correctness tests\GH_001105_custom_streambuf_throws tests\GH_001123_random_cast_out_of_range tests\GH_001411_core_headers +tests\GH_001530_binomial_accuracy tests\GH_001541_case_sensitive_boolalpha +tests\GH_001638_dllexport_derived_classes tests\LWG2597_complex_branch_cut tests\LWG3018_shared_ptr_function tests\P0019R8_atomic_ref diff --git a/tests/std/tests/GH_001530_binomial_accuracy/env.lst b/tests/std/tests/GH_001530_binomial_accuracy/env.lst new file mode 100644 index 00000000000..19f025bd0e6 --- /dev/null +++ b/tests/std/tests/GH_001530_binomial_accuracy/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_001530_binomial_accuracy/test.cpp b/tests/std/tests/GH_001530_binomial_accuracy/test.cpp new file mode 100644 index 00000000000..4c3d704e7e4 --- /dev/null +++ b/tests/std/tests/GH_001530_binomial_accuracy/test.cpp @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include + +using namespace std; + +template +void test_binomial(const int n, const double mean, Generator& gen) { + const double p = mean / n; + const double var = n * p * (1.0 - p); + constexpr double tol = 0.01; + constexpr double x = 4.0; // Standard deviation of sample variance should be less than tol / x. + const size_t it_max = 2 * static_cast(pow(var / (tol / x), 2.0)); + binomial_distribution<> dist(n, p); + + vector counts(static_cast(n) + 1); + for (size_t i = 0; i < it_max; ++i) { + ++counts[static_cast(dist(gen))]; + } + + double sample_mean = 0.0; + for (size_t i = 1; i < counts.size(); ++i) { + sample_mean += static_cast(i) * counts[i]; + } + sample_mean /= it_max; + + double sample_var = 0.0; + for (size_t i = 0; i < counts.size(); ++i) { + sample_var += counts[i] * pow(i - sample_mean, 2); + } + sample_var /= it_max - 1; + + assert(abs(sample_mean / mean - 1.0) < tol); + assert(abs(sample_var / var - 1.0) < tol); +} + +int main() { + mt19937 gen; + constexpr int n = 25; + test_binomial(n, 0.99, gen); + test_binomial(n, n - 0.99, gen); + return 0; +} diff --git a/tests/std/tests/GH_001638_dllexport_derived_classes/env.lst b/tests/std/tests/GH_001638_dllexport_derived_classes/env.lst new file mode 100644 index 00000000000..f141421b292 --- /dev/null +++ b/tests/std/tests/GH_001638_dllexport_derived_classes/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\impure_matrix.lst diff --git a/tests/std/tests/GH_001638_dllexport_derived_classes/test.compile.pass.cpp b/tests/std/tests/GH_001638_dllexport_derived_classes/test.compile.pass.cpp new file mode 100644 index 00000000000..3989d13f884 --- /dev/null +++ b/tests/std/tests/GH_001638_dllexport_derived_classes/test.compile.pass.cpp @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if _HAS_CXX20 +#include +#endif // _HAS_CXX20 + +using namespace std; + +int main() {} // COMPILE-ONLY + +#pragma warning(disable : 4251) // class 'A' needs to have dll-interface to be used by clients of class 'B' +#pragma warning(disable : 4275) // non dll-interface struct 'A' used as base for dll-interface class 'B' + +struct __declspec(dllexport) ExportedArray : array {}; +struct __declspec(dllexport) ExportedArrayZero : array {}; +struct __declspec(dllexport) ExportedDeque : deque {}; +struct __declspec(dllexport) ExportedForwardList : forward_list {}; +struct __declspec(dllexport) ExportedList : list {}; +struct __declspec(dllexport) ExportedVector : vector {}; +struct __declspec(dllexport) ExportedVectorBool : vector {}; + +struct __declspec(dllexport) ExportedMap : map {}; +struct __declspec(dllexport) ExportedMultimap : multimap {}; +struct __declspec(dllexport) ExportedSet : set {}; +struct __declspec(dllexport) ExportedMultiset : multiset {}; + +struct __declspec(dllexport) ExportedUnorderedMap : unordered_map {}; +struct __declspec(dllexport) ExportedUnorderedMultimap : unordered_multimap {}; +struct __declspec(dllexport) ExportedUnorderedSet : unordered_set {}; +struct __declspec(dllexport) ExportedUnorderedMultiset : unordered_multiset {}; + +struct __declspec(dllexport) ExportedQueue : queue {}; +struct __declspec(dllexport) ExportedPriorityQueue : priority_queue {}; +struct __declspec(dllexport) ExportedStack : stack {}; + +#if _HAS_CXX20 +struct __declspec(dllexport) ExportedSpan : span {}; +struct __declspec(dllexport) ExportedSpanThree : span {}; +#endif // _HAS_CXX20 diff --git a/tests/std/tests/P0355R7_calendars_and_time_zones_dates/test.cpp b/tests/std/tests/P0355R7_calendars_and_time_zones_dates/test.cpp index 90d6d7ad946..4bb31c8a863 100644 --- a/tests/std/tests/P0355R7_calendars_and_time_zones_dates/test.cpp +++ b/tests/std/tests/P0355R7_calendars_and_time_zones_dates/test.cpp @@ -700,6 +700,190 @@ constexpr void year_month_day_test() { } } } + + if (is_constant_evaluated()) { + // clang-format off + static_assert(sys_days{ 2000y/ 1/ 1} == sys_days{days{ 10957}}); + static_assert(sys_days{ 2000y/ 1/31} == sys_days{days{ 10987}}); + static_assert(sys_days{ 2000y/ 2/ 1} == sys_days{days{ 10988}}); + static_assert(sys_days{ 2000y/ 2/29} == sys_days{days{ 11016}}); + static_assert(sys_days{ 2000y/ 3/ 1} == sys_days{days{ 11017}}); + static_assert(sys_days{ 2000y/ 3/31} == sys_days{days{ 11047}}); + static_assert(sys_days{ 2000y/ 4/ 1} == sys_days{days{ 11048}}); + static_assert(sys_days{ 2000y/ 4/30} == sys_days{days{ 11077}}); + static_assert(sys_days{ 2000y/ 5/ 1} == sys_days{days{ 11078}}); + static_assert(sys_days{ 2000y/ 5/31} == sys_days{days{ 11108}}); + static_assert(sys_days{ 2000y/ 6/ 1} == sys_days{days{ 11109}}); + static_assert(sys_days{ 2000y/ 6/30} == sys_days{days{ 11138}}); + static_assert(sys_days{ 2000y/ 7/ 1} == sys_days{days{ 11139}}); + static_assert(sys_days{ 2000y/ 7/31} == sys_days{days{ 11169}}); + static_assert(sys_days{ 2000y/ 8/ 1} == sys_days{days{ 11170}}); + static_assert(sys_days{ 2000y/ 8/31} == sys_days{days{ 11200}}); + static_assert(sys_days{ 2000y/ 9/ 1} == sys_days{days{ 11201}}); + static_assert(sys_days{ 2000y/ 9/30} == sys_days{days{ 11230}}); + static_assert(sys_days{ 2000y/10/ 1} == sys_days{days{ 11231}}); + static_assert(sys_days{ 2000y/10/31} == sys_days{days{ 11261}}); + static_assert(sys_days{ 2000y/11/ 1} == sys_days{days{ 11262}}); + static_assert(sys_days{ 2000y/11/30} == sys_days{days{ 11291}}); + static_assert(sys_days{ 2000y/12/ 1} == sys_days{days{ 11292}}); + static_assert(sys_days{ 2000y/12/31} == sys_days{days{ 11322}}); + static_assert(sys_days{ -400y/ 2/29} == sys_days{days{ -865566}}); + static_assert(sys_days{ -400y/ 3/ 1} == sys_days{days{ -865565}}); + static_assert(sys_days{ -1y/ 2/28} == sys_days{days{ -719835}}); + static_assert(sys_days{ -1y/ 3/ 1} == sys_days{days{ -719834}}); + static_assert(sys_days{ -1y/12/31} == sys_days{days{ -719529}}); + static_assert(sys_days{ 0y/ 1/ 1} == sys_days{days{ -719528}}); + static_assert(sys_days{ 0y/ 2/29} == sys_days{days{ -719469}}); + static_assert(sys_days{ 0y/ 3/ 1} == sys_days{days{ -719468}}); + static_assert(sys_days{ 1900y/ 3/ 1} == sys_days{days{ -25508}}); + static_assert(sys_days{ 1901y/ 2/28} == sys_days{days{ -25144}}); + static_assert(sys_days{ 1903y/ 3/ 1} == sys_days{days{ -24413}}); + static_assert(sys_days{ 1904y/ 2/29} == sys_days{days{ -24048}}); + static_assert(sys_days{ 1996y/ 3/ 1} == sys_days{days{ 9556}}); + static_assert(sys_days{ 1997y/ 2/28} == sys_days{days{ 9920}}); + static_assert(sys_days{ 1999y/ 3/ 1} == sys_days{days{ 10651}}); + static_assert(sys_days{ 2000y/ 2/29} == sys_days{days{ 11016}}); + static_assert(sys_days{ 2000y/ 3/ 1} == sys_days{days{ 11017}}); + static_assert(sys_days{ 2001y/ 2/28} == sys_days{days{ 11381}}); + static_assert(sys_days{ 2003y/ 3/ 1} == sys_days{days{ 12112}}); + static_assert(sys_days{ 2004y/ 2/29} == sys_days{days{ 12477}}); + static_assert(sys_days{ 2096y/ 3/ 1} == sys_days{days{ 46081}}); + static_assert(sys_days{ 2097y/ 2/28} == sys_days{days{ 46445}}); + static_assert(sys_days{ 2099y/ 3/ 1} == sys_days{days{ 47176}}); + static_assert(sys_days{ 2100y/ 2/28} == sys_days{days{ 47540}}); + static_assert(sys_days{-32767y/ 1/ 1} == sys_days{days{-12687428}}); + static_assert(sys_days{ 32767y/12/31} == sys_days{days{ 11248737}}); + + static_assert( 2000y/ 1/ 1 == year_month_day{sys_days{days{ 10957}}}); + static_assert( 2000y/ 1/31 == year_month_day{sys_days{days{ 10987}}}); + static_assert( 2000y/ 2/ 1 == year_month_day{sys_days{days{ 10988}}}); + static_assert( 2000y/ 2/29 == year_month_day{sys_days{days{ 11016}}}); + static_assert( 2000y/ 3/ 1 == year_month_day{sys_days{days{ 11017}}}); + static_assert( 2000y/ 3/31 == year_month_day{sys_days{days{ 11047}}}); + static_assert( 2000y/ 4/ 1 == year_month_day{sys_days{days{ 11048}}}); + static_assert( 2000y/ 4/30 == year_month_day{sys_days{days{ 11077}}}); + static_assert( 2000y/ 5/ 1 == year_month_day{sys_days{days{ 11078}}}); + static_assert( 2000y/ 5/31 == year_month_day{sys_days{days{ 11108}}}); + static_assert( 2000y/ 6/ 1 == year_month_day{sys_days{days{ 11109}}}); + static_assert( 2000y/ 6/30 == year_month_day{sys_days{days{ 11138}}}); + static_assert( 2000y/ 7/ 1 == year_month_day{sys_days{days{ 11139}}}); + static_assert( 2000y/ 7/31 == year_month_day{sys_days{days{ 11169}}}); + static_assert( 2000y/ 8/ 1 == year_month_day{sys_days{days{ 11170}}}); + static_assert( 2000y/ 8/31 == year_month_day{sys_days{days{ 11200}}}); + static_assert( 2000y/ 9/ 1 == year_month_day{sys_days{days{ 11201}}}); + static_assert( 2000y/ 9/30 == year_month_day{sys_days{days{ 11230}}}); + static_assert( 2000y/10/ 1 == year_month_day{sys_days{days{ 11231}}}); + static_assert( 2000y/10/31 == year_month_day{sys_days{days{ 11261}}}); + static_assert( 2000y/11/ 1 == year_month_day{sys_days{days{ 11262}}}); + static_assert( 2000y/11/30 == year_month_day{sys_days{days{ 11291}}}); + static_assert( 2000y/12/ 1 == year_month_day{sys_days{days{ 11292}}}); + static_assert( 2000y/12/31 == year_month_day{sys_days{days{ 11322}}}); + static_assert( -400y/ 2/29 == year_month_day{sys_days{days{ -865566}}}); + static_assert( -400y/ 3/ 1 == year_month_day{sys_days{days{ -865565}}}); + static_assert( -1y/ 2/28 == year_month_day{sys_days{days{ -719835}}}); + static_assert( -1y/ 3/ 1 == year_month_day{sys_days{days{ -719834}}}); + static_assert( -1y/12/31 == year_month_day{sys_days{days{ -719529}}}); + static_assert( 0y/ 1/ 1 == year_month_day{sys_days{days{ -719528}}}); + static_assert( 0y/ 2/29 == year_month_day{sys_days{days{ -719469}}}); + static_assert( 0y/ 3/ 1 == year_month_day{sys_days{days{ -719468}}}); + static_assert( 1900y/ 3/ 1 == year_month_day{sys_days{days{ -25508}}}); + static_assert( 1901y/ 2/28 == year_month_day{sys_days{days{ -25144}}}); + static_assert( 1903y/ 3/ 1 == year_month_day{sys_days{days{ -24413}}}); + static_assert( 1904y/ 2/29 == year_month_day{sys_days{days{ -24048}}}); + static_assert( 1996y/ 3/ 1 == year_month_day{sys_days{days{ 9556}}}); + static_assert( 1997y/ 2/28 == year_month_day{sys_days{days{ 9920}}}); + static_assert( 1999y/ 3/ 1 == year_month_day{sys_days{days{ 10651}}}); + static_assert( 2000y/ 2/29 == year_month_day{sys_days{days{ 11016}}}); + static_assert( 2000y/ 3/ 1 == year_month_day{sys_days{days{ 11017}}}); + static_assert( 2001y/ 2/28 == year_month_day{sys_days{days{ 11381}}}); + static_assert( 2003y/ 3/ 1 == year_month_day{sys_days{days{ 12112}}}); + static_assert( 2004y/ 2/29 == year_month_day{sys_days{days{ 12477}}}); + static_assert( 2096y/ 3/ 1 == year_month_day{sys_days{days{ 46081}}}); + static_assert( 2097y/ 2/28 == year_month_day{sys_days{days{ 46445}}}); + static_assert( 2099y/ 3/ 1 == year_month_day{sys_days{days{ 47176}}}); + static_assert( 2100y/ 2/28 == year_month_day{sys_days{days{ 47540}}}); + static_assert(-32767y/ 1/ 1 == year_month_day{sys_days{days{-12687428}}}); + static_assert( 32767y/12/31 == year_month_day{sys_days{days{ 11248737}}}); + + static_assert(sys_days{ 2000y/ 1/ 0} == sys_days{days{ 10956}}); + static_assert(sys_days{ 2000y/ 1/255} == sys_days{days{ 11211}}); + static_assert(sys_days{ 2000y/ 2/ 0} == sys_days{days{ 10987}}); + static_assert(sys_days{ 2000y/ 2/255} == sys_days{days{ 11242}}); + static_assert(sys_days{ 2000y/ 3/ 0} == sys_days{days{ 11016}}); + static_assert(sys_days{ 2000y/ 3/255} == sys_days{days{ 11271}}); + static_assert(sys_days{ 2000y/ 4/ 0} == sys_days{days{ 11047}}); + static_assert(sys_days{ 2000y/ 4/255} == sys_days{days{ 11302}}); + static_assert(sys_days{ 2000y/ 5/ 0} == sys_days{days{ 11077}}); + static_assert(sys_days{ 2000y/ 5/255} == sys_days{days{ 11332}}); + static_assert(sys_days{ 2000y/ 6/ 0} == sys_days{days{ 11108}}); + static_assert(sys_days{ 2000y/ 6/255} == sys_days{days{ 11363}}); + static_assert(sys_days{ 2000y/ 7/ 0} == sys_days{days{ 11138}}); + static_assert(sys_days{ 2000y/ 7/255} == sys_days{days{ 11393}}); + static_assert(sys_days{ 2000y/ 8/ 0} == sys_days{days{ 11169}}); + static_assert(sys_days{ 2000y/ 8/255} == sys_days{days{ 11424}}); + static_assert(sys_days{ 2000y/ 9/ 0} == sys_days{days{ 11200}}); + static_assert(sys_days{ 2000y/ 9/255} == sys_days{days{ 11455}}); + static_assert(sys_days{ 2000y/10/ 0} == sys_days{days{ 11230}}); + static_assert(sys_days{ 2000y/10/255} == sys_days{days{ 11485}}); + static_assert(sys_days{ 2000y/11/ 0} == sys_days{days{ 11261}}); + static_assert(sys_days{ 2000y/11/255} == sys_days{days{ 11516}}); + static_assert(sys_days{ 2000y/12/ 0} == sys_days{days{ 11291}}); + static_assert(sys_days{ 2000y/12/255} == sys_days{days{ 11546}}); + static_assert(sys_days{ -400y/ 2/255} == sys_days{days{ -865340}}); + static_assert(sys_days{ -400y/ 3/ 0} == sys_days{days{ -865566}}); + static_assert(sys_days{ -1y/ 2/255} == sys_days{days{ -719608}}); + static_assert(sys_days{ -1y/ 3/ 0} == sys_days{days{ -719835}}); + static_assert(sys_days{ -1y/12/255} == sys_days{days{ -719305}}); + static_assert(sys_days{ 0y/ 1/ 0} == sys_days{days{ -719529}}); + static_assert(sys_days{ 0y/ 2/255} == sys_days{days{ -719243}}); + static_assert(sys_days{ 0y/ 3/ 0} == sys_days{days{ -719469}}); + static_assert(sys_days{ 1900y/ 3/ 0} == sys_days{days{ -25509}}); + static_assert(sys_days{ 1901y/ 2/255} == sys_days{days{ -24917}}); + static_assert(sys_days{ 1903y/ 3/ 0} == sys_days{days{ -24414}}); + static_assert(sys_days{ 1904y/ 2/255} == sys_days{days{ -23822}}); + static_assert(sys_days{ 1996y/ 3/ 0} == sys_days{days{ 9555}}); + static_assert(sys_days{ 1997y/ 2/255} == sys_days{days{ 10147}}); + static_assert(sys_days{ 1999y/ 3/ 0} == sys_days{days{ 10650}}); + static_assert(sys_days{ 2000y/ 2/255} == sys_days{days{ 11242}}); + static_assert(sys_days{ 2000y/ 3/ 0} == sys_days{days{ 11016}}); + static_assert(sys_days{ 2001y/ 2/255} == sys_days{days{ 11608}}); + static_assert(sys_days{ 2003y/ 3/ 0} == sys_days{days{ 12111}}); + static_assert(sys_days{ 2004y/ 2/255} == sys_days{days{ 12703}}); + static_assert(sys_days{ 2096y/ 3/ 0} == sys_days{days{ 46080}}); + static_assert(sys_days{ 2097y/ 2/255} == sys_days{days{ 46672}}); + static_assert(sys_days{ 2099y/ 3/ 0} == sys_days{days{ 47175}}); + static_assert(sys_days{ 2100y/ 2/255} == sys_days{days{ 47767}}); + static_assert(sys_days{-32767y/ 1/ 0} == sys_days{days{-12687429}}); + static_assert(sys_days{ 32767y/12/255} == sys_days{days{ 11248961}}); + // clang-format on + } else { + sys_days sys2{year{y_min} / 1 / 1}; + + for (int iy = y_min; iy <= y_max; ++iy) { + const year y{iy}; + + for (auto um = 1u; um <= 12u; ++um) { + const month m{um}; + + const year_month_day ymd_first = y / m / 1; + assert(sys_days{ymd_first} == sys2); + assert(year_month_day{sys2} == ymd_first); + + const year_month_day ymd_min = y / m / 0; + assert(sys_days{ymd_min} == sys2 - days{1}); + + const year_month_day ymd_max = y / m / 255; + assert(sys_days{ymd_max} == sys2 + days{254}); + + const year_month_day ymd_last = y / m / last; + sys2 += (ymd_last.day() - 1d); + assert(sys_days{ymd_last} == sys2); + assert(year_month_day{sys2} == ymd_last); + + sys2 += days{1}; + } + } + } } constexpr void year_month_day_last_test() { diff --git a/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp b/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp index 52da34b9f96..7939af14b21 100644 --- a/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp +++ b/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp @@ -227,6 +227,7 @@ void test_array(const T& val) { } #ifdef __cpp_lib_constexpr_dynamic_alloc +#ifndef __EDG__ // TRANSITION, VSO-1269976 template struct storage_for { union { @@ -244,9 +245,11 @@ constexpr void test_compiletime() { assert(s.object == 42); destroy_at(&s.object); +#ifdef __cpp_lib_concepts ranges::construct_at(&s.object, 1729); assert(s.object == 1729); ranges::destroy_at(&s.object); +#endif // __cpp_lib_concepts } struct nontrivial { @@ -262,12 +265,15 @@ constexpr void test_compiletime() { assert(s.object.x == 42); destroy_at(&s.object); +#ifdef __cpp_lib_concepts ranges::construct_at(&s.object, 1729); assert(s.object.x == 1729); ranges::destroy_at(&s.object); +#endif // __cpp_lib_concepts } } static_assert((test_compiletime(), true)); +#endif // __EDG__ template struct A { @@ -286,6 +292,7 @@ struct nontrivial_A { }; constexpr void test_compiletime_destroy_variants() { +#ifndef __EDG__ // TRANSITION, VSO-1270011 { allocator> alloc{}; A* a = alloc.allocate(10); @@ -304,6 +311,7 @@ constexpr void test_compiletime_destroy_variants() { destroy(a, a + 10); alloc.deallocate(a, 10); } +#endif // __EDG__ #ifdef __cpp_lib_concepts { allocator> alloc{}; @@ -385,6 +393,7 @@ constexpr void test_compiletime_destroy_variants() { } static_assert((test_compiletime_destroy_variants(), true)); +#ifndef __EDG__ // TRANSITION, VSO-1269976 template struct Alloc { using value_type = T; @@ -498,6 +507,7 @@ constexpr void test_compiletime_allocator_traits() { } } static_assert((test_compiletime_allocator_traits(), true)); +#endif // __EDG__ constexpr void test_compiletime_allocator() { { diff --git a/tests/std/tests/P0898R3_concepts/test.cpp b/tests/std/tests/P0898R3_concepts/test.cpp index 4ae135c53ad..a0d79d6010f 100644 --- a/tests/std/tests/P0898R3_concepts/test.cpp +++ b/tests/std/tests/P0898R3_concepts/test.cpp @@ -150,6 +150,10 @@ struct ExplicitDefault { explicit ExplicitDefault() = default; }; +struct AggregatesExplicitDefault { + ExplicitDefault meow; +}; + struct DeletedDefault { DeletedDefault() = delete; }; @@ -1488,17 +1492,17 @@ namespace test_default_initializable { using std::default_initializable, std::initializer_list; STATIC_ASSERT(default_initializable); -#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-1084668 +#if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-952724 STATIC_ASSERT(!default_initializable); -#else // ^^^ no workaround / workaround vvv +#else // ^^^ no workaround / assert bug so we'll notice when it's fixed vvv STATIC_ASSERT(default_initializable); -#endif // TRANSITION, VSO-1084668 +#endif // TRANSITION, DevCom-952724 STATIC_ASSERT(default_initializable); -#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-1084668 +#if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-952724 STATIC_ASSERT(!default_initializable); -#else // ^^^ no workaround / workaround vvv +#else // ^^^ no workaround / assert bug so we'll notice when it's fixed vvv STATIC_ASSERT(default_initializable); -#endif // TRANSITION, VSO-1084668 +#endif // TRANSITION, DevCom-952724 STATIC_ASSERT(default_initializable); STATIC_ASSERT(!default_initializable); @@ -1511,11 +1515,11 @@ namespace test_default_initializable { STATIC_ASSERT(!default_initializable); STATIC_ASSERT(!default_initializable); STATIC_ASSERT(!default_initializable); -#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-1084668 +#if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-952724 STATIC_ASSERT(!default_initializable); -#else // ^^^ no workaround / workaround vvv +#else // ^^^ no workaround / assert bug so we'll notice when it's fixed vvv STATIC_ASSERT(default_initializable); -#endif // TRANSITION, VSO-1084668 +#endif // TRANSITION, DevCom-952724 STATIC_ASSERT(!default_initializable); STATIC_ASSERT(!default_initializable); @@ -1559,11 +1563,18 @@ namespace test_default_initializable { int x; }; STATIC_ASSERT(default_initializable); -#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-1084668 +#if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-952724 STATIC_ASSERT(!default_initializable); -#else // ^^^ no workaround / workaround vvv +#else // ^^^ no workaround / assert bug so we'll notice when it's fixed vvv STATIC_ASSERT(default_initializable); -#endif // TRANSITION, VSO-1084668 +#endif // TRANSITION, DevCom-952724 + + // Also test GH-1603 "default_initializable accepts types that are not default-initializable" +#if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-1326684 + STATIC_ASSERT(!default_initializable); +#else // ^^^ no workaround / assert bug so we'll notice when it's fixed vvv + STATIC_ASSERT(default_initializable); +#endif // TRANSITION, DevCom-1326684 } // namespace test_default_initializable namespace test_move_constructible { diff --git a/tests/std/tests/P1502R1_standard_library_header_units/test.cpp b/tests/std/tests/P1502R1_standard_library_header_units/test.cpp index 1fa579ad294..7dba262dbb0 100644 --- a/tests/std/tests/P1502R1_standard_library_header_units/test.cpp +++ b/tests/std/tests/P1502R1_standard_library_header_units/test.cpp @@ -324,11 +324,11 @@ int main() { puts("Testing ."); promise p{}; future f{p.get_future()}; -#if 0 // TRANSITION, VSO-1271718 (Standard Library Header Units ICE with C++20 chrono) +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, VSO-1271718 (Standard Library Header Units ICE with C++20 chrono) assert(f.wait_for(chrono::seconds{0}) == future_status::timeout); #endif // ^^^ no workaround ^^^ p.set_value(1729); -#if 0 // TRANSITION, VSO-1271718 (Standard Library Header Units ICE with C++20 chrono) +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, VSO-1271718 (Standard Library Header Units ICE with C++20 chrono) assert(f.wait_for(chrono::seconds{0}) == future_status::ready); #endif // ^^^ no workaround ^^^ assert(f.get() == 1729); @@ -760,7 +760,7 @@ int main() { } l.count_down(); // tell main() that we're done while (!token.stop_requested()) { -#if 0 // TRANSITION, VSO-1271718 (Standard Library Header Units ICE with C++20 chrono) +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, VSO-1271718 (Standard Library Header Units ICE with C++20 chrono) this_thread::sleep_for(10ms); // not a timing assumption; avoids spinning furiously #endif // ^^^ no workaround ^^^ } diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp index db066537944..b0f604ebbca 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 @@ -411,8 +411,7 @@ STATIC_ASSERT(__cpp_lib_constexpr_complex == 201711L); #endif #endif -#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) \ - && defined(__clang__) // TRANSITION, MSVC support for constexpr dynamic allocation +#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) #ifndef __cpp_lib_constexpr_dynamic_alloc #error __cpp_lib_constexpr_dynamic_alloc is not defined #elif __cpp_lib_constexpr_dynamic_alloc != 201907L diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 26fca70de49..e421dd22218 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,7 +1,7 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.19) project(msvc_standard_libraries_tools LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20)