Skip to content

Commit

Permalink
Merge pull request #1212 from microsoft/master
Browse files Browse the repository at this point in the history
feature/spaceship: Merge fix for test timing assumption
  • Loading branch information
StephanTLavavej authored Aug 20, 2020
2 parents fa344bf + 3cca473 commit b9642bf
Show file tree
Hide file tree
Showing 64 changed files with 3,307 additions and 634 deletions.
4 changes: 3 additions & 1 deletion stl/inc/algorithm
Original file line number Diff line number Diff line change
Expand Up @@ -5118,7 +5118,9 @@ namespace ranges {

return {_STD move(_First), _STD move(_Final)};
} else {
auto [_Mid_first, _Mid_last] = _Reverse_until_mid_unchecked(_STD move(_First), _Mid, _Final);
const auto _Result = _Reverse_until_mid_unchecked(_STD move(_First), _Mid, _Final);
auto _Mid_first = _Result.begin();
auto _Mid_last = _Result.end();
_Reverse_common(_Mid_first, _Mid_last);

if (_Mid_first == _Mid) {
Expand Down
6 changes: 3 additions & 3 deletions stl/inc/any
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ inline constexpr bool _Any_is_small = alignof(_Ty) <= alignof(max_align_t)
enum class _Any_representation : uintptr_t { _Trivial, _Big, _Small };

struct _Any_big_RTTI { // Hand-rolled vtable for types that must be heap allocated in an any
using _Destroy_fn = void __CLRCALL_PURE_OR_CDECL(void*) noexcept;
using _Destroy_fn = void __CLRCALL_PURE_OR_CDECL(void*) _NOEXCEPT_FNPTR;
using _Copy_fn = void* __CLRCALL_PURE_OR_CDECL(const void*);

template <class _Ty>
Expand All @@ -76,9 +76,9 @@ struct _Any_big_RTTI { // Hand-rolled vtable for types that must be heap allocat
};

struct _Any_small_RTTI { // Hand-rolled vtable for nontrivial types that can be stored internally in an any
using _Destroy_fn = void __CLRCALL_PURE_OR_CDECL(void*) noexcept;
using _Destroy_fn = void __CLRCALL_PURE_OR_CDECL(void*) _NOEXCEPT_FNPTR;
using _Copy_fn = void __CLRCALL_PURE_OR_CDECL(void*, const void*);
using _Move_fn = void __CLRCALL_PURE_OR_CDECL(void*, void*) noexcept;
using _Move_fn = void __CLRCALL_PURE_OR_CDECL(void*, void*) _NOEXCEPT_FNPTR;

template <class _Ty>
static void __CLRCALL_PURE_OR_CDECL _Destroy_impl(void* const _Target) noexcept {
Expand Down
934 changes: 681 additions & 253 deletions stl/inc/atomic

Large diffs are not rendered by default.

8 changes: 5 additions & 3 deletions stl/inc/charconv
Original file line number Diff line number Diff line change
Expand Up @@ -1327,9 +1327,11 @@ _NODISCARD errc _Assemble_floating_point_value(const uint64_t _Initial_mantissa,

// We detect this case here and re-adjust the mantissa and exponent appropriately, to form a normal number:
if (_Mantissa > _Traits::_Denormal_mantissa_mask) {
// We add one to the _Denormal_mantissa_shift to account for the hidden mantissa bit
// (we subtracted one to account for this bit when we computed the _Denormal_mantissa_shift above).
_Exponent = _Initial_exponent - (_Denormal_mantissa_shift + 1) - _Normal_mantissa_shift;
// The mantissa is already in the correct position for a normal value. (The carried over bit when we
// added 1 to round the mantissa is in the correct position for the hidden bit.)
// _Denormal_mantissa_shift is the actual number of bits by which we have shifted the mantissa into its
// final position.
_Exponent = _Initial_exponent - _Denormal_mantissa_shift;
}
} else {
_Mantissa <<= _Denormal_mantissa_shift;
Expand Down
305 changes: 305 additions & 0 deletions stl/inc/iterator
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,311 @@ private:
bool _Failed; // true if any stores have failed
streambuf_type* _Strbuf; // the wrapped stream buffer
};

#ifdef __cpp_lib_concepts
// CLASS TEMPLATE counted_iterator
template <input_or_output_iterator _Iter>
class counted_iterator {
public:
using iterator_type = _Iter;

// [counted.iter.const]
constexpr counted_iterator() = default;
constexpr counted_iterator(_Iter _Right, const iter_difference_t<_Iter> _Diff) noexcept(
is_nothrow_move_constructible_v<_Iter>) // strengthened
: _Current(_STD move(_Right)), _Length(_Diff) {
#if _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Diff >= 0, "counted_iterator requires non-negative length n");
#endif // _ITERATOR_DEBUG_LEVEL != 0
}

// clang-format off
template <class _Other>
requires convertible_to<const _Other&, _Iter>
constexpr counted_iterator(const counted_iterator<_Other>& _Right) noexcept(
is_nothrow_constructible_v<_Iter, const _Other&>) // strengthened
: _Current(_Right._Current), _Length(_Right._Length) {}

template <class _Other>
requires assignable_from<_Iter&, const _Other&>
constexpr counted_iterator& operator=(const counted_iterator<_Other>& _Right) noexcept(
is_nothrow_assignable_v<_Iter&, const _Other&>) /* strengthened */ {
// clang-format on
_Current = _Right._Current;
_Length = _Right._Length;
return *this;
}

// [counted.iter.access]
_NODISCARD constexpr _Iter base() const& noexcept(is_nothrow_copy_constructible_v<_Iter>) /* strengthened */
requires copy_constructible<_Iter> {
return _Current;
}

_NODISCARD constexpr _Iter base() && noexcept(is_nothrow_move_constructible_v<_Iter>) /* strengthened */ {
return _STD move(_Current);
}

_NODISCARD constexpr iter_difference_t<_Iter> count() const noexcept {
return _Length;
}

// [counted.iter.elem]
_NODISCARD constexpr decltype(auto) operator*() noexcept(noexcept(*_Current)) /* strengthened */ {
#if _ITERATOR_DEBUG_LEVEL != 0
// Per proposed resolution of LWG-3472
_STL_VERIFY(_Length > 0, "counted_iterator dereference beyond end of range");
#endif // _ITERATOR_DEBUG_LEVEL != 0
return *_Current;
}

_NODISCARD constexpr decltype(auto) operator*() const noexcept(noexcept(*_Current)) /* strengthened */
requires _Dereferenceable<const _Iter> {
#if _ITERATOR_DEBUG_LEVEL != 0
// Per proposed resolution of LWG-3472
_STL_VERIFY(_Length > 0, "counted_iterator dereference beyond end of range");
#endif // _ITERATOR_DEBUG_LEVEL != 0
return *_Current;
}

_NODISCARD constexpr decltype(auto) operator[](const iter_difference_t<_Iter> _Diff) const
requires random_access_iterator<_Iter> {
#if _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Diff < _Length, "counted_iterator index out of range");
#endif // _ITERATOR_DEBUG_LEVEL != 0
return _Current[_Diff];
}

// [counted.iter.nav]
constexpr counted_iterator& operator++() {
#if _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Length > 0, "counted_iterator increment beyond end of range");
#endif // _ITERATOR_DEBUG_LEVEL != 0
++_Current;
--_Length;
return *this;
}

constexpr decltype(auto) operator++(int) {
#if _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Length > 0, "counted_iterator increment beyond end of range");
#endif // _ITERATOR_DEBUG_LEVEL != 0
--_Length;
_TRY_BEGIN
return _Current++;

_CATCH_ALL
++_Length;

_RERAISE;
_CATCH_END
}

constexpr counted_iterator operator++(int) requires forward_iterator<_Iter> {
#if _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Length > 0, "counted_iterator increment beyond end of range");
#endif // _ITERATOR_DEBUG_LEVEL != 0
counted_iterator _Tmp = *this;
++_Current;
--_Length;
return _Tmp;
}

constexpr counted_iterator& operator--() requires bidirectional_iterator<_Iter> {
--_Current;
++_Length;
return *this;
}

constexpr counted_iterator operator--(int) requires bidirectional_iterator<_Iter> {
counted_iterator _Tmp = *this;
--_Current;
++_Length;
return _Tmp;
}

_NODISCARD constexpr counted_iterator operator+(const iter_difference_t<_Iter> _Diff) const
requires random_access_iterator<_Iter> {
return counted_iterator{_Current + _Diff, static_cast<iter_difference_t<_Iter>>(_Length - _Diff)};
}

_NODISCARD friend constexpr counted_iterator operator+(
const iter_difference_t<_Iter> _Diff, const counted_iterator& _Right) requires random_access_iterator<_Iter> {
return counted_iterator{_Right._Current + _Diff, static_cast<iter_difference_t<_Iter>>(_Right._Length - _Diff)};
}

constexpr counted_iterator& operator+=(
const iter_difference_t<_Iter> _Diff) requires random_access_iterator<_Iter> {
#if _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Diff <= _Length, "counted_iterator seek beyond end of range");
#endif // _ITERATOR_DEBUG_LEVEL != 0
_Current += _Diff;
_Length -= _Diff;
return *this;
}

_NODISCARD constexpr counted_iterator operator-(const iter_difference_t<_Iter> _Diff) const
requires random_access_iterator<_Iter> {
return counted_iterator{_Current - _Diff, static_cast<iter_difference_t<_Iter>>(_Length + _Diff)};
}

template <common_with<_Iter> _Other>
_NODISCARD friend constexpr iter_difference_t<_Other> operator-(
const counted_iterator& _Left, const counted_iterator<_Other>& _Right) noexcept /* strengthened */ {
#if _ITERATOR_DEBUG_LEVEL != 0
_Same_sequence(_Left, _Right);
#endif // _ITERATOR_DEBUG_LEVEL != 0
return _Right.count() - _Left._Length;
}

_NODISCARD friend constexpr iter_difference_t<_Iter> operator-(
const counted_iterator& _Left, default_sentinel_t) noexcept /* strengthened */ {
return -_Left._Length;
}

_NODISCARD friend constexpr iter_difference_t<_Iter> operator-(
default_sentinel_t, const counted_iterator& _Right) noexcept /* strengthened */ {
return _Right._Length;
}

constexpr counted_iterator& operator-=(
const iter_difference_t<_Iter> _Diff) requires random_access_iterator<_Iter> {
#if _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(-_Diff <= _Length, "counted_iterator decrement beyond end of range");
#endif // _ITERATOR_DEBUG_LEVEL != 0
_Current -= _Diff;
_Length += _Diff;
return *this;
}

// [counted.iter.cmp]
template <common_with<_Iter> _Other>
_NODISCARD friend constexpr bool operator==(
const counted_iterator& _Left, const counted_iterator<_Other>& _Right) noexcept /* strengthened */ {
#if _ITERATOR_DEBUG_LEVEL != 0
_Same_sequence(_Left, _Right);
#endif // _ITERATOR_DEBUG_LEVEL != 0
return _Left._Length == _Right.count();
}

_NODISCARD friend constexpr bool operator==(const counted_iterator& _Left, default_sentinel_t) noexcept
/* strengthened */ {
return _Left._Length == 0;
}

template <common_with<_Iter> _Other>
_NODISCARD friend constexpr strong_ordering operator<=>(
const counted_iterator& _Left, const counted_iterator<_Other>& _Right) noexcept /* strengthened */ {
#if _ITERATOR_DEBUG_LEVEL != 0
_Same_sequence(_Left, _Right);
#endif // _ITERATOR_DEBUG_LEVEL != 0
return _Right.count() <=> _Left._Length;
}

// [counted.iter.cust]
_NODISCARD friend constexpr iter_rvalue_reference_t<_Iter> iter_move(const counted_iterator& _Right) noexcept(
noexcept(_RANGES iter_move(_Right._Current))) requires input_iterator<_Iter> {
return _RANGES iter_move(_Right._Current);
}

template <indirectly_swappable<_Iter> _Other>
friend constexpr void iter_swap(const counted_iterator& _Left, const counted_iterator<_Other>& _Right) noexcept(
noexcept(_RANGES iter_swap(_Left._Current, _Right._Current))) {
_RANGES iter_swap(_Left._Current, _Right._Current);
}

template <common_with<_Iter> _Other>
friend constexpr void _Same_sequence(
const counted_iterator& _Left, const counted_iterator<_Other>& _Right) noexcept {
// Per N4861 [counted.iterator]/2, two counted_iterators x and y refer to elements of the same sequence iff
// next(x.base(), x.count()) and next(y.base(), y.count()) "refer to the same element." Iterator equality is a
// fair proxy for this condition.
if constexpr (forward_iterator<_Iter> && forward_iterator<_Other>) {
using _CIter = common_type_t<_Iter, _Other>;
using _CDiff = common_type_t<iter_difference_t<_Iter>, iter_difference_t<_Other>>;

const _CDiff _Diff = static_cast<_CDiff>(_Left._Length) - static_cast<_CDiff>(_Right.count());
if (_Diff < 0) {
_STL_VERIFY(
static_cast<_CIter>(_Left._Current) == _RANGES next(static_cast<_CIter>(_Right.base()), -_Diff),
"counted_iterators from different ranges");
} else {
_STL_VERIFY(
_RANGES next(static_cast<_CIter>(_Left._Current), _Diff) == static_cast<_CIter>(_Right.base()),
"counted_iterators from different ranges");
}
}
}

template <common_with<_Iter> _Other>
friend constexpr void _Verify_range(const counted_iterator& _Left, const counted_iterator<_Other>& _Right) {
if constexpr (_Range_verifiable_v<_Iter, _Other>) {
_Verify_range(_Left._Current, _Right._Current);
}
#if _ITERATOR_DEBUG_LEVEL != 0
_Same_sequence(_Left, _Right);
#endif // _ITERATOR_DEBUG_LEVEL != 0
}

constexpr void _Verify_offset(const iter_difference_t<_Iter> _Off) const {
#if _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Off <= _Length, "Offset larger than counted_iterator length");
#endif // _ITERATOR_DEBUG_LEVEL != 0
if constexpr (_Offset_verifiable_v<_Iter>) {
_Current._Verify_offset(_Off);
}
}

using _Prevent_inheriting_unwrap = counted_iterator;

_NODISCARD constexpr counted_iterator<_Unwrapped_t<const _Iter&>>
_Unwrapped() const& requires _Unwrappable_v<const _Iter&> {
return static_cast<counted_iterator<_Unwrapped_t<const _Iter&>>>(_Current._Unwrapped());
}

_NODISCARD constexpr counted_iterator<_Unwrapped_t<_Iter>> _Unwrapped() && requires _Unwrappable_v<const _Iter&> {
return static_cast<counted_iterator<_Unwrapped_t<_Iter>>>(_STD move(_Current)._Unwrapped());
}

static constexpr bool _Unwrap_when_unverified = _Do_unwrap_when_unverified_v<_Iter>;

// clang-format off
template <class _Other>
requires _Wrapped_seekable_v<_Iter, const _Other&>
constexpr void _Seek_to(const counted_iterator<_Other>& _It) {
// clang-format on
_Current._Seek_to(_It._Current);
_Length = _It._Length;
}

// clang-format off
template <class _Other>
requires _Wrapped_seekable_v<_Iter, _Other>
constexpr void _Seek_to(counted_iterator<_Other>&& _It) {
// clang-format on
_Current._Seek_to(_STD move(_It)._Current);
_Length = _It._Length;
}

private:
template <input_or_output_iterator>
friend class counted_iterator;

_Iter _Current{};
iter_difference_t<_Iter> _Length = 0;
};

template <class _Iter>
struct incrementable_traits<counted_iterator<_Iter>> {
using difference_type = iter_difference_t<_Iter>;
};

template <input_iterator _Iter>
struct iterator_traits<counted_iterator<_Iter>> : iterator_traits<_Iter> {
using pointer = void;
};
#endif // __cpp_lib_concepts

_STD_END

_STDEXT_BEGIN
Expand Down
3 changes: 3 additions & 0 deletions stl/inc/xatomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@

#include <intrin0.h>
#include <type_traits>
#if defined(_WIN64) && (_MSC_FULL_VER < 192829203) // TRANSITION
#include <intrin.h> // Visual Studio 2019 to define 128-bit CAS in <intrin0.h>
#endif // defined(_WIN64) && (_MSC_FULL_VER < 192829203), TRANSITION

#pragma pack(push, _CRT_PACKING)
#pragma warning(push, _STL_WARNING_LEVEL)
Expand Down
2 changes: 1 addition & 1 deletion stl/inc/xatomic_wait.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ void __stdcall __std_atomic_notify_all_direct(const void* _Storage) noexcept;
// of one of those sizes whose value changes upon notify, hence "indirect". (As of 2020-07-24, this always uses the
// fallback SRWLOCK and CONDITION_VARIABLE implementation but that is not contractual.)
using _Atomic_wait_indirect_equal_callback_t = bool(__stdcall*)(
const void* _Storage, void* _Comparand, size_t _Size, void* _Param) noexcept;
const void* _Storage, void* _Comparand, size_t _Size, void* _Param) _NOEXCEPT_FNPTR;

int __stdcall __std_atomic_wait_indirect(const void* _Storage, void* _Comparand, size_t _Size, void* _Param,
_Atomic_wait_indirect_equal_callback_t _Are_equal, unsigned long _Remaining_timeout) noexcept;
Expand Down
Loading

0 comments on commit b9642bf

Please sign in to comment.