Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

cmake_minimum_required(VERSION 3.25)

# TRANSITION, CMake-24249
cmake_policy(SET CMP0141 OLD)
cmake_minimum_required(VERSION 3.25.2)

set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
project(msvc_standard_libraries LANGUAGES CXX)
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,11 @@ Just try to follow these rules, so we can spend more time fixing bugs and implem

# How To Build With The Visual Studio IDE

1. Install Visual Studio 2022 17.5 Preview 6 or later.
1. Install Visual Studio 2022 17.6 Preview 1 or later.
* Select "Windows 11 SDK (10.0.22000.0)" in the VS Installer.
* We recommend selecting "C++ CMake tools for Windows" in the VS Installer.
This will ensure that you're using supported versions of CMake and Ninja.
* Otherwise, install [CMake][] 3.25 or later, and [Ninja][] 1.11.0 or later.
* Otherwise, install [CMake][] 3.25.2 or later, and [Ninja][] 1.11.0 or later.
* We recommend selecting "Python 3 64-bit" in the VS Installer.
* Otherwise, make sure [Python][] 3.9 or later is available to CMake.
2. Open Visual Studio, and choose the "Clone or check out code" option. Enter the URL of this repository,
Expand All @@ -157,11 +157,11 @@ Just try to follow these rules, so we can spend more time fixing bugs and implem

# How To Build With A Native Tools Command Prompt

1. Install Visual Studio 2022 17.5 Preview 6 or later.
1. Install Visual Studio 2022 17.6 Preview 1 or later.
* Select "Windows 11 SDK (10.0.22000.0)" in the VS Installer.
* We recommend selecting "C++ CMake tools for Windows" in the VS Installer.
This will ensure that you're using supported versions of CMake and Ninja.
* Otherwise, install [CMake][] 3.25 or later, and [Ninja][] 1.11.0 or later.
* Otherwise, install [CMake][] 3.25.2 or later, and [Ninja][] 1.11.0 or later.
* We recommend selecting "Python 3 64-bit" in the VS Installer.
* Otherwise, make sure [Python][] 3.9 or later is available to CMake.
2. Open a command prompt.
Expand Down
2 changes: 1 addition & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ variables:
benchmarkBuildOutputLocation: 'D:\benchmark'

pool:
name: 'StlBuild-2023-02-14T1520-Pool'
name: 'StlBuild-2023-02-21T1058-Pool'
demands: EnableSpotVM -equals true

pr:
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

cmake_minimum_required(VERSION 3.25)
cmake_minimum_required(VERSION 3.25.2)
project(msvc_standard_libraries_benchmarks LANGUAGES CXX)

if(DEFINED STL_BINARY_DIR)
Expand Down
8 changes: 5 additions & 3 deletions stl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -492,10 +492,12 @@ set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "")
# Toolset options must appear before add_library() for the options to take effect.
add_compile_definitions(_CRTBLD _VCRT_ALLOW_INTERNALS _HAS_OLD_IOSTREAMS_MEMBERS=1 _STL_CONCRT_SUPPORT)

# /Z7 for MSVC, /Zi for MASM
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "Embedded")

add_compile_options(/WX /Gy
"$<$<COMPILE_LANGUAGE:CXX>:/diagnostics:caret;/W4;/w14265;/w15038;/fastfail;/guard:cf;/Z7;/Zp8;/std:c++latest;/permissive-;/Zc:threadSafeInit-;/Zl>"
# note that /Zi generates debug info inside the object file, it's the same as /Z7 for msvc
"$<$<COMPILE_LANGUAGE:ASM_MASM>:/Zi;/W3;/nologo>"
"$<$<COMPILE_LANGUAGE:CXX>:/diagnostics:caret;/W4;/w14265;/w15038;/fastfail;/guard:cf;/Zp8;/std:c++latest;/permissive-;/Zc:threadSafeInit-;/Zl>"
"$<$<COMPILE_LANGUAGE:ASM_MASM>:/W3;/nologo>"
)

include_directories(BEFORE
Expand Down
5 changes: 2 additions & 3 deletions stl/inc/charconv
Original file line number Diff line number Diff line change
Expand Up @@ -444,11 +444,10 @@ _NODISCARD inline uint32_t _Bit_scan_reverse(const _Big_integer_flt& _Xval) noex

const uint32_t _Bx = _Xval._Myused - 1;

_STL_INTERNAL_CHECK(_Xval._Mydata[_Bx] != 0); // _Big_integer_flt should always be trimmed

unsigned long _Index; // Intentionally uninitialized for better codegen

_BitScanReverse(&_Index, _Xval._Mydata[_Bx]); // assumes _Xval._Mydata[_Bx] != 0
_STL_INTERNAL_CHECK(_Xval._Mydata[_Bx] != 0); // _Big_integer_flt should always be trimmed
_BitScanReverse(&_Index, _Xval._Mydata[_Bx]); // lgtm [cpp/conditionallyuninitializedvariable]

return _Index + 1 + _Bx * _Big_integer_flt::_Element_bits;
}
Expand Down
4 changes: 0 additions & 4 deletions stl/inc/format
Original file line number Diff line number Diff line change
Expand Up @@ -3364,10 +3364,6 @@ struct formatter<const _CharT*, _CharT>
template <_Format_supported_charT _CharT, size_t _Nx>
struct formatter<_CharT[_Nx], _CharT> : _Formatter_base<_CharT[_Nx], _CharT, _Basic_format_arg_type::_CString_type> {};

template <_Format_supported_charT _CharT, size_t _Nx>
struct formatter<const _CharT[_Nx], _CharT>
: _Formatter_base<_CharT[_Nx], _CharT, _Basic_format_arg_type::_CString_type> {};

template <_Format_supported_charT _CharT, class _Traits, class _Allocator>
struct formatter<basic_string<_CharT, _Traits, _Allocator>, _CharT>
: _Formatter_base<basic_string<_CharT, _Traits, _Allocator>, _CharT, _Basic_format_arg_type::_String_type> {};
Expand Down
66 changes: 62 additions & 4 deletions stl/inc/mutex
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,34 @@ _STD_BEGIN
_EXPORT_STD class condition_variable;
_EXPORT_STD class condition_variable_any;

struct _Mtx_internal_imp_mirror {
#ifdef _CRT_WINDOWS
#ifdef _WIN64
static constexpr size_t _Critical_section_size = 8;
#else // _WIN64
static constexpr size_t _Critical_section_size = 4;
#endif // _WIN64
#else // _CRT_WINDOWS
#ifdef _WIN64
static constexpr size_t _Critical_section_size = 56;
#else // _WIN64
static constexpr size_t _Critical_section_size = 32;
#endif // _WIN64
#endif // _CRT_WINDOWS

int _Type;
const void* _Vptr;
union {
void* _Srw_lock_placeholder;
unsigned char _Padding[_Critical_section_size];
};
long _Thread_id;
int _Count;
};

static_assert(sizeof(_Mtx_internal_imp_mirror) == _Mtx_internal_imp_size, "inconsistent size for mutex");
static_assert(alignof(_Mtx_internal_imp_mirror) == _Mtx_internal_imp_alignment, "inconsistent alignment for mutex");

class _Mutex_base { // base class for all mutex types
public:
_Mutex_base(int _Flags = 0) noexcept {
Expand All @@ -45,10 +73,21 @@ public:
_Mutex_base& operator=(const _Mutex_base&) = delete;

void lock() {
_Check_C_return(_Mtx_lock(_Mymtx()));
if (_Mtx_lock(_Mymtx()) != _Thrd_success) {
// undefined behavior, only occurs for plain mutexes (N4928 [thread.mutex.requirements.mutex.general]/6)
_STD _Throw_Cpp_error(_RESOURCE_DEADLOCK_WOULD_OCCUR);
}

if (!_Verify_ownership_levels()) {
// only occurs for recursive mutexes (N4928 [thread.mutex.recursive]/3)
// POSIX specifies EAGAIN in the corresponding situation:
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_lock.html
_STD _Throw_Cpp_error(_RESOURCE_UNAVAILABLE_TRY_AGAIN);
}
}

_NODISCARD_TRY_CHANGE_STATE bool try_lock() noexcept /* strengthened */ {
// false may be from undefined behavior for plain mutexes (N4928 [thread.mutex.requirements.mutex.general]/6)
return _Mtx_trylock(_Mymtx()) == _Thrd_success;
}

Expand All @@ -62,17 +101,34 @@ public:
return _Mtx_getconcrtcs(_Mymtx());
}

protected:
_NODISCARD_TRY_CHANGE_STATE bool _Verify_ownership_levels() noexcept {
if (_Mtx_storage_mirror._Count == INT_MAX) {
// only occurs for recursive mutexes (N4928 [thread.mutex.recursive]/3)
--_Mtx_storage_mirror._Count;
return false;
}

return true;
}

private:
friend condition_variable;
friend condition_variable_any;

_Aligned_storage_t<_Mtx_internal_imp_size, _Mtx_internal_imp_alignment> _Mtx_storage;
union {
_Aligned_storage_t<_Mtx_internal_imp_size, _Mtx_internal_imp_alignment> _Mtx_storage;
_Mtx_internal_imp_mirror _Mtx_storage_mirror;
};

_Mtx_t _Mymtx() noexcept { // get pointer to _Mtx_internal_imp_t inside _Mtx_storage
return reinterpret_cast<_Mtx_t>(&_Mtx_storage);
}
};

static_assert(sizeof(_Mutex_base) == _Mtx_internal_imp_size, "inconsistent size for mutex");
static_assert(alignof(_Mutex_base) == _Mtx_internal_imp_alignment, "inconsistent alignment for mutex");

_EXPORT_STD class mutex : public _Mutex_base { // class for mutual exclusion
public:
/* constexpr */ mutex() noexcept // TRANSITION, ABI
Expand All @@ -88,7 +144,7 @@ public:
: _Mutex_base(_Mtx_recursive) {}

_NODISCARD_TRY_CHANGE_STATE bool try_lock() noexcept {
return _Mutex_base::try_lock();
return _Mutex_base::try_lock() && _Verify_ownership_levels();
}

recursive_mutex(const recursive_mutex&) = delete;
Expand Down Expand Up @@ -852,7 +908,9 @@ public:
if (_My_locked < UINT_MAX) {
++_My_locked;
} else {
_Throw_system_error(errc::device_or_resource_busy);
// POSIX specifies EAGAIN in the corresponding situation:
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_lock.html
_STD _Throw_system_error(errc::resource_unavailable_try_again);
}
} else {
while (_My_locked != 0) {
Expand Down
46 changes: 35 additions & 11 deletions stl/inc/ranges
Original file line number Diff line number Diff line change
Expand Up @@ -1389,9 +1389,23 @@ namespace ranges {
} // namespace views

#if _HAS_CXX23
template <class _Ty>
concept _Integer_like_with_usable_difference_type = _Signed_integer_like<_Ty>
|| (_Integer_like<_Ty> && weakly_incrementable<_Ty>);

template <class _Ty>
struct _Repeat_view_difference_type {
using type = _Iota_diff_t<_Ty>;
};

template <_Signed_integer_like _Ty>
struct _Repeat_view_difference_type<_Ty> {
using type = _Ty;
};

_EXPORT_STD template <move_constructible _Ty, semiregular _Bo = unreachable_sentinel_t>
requires (is_object_v<_Ty> && same_as<_Ty, remove_cv_t<_Ty>>
&& (_Integer_like<_Bo> || same_as<_Bo, unreachable_sentinel_t>) )
&& (_Integer_like_with_usable_difference_type<_Bo> || same_as<_Bo, unreachable_sentinel_t>) )
class repeat_view : public view_interface<repeat_view<_Ty, _Bo>> {
private:
friend views::_Take_fn;
Expand All @@ -1416,8 +1430,7 @@ namespace ranges {
using iterator_concept = random_access_iterator_tag;
using iterator_category = random_access_iterator_tag;
using value_type = _Ty;
using difference_type =
conditional_t<_Signed_integer_like<_Index_type>, _Index_type, _Iota_diff_t<_Index_type>>;
using difference_type = typename _Repeat_view_difference_type<_Index_type>::type;

_Iterator() = default;

Expand Down Expand Up @@ -7570,6 +7583,12 @@ namespace ranges {
&& (convertible_to<sentinel_t<_ViewTypes>, sentinel_t<const _ViewTypes>> && ...);
#endif // ^^^ workaround ^^^

template <class _Func, class... _Views>
concept _Zip_transform_constraints = move_constructible<_Func> && is_object_v<_Func> && (sizeof...(_Views) > 0)
&& (input_range<_Views> && ...) && (view<_Views> && ...)
&& regular_invocable<_Func&, range_reference_t<_Views>...>
&& _Can_reference<invoke_result_t<_Func&, range_reference_t<_Views>...>>;

_EXPORT_STD template <input_range... _ViewTypes>
requires (view<_ViewTypes> && ...) && (sizeof...(_ViewTypes) > 0)
class zip_view : public view_interface<zip_view<_ViewTypes...>> {
Expand All @@ -7590,10 +7609,8 @@ namespace ranges {
private:
friend zip_view;

template <move_constructible _Func, input_range... _OtherViews>
requires ((view<_OtherViews> && ...) && (sizeof...(_OtherViews) > 0)
&& is_object_v<_Func> && regular_invocable<_Func&, range_reference_t<_OtherViews>...>
&& _Can_reference<invoke_result_t<_Func&, range_reference_t<_OtherViews>...>>)
template <class _Func, class... _OtherViews>
requires _Zip_transform_constraints<_Func, _OtherViews...>
friend class zip_transform_view;

using _My_tuple = tuple<iterator_t<_Maybe_const<_IsConst, _ViewTypes>>...>;
Expand Down Expand Up @@ -7988,10 +8005,8 @@ namespace ranges {
_EXPORT_STD inline constexpr _Zip_fn zip{};
} // namespace views

_EXPORT_STD template <move_constructible _Func, input_range... _ViewTypes>
requires ((view<_ViewTypes> && ...) && (sizeof...(_ViewTypes) > 0)
&& is_object_v<_Func> && regular_invocable<_Func&, range_reference_t<_ViewTypes>...>
&& _Can_reference<invoke_result_t<_Func&, range_reference_t<_ViewTypes>...>>)
_EXPORT_STD template <class _Func, class... _ViewTypes>
requires _Zip_transform_constraints<_Func, _ViewTypes...>
class zip_transform_view : public view_interface<zip_transform_view<_Func, _ViewTypes...>> {
private:
using _Inner_view = zip_view<_ViewTypes...>;
Expand Down Expand Up @@ -8402,6 +8417,9 @@ namespace ranges {
_EXPORT_STD template <class _Container, input_range _Rng, class... _Types>
requires (!view<_Container>)
_NODISCARD constexpr _Container to(_Rng&& _Range, _Types&&... _Args) {
static_assert(!is_const_v<_Container>, "C must not be const. ([range.utility.conv.to])");
static_assert(!is_volatile_v<_Container>, "C must not be volatile. ([range.utility.conv.to])");
static_assert(is_class_v<_Container>, "C must be a class type. ([range.utility.conv.to])");
if constexpr (_Converts_direct_constructible<_Rng, _Container, _Types...>) {
return _Container(_STD forward<_Rng>(_Range), _STD forward<_Types>(_Args)...);
} else if constexpr (_Converts_tag_constructible<_Rng, _Container, _Types...>) {
Expand All @@ -8427,6 +8445,9 @@ namespace ranges {

template <class _Container>
struct _To_class_fn {
_STL_INTERNAL_STATIC_ASSERT(!is_const_v<_Container>);
_STL_INTERNAL_STATIC_ASSERT(!is_volatile_v<_Container>);
_STL_INTERNAL_STATIC_ASSERT(is_class_v<_Container>);
_STL_INTERNAL_STATIC_ASSERT(!view<_Container>);

template <input_range _Rng, class... _Types>
Expand All @@ -8440,6 +8461,9 @@ namespace ranges {
_EXPORT_STD template <class _Container, class... _Types>
requires (!view<_Container>)
_NODISCARD constexpr auto to(_Types&&... _Args) {
static_assert(!is_const_v<_Container>, "C must not be const. ([range.utility.conv.adaptors])");
static_assert(!is_volatile_v<_Container>, "C must not be volatile. ([range.utility.conv.adaptors])");
static_assert(is_class_v<_Container>, "C must be a class type. ([range.utility.conv.adaptors])");
return _Range_closure<_To_class_fn<_Container>, decay_t<_Types>...>{_STD forward<_Types>(_Args)...};
}

Expand Down
3 changes: 2 additions & 1 deletion stl/inc/system_error
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,8 @@ public:
constexpr size_t _Unknown_error_length = sizeof(_Unknown_error) - 1; // TRANSITION, DevCom-906503
return string{_Unknown_error, _Unknown_error_length};
} else {
return string{_Msg._Str, _Msg._Length};
_STL_INTERNAL_CHECK(_Msg._Str != nullptr);
return string{_Msg._Str, _Msg._Length}; // lgtm [cpp/uninitializedptrfield]
}
}

Expand Down
4 changes: 2 additions & 2 deletions stl/inc/type_traits
Original file line number Diff line number Diff line change
Expand Up @@ -615,8 +615,8 @@ struct has_unique_object_representations : bool_constant<__has_unique_object_rep
_EXPORT_STD template <class _Ty>
_INLINE_VAR constexpr bool has_unique_object_representations_v = __has_unique_object_representations(_Ty);

// TRANSITION, Clang 16, VSO-1690654, and VS17.6p1
#if defined(__clang__) || defined(__EDG__) || !defined(_MSVC_INTERNAL_TESTING)
// TRANSITION, Clang 16 and VSO-1690654
#if defined(__clang__) || defined(__EDG__)
template <class _Ty>
struct _Is_aggregate_impl : bool_constant<__is_aggregate(_Ty)> {};

Expand Down
31 changes: 16 additions & 15 deletions stl/inc/utility
Original file line number Diff line number Diff line change
Expand Up @@ -480,45 +480,46 @@ constexpr void swap(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Righ
}
#endif // _HAS_CXX23

_EXPORT_STD template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool operator==(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) {
_EXPORT_STD template <class _Ty1, class _Ty2, class _Uty1, class _Uty2>
_NODISCARD constexpr bool operator==(const pair<_Ty1, _Ty2>& _Left, const pair<_Uty1, _Uty2>& _Right) {
return _Left.first == _Right.first && _Left.second == _Right.second;
}

#ifdef __cpp_lib_concepts
_EXPORT_STD template <class _Ty1, class _Ty2>
_NODISCARD constexpr common_comparison_category_t<_Synth_three_way_result<_Ty1>, _Synth_three_way_result<_Ty2>>
operator<=>(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) {
_EXPORT_STD template <class _Ty1, class _Ty2, class _Uty1, class _Uty2>
_NODISCARD constexpr common_comparison_category_t<_Synth_three_way_result<_Ty1, _Uty1>,
_Synth_three_way_result<_Ty2, _Uty2>>
operator<=>(const pair<_Ty1, _Ty2>& _Left, const pair<_Uty1, _Uty2>& _Right) {
if (auto _Result = _Synth_three_way{}(_Left.first, _Right.first); _Result != 0) {
return _Result;
}
return _Synth_three_way{}(_Left.second, _Right.second);
}
#else // ^^^ defined(__cpp_lib_concepts) / !defined(__cpp_lib_concepts) vvv
#if !_HAS_CXX20
template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool operator!=(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) {
template <class _Ty1, class _Ty2, class _Uty1, class _Uty2>
_NODISCARD constexpr bool operator!=(const pair<_Ty1, _Ty2>& _Left, const pair<_Uty1, _Uty2>& _Right) {
return !(_Left == _Right);
}
#endif // !_HAS_CXX20

template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool operator<(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) {
template <class _Ty1, class _Ty2, class _Uty1, class _Uty2>
_NODISCARD constexpr bool operator<(const pair<_Ty1, _Ty2>& _Left, const pair<_Uty1, _Uty2>& _Right) {
return _Left.first < _Right.first || (!(_Right.first < _Left.first) && _Left.second < _Right.second);
}

template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool operator>(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) {
template <class _Ty1, class _Ty2, class _Uty1, class _Uty2>
_NODISCARD constexpr bool operator>(const pair<_Ty1, _Ty2>& _Left, const pair<_Uty1, _Uty2>& _Right) {
return _Right < _Left;
}

template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool operator<=(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) {
template <class _Ty1, class _Ty2, class _Uty1, class _Uty2>
_NODISCARD constexpr bool operator<=(const pair<_Ty1, _Ty2>& _Left, const pair<_Uty1, _Uty2>& _Right) {
return !(_Right < _Left);
}

template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool operator>=(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) {
template <class _Ty1, class _Ty2, class _Uty1, class _Uty2>
_NODISCARD constexpr bool operator>=(const pair<_Ty1, _Ty2>& _Left, const pair<_Uty1, _Uty2>& _Right) {
return !(_Left < _Right);
}
#endif // ^^^ !defined(__cpp_lib_concepts) ^^^
Expand Down
Loading