Skip to content
Merged
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
12 changes: 9 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ option(BUILD_TESTING "Enable testing" ON)
set(VCLIBS_SUFFIX "_oss" CACHE STRING "suffix for built DLL names to avoid conflicts with distributed DLLs")

option(STL_USE_ANALYZE "Pass the /analyze flag to MSVC" OFF)
option(STL_ASAN_BUILD "Build the STL with ASan enabled" OFF)

set(VCLIBS_EXPLICIT_MACHINE "")

Expand Down Expand Up @@ -117,10 +118,15 @@ set(VCLIBS_DEBUG_OPTIONS "$<$<COMPILE_LANGUAGE:CXX>:/Od>")
# See GH-2108 for more info.
set(VCLIBS_RELEASE_OPTIONS "$<$<COMPILE_LANGUAGE:CXX>:/O2;/Os>")

add_subdirectory(boost-math)
add_subdirectory(stl)

if(BUILD_TESTING)
enable_testing()
add_subdirectory(tests)
endif()

if(STL_ASAN_BUILD)
message(STATUS "Building with ASan enabled")
add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:-fsanitize=address;-fno-sanitize-address-vcasan-lib>")
endif()

add_subdirectory(boost-math)
add_subdirectory(stl)
2 changes: 2 additions & 0 deletions azure-devops/asan-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ stages:
targetPlatform: x64
vsDevCmdArch: amd64
buildBenchmarks: false
asanBuild: true
testSelection: ${{ variables.testSelection }}

- stage: Build_And_Test_x86
Expand All @@ -43,6 +44,7 @@ stages:
targetPlatform: x86
vsDevCmdArch: x86
buildBenchmarks: false
asanBuild: true
testSelection: ${{ variables.testSelection }}

# no coverage for ARM and ARM64
4 changes: 4 additions & 0 deletions azure-devops/cmake-configure-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ parameters:
type: string
- name: buildBenchmarks
type: boolean
- name: asanBuild
type: boolean
default: false
- name: cmakeAdditionalFlags
type: string
default: ''
Expand Down Expand Up @@ -43,6 +46,7 @@ steps:
-DCMAKE_BUILD_TYPE=Release ^
-DLIT_FLAGS=${{ join(';', parameters.litFlags) }} ^
-DSTL_USE_ANALYZE=ON ^
-DSTL_ASAN_BUILD=${{ parameters.asanBuild }} ^
-S $(Build.SourcesDirectory) -B "$(buildOutputLocation)"
displayName: 'Configure the STL'
timeoutInMinutes: 2
Expand Down
4 changes: 4 additions & 0 deletions azure-devops/native-build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ parameters:
- name: buildBenchmarks
type: boolean
default: true
- name: asanBuild
type: boolean
default: false
- name: numShards
type: number
default: 8
Expand All @@ -35,6 +38,7 @@ jobs:
targetArch: ${{ parameters.vsDevCmdArch }}
hostArch: ${{ parameters.vsDevCmdArch }}
buildBenchmarks: ${{ parameters.buildBenchmarks }}
asanBuild: ${{ parameters.asanBuild }}
- template: run-tests.yml
parameters:
hostArch: ${{ parameters.vsDevCmdArch }}
Expand Down
8 changes: 7 additions & 1 deletion stl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,12 @@ else()
string(APPEND CMAKE_CXX_STANDARD_LIBRARIES " Synchronization.lib")
endif()

if(STL_ASAN_BUILD)
set(DLL_ASAN_SOURCES ${ASAN_SOURCES})
else()
set(DLL_ASAN_SOURCES "")
endif()

function(target_stl_compile_options tgt rel_or_dbg)
if(rel_or_dbg STREQUAL "Release")
target_compile_options(${tgt} PRIVATE ${VCLIBS_RELEASE_OPTIONS})
Expand Down Expand Up @@ -563,7 +569,7 @@ function(add_stl_dlls D_SUFFIX REL_OR_DBG)
set(gl_flag_Debug "")

# msvcp140.dll
add_library(msvcp${D_SUFFIX}_objects OBJECT ${DLL_SOURCES} ${SOURCES})
add_library(msvcp${D_SUFFIX}_objects OBJECT ${DLL_SOURCES} ${SOURCES} ${DLL_ASAN_SOURCES})
target_compile_definitions(msvcp${D_SUFFIX}_objects PRIVATE CRTDLL2 _DLL)
target_compile_options(msvcp${D_SUFFIX}_objects PRIVATE ${gl_flag_${REL_OR_DBG}} /EHsc)
target_stl_compile_options(msvcp${D_SUFFIX}_objects ${REL_OR_DBG})
Expand Down
716 changes: 370 additions & 346 deletions stl/inc/algorithm

Large diffs are not rendered by default.

201 changes: 102 additions & 99 deletions stl/inc/atomic

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions stl/inc/deque
Original file line number Diff line number Diff line change
Expand Up @@ -825,8 +825,8 @@ public:

template <class _Iter, enable_if_t<_Is_iterator_v<_Iter>, int> = 0>
void assign(_Iter _First, _Iter _Last) {
_Adl_verify_range(_First, _Last);
_Assign_range(_Get_unwrapped(_First), _Get_unwrapped(_Last));
_STD _Adl_verify_range(_First, _Last);
_Assign_range(_STD _Get_unwrapped(_First), _STD _Get_unwrapped(_Last));
}

#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395
Expand Down Expand Up @@ -1244,10 +1244,10 @@ public:
template <class _Iter, enable_if_t<_Is_iterator_v<_Iter>, int> = 0>
iterator insert(const_iterator _Where, _Iter _First, _Iter _Last) {
// insert [_First, _Last) at _Where
_Adl_verify_range(_First, _Last);
_STD _Adl_verify_range(_First, _Last);
const size_type _Off = static_cast<size_type>(_Where - begin());
return _Insert_range<static_cast<_Is_bidi>(_Is_cpp17_bidi_iter_v<_Iter>)>(
_Off, _Get_unwrapped(_First), _Get_unwrapped(_Last));
_Off, _STD _Get_unwrapped(_First), _STD _Get_unwrapped(_Last));
}

#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395
Expand Down Expand Up @@ -1469,7 +1469,7 @@ public:

#if _ITERATOR_DEBUG_LEVEL == 2
_STL_VERIFY(_First <= _Last && begin() <= _First && _Last <= end(), "deque erase iterator outside range");
_Adl_verify_range(_First, _Last);
_STD _Adl_verify_range(_First, _Last);

auto _Off = static_cast<size_type>(_First - begin());
auto _Count = static_cast<size_type>(_Last - _First);
Expand Down
92 changes: 47 additions & 45 deletions stl/inc/execution
Original file line number Diff line number Diff line change
Expand Up @@ -2315,7 +2315,7 @@ struct _Static_partitioned_unary_transform2 {

static void __stdcall _Threadpool_callback(
__std_PTP_CALLBACK_INSTANCE, void* const _Context, __std_PTP_WORK) noexcept /* terminates */ {
_Run_available_chunked_work(*static_cast<_Static_partitioned_unary_transform2*>(_Context));
_STD _Run_available_chunked_work(*static_cast<_Static_partitioned_unary_transform2*>(_Context));
}
};

Expand All @@ -2326,36 +2326,38 @@ _FwdIt2 transform(_ExPo&&, const _FwdIt1 _First, const _FwdIt1 _Last, _FwdIt2 _D
// transform [_First, _Last) with _Func
_REQUIRE_PARALLEL_ITERATOR(_FwdIt1);
_REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt2);
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_First);
const auto _ULast = _Get_unwrapped(_Last);
_STD _Adl_verify_range(_First, _Last);
auto _UFirst = _STD _Get_unwrapped(_First);
const auto _ULast = _STD _Get_unwrapped(_Last);
if constexpr (remove_reference_t<_ExPo>::_Parallelize) {
const size_t _Hw_threads = __std_parallel_algorithms_hw_threads();
if (_Hw_threads > 1) { // parallelize on multiprocessor machines...
const auto _Count = _STD distance(_UFirst, _ULast);
const auto _UDest = _Get_unwrapped_n(_Dest, _Count);
const auto _UDest = _STD _Get_unwrapped_n(_Dest, _Count);
if (_Count >= 2) { // ... with at least 2 elements
_TRY_BEGIN
_Static_partitioned_unary_transform2 _Operation{_Hw_threads, _Count, _UFirst, _Pass_fn(_Func), _UDest};
_Seek_wrapped(_Dest, _Operation._Dest_basis._Populate(_Operation._Team, _UDest));
_Run_chunked_parallel_work(_Hw_threads, _Operation);
_Static_partitioned_unary_transform2 _Operation{
_Hw_threads, _Count, _UFirst, _STD _Pass_fn(_Func), _UDest};
_STD _Seek_wrapped(_Dest, _Operation._Dest_basis._Populate(_Operation._Team, _UDest));
_STD _Run_chunked_parallel_work(_Hw_threads, _Operation);
return _Dest;
_CATCH(const _Parallelism_resources_exhausted&)
// fall through to serial case below
_CATCH_END
}

_Seek_wrapped(_Dest, _STD transform(_UFirst, _ULast, _UDest, _Pass_fn(_Func)));
_STD _Seek_wrapped(_Dest, _STD transform(_UFirst, _ULast, _UDest, _STD _Pass_fn(_Func)));
return _Dest;
} else {
_Seek_wrapped(
_Dest, _STD transform(_UFirst, _ULast, _Get_unwrapped_n(_Dest, _Idl_distance<_FwdIt1>(_UFirst, _ULast)),
_Pass_fn(_Func)));
_STD _Seek_wrapped(_Dest,
_STD transform(_UFirst, _ULast,
_STD _Get_unwrapped_n(_Dest, _STD _Idl_distance<_FwdIt1>(_UFirst, _ULast)), _STD _Pass_fn(_Func)));
return _Dest;
}
} else {
_Seek_wrapped(_Dest, _STD transform(_UFirst, _ULast,
_Get_unwrapped_n(_Dest, _Idl_distance<_FwdIt1>(_UFirst, _ULast)), _Pass_fn(_Func)));
_STD _Seek_wrapped(_Dest,
_STD transform(_UFirst, _ULast, _STD _Get_unwrapped_n(_Dest, _STD _Idl_distance<_FwdIt1>(_UFirst, _ULast)),
_STD _Pass_fn(_Func)));
return _Dest;
}
}
Expand Down Expand Up @@ -2391,7 +2393,7 @@ struct _Static_partitioned_binary_transform2 {

static void __stdcall _Threadpool_callback(
__std_PTP_CALLBACK_INSTANCE, void* const _Context, __std_PTP_WORK) noexcept /* terminates */ {
_Run_available_chunked_work(*static_cast<_Static_partitioned_binary_transform2*>(_Context));
_STD _Run_available_chunked_work(*static_cast<_Static_partitioned_binary_transform2*>(_Context));
}
};

Expand All @@ -2403,39 +2405,39 @@ _FwdIt3 transform(_ExPo&&, const _FwdIt1 _First1, const _FwdIt1 _Last1, const _F
_REQUIRE_PARALLEL_ITERATOR(_FwdIt1);
_REQUIRE_PARALLEL_ITERATOR(_FwdIt2);
_REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt3);
_Adl_verify_range(_First1, _Last1);
const auto _UFirst1 = _Get_unwrapped(_First1);
const auto _ULast1 = _Get_unwrapped(_Last1);
_STD _Adl_verify_range(_First1, _Last1);
const auto _UFirst1 = _STD _Get_unwrapped(_First1);
const auto _ULast1 = _STD _Get_unwrapped(_Last1);
if constexpr (remove_reference_t<_ExPo>::_Parallelize) {
const size_t _Hw_threads = __std_parallel_algorithms_hw_threads();
if (_Hw_threads > 1) { // parallelize on multiprocessor machines...
const auto _Count = _STD distance(_UFirst1, _ULast1);
const auto _UFirst2 = _Get_unwrapped_n(_First2, _Count);
const auto _UDest = _Get_unwrapped_n(_Dest, _Count);
const auto _UFirst2 = _STD _Get_unwrapped_n(_First2, _Count);
const auto _UDest = _STD _Get_unwrapped_n(_Dest, _Count);
if (_Count >= 2) { // ... with at least 2 elements
_TRY_BEGIN
_Static_partitioned_binary_transform2 _Operation{
_Hw_threads, _Count, _UFirst1, _UFirst2, _Pass_fn(_Func), _UDest};
_Seek_wrapped(_Dest, _Operation._Dest_basis._Populate(_Operation._Team, _UDest));
_Run_chunked_parallel_work(_Hw_threads, _Operation);
_Hw_threads, _Count, _UFirst1, _UFirst2, _STD _Pass_fn(_Func), _UDest};
_STD _Seek_wrapped(_Dest, _Operation._Dest_basis._Populate(_Operation._Team, _UDest));
_STD _Run_chunked_parallel_work(_Hw_threads, _Operation);
return _Dest;
_CATCH(const _Parallelism_resources_exhausted&)
// fall through to serial case below
_CATCH_END
}

_Seek_wrapped(_Dest, _STD transform(_UFirst1, _ULast1, _UFirst2, _UDest, _Pass_fn(_Func)));
_STD _Seek_wrapped(_Dest, _STD transform(_UFirst1, _ULast1, _UFirst2, _UDest, _STD _Pass_fn(_Func)));
return _Dest;
} else {
const auto _Count = _Idl_distance<_FwdIt1>(_UFirst1, _ULast1);
_Seek_wrapped(_Dest, _STD transform(_UFirst1, _ULast1, _Get_unwrapped_n(_First2, _Count),
_Get_unwrapped_n(_Dest, _Count), _Pass_fn(_Func)));
const auto _Count = _STD _Idl_distance<_FwdIt1>(_UFirst1, _ULast1);
_STD _Seek_wrapped(_Dest, _STD transform(_UFirst1, _ULast1, _STD _Get_unwrapped_n(_First2, _Count),
_STD _Get_unwrapped_n(_Dest, _Count), _STD _Pass_fn(_Func)));
return _Dest;
}
} else {
const auto _Count = _Idl_distance<_FwdIt1>(_UFirst1, _ULast1);
_Seek_wrapped(_Dest, _STD transform(_UFirst1, _ULast1, _Get_unwrapped_n(_First2, _Count),
_Get_unwrapped_n(_Dest, _Count), _Pass_fn(_Func)));
const auto _Count = _STD _Idl_distance<_FwdIt1>(_UFirst1, _ULast1);
_STD _Seek_wrapped(_Dest, _STD transform(_UFirst1, _ULast1, _STD _Get_unwrapped_n(_First2, _Count),
_STD _Get_unwrapped_n(_Dest, _Count), _STD _Pass_fn(_Func)));
return _Dest;
}
}
Expand All @@ -2457,12 +2459,12 @@ void replace_if(_ExPo&& _Exec, const _FwdIt _First, const _FwdIt _Last, _Pr _Pre
/* terminates */ {
// replace each satisfying _Pred with _Val
_REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt);
_STD for_each(
_STD forward<_ExPo>(_Exec), _First, _Last, [&_Val, _Lambda_pred = _Pass_fn(_Pred)](auto&& _Value) mutable {
if (_Lambda_pred(_STD forward<decltype(_Value)>(_Value))) {
_STD forward<decltype(_Value)>(_Value) = _Val;
}
});
auto _Lambda_pred = _STD _Pass_fn(_Pred); // TRANSITION, DevCom-10456445
_STD for_each(_STD forward<_ExPo>(_Exec), _First, _Last, [&_Val, _Lambda_pred](auto&& _Value) mutable {
if (_Lambda_pred(_STD forward<decltype(_Value)>(_Value))) {
_STD forward<decltype(_Value)>(_Value) = _Val;
}
});
}

template <class _FwdIt, class _Pr>
Expand Down Expand Up @@ -2530,7 +2532,7 @@ struct _Static_partitioned_remove_if2 {
if (_Merge_index == 0 || _Results == _Range._First) {
_Results = _STD remove_if(_Range._First, _Range._Last, _Pred);
} else {
_Results = _Remove_move_if_unchecked(_Range._First, _Range._Last, _Results, _Pred);
_Results = _STD _Remove_move_if_unchecked(_Range._First, _Range._Last, _Results, _Pred);
}

_Chunk_data._State.store(_Chunk_state::_Done);
Expand Down Expand Up @@ -2572,7 +2574,7 @@ struct _Static_partitioned_remove_if2 {

static void __stdcall _Threadpool_callback(
__std_PTP_CALLBACK_INSTANCE, void* const _Context, __std_PTP_WORK) noexcept /* terminates */ {
_Run_available_chunked_work(*static_cast<_Static_partitioned_remove_if2*>(_Context));
_STD _Run_available_chunked_work(*static_cast<_Static_partitioned_remove_if2*>(_Context));
}
};

Expand All @@ -2581,18 +2583,18 @@ _NODISCARD_REMOVE_ALG _FwdIt remove_if(_ExPo&&, _FwdIt _First, const _FwdIt _Las
/* terminates */ {
// remove each satisfying _Pred
_REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt);
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_First);
const auto _ULast = _Get_unwrapped(_Last);
_STD _Adl_verify_range(_First, _Last);
auto _UFirst = _STD _Get_unwrapped(_First);
const auto _ULast = _STD _Get_unwrapped(_Last);
if constexpr (remove_reference_t<_ExPo>::_Parallelize) {
const size_t _Hw_threads = __std_parallel_algorithms_hw_threads();
if (_Hw_threads > 1) {
const auto _Count = _STD distance(_UFirst, _ULast);
if (_Count >= 2) {
_TRY_BEGIN
_Static_partitioned_remove_if2 _Operation{_Hw_threads, _Count, _UFirst, _Pass_fn(_Pred)};
_Run_chunked_parallel_work(_Hw_threads, _Operation);
_Seek_wrapped(_First, _Operation._Results);
_Static_partitioned_remove_if2 _Operation{_Hw_threads, _Count, _UFirst, _STD _Pass_fn(_Pred)};
_STD _Run_chunked_parallel_work(_Hw_threads, _Operation);
_STD _Seek_wrapped(_First, _Operation._Results);
return _First;
_CATCH(const _Parallelism_resources_exhausted&)
// fall through to serial case below
Expand All @@ -2601,7 +2603,7 @@ _NODISCARD_REMOVE_ALG _FwdIt remove_if(_ExPo&&, _FwdIt _First, const _FwdIt _Las
}
}

_Seek_wrapped(_First, _STD remove_if(_UFirst, _ULast, _Pass_fn(_Pred)));
_STD _Seek_wrapped(_First, _STD remove_if(_UFirst, _ULast, _STD _Pass_fn(_Pred)));
return _First;
}

Expand Down
10 changes: 10 additions & 0 deletions stl/inc/filesystem
Original file line number Diff line number Diff line change
Expand Up @@ -2505,6 +2505,8 @@ namespace filesystem {
_EXPORT_STD enum class directory_options { none = 0, follow_directory_symlink = 1, skip_permission_denied = 2 };
_BITMASK_OPS(_EXPORT_STD, directory_options)

_EXPORT_STD _NODISCARD inline bool exists(const path& _Target, error_code& _Ec) noexcept;

struct _Dir_enum_impl {
_NODISCARD static __std_win_error _Advance_and_reset_if_no_more_files(shared_ptr<_Dir_enum_impl>& _Ptr) {
auto& _Impl = *_Ptr;
Expand Down Expand Up @@ -2543,6 +2545,7 @@ namespace filesystem {
return __std_win_error::_File_not_found;
}

const path _Original_path = _Path;
_Path /= L"*"sv;
auto _Error = _Dir._Open(_Path.c_str(), &_Data);
if (_Error == __std_win_error::_Success) {
Expand All @@ -2552,6 +2555,13 @@ namespace filesystem {
if (_Error == __std_win_error::_Access_denied
&& _Bitmask_includes_any(_Options_arg, directory_options::skip_permission_denied)) {
_Error = __std_win_error::_No_more_files;
} else if (_Error == __std_win_error::_File_not_found) {
error_code _Ignored; // When exists() returns true, that implies that the error_code is successful.
// When exists() returns false, we don't want to interfere with _Open_dir()'s behavior,
// as it's going to return __std_win_error::_File_not_found.
if (_STD filesystem::exists(_Original_path, _Ignored)) {
_Error = __std_win_error::_No_more_files; // Handle empty volumes, see GH-4291
}
}

return _Error;
Expand Down
Loading