diff --git a/azure-devops/format-validation.yml b/azure-devops/format-validation.yml new file mode 100644 index 00000000000..fa86b6b67a2 --- /dev/null +++ b/azure-devops/format-validation.yml @@ -0,0 +1,52 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# run the `validator` tool, and ensure code is properly clang-formatted + +jobs: +- job: Code_Format_Validation + timeoutInMinutes: 5 + displayName: 'Validation' + steps: + - script: | + if exist "$(tmpDir)" ( + rmdir /S /Q $(tmpDir) + ) + mkdir $(tmpDir) + displayName: 'Setup TMP Directory' + - checkout: self + clean: true + submodules: false + - script: | + cd $(Build.SourcesDirectory) + git clean --quiet -x -d -f -f + displayName: 'Clean after checkout' + - script: | + call "%ProgramFiles%\Microsoft Visual Studio\2022\Preview\Common7\Tools\VsDevCmd.bat" ^ + -host_arch=amd64 -arch=amd64 -no_logo + cmake -G Ninja -S $(Build.SourcesDirectory)/tools -B $(tmpDir)/format-validate-build + cmake --build $(tmpDir)/format-validate-build + displayName: 'Build format and validation' + timeoutInMinutes: 5 + env: { TMP: $(tmpDir), TEMP: $(tmpDir) } + - script: | + call "%ProgramFiles%\Microsoft Visual Studio\2022\Preview\Common7\Tools\VsDevCmd.bat" ^ + -host_arch=amd64 -arch=amd64 -no_logo + cmake --build $(tmpDir)/format-validate-build --target run-format + displayName: 'clang-format Files' + timeoutInMinutes: 5 + env: { TMP: $(tmpDir), TEMP: $(tmpDir) } + - script: | + call "%ProgramFiles%\Microsoft Visual Studio\2022\Preview\Common7\Tools\VsDevCmd.bat" ^ + -host_arch=amd64 -arch=amd64 -no_logo + cmake --build $(tmpDir)/format-validate-build --target run-validate + displayName: 'Validate Files' + timeoutInMinutes: 2 + env: { TMP: $(tmpDir), TEMP: $(tmpDir) } + - task: Powershell@2 + displayName: 'Create Diff' + inputs: + filePath: azure-devops/create-prdiff.ps1 + pwsh: false + condition: succeededOrFailed() + env: { TMP: $(tmpDir), TEMP: $(tmpDir) } diff --git a/azure-pipelines.yml b/azure-pipelines.yml index e469634c6e9..628467f9539 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -19,52 +19,7 @@ stages: - stage: Code_Format displayName: 'Code Format' jobs: - - job: Code_Format_Validation - timeoutInMinutes: 5 - displayName: 'Validation' - steps: - - script: | - if exist "$(tmpDir)" ( - rmdir /S /Q $(tmpDir) - ) - mkdir $(tmpDir) - displayName: 'Setup TMP Directory' - - checkout: self - clean: true - submodules: false - - script: | - cd $(Build.SourcesDirectory) - git clean --quiet -x -d -f -f - displayName: 'Clean after checkout' - - script: | - call "%ProgramFiles%\Microsoft Visual Studio\2022\Preview\Common7\Tools\VsDevCmd.bat" ^ - -host_arch=amd64 -arch=amd64 -no_logo - cmake -G Ninja -S $(Build.SourcesDirectory)/tools -B $(tmpDir)/format-validate-build - cmake --build $(tmpDir)/format-validate-build - displayName: 'Build format and validation' - timeoutInMinutes: 5 - env: { TMP: $(tmpDir), TEMP: $(tmpDir) } - - script: | - call "%ProgramFiles%\Microsoft Visual Studio\2022\Preview\Common7\Tools\VsDevCmd.bat" ^ - -host_arch=amd64 -arch=amd64 -no_logo - cmake --build $(tmpDir)/format-validate-build --target run-format - displayName: 'clang-format Files' - timeoutInMinutes: 5 - env: { TMP: $(tmpDir), TEMP: $(tmpDir) } - - script: | - call "%ProgramFiles%\Microsoft Visual Studio\2022\Preview\Common7\Tools\VsDevCmd.bat" ^ - -host_arch=amd64 -arch=amd64 -no_logo - cmake --build $(tmpDir)/format-validate-build --target run-validate - displayName: 'Validate Files' - timeoutInMinutes: 2 - env: { TMP: $(tmpDir), TEMP: $(tmpDir) } - - task: Powershell@2 - displayName: 'Create Diff' - inputs: - filePath: azure-devops/create-prdiff.ps1 - pwsh: false - condition: succeededOrFailed() - env: { TMP: $(tmpDir), TEMP: $(tmpDir) } + - template: azure-devops/format-validation.yml - stage: Build_And_Test_x64 dependsOn: Code_Format diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt index 9568e6f8bc8..3857d4c1e2c 100644 --- a/benchmarks/CMakeLists.txt +++ b/benchmarks/CMakeLists.txt @@ -108,5 +108,10 @@ endfunction() add_benchmark(bitset_to_string src/bitset_to_string.cpp) add_benchmark(locale_classic src/locale_classic.cpp) add_benchmark(path_lexically_normal src/path_lexically_normal.cpp) +add_benchmark(priority_queue_push_range src/priority_queue_push_range.cpp) add_benchmark(random_integer_generation src/random_integer_generation.cpp) add_benchmark(std_copy src/std_copy.cpp) + +add_benchmark(vector_bool_copy src/std/containers/sequences/vector.bool/copy/test.cpp) +add_benchmark(vector_bool_copy_n src/std/containers/sequences/vector.bool/copy_n/test.cpp) +add_benchmark(vector_bool_move src/std/containers/sequences/vector.bool/move/test.cpp) diff --git a/benchmarks/src/priority_queue_push_range.cpp b/benchmarks/src/priority_queue_push_range.cpp new file mode 100644 index 00000000000..444d2c2b30d --- /dev/null +++ b/benchmarks/src/priority_queue_push_range.cpp @@ -0,0 +1,89 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +using namespace std; + +namespace { + constexpr size_t vec_size = 10'000; + + template + auto create_vec(Fn transformation) { + vector vec(vec_size); + for (mt19937_64 rnd(1); auto& e : vec) { + e = transformation(rnd()); + } + return vec; + } + + template + T cast_to(uint64_t val) { + return static_cast(val); + } + + const auto vec_u8 = create_vec(cast_to); + const auto vec_u16 = create_vec(cast_to); + const auto vec_u32 = create_vec(cast_to); + const auto vec_u64 = create_vec(cast_to); + const auto vec_float = create_vec(cast_to); + const auto vec_double = create_vec(cast_to); + + const auto vec_str = create_vec([](uint64_t val) { return to_string(static_cast(val)); }); + const auto vec_wstr = create_vec([](uint64_t val) { return to_wstring(static_cast(val)); }); + + template + void BM_push_range(benchmark::State& state) { + const size_t frag_size = static_cast(state.range(0)); + + for (auto _ : state) { + priority_queue que; + span spn{Data}; + + while (!spn.empty()) { + const size_t take_size = min(spn.size(), frag_size); + que.push_range(spn.first(take_size)); + spn = spn.subspan(take_size); + } + benchmark::DoNotOptimize(que); + } + } + + template + void putln(const benchmark::State&) { + static bool b = [] { + puts(""); + return true; + }(); + } +} // namespace + +#define TEST_PUSH_RANGE(T, source) \ + BENCHMARK(BM_push_range) \ + ->Setup(putln<__LINE__>) \ + ->RangeMultiplier(100) \ + ->Range(1, vec_size) \ + ->Arg(vec_size / 2 + 1); + +TEST_PUSH_RANGE(uint8_t, vec_u8); +TEST_PUSH_RANGE(uint16_t, vec_u16); +TEST_PUSH_RANGE(uint32_t, vec_u32); +TEST_PUSH_RANGE(uint64_t, vec_u64); +TEST_PUSH_RANGE(float, vec_float); +TEST_PUSH_RANGE(double, vec_double); + +TEST_PUSH_RANGE(string_view, vec_str); +TEST_PUSH_RANGE(string, vec_str); +TEST_PUSH_RANGE(wstring_view, vec_wstr); +TEST_PUSH_RANGE(wstring, vec_wstr); + +BENCHMARK_MAIN(); diff --git a/benchmarks/src/std/containers/sequences/vector.bool/copy/test.cpp b/benchmarks/src/std/containers/sequences/vector.bool/copy/test.cpp new file mode 100644 index 00000000000..c5c0777526b --- /dev/null +++ b/benchmarks/src/std/containers/sequences/vector.bool/copy/test.cpp @@ -0,0 +1,100 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +// +#include +#include +#include + +using namespace std; + +static vector createRandomVector(const size_t size) { + static mt19937 gen{random_device{}()}; + vector result(size); + generate_n(result.begin(), size, [] { return bernoulli_distribution{0.5}(gen); }); + return result; +} + +static void copy_block_aligned(benchmark::State& state) { + const auto size = state.range(0); + const vector source = createRandomVector(size); + vector dest(size, false); + + for (auto _ : state) { + copy(source.cbegin(), source.cend(), dest.begin()); + } +} + +static void copy_source_misaligned(benchmark::State& state) { + const auto size = state.range(0); + const vector source = createRandomVector(size); + vector dest(size, false); + + for (auto _ : state) { + copy(source.cbegin() + 1, source.cend(), dest.begin()); + } +} + +static void copy_dest_misaligned(benchmark::State& state) { + const auto size = state.range(0); + const vector source = createRandomVector(size); + vector dest(size, false); + + for (auto _ : state) { + copy(source.cbegin(), source.cend() - 1, dest.begin() + 1); + } +} + +// Special benchmark for matching char alignment +static void copy_matching_alignment(benchmark::State& state) { + const auto size = state.range(0); + const vector source = createRandomVector(size); + vector dest(size, false); + + for (auto _ : state) { + copy(source.cbegin() + 5, source.cend(), dest.begin() + 5); + } +} + +// Special benchmarks for single block corner case +static void copy_both_single_blocks(benchmark::State& state) { + const vector source = createRandomVector(50); + vector dest(50, false); + + const size_t length = 20; + for (auto _ : state) { + copy(source.cbegin() + 5, source.cbegin() + 5 + length, dest.begin() + 5); + } +} + +static void copy_source_single_block(benchmark::State& state) { + const vector source = createRandomVector(50); + vector dest(50, false); + + const size_t length = 20; + for (auto _ : state) { + copy(source.cbegin() + 5, source.cbegin() + 5 + length, dest.begin() + 25); + } +} + +static void copy_dest_single_block(benchmark::State& state) { + const vector source = createRandomVector(50); + vector dest(50, false); + + const size_t length = 20; + for (auto _ : state) { + copy(source.cbegin() + 25, source.cbegin() + 25 + length, dest.begin() + 5); + } +} + +BENCHMARK(copy_block_aligned)->RangeMultiplier(64)->Range(64, 64 << 10); +BENCHMARK(copy_source_misaligned)->RangeMultiplier(64)->Range(64, 64 << 10); +BENCHMARK(copy_dest_misaligned)->RangeMultiplier(64)->Range(64, 64 << 10); +BENCHMARK(copy_matching_alignment)->RangeMultiplier(64)->Range(64, 64 << 10); + +BENCHMARK(copy_both_single_blocks); +BENCHMARK(copy_source_single_block); +BENCHMARK(copy_dest_single_block); + +BENCHMARK_MAIN(); diff --git a/benchmarks/src/std/containers/sequences/vector.bool/copy_n/test.cpp b/benchmarks/src/std/containers/sequences/vector.bool/copy_n/test.cpp new file mode 100644 index 00000000000..5a4babf5c54 --- /dev/null +++ b/benchmarks/src/std/containers/sequences/vector.bool/copy_n/test.cpp @@ -0,0 +1,100 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +// +#include +#include +#include + +using namespace std; + +static vector createRandomVector(const size_t size) { + static mt19937 gen{random_device{}()}; + vector result(size); + generate_n(result.begin(), size, [] { return bernoulli_distribution{0.5}(gen); }); + return result; +} + +static void copy_n_block_aligned(benchmark::State& state) { + const auto size = state.range(0); + const vector source = createRandomVector(size); + vector dest(size, false); + + for (auto _ : state) { + copy_n(source.cbegin(), size, dest.begin()); + } +} + +static void copy_n_source_misaligned(benchmark::State& state) { + const auto size = state.range(0); + const vector source = createRandomVector(size); + vector dest(size, false); + + for (auto _ : state) { + copy_n(source.cbegin() + 1, size - 1, dest.begin()); + } +} + +static void copy_n_dest_misaligned(benchmark::State& state) { + const auto size = state.range(0); + const vector source = createRandomVector(size); + vector dest(size, false); + + for (auto _ : state) { + copy_n(source.cbegin(), size - 1, dest.begin() + 1); + } +} + +// Special benchmark for matching char alignment +static void copy_n_matching_alignment(benchmark::State& state) { + const auto size = state.range(0); + const vector source = createRandomVector(size); + vector dest(size, false); + + for (auto _ : state) { + copy_n(source.cbegin() + 5, size - 5, dest.begin() + 5); + } +} + +// Special benchmarks for single block corner case +static void copy_n_both_single_blocks(benchmark::State& state) { + const vector source = createRandomVector(50); + vector dest(50, false); + + const size_t length = 20; + for (auto _ : state) { + copy_n(source.cbegin() + 5, length, dest.begin() + 5); + } +} + +static void copy_n_source_single_block(benchmark::State& state) { + const vector source = createRandomVector(50); + vector dest(50, false); + + const size_t length = 20; + for (auto _ : state) { + copy_n(source.cbegin() + 5, length, dest.begin() + 25); + } +} + +static void copy_n_dest_single_block(benchmark::State& state) { + const vector source = createRandomVector(50); + vector dest(50, false); + + const size_t length = 20; + for (auto _ : state) { + copy_n(source.cbegin() + 25, length, dest.begin() + 5); + } +} + +BENCHMARK(copy_n_block_aligned)->RangeMultiplier(64)->Range(64, 64 << 10); +BENCHMARK(copy_n_source_misaligned)->RangeMultiplier(64)->Range(64, 64 << 10); +BENCHMARK(copy_n_dest_misaligned)->RangeMultiplier(64)->Range(64, 64 << 10); +BENCHMARK(copy_n_matching_alignment)->RangeMultiplier(64)->Range(64, 64 << 10); + +BENCHMARK(copy_n_both_single_blocks); +BENCHMARK(copy_n_source_single_block); +BENCHMARK(copy_n_dest_single_block); + +BENCHMARK_MAIN(); diff --git a/benchmarks/src/std/containers/sequences/vector.bool/move/test.cpp b/benchmarks/src/std/containers/sequences/vector.bool/move/test.cpp new file mode 100644 index 00000000000..db797917885 --- /dev/null +++ b/benchmarks/src/std/containers/sequences/vector.bool/move/test.cpp @@ -0,0 +1,100 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +// +#include +#include +#include + +using namespace std; + +static vector createRandomVector(const size_t size) { + static mt19937 gen{random_device{}()}; + vector result(size); + generate_n(result.begin(), size, [] { return bernoulli_distribution{0.5}(gen); }); + return result; +} + +static void move_block_aligned(benchmark::State& state) { + const auto size = state.range(0); + const vector source = createRandomVector(size); + vector dest(size, false); + + for (auto _ : state) { + move(source.cbegin(), source.cend(), dest.begin()); + } +} + +static void move_source_misaligned(benchmark::State& state) { + const auto size = state.range(0); + const vector source = createRandomVector(size); + vector dest(size, false); + + for (auto _ : state) { + move(source.cbegin() + 1, source.cend(), dest.begin()); + } +} + +static void move_dest_misaligned(benchmark::State& state) { + const auto size = state.range(0); + const vector source = createRandomVector(size); + vector dest(size, false); + + for (auto _ : state) { + move(source.cbegin(), source.cend() - 1, dest.begin() + 1); + } +} + +// Special benchmark for matching char alignment +static void move_matching_alignment(benchmark::State& state) { + const auto size = state.range(0); + const vector source = createRandomVector(size); + vector dest(size, false); + + for (auto _ : state) { + move(source.cbegin() + 5, source.cend(), dest.begin() + 5); + } +} + +// Special benchmarks for single block corner case +static void move_both_single_blocks(benchmark::State& state) { + const vector source = createRandomVector(50); + vector dest(50, false); + + const size_t length = 20; + for (auto _ : state) { + move(source.cbegin() + 5, source.cbegin() + 5 + length, dest.begin() + 5); + } +} + +static void move_source_single_block(benchmark::State& state) { + const vector source = createRandomVector(50); + vector dest(50, false); + + const size_t length = 20; + for (auto _ : state) { + move(source.cbegin() + 5, source.cbegin() + 5 + length, dest.begin() + 25); + } +} + +static void move_dest_single_block(benchmark::State& state) { + const vector source = createRandomVector(50); + vector dest(50, false); + + const size_t length = 20; + for (auto _ : state) { + move(source.cbegin() + 25, source.cbegin() + 25 + length, dest.begin() + 5); + } +} + +BENCHMARK(move_block_aligned)->RangeMultiplier(64)->Range(64, 64 << 10); +BENCHMARK(move_source_misaligned)->RangeMultiplier(64)->Range(64, 64 << 10); +BENCHMARK(move_dest_misaligned)->RangeMultiplier(64)->Range(64, 64 << 10); +BENCHMARK(move_matching_alignment)->RangeMultiplier(64)->Range(64, 64 << 10); + +BENCHMARK(move_both_single_blocks); +BENCHMARK(move_source_single_block); +BENCHMARK(move_dest_single_block); + +BENCHMARK_MAIN(); diff --git a/stl/inc/__msvc_all_public_headers.hpp b/stl/inc/__msvc_all_public_headers.hpp index be95f48f735..17b5f7595ad 100644 --- a/stl/inc/__msvc_all_public_headers.hpp +++ b/stl/inc/__msvc_all_public_headers.hpp @@ -22,7 +22,7 @@ // VSO-768746: mbctype.h macroizes _MS, _MP, _M1, and _M2. Include it first for test coverage. #ifndef _MSVC_TESTING_NVCC #include -#endif // _MSVC_TESTING_NVCC +#endif // !defined(_MSVC_TESTING_NVCC) #if 1 // TRANSITION, OS-17090155 (UCRT) #define _CRT_DECLARE_NONSTDC_NAMES 0 @@ -30,7 +30,7 @@ #include #include #include -#endif // _MSVC_TESTING_NVCC +#endif // !defined(_MSVC_TESTING_NVCC) #undef _CRT_DECLARE_NONSTDC_NAMES #endif // TRANSITION, OS-17090155 (UCRT) @@ -155,7 +155,7 @@ #include #include #include -#endif // _M_CEE_PURE +#endif // !defined(_M_CEE_PURE) // Non-Core C Wrapper Headers #include @@ -177,7 +177,7 @@ #include #include -#endif // _CORE_HEADERS_ONLY +#endif // !defined(_CORE_HEADERS_ONLY) #ifndef _MSVC_TESTING_NVCC #include @@ -230,12 +230,12 @@ #ifndef _CORE_HEADERS_ONLY #include #include -#endif // _CORE_HEADERS_ONLY +#endif // !defined(_CORE_HEADERS_ONLY) #ifndef _M_CEE_PURE #include -#endif // _M_CEE_PURE -#endif // _MSVC_TESTING_NVCC +#endif // !defined(_M_CEE_PURE) +#endif // !defined(_MSVC_TESTING_NVCC) #if !(defined(__CUDACC__) && defined(__clang__)) #pragma pop_macro("new") diff --git a/stl/inc/__msvc_filebuf.hpp b/stl/inc/__msvc_filebuf.hpp index fb41dfbf734..f64c9233391 100644 --- a/stl/inc/__msvc_filebuf.hpp +++ b/stl/inc/__msvc_filebuf.hpp @@ -34,9 +34,9 @@ namespace filesystem { #ifndef _FSTREAM_SUPPORTS_EXPERIMENTAL_FILESYSTEM #ifdef _M_CEE #define _FSTREAM_SUPPORTS_EXPERIMENTAL_FILESYSTEM 0 -#else // _M_CEE +#else // ^^^ defined(_M_CEE) / !defined(_M_CEE) vvv #define _FSTREAM_SUPPORTS_EXPERIMENTAL_FILESYSTEM 1 -#endif // _M_CEE +#endif // ^^^ !defined(_M_CEE) ^^^ #endif // _FSTREAM_SUPPORTS_EXPERIMENTAL_FILESYSTEM #if _FSTREAM_SUPPORTS_EXPERIMENTAL_FILESYSTEM diff --git a/stl/inc/__msvc_int128.hpp b/stl/inc/__msvc_int128.hpp index f140866fc2c..7c7443c4075 100644 --- a/stl/inc/__msvc_int128.hpp +++ b/stl/inc/__msvc_int128.hpp @@ -160,7 +160,7 @@ struct constexpr auto _Int_max = static_cast(INT_MAX); _STL_INTERNAL_STATIC_ASSERT(__m <= _Int_max); _STL_INTERNAL_STATIC_ASSERT(__n <= _Int_max); -#endif // _ENABLE_STL_INTERNAL_CHECK +#endif // defined(_ENABLE_STL_INTERNAL_CHECK) for (auto& _Elem : __w) { _Elem = 0; diff --git a/stl/inc/__msvc_sanitizer_annotate_container.hpp b/stl/inc/__msvc_sanitizer_annotate_container.hpp index e56f417259b..3633425feb3 100644 --- a/stl/inc/__msvc_sanitizer_annotate_container.hpp +++ b/stl/inc/__msvc_sanitizer_annotate_container.hpp @@ -24,7 +24,7 @@ _STL_DISABLE_CLANG_WARNINGS #define _ACTIVATE_VECTOR_ANNOTATION #define _INSERT_VECTOR_ANNOTATION -#elif defined(__clang__) // ^^^ __SANITIZE_ADDRESS__ / __clang__ vvv +#elif defined(__clang__) // ^^^ defined(__SANITIZE_ADDRESS__) / defined(__clang__) vvv #if __has_feature(address_sanitizer) #define _ACTIVATE_STRING_ANNOTATION @@ -34,41 +34,41 @@ _STL_DISABLE_CLANG_WARNINGS #pragma comment(linker, "/INFERASANLIBS") #endif // __has_feature(address_sanitizer) -#else // ^^^ __clang__ / !__clang__ && !__SANITIZE_ADDRESS__ vvv +#else // ^^^ defined(__clang__) / !defined(__clang__) && !defined(__SANITIZE_ADDRESS__) vvv #ifdef _ANNOTATE_STRING #define _INSERT_STRING_ANNOTATION -#endif // _ANNOTATE_STRING +#endif // defined(_ANNOTATE_STRING) #ifdef _ANNOTATE_VECTOR #define _INSERT_VECTOR_ANNOTATION -#endif // _ANNOTATE_VECTOR +#endif // defined(_ANNOTATE_VECTOR) -#endif // __SANITIZE_ADDRESS__ +#endif // ^^^ !defined(__clang__) && !defined(__SANITIZE_ADDRESS__) ^^^ #ifdef _DISABLE_STRING_ANNOTATION #undef _ACTIVATE_STRING_ANNOTATION #undef _INSERT_STRING_ANNOTATION -#endif // _DISABLE_STRING_ANNOTATION +#endif // defined(_DISABLE_STRING_ANNOTATION) #ifdef _DISABLE_VECTOR_ANNOTATION #undef _ACTIVATE_VECTOR_ANNOTATION #undef _INSERT_VECTOR_ANNOTATION -#endif // _DISABLE_VECTOR_ANNOTATION +#endif // defined(_DISABLE_VECTOR_ANNOTATION) #ifndef _INSERT_STRING_ANNOTATION #pragma detect_mismatch("annotate_string", "0") -#endif // !_INSERT_STRING_ANNOTATION +#endif // !defined(_INSERT_STRING_ANNOTATION) #ifndef _INSERT_VECTOR_ANNOTATION #pragma detect_mismatch("annotate_vector", "0") -#endif // !_INSERT_VECTOR_ANNOTATION +#endif // !defined(_INSERT_VECTOR_ANNOTATION) #ifdef _ACTIVATE_STRING_ANNOTATION #pragma comment(lib, "stl_asan") #pragma detect_mismatch("annotate_string", "1") -#endif // _ACTIVATE_STRING_ANNOTATION +#endif // defined(_ACTIVATE_STRING_ANNOTATION) #ifdef _ACTIVATE_VECTOR_ANNOTATION #pragma comment(lib, "stl_asan") #pragma detect_mismatch("annotate_vector", "1") -#endif // _ACTIVATE_VECTOR_ANNOTATION +#endif // defined(_ACTIVATE_VECTOR_ANNOTATION) #undef _ACTIVATE_STRING_ANNOTATION #undef _ACTIVATE_VECTOR_ANNOTATION @@ -123,7 +123,7 @@ void __cdecl __sanitizer_annotate_contiguous_container( #endif // insert asan annotations -#endif // !_M_CEE_PURE && asan not disabled +#endif // !defined(_M_CEE_PURE) && asan not disabled #pragma pop_macro("new") _STL_RESTORE_CLANG_WARNINGS diff --git a/stl/inc/any b/stl/inc/any index b3be1b10015..4986245dc3b 100644 --- a/stl/inc/any +++ b/stl/inc/any @@ -78,17 +78,17 @@ struct _Any_small_RTTI { // Hand-rolled vtable for nontrivial types that can be template static void __CLRCALL_PURE_OR_CDECL _Destroy_impl(void* const _Target) noexcept { - _Destroy_in_place(*static_cast<_Ty*>(_Target)); + _STD _Destroy_in_place(*static_cast<_Ty*>(_Target)); } template static void __CLRCALL_PURE_OR_CDECL _Copy_impl(void* const _Target, const void* const _Source) { - _Construct_in_place(*static_cast<_Ty*>(_Target), *static_cast(_Source)); + _STD _Construct_in_place(*static_cast<_Ty*>(_Target), *static_cast(_Source)); } template static void __CLRCALL_PURE_OR_CDECL _Move_impl(void* const _Target, void* const _Source) noexcept { - _Construct_in_place(*static_cast<_Ty*>(_Target), _STD move(*static_cast<_Ty*>(_Source))); + _STD _Construct_in_place(*static_cast<_Ty*>(_Target), _STD move(*static_cast<_Ty*>(_Source))); } _Destroy_fn* _Destroy; @@ -163,13 +163,12 @@ public: // Assignment [any.assign] any& operator=(const any& _That) { - *this = any{_That}; + _Assign(_That); return *this; } any& operator=(any&& _That) noexcept { - reset(); - _Move_from(_That); + _Assign(_STD move(_That)); return *this; } @@ -178,7 +177,7 @@ public: int> = 0> any& operator=(_ValueType&& _Value) { // replace contained value with an object of type decay_t<_ValueType> initialized from _Value - *this = any{_STD forward<_ValueType>(_Value)}; + _Assign(_STD forward<_ValueType>(_Value)); return *this; } @@ -290,19 +289,24 @@ private: } } + void _Assign(any _That) noexcept { // intentionally pass by value + reset(); + _Move_from(_That); + } + template _Decayed& _Emplace(_Types&&... _Args) { // emplace construct _Decayed if constexpr (_Any_is_trivial<_Decayed>) { // using the _Trivial representation auto& _Obj = reinterpret_cast<_Decayed&>(_Storage._TrivialData); - _Construct_in_place(_Obj, _STD forward<_Types>(_Args)...); + _STD _Construct_in_place(_Obj, _STD forward<_Types>(_Args)...); _Storage._TypeData = reinterpret_cast(&typeid(_Decayed)) | static_cast(_Any_representation::_Trivial); return _Obj; } else if constexpr (_Any_is_small<_Decayed>) { // using the _Small representation auto& _Obj = reinterpret_cast<_Decayed&>(_Storage._SmallStorage._Data); - _Construct_in_place(_Obj, _STD forward<_Types>(_Args)...); + _STD _Construct_in_place(_Obj, _STD forward<_Types>(_Args)...); _Storage._SmallStorage._RTTI = &_Any_small_RTTI_obj<_Decayed>; _Storage._TypeData = reinterpret_cast(&typeid(_Decayed)) | static_cast(_Any_representation::_Small); diff --git a/stl/inc/array b/stl/inc/array index 7cd41156dbe..1513b3829be 100644 --- a/stl/inc/array +++ b/stl/inc/array @@ -107,7 +107,7 @@ public: _NODISCARD _CONSTEXPR17 bool operator<(const _Array_const_iterator& _Right) const noexcept { return _Ptr < _Right._Ptr; } -#endif // !_HAS_CXX20 +#endif // ^^^ !_HAS_CXX20 ^^^ using _Prevent_inheriting_unwrap = _Array_const_iterator; @@ -213,7 +213,7 @@ private: _Compat(_Right); return _Idx < _Right._Idx; } -#endif // !_HAS_CXX20 +#endif // ^^^ !_HAS_CXX20 ^^^ _CONSTEXPR17 void _Compat(const _Array_const_iterator& _Right) const noexcept { // test for compatible iterator pair _STL_VERIFY(_Ptr == _Right._Ptr, "array iterators incompatible"); @@ -237,7 +237,7 @@ private: private: pointer _Ptr; // beginning of array size_t _Idx; // offset into array -#endif // _ITERATOR_DEBUG_LEVEL == 0 +#endif // ^^^ _ITERATOR_DEBUG_LEVEL != 0 ^^^ public: _NODISCARD _CONSTEXPR17 _Array_const_iterator operator+(const ptrdiff_t _Off) const noexcept { diff --git a/stl/inc/atomic b/stl/inc/atomic index 4ed3c3ccd21..1dbbc82fc48 100644 --- a/stl/inc/atomic +++ b/stl/inc/atomic @@ -10,7 +10,7 @@ #ifdef _M_CEE_PURE #error is not supported when compiling with /clr:pure. -#endif // _M_CEE_PURE +#endif // defined(_M_CEE_PURE) #include #include @@ -42,15 +42,15 @@ extern "C" _NODISCARD unsigned char __stdcall __std_atomic_compare_exchange_128( _Inout_bytecount_(16) long long* _ComparandResult) noexcept; extern "C" _NODISCARD char __stdcall __std_atomic_has_cmpxchg16b() noexcept; #define _STD_COMPARE_EXCHANGE_128 __std_atomic_compare_exchange_128 -#endif // _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B == 1 -#endif // _WIN64 +#endif // ^^^ _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B == 0 ^^^ +#endif // defined(_WIN64) // Controls whether atomic::is_always_lock_free triggers for sizeof(void *) or 2 * sizeof(void *) #if _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B == 1 || !defined(_M_X64) || defined(_M_ARM64EC) #define _ATOMIC_HAS_DCAS 1 #else // ^^^ We always have DCAS / We only sometimes have DCAS vvv #define _ATOMIC_HAS_DCAS 0 -#endif // _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B == 1 || !defined(_M_X64) || defined(_M_ARM64EC) +#endif // ^^^ We only sometimes have DCAS ^^^ // Controls whether ARM64 ldar/ldapr/stlr should be used #ifndef _STD_ATOMIC_USE_ARM64_LDAR_STLR @@ -62,7 +62,7 @@ extern "C" _NODISCARD char __stdcall __std_atomic_has_cmpxchg16b() noexcept; #endif // ^^^ __load_acquire/__stlr intrinsics are available ^^^ #else // ^^^ ARM64/ARM64EC / Other architectures vvv #define _STD_ATOMIC_USE_ARM64_LDAR_STLR 0 -#endif // defined(_M_ARM64) || defined(_M_ARM64EC) +#endif // ^^^ Other architectures ^^^ #endif // _STD_ATOMIC_USE_ARM64_LDAR_STLR #define ATOMIC_BOOL_LOCK_FREE 2 @@ -219,9 +219,9 @@ extern "C" inline void _Check_memory_order(const unsigned int _Order) noexcept { __stlr##_Width( \ reinterpret_cast(_Ptr), static_cast(_Desired)); \ _Memory_barrier(); -#else +#else // ^^^ _STD_ATOMIC_USE_ARM64_LDAR_STLR == 1 / _STD_ATOMIC_USE_ARM64_LDAR_STLR == 0 vvv #define _ATOMIC_STORE_SEQ_CST_ARM64 _ATOMIC_STORE_SEQ_CST_ARM -#endif +#endif // ^^^ _STD_ATOMIC_USE_ARM64_LDAR_STLR == 0 ^^^ #define _ATOMIC_STORE_SEQ_CST_X86_X64(_Width, _Ptr, _Desired) (void) _InterlockedExchange##_Width((_Ptr), (_Desired)); #define _ATOMIC_STORE_32_SEQ_CST_X86_X64(_Ptr, _Desired) \ @@ -250,7 +250,7 @@ extern "C" inline void _Check_memory_order(const unsigned int _Order) noexcept { #endif // ^^^ x64 ^^^ #else // ^^^ x86/x64 / Unsupported hardware vvv #error "Unsupported hardware" -#endif +#endif // ^^^ Unsupported hardware ^^^ #pragma warning(push) #pragma warning(disable : 6001) // "Using uninitialized memory '_Guard'" @@ -276,7 +276,7 @@ extern "C" inline void _Atomic_thread_fence(const unsigned int _Order) noexcept _Memory_barrier(); #else // ^^^ ARM32/ARM64/ARM64EC / unsupported hardware vvv #error Unsupported hardware -#endif // unsupported hardware +#endif // ^^^ unsupported hardware ^^^ } #pragma warning(pop) @@ -469,7 +469,7 @@ struct _Atomic_padded<_Ty&, false> { _Ty& _Value; }; -#endif // TRANSITION, ABI +#endif // ^^^ break ABI ^^^ template struct _Atomic_storage_types { @@ -487,7 +487,7 @@ struct _Atomic_storage_types<_Ty&> { template )> #else // ^^^ don't break ABI / break ABI vvv template ::_Storage_size> -#endif // TRANSITION, ABI +#endif // ^^^ break ABI ^^^ struct _Atomic_storage; #if _HAS_CXX20 @@ -706,7 +706,7 @@ struct _Atomic_storage { return; } } else -#endif // #if _CMPXCHG_MASK_OUT_PADDING_BITS +#endif // _CMPXCHG_MASK_OUT_PADDING_BITS { return; } @@ -743,7 +743,7 @@ public: #else // ^^^ don't break ABI / break ABI vvv _Ty _Storage; mutable _Smtx_t _Mutex{}; -#endif // TRANSITION, ABI +#endif // ^^^ break ABI ^^^ }; template @@ -787,10 +787,10 @@ struct _Atomic_storage<_Ty, 1> { // lock-free using 1-byte intrinsics char _As_bytes; #if _STD_ATOMIC_USE_ARM64_LDAR_STLR == 1 _ATOMIC_LOAD_ARM64(_As_bytes, 8, _Mem, static_cast(_Order)) -#else +#else // ^^^ _STD_ATOMIC_USE_ARM64_LDAR_STLR == 1 / _STD_ATOMIC_USE_ARM64_LDAR_STLR == 0 vvv _As_bytes = __iso_volatile_load8(_Mem); _ATOMIC_POST_LOAD_BARRIER_AS_NEEDED(static_cast(_Order)) -#endif +#endif // ^^^ _STD_ATOMIC_USE_ARM64_LDAR_STLR == 0 ^^^ return reinterpret_cast<_TVal&>(_As_bytes); } @@ -895,10 +895,10 @@ struct _Atomic_storage<_Ty, 2> { // lock-free using 2-byte intrinsics short _As_bytes; #if _STD_ATOMIC_USE_ARM64_LDAR_STLR == 1 _ATOMIC_LOAD_ARM64(_As_bytes, 16, _Mem, static_cast(_Order)) -#else +#else // ^^^ _STD_ATOMIC_USE_ARM64_LDAR_STLR == 1 / _STD_ATOMIC_USE_ARM64_LDAR_STLR == 0 vvv _As_bytes = __iso_volatile_load16(_Mem); _ATOMIC_POST_LOAD_BARRIER_AS_NEEDED(static_cast(_Order)) -#endif +#endif // ^^^ _STD_ATOMIC_USE_ARM64_LDAR_STLR == 0 ^^^ return reinterpret_cast<_TVal&>(_As_bytes); } @@ -1002,10 +1002,10 @@ struct _Atomic_storage<_Ty, 4> { // lock-free using 4-byte intrinsics int _As_bytes; #if _STD_ATOMIC_USE_ARM64_LDAR_STLR == 1 _ATOMIC_LOAD_ARM64(_As_bytes, 32, _Mem, static_cast(_Order)) -#else +#else // ^^^ _STD_ATOMIC_USE_ARM64_LDAR_STLR == 1 / _STD_ATOMIC_USE_ARM64_LDAR_STLR == 0 vvv _As_bytes = __iso_volatile_load32(_Mem); _ATOMIC_POST_LOAD_BARRIER_AS_NEEDED(static_cast(_Order)) -#endif +#endif // ^^^ _STD_ATOMIC_USE_ARM64_LDAR_STLR == 0 ^^^ return reinterpret_cast<_TVal&>(_As_bytes); } @@ -1122,7 +1122,7 @@ struct _Atomic_storage<_Ty, 8> { // lock-free using 8-byte intrinsics #endif _ATOMIC_POST_LOAD_BARRIER_AS_NEEDED(static_cast(_Order)) -#endif // _STD_ATOMIC_USE_ARM64_LDAR_STLR == 1 +#endif // ^^^ _STD_ATOMIC_USE_ARM64_LDAR_STLR != 1 ^^^ return reinterpret_cast<_TVal&>(_As_bytes); } @@ -1677,7 +1677,7 @@ _INLINE_VAR constexpr bool _Is_always_lock_free = _TypeSize <= 2 * sizeof(void*) template _INLINE_VAR constexpr bool _Is_always_lock_free = _TypeSize <= sizeof(void*); #endif // _ATOMIC_HAS_DCAS -#endif // break ABI +#endif // ^^^ break ABI ^^^ template > _INLINE_VAR constexpr bool _Deprecate_non_lock_free_volatile = true; @@ -2010,7 +2010,7 @@ struct _Atomic_pointer : _Atomic_storage<_Ty> { #else // ^^^ 32 bits / 64 bits vvv _ATOMIC_CHOOSE_INTRINSIC(static_cast(_Order), _Result, _InterlockedExchangeAdd64, _Atomic_address_as(this->_Storage), _Shift_bytes); -#endif // hardware +#endif // ^^^ 64 bits ^^^ return reinterpret_cast<_Ty>(_Result); } @@ -2106,7 +2106,7 @@ struct _Atomic_pointer<_Ty&> : _Atomic_storage<_Ty&> { #else // ^^^ 32 bits / 64 bits vvv _ATOMIC_CHOOSE_INTRINSIC(static_cast(_Order), _Result, _InterlockedExchangeAdd64, _Atomic_address_as(this->_Storage), _Shift_bytes); -#endif // hardware +#endif // ^^^ 64 bits ^^^ return reinterpret_cast<_Ty>(_Result); } @@ -2159,7 +2159,7 @@ using _Choose_atomic_base_t = #else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv template using _Choose_atomic_base_t = _Choose_atomic_base2_t<_TVal, _Ty>; -#endif // _HAS_CXX20 +#endif // ^^^ !_HAS_CXX20 ^^^ _EXPORT_STD template struct atomic : _Choose_atomic_base_t<_Ty> { // atomic value @@ -2200,7 +2200,7 @@ public: return sizeof(_Ty) <= sizeof(void*) || (sizeof(_Ty) <= 2 * sizeof(void*) && __std_atomic_has_cmpxchg16b()); #endif // _ATOMIC_HAS_DCAS } -#endif // TRANSITION, ABI +#endif // ^^^ break ABI ^^^ _NODISCARD bool is_lock_free() const noexcept { return static_cast(this)->is_lock_free(); @@ -2885,7 +2885,7 @@ _EXPORT_STD struct atomic_flag { // flag with test-and-set semantics atomic _Storage; #else // ^^^ don't break ABI / break ABI vvv atomic _Storage; -#endif // TRANSITION, ABI +#endif // ^^^ break ABI ^^^ }; #if _HAS_CXX20 diff --git a/stl/inc/bitset b/stl/inc/bitset index a3b17e6b23d..826752bd49e 100644 --- a/stl/inc/bitset +++ b/stl/inc/bitset @@ -74,7 +74,7 @@ private: (void) _Pos; #else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 / _ITERATOR_DEBUG_LEVEL != 0 vvv _STL_VERIFY(_Pos < _Bits, "bitset index outside range"); -#endif // _ITERATOR_DEBUG_LEVEL == 0 +#endif // ^^^ _ITERATOR_DEBUG_LEVEL != 0 ^^^ } constexpr bool _Subscript(size_t _Pos) const noexcept { diff --git a/stl/inc/charconv b/stl/inc/charconv index a522515ee58..01f73e6d6e6 100644 --- a/stl/inc/charconv +++ b/stl/inc/charconv @@ -2609,6 +2609,6 @@ _STD_END _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) #pragma pack(pop) -#endif // _HAS_CXX17 +#endif // ^^^ _HAS_CXX17 ^^^ #endif // _STL_COMPILER_PREPROCESSOR #endif // _CHARCONV_ diff --git a/stl/inc/condition_variable b/stl/inc/condition_variable index fdf0f775bb6..6f2908d2855 100644 --- a/stl/inc/condition_variable +++ b/stl/inc/condition_variable @@ -24,7 +24,7 @@ _STL_DISABLE_CLANG_WARNINGS #ifdef _M_CEE_PURE #error is not supported when compiling with /clr:pure. -#endif // _M_CEE_PURE +#endif // defined(_M_CEE_PURE) _STD_BEGIN template diff --git a/stl/inc/coroutine b/stl/inc/coroutine index b6c95113f45..17c04ae1039 100644 --- a/stl/inc/coroutine +++ b/stl/inc/coroutine @@ -263,7 +263,7 @@ _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) #pragma pack(pop) -#endif // is available -#endif // ^^^ no /await ^^^ +#endif // ^^^ defined(__cpp_lib_coroutine) ^^^ +#endif // ^^^ !defined(_RESUMABLE_FUNCTIONS_SUPPORTED) ^^^ #endif // _STL_COMPILER_PREPROCESSOR #endif // _COROUTINE_ diff --git a/stl/inc/deque b/stl/inc/deque index 2800f211443..964b8c4f771 100644 --- a/stl/inc/deque +++ b/stl/inc/deque @@ -137,7 +137,7 @@ public: _NODISCARD bool operator>=(const _Deque_unchecked_const_iterator& _Right) const noexcept { return !(*this < _Right); } -#endif // !_HAS_CXX20 +#endif // ^^^ !_HAS_CXX20 ^^^ const _Container_base12* _Getcont() const noexcept { // get container pointer return _Mycont; @@ -383,7 +383,7 @@ public: _NODISCARD bool operator>=(const _Deque_const_iterator& _Right) const noexcept { return !(*this < _Right); } -#endif // !_HAS_CXX20 +#endif // ^^^ !_HAS_CXX20 ^^^ void _Compat(const _Deque_const_iterator& _Right) const noexcept { // test for compatible iterator pair #if _ITERATOR_DEBUG_LEVEL == 0 @@ -414,7 +414,7 @@ public: _Mycont->_Myoff <= this->_Myoff + _Off && this->_Myoff + _Off <= _Mycont->_Myoff + _Mycont->_Mysize, "cannot seek deque iterator out of range"); } -#endif // _ITERATOR_DEBUG_LEVEL == 0 +#endif // ^^^ _ITERATOR_DEBUG_LEVEL != 0 ^^^ } #if _ITERATOR_DEBUG_LEVEL != 0 @@ -629,109 +629,138 @@ public: } deque(_CRT_GUARDOVERFLOW size_type _Count, const _Ty& _Val) : _Mypair(_Zero_then_variadic_args_t{}) { - _Alproxy_ty _Alproxy(_Getal()); - _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data()); _Construct_n(_Count, _Val); - _Proxy._Release(); } deque(_CRT_GUARDOVERFLOW size_type _Count, const _Ty& _Val, const _Alloc& _Al) : _Mypair(_One_then_variadic_args_t{}, _Al) { - _Alproxy_ty _Alproxy(_Getal()); - _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data()); _Construct_n(_Count, _Val); - _Proxy._Release(); - } - - deque(const deque& _Right) - : _Mypair(_One_then_variadic_args_t{}, _Alty_traits::select_on_container_copy_construction(_Right._Getal())) { - _Alproxy_ty _Alproxy(_Getal()); - _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data()); - _Construct(_Right._Unchecked_begin(), _Right._Unchecked_end()); - _Proxy._Release(); - } - - deque(const deque& _Right, const _Identity_t<_Alloc>& _Al) : _Mypair(_One_then_variadic_args_t{}, _Al) { - _Alproxy_ty _Alproxy(_Getal()); - _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data()); - _Construct(_Right._Unchecked_begin(), _Right._Unchecked_end()); - _Proxy._Release(); } template , int> = 0> deque(_Iter _First, _Iter _Last) : _Mypair(_Zero_then_variadic_args_t{}) { - _Alproxy_ty _Alproxy(_Getal()); - _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data()); _Construct(_First, _Last); - _Proxy._Release(); } template , int> = 0> deque(_Iter _First, _Iter _Last, const _Alloc& _Al) : _Mypair(_One_then_variadic_args_t{}, _Al) { - _Alproxy_ty _Alproxy(_Getal()); - _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data()); _Construct(_First, _Last); - _Proxy._Release(); } #if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 template <_Container_compatible_range<_Ty> _Rng> deque(from_range_t, _Rng&& _Range) : _Mypair(_Zero_then_variadic_args_t{}) { - _Alproxy_ty _Alproxy(_Getal()); - _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data()); _Construct(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range)); - _Proxy._Release(); } template <_Container_compatible_range<_Ty> _Rng> deque(from_range_t, _Rng&& _Range, const _Alloc& _Al) : _Mypair(_One_then_variadic_args_t{}, _Al) { - _Alproxy_ty _Alproxy(_Getal()); - _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data()); _Construct(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range)); - _Proxy._Release(); } #endif // _HAS_CXX23 && defined(__cpp_lib_concepts) + deque(const deque& _Right) + : _Mypair(_One_then_variadic_args_t{}, _Alty_traits::select_on_container_copy_construction(_Right._Getal())) { + _Construct(_Right._Unchecked_begin(), _Right._Unchecked_end()); + } + + deque(const deque& _Right, const _Identity_t<_Alloc>& _Al) : _Mypair(_One_then_variadic_args_t{}, _Al) { + _Construct(_Right._Unchecked_begin(), _Right._Unchecked_end()); + } + + deque(deque&& _Right) : _Mypair(_One_then_variadic_args_t{}, _STD move(_Right._Getal())) { + _Get_data()._Alloc_proxy(static_cast<_Alproxy_ty>(_Getal())); + _Take_contents(_Right); + } + + deque(deque&& _Right, const _Identity_t<_Alloc>& _Al) : _Mypair(_One_then_variadic_args_t{}, _Al) { + if constexpr (!_Alty_traits::is_always_equal::value) { + if (_Getal() != _Right._Getal()) { + _Construct(_STD make_move_iterator(_Right._Unchecked_begin()), + _STD make_move_iterator(_Right._Unchecked_end())); + return; + } + } + + _Get_data()._Alloc_proxy(static_cast<_Alproxy_ty>(_Getal())); + _Take_contents(_Right); + } + + deque(initializer_list<_Ty> _Ilist, const _Alloc& _Al = allocator_type()) + : _Mypair(_One_then_variadic_args_t{}, _Al) { + _Construct(_Ilist.begin(), _Ilist.end()); + } + private: template void _Construct(_Iter _First, const _Sent _Last) { // initialize from input range [_First, _Last) + _Alproxy_ty _Alproxy(_Getal()); + _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data()); + _Tidy_guard _Guard{this}; for (; _First != _Last; ++_First) { _Emplace_back_internal(*_First); } _Guard._Target = nullptr; + _Proxy._Release(); } void _Construct_n(size_type _Count, const _Ty& _Val) { // construct from _Count * _Val + _Alproxy_ty _Alproxy(_Getal()); + _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data()); + _Tidy_guard _Guard{this}; for (; _Count > 0; --_Count) { _Emplace_back_internal(_Val); } _Guard._Target = nullptr; + _Proxy._Release(); + } + + void _Take_contents(deque& _Right) noexcept { + // move from _Right, stealing its contents + // pre: _Getal() == _Right._Getal() + auto& _My_data = _Get_data(); + auto& _Right_data = _Right._Get_data(); + _My_data._Swap_proxy_and_iterators(_Right_data); + _My_data._Map = _Right_data._Map; + _My_data._Mapsize = _Right_data._Mapsize; + _My_data._Myoff = _Right_data._Myoff; + _My_data._Mysize = _Right_data._Mysize; + + _Right_data._Map = nullptr; + _Right_data._Mapsize = 0; + _Right_data._Myoff = 0; + _Right_data._Mysize = 0; } public: - deque(deque&& _Right) : _Mypair(_One_then_variadic_args_t{}, _STD move(_Right._Getal())) { - _Get_data()._Alloc_proxy(static_cast<_Alproxy_ty>(_Getal())); - _Take_contents(_Right); + ~deque() noexcept { + _Tidy(); + _Alproxy_ty _Proxy_allocator(_Getal()); + _Delete_plain_internal(_Proxy_allocator, _STD exchange(_Get_data()._Myproxy, nullptr)); } - deque(deque&& _Right, const _Identity_t<_Alloc>& _Al) : _Mypair(_One_then_variadic_args_t{}, _Al) { - _Alproxy_ty _Alproxy(_Getal()); - if constexpr (!_Alty_traits::is_always_equal::value) { - if (_Getal() != _Right._Getal()) { - _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data()); - _Construct(_STD make_move_iterator(_Right._Unchecked_begin()), - _STD make_move_iterator(_Right._Unchecked_end())); - _Proxy._Release(); - return; + deque& operator=(const deque& _Right) { + if (this == _STD addressof(_Right)) { + return *this; + } + + auto& _Al = _Getal(); + auto& _Right_al = _Right._Getal(); + if constexpr (_Choose_pocca_v<_Alty>) { + if (_Al != _Right_al) { + _Tidy(); + _Get_data()._Reload_proxy(static_cast<_Alproxy_ty>(_Al), static_cast<_Alproxy_ty>(_Right_al)); } } - _Get_data()._Alloc_proxy(_Alproxy); - _Take_contents(_Right); + _Pocca(_Al, _Right_al); + assign(_Right._Unchecked_begin(), _Right._Unchecked_end()); + + return *this; } deque& operator=(deque&& _Right) noexcept(_Alty_traits::is_always_equal::value) { @@ -768,180 +797,87 @@ public: return *this; } -private: - void _Take_contents(deque& _Right) noexcept { - // move from _Right, stealing its contents - // pre: _Getal() == _Right._Getal() - auto& _My_data = _Get_data(); - auto& _Right_data = _Right._Get_data(); - _My_data._Swap_proxy_and_iterators(_Right_data); - _My_data._Map = _Right_data._Map; - _My_data._Mapsize = _Right_data._Mapsize; - _My_data._Myoff = _Right_data._Myoff; - _My_data._Mysize = _Right_data._Mysize; - - _Right_data._Map = nullptr; - _Right_data._Mapsize = 0; - _Right_data._Myoff = 0; - _Right_data._Mysize = 0; + deque& operator=(initializer_list<_Ty> _Ilist) { + assign(_Ilist.begin(), _Ilist.end()); + return *this; } -public: - void push_front(_Ty&& _Val) { - emplace_front(_STD move(_Val)); + template , int> = 0> + void assign(_Iter _First, _Iter _Last) { + _Adl_verify_range(_First, _Last); + _Assign_range(_Get_unwrapped(_First), _Get_unwrapped(_Last)); } #if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 template <_Container_compatible_range<_Ty> _Rng> - void prepend_range(_Rng&& _Range) { - _Orphan_all(); + void assign_range(_Rng&& _Range) { + _Assign_range(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range)); + } +#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) + void assign(_CRT_GUARDOVERFLOW size_type _Count, const _Ty& _Val) { // assign _Count * _Val + _Orphan_all(); + auto _Myfirst = _Unchecked_begin(); const auto _Oldsize = _Mysize(); - _Restore_old_size_guard<_Pop_direction::_Front> _Guard{this, _Oldsize}; - if constexpr (_RANGES bidirectional_range<_Rng>) { - const auto _UFirst = _RANGES _Ubegin(_Range); - auto _ULast = _RANGES _Get_final_iterator_unwrapped(_Range); - while (_UFirst != _ULast) { - _Emplace_front_internal(*--_ULast); // prepend in order - } - } else { - auto _UFirst = _RANGES _Ubegin(_Range); - const auto _ULast = _RANGES _Uend(_Range); - for (; _UFirst != _ULast; ++_UFirst) { - _Emplace_front_internal(*_UFirst); // prepend flipped - } + auto _Assign_count = (_STD min)(_Count, _Oldsize); + for (; _Assign_count > 0; --_Assign_count) { + *_Myfirst = _Val; + ++_Myfirst; + } - const auto _Num = static_cast(_Mysize() - _Oldsize); - _STD reverse(begin(), begin() + _Num); + const auto _Shrink_by = _Oldsize - _Assign_count; + auto _Extend_by = _Count - _Assign_count; + _Erase_last_n(_Shrink_by); + for (; _Extend_by > 0; --_Extend_by) { + _Emplace_back_internal(_Val); } - _Guard._Container = nullptr; } -#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) - void push_back(_Ty&& _Val) { - _Orphan_all(); - _Emplace_back_internal(_STD move(_Val)); + void assign(initializer_list<_Ty> _Ilist) { + assign(_Ilist.begin(), _Ilist.end()); } -#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 - template <_Container_compatible_range<_Ty> _Rng> - void append_range(_Rng&& _Range) { + _NODISCARD allocator_type get_allocator() const noexcept { + return static_cast(_Getal()); + } + +private: + template + void _Assign_range(_Iter _First, const _Sent _Last) { _Orphan_all(); + auto _Myfirst = _Unchecked_begin(); + const auto _Mylast = _Unchecked_end(); + // Reuse existing elements + for (; _Myfirst != _Mylast; ++_Myfirst, (void) ++_First) { + if (_First == _Last) { + _Erase_last_n(static_cast(_Mylast - _Myfirst)); + return; + } - const auto _Oldsize = _Mysize(); - auto _UFirst = _RANGES _Ubegin(_Range); - const auto _ULast = _RANGES _Uend(_Range); + *_Myfirst = *_First; + } - _Restore_old_size_guard<_Pop_direction::_Back> _Guard{this, _Oldsize}; - for (; _UFirst != _ULast; ++_UFirst) { - _Emplace_back_internal(*_UFirst); + // Allocate new elements for remaining tail of values + for (; _First != _Last; ++_First) { + _Emplace_back_internal(*_First); } - _Guard._Container = nullptr; } -#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) - iterator insert(const_iterator _Where, _Ty&& _Val) { - return emplace(_Where, _STD move(_Val)); +public: + _NODISCARD iterator begin() noexcept { + return iterator(_Myoff(), _STD addressof(_Get_data())); } - template - decltype(auto) emplace_front(_Valty&&... _Val) { - _Orphan_all(); - _Emplace_front_internal(_STD forward<_Valty>(_Val)...); -#if _HAS_CXX17 - return front(); -#endif // _HAS_CXX17 + _NODISCARD const_iterator begin() const noexcept { + return const_iterator(_Myoff(), _STD addressof(_Get_data())); } - template - decltype(auto) emplace_back(_Valty&&... _Val) { - _Orphan_all(); - _Emplace_back_internal(_STD forward<_Valty>(_Val)...); - -#if _HAS_CXX17 - return back(); -#endif // _HAS_CXX17 + _NODISCARD iterator end() noexcept { + return iterator(_Myoff() + _Mysize(), _STD addressof(_Get_data())); } - template - iterator emplace(const_iterator _Where, _Valty&&... _Val) { - const auto _Off = static_cast(_Where - begin()); - -#if _ITERATOR_DEBUG_LEVEL == 2 - _STL_VERIFY(_Off <= _Mysize(), "deque emplace iterator outside range"); -#endif // _ITERATOR_DEBUG_LEVEL == 2 - - if (_Off <= _Mysize() / 2) { // closer to front, push to front then rotate - emplace_front(_STD forward<_Valty>(_Val)...); - _STD rotate(begin(), _Next_iter(begin()), begin() + static_cast(1 + _Off)); - } else { // closer to back, push to back then rotate - emplace_back(_STD forward<_Valty>(_Val)...); - _STD rotate(begin() + static_cast(_Off), _Prev_iter(end()), end()); - } - return begin() + static_cast(_Off); - } - - deque(initializer_list<_Ty> _Ilist, const _Alloc& _Al = allocator_type()) - : _Mypair(_One_then_variadic_args_t{}, _Al) { - _Alproxy_ty _Alproxy(_Getal()); - _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data()); - _Construct(_Ilist.begin(), _Ilist.end()); - _Proxy._Release(); - } - - deque& operator=(initializer_list<_Ty> _Ilist) { - assign(_Ilist.begin(), _Ilist.end()); - return *this; - } - - void assign(initializer_list<_Ty> _Ilist) { - assign(_Ilist.begin(), _Ilist.end()); - } - - iterator insert(const_iterator _Where, initializer_list<_Ty> _Ilist) { - return insert(_Where, _Ilist.begin(), _Ilist.end()); - } - - ~deque() noexcept { - _Tidy(); - _Alproxy_ty _Proxy_allocator(_Getal()); - _Delete_plain_internal(_Proxy_allocator, _STD exchange(_Get_data()._Myproxy, nullptr)); - } - - deque& operator=(const deque& _Right) { - if (this == _STD addressof(_Right)) { - return *this; - } - - auto& _Al = _Getal(); - auto& _Right_al = _Right._Getal(); - if constexpr (_Choose_pocca_v<_Alty>) { - if (_Al != _Right_al) { - _Tidy(); - _Get_data()._Reload_proxy(static_cast<_Alproxy_ty>(_Al), static_cast<_Alproxy_ty>(_Right_al)); - } - } - - _Pocca(_Al, _Right_al); - assign(_Right._Unchecked_begin(), _Right._Unchecked_end()); - - return *this; - } - - _NODISCARD iterator begin() noexcept { - return iterator(_Myoff(), _STD addressof(_Get_data())); - } - - _NODISCARD const_iterator begin() const noexcept { - return const_iterator(_Myoff(), _STD addressof(_Get_data())); - } - - _NODISCARD iterator end() noexcept { - return iterator(_Myoff() + _Mysize(), _STD addressof(_Get_data())); - } - - _NODISCARD const_iterator end() const noexcept { - return const_iterator(_Myoff() + _Mysize(), _STD addressof(_Get_data())); + _NODISCARD const_iterator end() const noexcept { + return const_iterator(_Myoff() + _Mysize(), _STD addressof(_Get_data())); } _Unchecked_iterator _Unchecked_begin() noexcept { @@ -996,19 +932,17 @@ public: return rend(); } - void shrink_to_fit() { - size_type _Oldcapacity = _Block_size * _Mapsize(); - size_type _Newcapacity = _Oldcapacity / 2; + _NODISCARD_EMPTY_MEMBER bool empty() const noexcept { + return _Mysize() == 0; + } - if (_Newcapacity < _Block_size * _Minimum_map_size) { - _Newcapacity = _Block_size * _Minimum_map_size; - } + _NODISCARD size_type size() const noexcept { + return _Mysize(); + } - if ((empty() && _Mapsize() > 0) - || (!empty() && size() <= _Newcapacity && _Newcapacity < _Oldcapacity)) { // worth shrinking, do it - deque _Tmp(_STD make_move_iterator(begin()), _STD make_move_iterator(end())); - swap(_Tmp); - } + _NODISCARD size_type max_size() const noexcept { + return (_STD min)( + static_cast((numeric_limits::max)()), _Alty_traits::max_size(_Getal())); } void resize(_CRT_GUARDOVERFLOW size_type _Newsize) { @@ -1033,21 +967,35 @@ public: } } - _NODISCARD size_type size() const noexcept { - return _Mysize(); - } + void shrink_to_fit() { + size_type _Oldcapacity = _Block_size * _Mapsize(); + size_type _Newcapacity = _Oldcapacity / 2; - _NODISCARD size_type max_size() const noexcept { - return (_STD min)( - static_cast((numeric_limits::max)()), _Alty_traits::max_size(_Getal())); + if (_Newcapacity < _Block_size * _Minimum_map_size) { + _Newcapacity = _Block_size * _Minimum_map_size; + } + + if ((empty() && _Mapsize() > 0) + || (!empty() && size() <= _Newcapacity && _Newcapacity < _Oldcapacity)) { // worth shrinking, do it + deque _Tmp(_STD make_move_iterator(begin()), _STD make_move_iterator(end())); + swap(_Tmp); + } } - _NODISCARD_EMPTY_MEMBER bool empty() const noexcept { - return _Mysize() == 0; + _NODISCARD const_reference operator[](size_type _Pos) const noexcept /* strengthened */ { +#if _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_Pos < _Mysize(), "deque subscript out of range"); +#endif // _CONTAINER_DEBUG_LEVEL > 0 + + return *(_Unchecked_begin() + static_cast(_Pos)); } - _NODISCARD allocator_type get_allocator() const noexcept { - return static_cast(_Getal()); + _NODISCARD reference operator[](size_type _Pos) noexcept /* strengthened */ { +#if _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_Pos < _Mysize(), "deque subscript out of range"); +#endif // _CONTAINER_DEBUG_LEVEL > 0 + + return *(_Unchecked_begin() + static_cast(_Pos)); } _NODISCARD const_reference at(size_type _Pos) const { @@ -1066,22 +1014,6 @@ public: return *(begin() + static_cast(_Pos)); } - _NODISCARD const_reference operator[](size_type _Pos) const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Pos < _Mysize(), "deque subscript out of range"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 - - return *(_Unchecked_begin() + static_cast(_Pos)); - } - - _NODISCARD reference operator[](size_type _Pos) noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Pos < _Mysize(), "deque subscript out of range"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 - - return *(_Unchecked_begin() + static_cast(_Pos)); - } - _NODISCARD reference front() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(!empty(), "front() called on empty deque"); @@ -1114,36 +1046,6 @@ public: return *_Prev_iter(_Unchecked_end()); } - void push_front(const _Ty& _Val) { - emplace_front(_Val); - } - - void pop_front() noexcept /* strengthened */ { -#if _ITERATOR_DEBUG_LEVEL == 2 - if (empty()) { - _STL_REPORT_ERROR("deque empty before pop"); - } else { // something to erase, do it - _Orphan_off(_Myoff()); - size_type _Block = _Getblock(_Myoff()); - _Alty_traits::destroy(_Getal(), _Unfancy(_Map()[_Block] + _Myoff() % _Block_size)); - if (--_Mysize() == 0) { - _Myoff() = 0; - } else { - ++_Myoff(); - } - } - -#else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 / _ITERATOR_DEBUG_LEVEL < 2 vvv - size_type _Block = _Getblock(_Myoff()); - _Alty_traits::destroy(_Getal(), _Unfancy(_Map()[_Block] + _Myoff() % _Block_size)); - if (--_Mysize() == 0) { - _Myoff() = 0; - } else { - ++_Myoff(); - } -#endif // ^^^ _ITERATOR_DEBUG_LEVEL < 2 ^^^ - } - private: template void _Emplace_back_internal(_Tys&&... _Vals) { @@ -1183,105 +1085,133 @@ private: } public: - void push_back(const _Ty& _Val) { + template + decltype(auto) emplace_front(_Valty&&... _Val) { _Orphan_all(); - _Emplace_back_internal(_Val); + _Emplace_front_internal(_STD forward<_Valty>(_Val)...); +#if _HAS_CXX17 + return front(); +#endif // _HAS_CXX17 } - void pop_back() noexcept /* strengthened */ { + template + decltype(auto) emplace_back(_Valty&&... _Val) { + _Orphan_all(); + _Emplace_back_internal(_STD forward<_Valty>(_Val)...); + +#if _HAS_CXX17 + return back(); +#endif // _HAS_CXX17 + } + + template + iterator emplace(const_iterator _Where, _Valty&&... _Val) { + const auto _Off = static_cast(_Where - begin()); + #if _ITERATOR_DEBUG_LEVEL == 2 - if (empty()) { - _STL_REPORT_ERROR("deque empty before pop"); - } else { // something to erase, do it - size_type _Newoff = _Myoff() + _Mysize() - 1; - _Orphan_off(_Newoff); - size_type _Block = _Getblock(_Newoff); - _Alty_traits::destroy(_Getal(), _Unfancy(_Map()[_Block] + _Newoff % _Block_size)); - if (--_Mysize() == 0) { - _Myoff() = 0; + _STL_VERIFY(_Off <= _Mysize(), "deque emplace iterator outside range"); +#endif // _ITERATOR_DEBUG_LEVEL == 2 + + _Orphan_all(); + if (_Off == 0) { // at the beginning + _Emplace_front_internal(_STD forward<_Valty>(_Val)...); + } else if (_Off == _Mysize()) { // at the end + _Emplace_back_internal(_STD forward<_Valty>(_Val)...); + } else { + _Alloc_temporary2<_Alty> _Obj(_Getal(), _STD forward<_Valty>(_Val)...); // handle aliasing + + if (_Off <= _Mysize() / 2) { // closer to front + _Emplace_front_internal(_STD move(*_Unchecked_begin())); + + auto _Moving_dst = _STD _Next_iter(_Unchecked_begin()); + auto _Moving_src_begin = _STD _Next_iter(_Moving_dst); + auto _Moving_src_end = _Moving_dst + static_cast(_Off); + + auto _Moving_dst_end = _STD _Move_unchecked(_Moving_src_begin, _Moving_src_end, _Moving_dst); + *_Moving_dst_end = _STD move(_Obj._Get_value()); + } else { // closer to back + _Emplace_back_internal(_STD move(*_STD _Prev_iter(_Unchecked_end()))); + + auto _Moving_dst_end = _STD _Prev_iter(_Unchecked_end()); + auto _Moving_src_end = _STD _Prev_iter(_Moving_dst_end); + auto _Moving_src_begin = _Unchecked_begin() + static_cast(_Off); + + _STD _Move_backward_unchecked(_Moving_src_begin, _Moving_src_end, _Moving_dst_end); + *_Moving_src_begin = _STD move(_Obj._Get_value()); } } -#else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 / _ITERATOR_DEBUG_LEVEL < 2 vvv - size_type _Newoff = _Myoff() + _Mysize() - 1; - size_type _Block = _Getblock(_Newoff); - _Alty_traits::destroy(_Getal(), _Unfancy(_Map()[_Block] + _Newoff % _Block_size)); - if (--_Mysize() == 0) { - _Myoff() = 0; - } -#endif // ^^^ _ITERATOR_DEBUG_LEVEL < 2 ^^^ + return begin() + static_cast(_Off); } -private: - template - void _Assign_range(_Iter _First, const _Sent _Last) { + void push_front(const _Ty& _Val) { _Orphan_all(); - auto _Myfirst = _Unchecked_begin(); - const auto _Mylast = _Unchecked_end(); - // Reuse existing elements - for (; _Myfirst != _Mylast; ++_Myfirst, (void) ++_First) { - if (_First == _Last) { - _Erase_last_n(static_cast(_Mylast - _Myfirst)); - return; - } + _Emplace_front_internal(_Val); + } - *_Myfirst = *_First; - } + void push_front(_Ty&& _Val) { + _Orphan_all(); + _Emplace_front_internal(_STD move(_Val)); + } - // Allocate new elements for remaining tail of values - for (; _First != _Last; ++_First) { - _Emplace_back_internal(*_First); - } + void push_back(const _Ty& _Val) { + _Orphan_all(); + _Emplace_back_internal(_Val); } -public: - template , int> = 0> - void assign(_Iter _First, _Iter _Last) { - _Adl_verify_range(_First, _Last); - _Assign_range(_Get_unwrapped(_First), _Get_unwrapped(_Last)); + void push_back(_Ty&& _Val) { + _Orphan_all(); + _Emplace_back_internal(_STD move(_Val)); } #if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 template <_Container_compatible_range<_Ty> _Rng> - void assign_range(_Rng&& _Range) { - _Assign_range(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range)); + void prepend_range(_Rng&& _Range) { + _Orphan_all(); + + const auto _Oldsize = _Mysize(); + _Restore_old_size_guard<_Pop_direction::_Front> _Guard{this, _Oldsize}; + if constexpr (_RANGES bidirectional_range<_Rng>) { + const auto _UFirst = _RANGES _Ubegin(_Range); + auto _ULast = _RANGES _Get_final_iterator_unwrapped(_Range); + while (_UFirst != _ULast) { + _Emplace_front_internal(*--_ULast); // prepend in order + } + } else { + auto _UFirst = _RANGES _Ubegin(_Range); + const auto _ULast = _RANGES _Uend(_Range); + for (; _UFirst != _ULast; ++_UFirst) { + _Emplace_front_internal(*_UFirst); // prepend flipped + } + + const auto _Num = static_cast(_Mysize() - _Oldsize); + _STD reverse(begin(), begin() + _Num); + } + _Guard._Container = nullptr; } -#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) - void assign(_CRT_GUARDOVERFLOW size_type _Count, const _Ty& _Val) { // assign _Count * _Val + template <_Container_compatible_range<_Ty> _Rng> + void append_range(_Rng&& _Range) { _Orphan_all(); - auto _Myfirst = _Unchecked_begin(); + const auto _Oldsize = _Mysize(); - auto _Assign_count = (_STD min)(_Count, _Oldsize); - for (; _Assign_count > 0; --_Assign_count) { - *_Myfirst = _Val; - ++_Myfirst; - } + auto _UFirst = _RANGES _Ubegin(_Range); + const auto _ULast = _RANGES _Uend(_Range); - const auto _Shrink_by = _Oldsize - _Assign_count; - auto _Extend_by = _Count - _Assign_count; - _Erase_last_n(_Shrink_by); - for (; _Extend_by > 0; --_Extend_by) { - _Emplace_back_internal(_Val); + _Restore_old_size_guard<_Pop_direction::_Back> _Guard{this, _Oldsize}; + for (; _UFirst != _ULast; ++_UFirst) { + _Emplace_back_internal(*_UFirst); } + _Guard._Container = nullptr; } +#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) iterator insert(const_iterator _Where, const _Ty& _Val) { - size_type _Off = static_cast(_Where - begin()); - -#if _ITERATOR_DEBUG_LEVEL == 2 - _STL_VERIFY(_Off <= _Mysize(), "deque insert iterator outside range"); -#endif // _ITERATOR_DEBUG_LEVEL == 2 - - if (_Off <= _Mysize() / 2) { // closer to front, push to front then copy - push_front(_Val); - _STD rotate(begin(), _Next_iter(begin()), begin() + static_cast(1 + _Off)); - } else { // closer to back, push to back then copy - push_back(_Val); - _STD rotate(begin() + static_cast(_Off), _Prev_iter(end()), end()); - } + return emplace(_Where, _Val); + } - return begin() + static_cast(_Off); + iterator insert(const_iterator _Where, _Ty&& _Val) { + return emplace(_Where, _STD move(_Val)); } iterator insert(const_iterator _Where, _CRT_GUARDOVERFLOW size_type _Count, const _Ty& _Val) { @@ -1291,6 +1221,33 @@ public: return begin() + static_cast(_Off); } + template , int> = 0> + iterator insert(const_iterator _Where, _Iter _First, _Iter _Last) { + // insert [_First, _Last) at _Where + _Adl_verify_range(_First, _Last); + const size_type _Off = static_cast(_Where - begin()); + return _Insert_range(_Is_cpp17_bidi_iter_v<_Iter>)>( + _Off, _Get_unwrapped(_First), _Get_unwrapped(_Last)); + } + +#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 + template <_Container_compatible_range<_Ty> _Rng> + iterator insert_range(const_iterator _Where, _Rng&& _Range) { + const size_type _Off = static_cast(_Where - begin()); + + if constexpr (_RANGES bidirectional_range<_Rng>) { + return _Insert_range<_Is_bidi::_Yes>( + _Off, _RANGES _Ubegin(_Range), _RANGES _Get_final_iterator_unwrapped(_Range)); + } else { + return _Insert_range<_Is_bidi::_Nope>(_Off, _RANGES _Ubegin(_Range), _RANGES _Uend(_Range)); + } + } +#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) + + iterator insert(const_iterator _Where, initializer_list<_Ty> _Ilist) { + return insert(_Where, _Ilist.begin(), _Ilist.end()); + } + private: enum class _Pop_direction : bool { _Front, @@ -1372,29 +1329,121 @@ private: return begin() + static_cast(_Off); } -public: - template , int> = 0> - iterator insert(const_iterator _Where, _Iter _First, _Iter _Last) { - // insert [_First, _Last) at _Where - _Adl_verify_range(_First, _Last); - const size_type _Off = static_cast(_Where - begin()); - return _Insert_range(_Is_cpp17_bidi_iter_v<_Iter>)>( - _Off, _Get_unwrapped(_First), _Get_unwrapped(_Last)); + void _Insert_n(const_iterator _Where, size_type _Count, const _Ty& _Val) { // insert _Count * _Val at _Where + iterator _Mid; + size_type _Num; + size_type _Off = static_cast(_Where - begin()); + size_type _Oldsize = _Mysize(); + size_type _Rem = _Oldsize - _Off; + +#if _ITERATOR_DEBUG_LEVEL == 2 + _STL_VERIFY(_Off <= _Oldsize, "deque insert iterator outside range"); +#endif // _ITERATOR_DEBUG_LEVEL == 2 + + if (_Off < _Rem) { // closer to front + _Restore_old_size_guard<_Pop_direction::_Front> _Guard{this, _Oldsize}; + if (_Off < _Count) { // insert longer than prefix + for (_Num = _Count - _Off; _Num > 0; --_Num) { + push_front(_Val); // push excess values + } + for (_Num = _Off; _Num > 0; --_Num) { + push_front(begin()[static_cast(_Count - 1)]); // push prefix + } + + _Mid = begin() + static_cast(_Count); + _STD fill_n(_Mid, _Off, _Val); // fill in rest of values + } else { // insert not longer than prefix + for (_Num = _Count; _Num > 0; --_Num) { + push_front(begin()[static_cast(_Count - 1)]); // push part of prefix + } + + _Mid = begin() + static_cast(_Count); + _Alloc_temporary2<_Alty> _Tmp(_Getal(), _Val); // in case _Val is in sequence + _STD move(_Mid + static_cast(_Count), _Mid + static_cast(_Off), + _Mid); // copy rest of prefix + _STD fill(begin() + static_cast(_Off), _Mid + static_cast(_Off), + _Tmp._Get_value()); // fill in values + } + _Guard._Container = nullptr; + } else { // closer to back + _Restore_old_size_guard<_Pop_direction::_Back> _Guard{this, _Oldsize}; + if (_Rem < _Count) { // insert longer than suffix + _Orphan_all(); + for (_Num = _Count - _Rem; _Num > 0; --_Num) { + _Emplace_back_internal(_Val); // push excess values + } + for (_Num = 0; _Num < _Rem; ++_Num) { + _Emplace_back_internal(begin()[static_cast(_Off + _Num)]); // push suffix + } + + _Mid = begin() + static_cast(_Off); + _STD fill_n(_Mid, _Rem, _Val); // fill in rest of values + } else { // insert not longer than prefix + for (_Num = 0; _Num < _Count; ++_Num) { + _Emplace_back_internal( + begin()[static_cast(_Off + _Rem - _Count + _Num)]); // push part of prefix + } + + _Mid = begin() + static_cast(_Off); + _Alloc_temporary2<_Alty> _Tmp(_Getal(), _Val); // in case _Val is in sequence + _STD move_backward(_Mid, _Mid + static_cast(_Rem - _Count), + _Mid + static_cast(_Rem)); // copy rest of prefix + _STD fill_n(_Mid, _Count, _Tmp._Get_value()); // fill in values + } + _Guard._Container = nullptr; + } } -#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 - template <_Container_compatible_range<_Ty> _Rng> - iterator insert_range(const_iterator _Where, _Rng&& _Range) { - const size_type _Off = static_cast(_Where - begin()); +public: + void pop_front() noexcept /* strengthened */ { +#if _ITERATOR_DEBUG_LEVEL == 2 + if (empty()) { + _STL_REPORT_ERROR("deque empty before pop"); + } else { // something to erase, do it + _Orphan_off(_Myoff()); + size_type _Block = _Getblock(_Myoff()); + _Alty_traits::destroy(_Getal(), _Unfancy(_Map()[_Block] + _Myoff() % _Block_size)); + if (--_Mysize() == 0) { + _Myoff() = 0; + } else { + ++_Myoff(); + } + } - if constexpr (_RANGES bidirectional_range<_Rng>) { - return _Insert_range<_Is_bidi::_Yes>( - _Off, _RANGES _Ubegin(_Range), _RANGES _Get_final_iterator_unwrapped(_Range)); +#else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 / _ITERATOR_DEBUG_LEVEL < 2 vvv + size_type _Block = _Getblock(_Myoff()); + _Alty_traits::destroy(_Getal(), _Unfancy(_Map()[_Block] + _Myoff() % _Block_size)); + if (--_Mysize() == 0) { + _Myoff() = 0; } else { - return _Insert_range<_Is_bidi::_Nope>(_Off, _RANGES _Ubegin(_Range), _RANGES _Uend(_Range)); + ++_Myoff(); } +#endif // ^^^ _ITERATOR_DEBUG_LEVEL < 2 ^^^ + } + + void pop_back() noexcept /* strengthened */ { +#if _ITERATOR_DEBUG_LEVEL == 2 + if (empty()) { + _STL_REPORT_ERROR("deque empty before pop"); + } else { // something to erase, do it + size_type _Newoff = _Myoff() + _Mysize() - 1; + _Orphan_off(_Newoff); + size_type _Block = _Getblock(_Newoff); + _Alty_traits::destroy(_Getal(), _Unfancy(_Map()[_Block] + _Newoff % _Block_size)); + if (--_Mysize() == 0) { + _Myoff() = 0; + } + } + +#else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 / _ITERATOR_DEBUG_LEVEL < 2 vvv + size_type _Newoff = _Myoff() + _Mysize() - 1; + size_type _Block = _Getblock(_Newoff); + _Alty_traits::destroy(_Getal(), _Unfancy(_Map()[_Block] + _Newoff % _Block_size)); + if (--_Mysize() == 0) { + _Myoff() = 0; + } +#endif // ^^^ _ITERATOR_DEBUG_LEVEL < 2 ^^^ } -#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) iterator erase(const_iterator _Where) noexcept(is_nothrow_move_assignable_v) /* strengthened */ { return erase(_Where, _Next_iter(_Where)); @@ -1470,71 +1519,6 @@ public: } private: - void _Insert_n(const_iterator _Where, size_type _Count, const _Ty& _Val) { // insert _Count * _Val at _Where - iterator _Mid; - size_type _Num; - size_type _Off = static_cast(_Where - begin()); - size_type _Oldsize = _Mysize(); - size_type _Rem = _Oldsize - _Off; - -#if _ITERATOR_DEBUG_LEVEL == 2 - _STL_VERIFY(_Off <= _Oldsize, "deque insert iterator outside range"); -#endif // _ITERATOR_DEBUG_LEVEL == 2 - - if (_Off < _Rem) { // closer to front - _Restore_old_size_guard<_Pop_direction::_Front> _Guard{this, _Oldsize}; - if (_Off < _Count) { // insert longer than prefix - for (_Num = _Count - _Off; _Num > 0; --_Num) { - push_front(_Val); // push excess values - } - for (_Num = _Off; _Num > 0; --_Num) { - push_front(begin()[static_cast(_Count - 1)]); // push prefix - } - - _Mid = begin() + static_cast(_Count); - _STD fill_n(_Mid, _Off, _Val); // fill in rest of values - } else { // insert not longer than prefix - for (_Num = _Count; _Num > 0; --_Num) { - push_front(begin()[static_cast(_Count - 1)]); // push part of prefix - } - - _Mid = begin() + static_cast(_Count); - _Alloc_temporary2<_Alty> _Tmp(_Getal(), _Val); // in case _Val is in sequence - _STD move(_Mid + static_cast(_Count), _Mid + static_cast(_Off), - _Mid); // copy rest of prefix - _STD fill(begin() + static_cast(_Off), _Mid + static_cast(_Off), - _Tmp._Get_value()); // fill in values - } - _Guard._Container = nullptr; - } else { // closer to back - _Restore_old_size_guard<_Pop_direction::_Back> _Guard{this, _Oldsize}; - if (_Rem < _Count) { // insert longer than suffix - _Orphan_all(); - for (_Num = _Count - _Rem; _Num > 0; --_Num) { - _Emplace_back_internal(_Val); // push excess values - } - for (_Num = 0; _Num < _Rem; ++_Num) { - _Emplace_back_internal(begin()[static_cast(_Off + _Num)]); // push suffix - } - - _Mid = begin() + static_cast(_Off); - _STD fill_n(_Mid, _Rem, _Val); // fill in rest of values - } else { // insert not longer than prefix - for (_Num = 0; _Num < _Count; ++_Num) { - _Emplace_back_internal( - begin()[static_cast(_Off + _Rem - _Count + _Num)]); // push part of prefix - } - - _Mid = begin() + static_cast(_Off); - _Alloc_temporary2<_Alty> _Tmp(_Getal(), _Val); // in case _Val is in sequence - _STD move_backward(_Mid, _Mid + static_cast(_Rem - _Count), - _Mid + static_cast(_Rem)); // copy rest of prefix - _STD fill_n(_Mid, _Count, _Tmp._Get_value()); // fill in values - } - _Guard._Container = nullptr; - } - } - [[noreturn]] static void _Xlen() { _Xlength_error("deque too long"); } @@ -1557,9 +1541,15 @@ private: _Newsize *= 2; } + size_type _Allocsize = _Newsize; + size_type _Myboff = _Myoff() / _Block_size; - _Mapptr _Newmap = _Allocate_at_least_helper(_Almap, _Newsize); + _Mapptr _Newmap = _Allocate_at_least_helper(_Almap, _Allocsize); _Mapptr _Myptr = _Newmap + _Myboff; + _STL_ASSERT(_Allocsize >= _Newsize, "_Allocsize >= _Newsize"); + while (_Newsize <= _Allocsize / 2) { + _Newsize *= 2; + } _Count = _Newsize - _Mapsize(); diff --git a/stl/inc/exception b/stl/inc/exception index afda3fb4b21..e9e9ef10a39 100644 --- a/stl/inc/exception +++ b/stl/inc/exception @@ -203,7 +203,7 @@ _EXPORT_STD using _STDEXT bad_exception; _STD_END -#endif // _HAS_EXCEPTIONS +#endif // ^^^ !_HAS_EXCEPTIONS ^^^ extern "C++" _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL __ExceptionPtrCreate(_Out_ void*) noexcept; extern "C++" _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL __ExceptionPtrDestroy(_Inout_ void*) noexcept; diff --git a/stl/inc/execution b/stl/inc/execution index ee31dac657e..dfab9661d35 100644 --- a/stl/inc/execution +++ b/stl/inc/execution @@ -5217,6 +5217,6 @@ _STD_END _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) #pragma pack(pop) -#endif // _HAS_CXX17 +#endif // ^^^ _HAS_CXX17 ^^^ #endif // _STL_COMPILER_PREPROCESSOR #endif // _EXECUTION_ diff --git a/stl/inc/experimental/generator b/stl/inc/experimental/generator index fcc1d2ba4d9..f6fea9c47c7 100644 --- a/stl/inc/experimental/generator +++ b/stl/inc/experimental/generator @@ -121,7 +121,7 @@ namespace experimental { _STD exchange(_Coro, nullptr).promise()._Rethrow_if_exception(); #else // ^^^ defined(_CPPUNWIND) / !defined(_CPPUNWIND) vvv _Coro = nullptr; -#endif // _CPPUNWIND +#endif // ^^^ !defined(_CPPUNWIND) ^^^ } return *this; @@ -156,7 +156,7 @@ namespace experimental { if (_Coro.done()) { #ifdef _CPPUNWIND _Coro.promise()._Rethrow_if_exception(); -#endif // _CPPUNWIND +#endif // ^^^ defined(_CPPUNWIND) ^^^ return {}; } } diff --git a/stl/inc/filesystem b/stl/inc/filesystem index 6675bc94f40..a2abcecd464 100644 --- a/stl/inc/filesystem +++ b/stl/inc/filesystem @@ -1374,7 +1374,7 @@ namespace filesystem { _NODISCARD_FRIEND bool operator>=(const path& _Left, const path& _Right) noexcept { return _Left.compare(_Right) >= 0; } -#endif // !_HAS_CXX20 +#endif // ^^^ !_HAS_CXX20 ^^^ _NODISCARD_FRIEND path operator/(const path& _Left, const path& _Right) { // append a pair of paths together path _Tmp = _Left; @@ -2454,7 +2454,7 @@ namespace filesystem { _NODISCARD bool operator>=(const directory_entry& _Rhs) const noexcept { return _Path >= _Rhs._Path; } -#endif // !_HAS_CXX20 +#endif // ^^^ !_HAS_CXX20 ^^^ // [fs.dir.entry.io], inserter template @@ -4430,6 +4430,6 @@ _STD_END _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) #pragma pack(pop) -#endif // _HAS_CXX17 +#endif // ^^^ _HAS_CXX17 ^^^ #endif // _STL_COMPILER_PREPROCESSOR #endif // _FILESYSTEM_ diff --git a/stl/inc/format b/stl/inc/format index 5b976f2f5d8..4dce53c7a23 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -125,10 +125,18 @@ static_assert(static_cast(_Basic_format_arg_type::_Custom_type) < 16, "must _NODISCARD constexpr bool _Is_integral_fmt_type(_Basic_format_arg_type _Ty) { return _Ty > _Basic_format_arg_type::_None && _Ty <= _Basic_format_arg_type::_Char_type; } + _NODISCARD constexpr bool _Is_arithmetic_fmt_type(_Basic_format_arg_type _Ty) { return _Ty > _Basic_format_arg_type::_None && _Ty <= _Basic_format_arg_type::_Long_double_type; } +#if _HAS_CXX23 +_NODISCARD consteval bool _Is_debug_enabled_fmt_type(_Basic_format_arg_type _Ty) { + return _Ty == _Basic_format_arg_type::_Char_type || _Ty == _Basic_format_arg_type::_CString_type + || _Ty == _Basic_format_arg_type::_String_type; +} +#endif // _HAS_CXX23 + struct _Auto_id_tag { explicit _Auto_id_tag() = default; }; @@ -3580,8 +3588,18 @@ struct formatter { _FMT_P2286_BEGIN template struct _Formatter_base { +private: using _Pc = basic_format_parse_context<_CharT>; +public: +#if _HAS_CXX23 + constexpr void _Set_debug_format() noexcept + requires (_Is_debug_enabled_fmt_type(_ArgType)) + { + _Specs._Type = '?'; + } +#endif // _HAS_CXX23 + constexpr _Pc::iterator parse(_Pc& _ParseCtx) { _Specs_checker<_Dynamic_specs_handler<_Pc>> _Handler(_Dynamic_specs_handler<_Pc>{_Specs, _ParseCtx}, _ArgType); const auto _It = _Parse_format_specs(_ParseCtx._Unchecked_begin(), _ParseCtx._Unchecked_end(), _Handler); @@ -3634,35 +3652,80 @@ _FORMAT_SPECIALIZE_FOR(short, _Basic_format_arg_type::_Int_type); _FORMAT_SPECIALIZE_FOR(unsigned short, _Basic_format_arg_type::_UInt_type); _FORMAT_SPECIALIZE_FOR(long, _Basic_format_arg_type::_Int_type); _FORMAT_SPECIALIZE_FOR(unsigned long, _Basic_format_arg_type::_UInt_type); -_FORMAT_SPECIALIZE_FOR(char, _Basic_format_arg_type::_Char_type); _FORMAT_SPECIALIZE_FOR(signed char, _Basic_format_arg_type::_Int_type); _FORMAT_SPECIALIZE_FOR(unsigned char, _Basic_format_arg_type::_UInt_type); #undef _FORMAT_SPECIALIZE_FOR +// not using the macro because we'd like to add 'set_debug_format' member function in C++23 mode +template <_Format_supported_charT _CharT> +struct formatter : _Formatter_base { +#if _HAS_CXX23 + constexpr void set_debug_format() noexcept { + this->_Set_debug_format(); + } +#endif // _HAS_CXX23 +}; + // not using the macro because we'd like to avoid the formatter specialization template <> -struct formatter : _Formatter_base {}; +struct formatter : _Formatter_base { +#if _HAS_CXX23 + constexpr void set_debug_format() noexcept { + _Set_debug_format(); + } +#endif // _HAS_CXX23 +}; // We could use the macro for these specializations, but it's confusing to refer to symbols that are defined // inside the macro in the macro's "call". template <_Format_supported_charT _CharT> -struct formatter<_CharT*, _CharT> : _Formatter_base<_CharT*, _CharT, _Basic_format_arg_type::_CString_type> {}; +struct formatter<_CharT*, _CharT> : _Formatter_base<_CharT*, _CharT, _Basic_format_arg_type::_CString_type> { +#if _HAS_CXX23 + constexpr void set_debug_format() noexcept { + this->_Set_debug_format(); + } +#endif // _HAS_CXX23 +}; template <_Format_supported_charT _CharT> struct formatter - : _Formatter_base {}; + : _Formatter_base { +#if _HAS_CXX23 + constexpr void set_debug_format() noexcept { + this->_Set_debug_format(); + } +#endif // _HAS_CXX23 +}; template <_Format_supported_charT _CharT, size_t _Nx> -struct formatter<_CharT[_Nx], _CharT> : _Formatter_base<_CharT[_Nx], _CharT, _Basic_format_arg_type::_CString_type> {}; +struct formatter<_CharT[_Nx], _CharT> : _Formatter_base<_CharT[_Nx], _CharT, _Basic_format_arg_type::_CString_type> { +#if _HAS_CXX23 + constexpr void set_debug_format() noexcept { + this->_Set_debug_format(); + } +#endif // _HAS_CXX23 +}; template <_Format_supported_charT _CharT, class _Traits, class _Allocator> struct formatter, _CharT> - : _Formatter_base, _CharT, _Basic_format_arg_type::_String_type> {}; + : _Formatter_base, _CharT, _Basic_format_arg_type::_String_type> { +#if _HAS_CXX23 + constexpr void set_debug_format() noexcept { + this->_Set_debug_format(); + } +#endif // _HAS_CXX23 +}; template <_Format_supported_charT _CharT, class _Traits> struct formatter, _CharT> - : _Formatter_base, _CharT, _Basic_format_arg_type::_String_type> {}; + : _Formatter_base, _CharT, _Basic_format_arg_type::_String_type> { +#if _HAS_CXX23 + constexpr void set_debug_format() noexcept { + this->_Set_debug_format(); + } +#endif // _HAS_CXX23 +}; _EXPORT_STD template struct basic_format_string { @@ -4074,6 +4137,6 @@ _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) #pragma pack(pop) -#endif // defined(__cpp_lib_concepts) +#endif // ^^^ defined(__cpp_lib_concepts) ^^^ #endif // _STL_COMPILER_PREPROCESSOR #endif // _FORMAT_ diff --git a/stl/inc/forward_list b/stl/inc/forward_list index da850f2803f..d76f67fbee7 100644 --- a/stl/inc/forward_list +++ b/stl/inc/forward_list @@ -1468,7 +1468,7 @@ private: if constexpr (!_Alnode_traits::is_always_equal::value) { _STL_VERIFY(_Getal() == _Right._Getal(), "forward_list containers incompatible for splice_after"); } -#endif // _ITERATOR_DEBUG_LEVEL == 0 +#endif // ^^^ _ITERATOR_DEBUG_LEVEL != 0 ^^^ #if _ITERATOR_DEBUG_LEVEL == 2 if (this != _STD addressof(_Right)) { @@ -1497,7 +1497,7 @@ private: if constexpr (!_Alnode_traits::is_always_equal::value) { _STL_VERIFY(_Getal() == _Right._Getal(), "forward_list containers incompatible for splice_after"); } -#endif // _ITERATOR_DEBUG_LEVEL == 0 +#endif // ^^^ _ITERATOR_DEBUG_LEVEL != 0 ^^^ if (_First == _Last) { return; diff --git a/stl/inc/future b/stl/inc/future index 9f8c6b7d9bb..3270c67b53f 100644 --- a/stl/inc/future +++ b/stl/inc/future @@ -10,7 +10,7 @@ #ifdef _M_CEE_PURE #error is not supported when compiling with /clr:pure. -#endif // _M_CEE_PURE +#endif // defined(_M_CEE_PURE) #ifdef _RESUMABLE_FUNCTIONS_SUPPORTED #include @@ -469,15 +469,6 @@ public: using _Mybase = _Associated_state<_Ret>; using _Mydel = typename _Mybase::_Mydel; - template - _Packaged_state(const _Fty2& _Fnarg) : _Fn(_Fnarg) {} - -#if _HAS_FUNCTION_ALLOCATOR_SUPPORT - template - _Packaged_state(const _Fty2& _Fnarg, const _Alloc& _Al, _Mydel* _Dp) - : _Mybase(_Dp), _Fn(allocator_arg, _Al, _Fnarg) {} -#endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT - template _Packaged_state(_Fty2&& _Fnarg) : _Fn(_STD forward<_Fty2>(_Fnarg)) {} @@ -507,7 +498,7 @@ public: _CATCH_END } - const function<_Ret(_ArgTypes...)>& _Get_fn() { + const auto& _Get_fn() const { return _Fn; } @@ -522,15 +513,6 @@ public: using _Mybase = _Associated_state<_Ret*>; using _Mydel = typename _Mybase::_Mydel; - template - _Packaged_state(const _Fty2& _Fnarg) : _Fn(_Fnarg) {} - -#if _HAS_FUNCTION_ALLOCATOR_SUPPORT - template - _Packaged_state(const _Fty2& _Fnarg, const _Alloc& _Al, _Mydel* _Dp) - : _Mybase(_Dp), _Fn(allocator_arg, _Al, _Fnarg) {} -#endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT - template _Packaged_state(_Fty2&& _Fnarg) : _Fn(_STD forward<_Fty2>(_Fnarg)) {} @@ -560,7 +542,7 @@ public: _CATCH_END } - const function<_Ret&(_ArgTypes...)>& _Get_fn() { + const auto& _Get_fn() const { return _Fn; } @@ -575,15 +557,6 @@ public: using _Mybase = _Associated_state; using _Mydel = typename _Mybase::_Mydel; - template - _Packaged_state(const _Fty2& _Fnarg) : _Fn(_Fnarg) {} - -#if _HAS_FUNCTION_ALLOCATOR_SUPPORT - template - _Packaged_state(const _Fty2& _Fnarg, const _Alloc& _Al, _Mydel* _Dp) - : _Mybase(_Dp), _Fn(allocator_arg, _Al, _Fnarg) {} -#endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT - template _Packaged_state(_Fty2&& _Fnarg) : _Fn(_STD forward<_Fty2>(_Fnarg)) {} @@ -615,7 +588,7 @@ public: _CATCH_END } - const function& _Get_fn() { + const auto& _Get_fn() const { return _Fn; } @@ -960,7 +933,7 @@ public: shared_future& operator=(const shared_future&) = default; - shared_future(future<_Ty>&& _Other) noexcept : _Mybase(_STD forward<_Mybase>(_Other)) {} + shared_future(future<_Ty>&& _Other) noexcept : _Mybase(static_cast<_Mybase&&>(_Other)) {} shared_future(shared_future&& _Other) noexcept : _Mybase(_STD move(_Other)) {} @@ -985,7 +958,7 @@ public: shared_future& operator=(const shared_future&) = default; - shared_future(future<_Ty&>&& _Other) noexcept : _Mybase(_STD forward<_Mybase>(_Other)) {} + shared_future(future<_Ty&>&& _Other) noexcept : _Mybase(static_cast<_Mybase&&>(_Other)) {} shared_future(shared_future&& _Other) noexcept : _Mybase(_STD move(_Other)) {} @@ -1012,7 +985,7 @@ public: shared_future(shared_future&& _Other) noexcept : _Mybase(_STD move(_Other)) {} - shared_future(future&& _Other) noexcept : _Mybase(_STD forward<_Mybase>(_Other)) {} + shared_future(future&& _Other) noexcept : _Mybase(static_cast<_Mybase&&>(_Other)) {} shared_future& operator=(shared_future&&) = default; @@ -1285,12 +1258,13 @@ class packaged_task; // not defined template class packaged_task<_Ret(_ArgTypes...)> { // class that defines an asynchronous provider that returns the result of a call to a function object -public: +private: using _Ptype = typename _P_arg_type<_Ret>::type; using _MyPromiseType = _Promise<_Ptype>; using _MyStateManagerType = _State_manager<_Ptype>; using _MyStateType = _Packaged_state<_Ret(_ArgTypes...)>; +public: packaged_task() = default; template , packaged_task>, int> = 0> @@ -1347,10 +1321,9 @@ public: } void reset() { // reset to newly constructed state - _MyStateManagerType& _State = _MyPromise._Get_state_for_set(); - _MyStateType* _MyState = static_cast<_MyStateType*>(_State._Ptr()); - function<_Ret(_ArgTypes...)> _Fnarg = _MyState->_Get_fn(); - _MyPromiseType _New_promise(new _MyStateType(_Fnarg)); + _MyStateManagerType& _State = _MyPromise._Get_state_for_set(); + _MyStateType* _MyState = static_cast<_MyStateType*>(_State._Ptr()); + _MyPromiseType _New_promise(new _MyStateType(_MyState->_Get_fn())); _MyPromise._Get_state()._Abandon(); _MyPromise._Swap(_New_promise); } @@ -1385,14 +1358,13 @@ void swap(packaged_task<_Ty>& _Left, packaged_task<_Ty>& _Right) noexcept { } template -auto _Invoke_stored_explicit(tuple<_Types...>&& _Tuple, index_sequence<_Indices...>) -> decltype(_STD invoke( - _STD get<_Indices>(_STD move(_Tuple))...)) { // invoke() a tuple with explicit parameter ordering +decltype(auto) _Invoke_stored_explicit( + tuple<_Types...>&& _Tuple, index_sequence<_Indices...>) { // invoke() a tuple with explicit parameter ordering return _STD invoke(_STD get<_Indices>(_STD move(_Tuple))...); } template -auto _Invoke_stored(tuple<_Types...>&& _Tuple) - -> decltype(_Invoke_stored_explicit(_STD move(_Tuple), index_sequence_for<_Types...>{})) { // invoke() a tuple +decltype(auto) _Invoke_stored(tuple<_Types...>&& _Tuple) { // invoke() a tuple return _Invoke_stored_explicit(_STD move(_Tuple), index_sequence_for<_Types...>{}); } @@ -1400,7 +1372,7 @@ template class _Fake_no_copy_callable_adapter { // async() is built on packaged_task internals which incorrectly use // std::function, which requires that things be copyable. We can't fix this in an - // update, so this adapter turns copies into terminate(). When VSO-153581 is + // update, so this adapter turns copies into abort(). When VSO-153581 is // fixed, remove this adapter. private: using _Storaget = tuple...>; @@ -1412,14 +1384,14 @@ public: [[noreturn]] _Fake_no_copy_callable_adapter(const _Fake_no_copy_callable_adapter& _Other) : _Storage(_STD move(_Other._Storage)) { - _CSTD abort(); // shouldn't be called, see GH-3888 + _CSTD abort(); // shouldn't be called } _Fake_no_copy_callable_adapter(_Fake_no_copy_callable_adapter&& _Other) = default; _Fake_no_copy_callable_adapter& operator=(const _Fake_no_copy_callable_adapter&) = delete; _Fake_no_copy_callable_adapter& operator=(_Fake_no_copy_callable_adapter&&) = delete; - auto operator()() -> decltype(_Invoke_stored(_STD move(_STD declval<_Storaget&>()))) { + decltype(auto) operator()() { return _Invoke_stored(_STD move(_Storage)); } diff --git a/stl/inc/iterator b/stl/inc/iterator index 531b468401f..50075d5bfc9 100644 --- a/stl/inc/iterator +++ b/stl/inc/iterator @@ -1635,7 +1635,7 @@ public: _NODISCARD constexpr bool operator>=(const checked_array_iterator& _Right) const noexcept { return !(*this < _Right); } -#endif // !_HAS_CXX20 +#endif // ^^^ !_HAS_CXX20 ^^^ friend constexpr void _Verify_range( const checked_array_iterator& _First, const checked_array_iterator& _Last) noexcept { @@ -1804,7 +1804,7 @@ public: _NODISCARD constexpr bool operator>=(const unchecked_array_iterator& _Right) const noexcept { return !(*this < _Right); } -#endif // !_HAS_CXX20 +#endif // ^^^ !_HAS_CXX20 ^^^ #if _ITERATOR_DEBUG_LEVEL != 0 friend constexpr void _Verify_range( diff --git a/stl/inc/latch b/stl/inc/latch index ce132e6b058..bea8aa7d633 100644 --- a/stl/inc/latch +++ b/stl/inc/latch @@ -10,7 +10,7 @@ #ifdef _M_CEE_PURE #error is not supported when compiling with /clr:pure. -#endif // _M_CEE_PURE +#endif // defined(_M_CEE_PURE) #if !_HAS_CXX20 _EMIT_STL_WARNING(STL4038, "The contents of are available only with C++20 or later."); @@ -31,7 +31,7 @@ _STD_BEGIN _EXPORT_STD class latch { public: _NODISCARD static constexpr ptrdiff_t(max)() noexcept { - return (1ULL << (sizeof(ptrdiff_t) * CHAR_BIT - 1)) - 1; + return PTRDIFF_MAX; } constexpr explicit latch(const ptrdiff_t _Expected) noexcept /* strengthened */ : _Counter{_Expected} { diff --git a/stl/inc/list b/stl/inc/list index 169d126468d..843459d4492 100644 --- a/stl/inc/list +++ b/stl/inc/list @@ -370,7 +370,7 @@ public: } #else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 / _ITERATOR_DEBUG_LEVEL != 2 vvv (void) _Ptr; -#endif // _ITERATOR_DEBUG_LEVEL == 2 +#endif // ^^^ _ITERATOR_DEBUG_LEVEL != 2 ^^^ } void _Orphan_non_end() noexcept { // orphan iterators except end() @@ -985,7 +985,7 @@ public: return _Result; #else // ^^^ _HAS_CXX17 / !_HAS_CXX17 vvv (void) _Result; -#endif // _HAS_CXX17 +#endif // ^^^ !_HAS_CXX17 ^^^ } template @@ -996,7 +996,7 @@ public: return _Result; #else // ^^^ _HAS_CXX17 / !_HAS_CXX17 vvv (void) _Result; -#endif // _HAS_CXX17 +#endif // ^^^ !_HAS_CXX17 ^^^ } template diff --git a/stl/inc/mdspan b/stl/inc/mdspan index 12e0219294b..a603de5f0b2 100644 --- a/stl/inc/mdspan +++ b/stl/inc/mdspan @@ -348,11 +348,13 @@ public: if constexpr (_Extents::rank() == 0) { return 1; } else { - typename _Extents::index_type _Result = 1; + // Use an unsigned type to prevent overflow when called from mdspan::size. + typename _Extents::size_type _Result = 1; for (size_t _Dim = 0; _Dim < _Idx; ++_Dim) { - _Result *= _Exts.extent(_Dim); + _Result *= static_cast<_Extents::size_type>(_Exts.extent(_Dim)); } - return _Result; + + return static_cast<_Extents::index_type>(_Result); } } }; diff --git a/stl/inc/memory b/stl/inc/memory index 8fdade31164..08c513e7b1d 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1843,7 +1843,7 @@ private: template friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, _Types&&... _Args); -#endif // !_HAS_CXX20 +#endif // ^^^ !_HAS_CXX20 ^^^ template void _Set_ptr_rep_and_enable_shared(_Ux* const _Px, _Ref_count_base* const _Rx) noexcept { // take ownership of _Px @@ -3009,7 +3009,7 @@ public: static constexpr bool _Must_avoid_expired_conversions_from<_Ty2, decltype(static_cast(static_cast<_Ty*>(nullptr)))> = false; -#endif // _M_CEE_PURE +#endif // ^^^ !defined(_M_CEE_PURE) ^^^ constexpr weak_ptr() noexcept {} diff --git a/stl/inc/memory_resource b/stl/inc/memory_resource index 415994c6d0c..9468c2508af 100644 --- a/stl/inc/memory_resource +++ b/stl/inc/memory_resource @@ -751,6 +751,6 @@ _STD_END _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) #pragma pack(pop) -#endif // _HAS_CXX17 +#endif // ^^^ _HAS_CXX17 ^^^ #endif // _STL_COMPILER_PREPROCESSOR #endif // _MEMORY_RESOURCE_ diff --git a/stl/inc/mutex b/stl/inc/mutex index 4954d7c3389..ce4c809f6a1 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -10,7 +10,7 @@ #ifdef _M_CEE_PURE #error is not supported when compiling with /clr:pure. -#endif // _M_CEE_PURE +#endif // defined(_M_CEE_PURE) #include <__msvc_chrono.hpp> #include @@ -43,7 +43,7 @@ public: _Mutex_base(int _Flags = 0) noexcept { _Mtx_init_in_situ(_Mymtx(), _Flags | _Mtx_try); } -#endif // !_ENABLE_CONSTEXPR_MUTEX_CONSTRUCTOR +#endif // ^^^ !_ENABLE_CONSTEXPR_MUTEX_CONSTRUCTOR ^^^ ~_Mutex_base() noexcept { _Mtx_destroy_in_situ(_Mymtx()); @@ -574,25 +574,16 @@ public: cv_status wait_for(unique_lock& _Lck, const chrono::duration<_Rep, _Period>& _Rel_time) { // wait for duration if (_Rel_time <= chrono::duration<_Rep, _Period>::zero()) { + // we don't unlock-and-relock _Lck for this case because it's not observable return cv_status::timeout; } - - // TRANSITION, ABI: The standard says that we should use a steady clock, - // but unfortunately our ABI relies on the system clock. - _timespec64 _Tgt; - const bool _Clamped = _To_timespec64_sys_10_day_clamped(_Tgt, _Rel_time); - const cv_status _Result = _Wait_until_sys_time(_Lck, &_Tgt); - if (_Clamped) { - return cv_status::no_timeout; - } - - return _Result; + return wait_until(_Lck, _To_absolute_time(_Rel_time)); } template bool wait_for(unique_lock& _Lck, const chrono::duration<_Rep, _Period>& _Rel_time, _Predicate _Pred) { // wait for signal with timeout and check predicate - return _Wait_until1(_Lck, _To_absolute_time(_Rel_time), _Pred); + return wait_until(_Lck, _To_absolute_time(_Rel_time), _Pass_fn(_Pred)); } template @@ -601,16 +592,25 @@ public: #if _HAS_CXX20 static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); #endif // _HAS_CXX20 +#if _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY( + _Lck.owns_lock(), "wait_until's caller must own the lock argument (N4958 [thread.condition.condvar]/17)"); + _STL_VERIFY(_Mtx_current_owns(_Lck.mutex()->_Mymtx()), + "wait_until's calling thread must hold the lock argument's mutex (N4958 [thread.condition.condvar]/17)"); +#endif // _CONTAINER_DEBUG_LEVEL > 0 for (;;) { const auto _Now = _Clock::now(); if (_Abs_time <= _Now) { + // we don't unlock-and-relock _Lck for this case because it's not observable return cv_status::timeout; } + // TRANSITION, ABI: should use a steady clock _timespec64 _Tgt; (void) _To_timespec64_sys_10_day_clamped(_Tgt, _Abs_time - _Now); - const cv_status _Result = _Wait_until_sys_time(_Lck, &_Tgt); - if (_Result == cv_status::no_timeout) { + // Nothing to do to comply with LWG-2135 because std::mutex lock/unlock are nothrow + const _Thrd_result _Res = _Cnd_timedwait(_Mycnd(), _Lck.mutex()->_Mymtx(), &_Tgt); + if (_Res == _Thrd_result::_Success) { return cv_status::no_timeout; } } @@ -623,7 +623,13 @@ public: #if _HAS_CXX20 static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); #endif // _HAS_CXX20 - return _Wait_until1(_Lck, _Abs_time, _Pred); + while (!_Pred()) { + if (wait_until(_Lck, _Abs_time) == cv_status::timeout) { + return _Pred(); + } + } + + return true; } // native_handle_type and native_handle() have intentionally been removed. See GH-3820. @@ -642,41 +648,6 @@ private: _Cnd_t _Mycnd() noexcept { // get pointer to _Cnd_internal_imp_t inside _Cnd_storage return reinterpret_cast<_Cnd_t>(&_Cnd_storage); } - - cv_status _Wait_until_sys_time(unique_lock& _Lck, const _timespec64* _Abs_time) { - // wait for signal with timeout - if (!_Mtx_current_owns(_Lck.mutex()->_Mymtx())) { - _Throw_Cpp_error(_OPERATION_NOT_PERMITTED); - } - - // Nothing to do to comply with LWG-2135 because std::mutex lock/unlock are nothrow - const _Thrd_result _Res = _Cnd_timedwait(_Mycnd(), _Lck.mutex()->_Mymtx(), _Abs_time); - - if (_Res == _Thrd_result::_Success) { - return cv_status::no_timeout; - } else { - return cv_status::timeout; - } - } - - template - bool _Wait_until1( - unique_lock& _Lck, const chrono::time_point<_Clock, _Duration>& _Abs_time, _Predicate& _Pred) { - while (!_Pred()) { - const auto _Now = _Clock::now(); - if (_Abs_time <= _Now) { - return false; - } - - _timespec64 _Tgt; - const bool _Clamped = _To_timespec64_sys_10_day_clamped(_Tgt, _Abs_time - _Now); - if (_Wait_until_sys_time(_Lck, &_Tgt) == cv_status::timeout && !_Clamped) { - return _Pred(); - } - } - - return true; - } }; struct _UInt_is_zero { diff --git a/stl/inc/new b/stl/inc/new index 2165ca81e1c..6b6a8164e3e 100644 --- a/stl/inc/new +++ b/stl/inc/new @@ -102,7 +102,7 @@ _EXPORT_STD inline constexpr size_t hardware_constructive_interference_size = 64 _EXPORT_STD inline constexpr size_t hardware_destructive_interference_size = 64; #else // ^^^ supported hardware / unsupported hardware vvv #error Unsupported architecture -#endif // hardware +#endif // ^^^ unsupported hardware ^^^ #endif // _HAS_CXX17 diff --git a/stl/inc/numbers b/stl/inc/numbers index 4c3ee75d23d..3d27bf35f00 100644 --- a/stl/inc/numbers +++ b/stl/inc/numbers @@ -144,6 +144,6 @@ _STD_END _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) #pragma pack(pop) -#endif // _HAS_CXX20 +#endif // ^^^ _HAS_CXX20 ^^^ #endif // _STL_COMPILER_PREPROCESSOR #endif // _NUMBERS_ diff --git a/stl/inc/numeric b/stl/inc/numeric index 0e06059b821..ed8abfafe91 100644 --- a/stl/inc/numeric +++ b/stl/inc/numeric @@ -35,7 +35,7 @@ _NODISCARD _CONSTEXPR20 _Ty accumulate(const _InIt _First, const _InIt _Last, _T _Val = _Reduce_op(_STD move(_Val), *_UFirst); #else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv _Val = _Reduce_op(_Val, *_UFirst); -#endif // _HAS_CXX20 +#endif // ^^^ !_HAS_CXX20 ^^^ } return _Val; } @@ -68,7 +68,7 @@ _Ty _Reduce_plus_arithmetic_ranges(_InIt _First, const _InIt _Last, _Ty _Val) { #else // ^^^ _STD_VECTORIZE_WITH_FLOAT_CONTROL / !_STD_VECTORIZE_WITH_FLOAT_CONTROL vvv template inline constexpr bool _Plus_on_arithmetic_ranges_reduction_v = false; -#endif // _STD_VECTORIZE_WITH_FLOAT_CONTROL +#endif // ^^^ !_STD_VECTORIZE_WITH_FLOAT_CONTROL ^^^ _EXPORT_STD template _NODISCARD _CONSTEXPR20 _Ty reduce(const _InIt _First, const _InIt _Last, _Ty _Val, _BinOp _Reduce_op) { @@ -137,7 +137,7 @@ _NODISCARD _CONSTEXPR20 _Ty inner_product( _Val = _Reduce_op(_STD move(_Val), _Transform_op(*_UFirst1, *_UFirst2)); // Requirement missing from N4950 #else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv _Val = _Reduce_op(_Val, _Transform_op(*_UFirst1, *_UFirst2)); // Requirement missing from N4950 -#endif // _HAS_CXX20 +#endif // ^^^ !_HAS_CXX20 ^^^ } return _Val; @@ -171,7 +171,7 @@ _Ty _Transform_reduce_arithmetic_defaults(_InIt1 _First1, const _InIt1 _Last1, _ #else // ^^^ _STD_VECTORIZE_WITH_FLOAT_CONTROL / !_STD_VECTORIZE_WITH_FLOAT_CONTROL vvv template inline constexpr bool _Default_ops_transform_reduce_v = false; -#endif // _STD_VECTORIZE_WITH_FLOAT_CONTROL +#endif // ^^^ !_STD_VECTORIZE_WITH_FLOAT_CONTROL ^^^ _EXPORT_STD template _NODISCARD _CONSTEXPR20 _Ty transform_reduce( @@ -260,7 +260,7 @@ _CONSTEXPR20 _OutIt partial_sum(const _InIt _First, const _InIt _Last, _OutIt _D _Val = _Reduce_op(_STD move(_Val), *_UFirst); #else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv _Val = _Reduce_op(_Val, *_UFirst); -#endif // _HAS_CXX20 +#endif // ^^^ !_HAS_CXX20 ^^^ } } @@ -484,7 +484,7 @@ _CONSTEXPR20 _OutIt adjacent_difference(const _InIt _First, const _InIt _Last, _ *++_UDest = _Func(_Tmp, _STD move(_Val)); #else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv *++_UDest = _Func(_Tmp, _Val); -#endif // _HAS_CXX20 +#endif // ^^^ !_HAS_CXX20 ^^^ _Val = _STD move(_Tmp); } diff --git a/stl/inc/optional b/stl/inc/optional index 060960a6503..3b42ba6ff94 100644 --- a/stl/inc/optional +++ b/stl/inc/optional @@ -797,7 +797,7 @@ template _NODISCARD constexpr bool operator>=(nullopt_t, const optional<_Ty>& _Right) noexcept { return !_Right.has_value(); } -#endif // !_HAS_CXX20 +#endif // ^^^ !_HAS_CXX20 ^^^ template using _Enable_if_bool_convertible = enable_if_t, int>; @@ -987,6 +987,6 @@ _STD_END _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) #pragma pack(pop) -#endif // _HAS_CXX17 +#endif // ^^^ _HAS_CXX17 ^^^ #endif // _STL_COMPILER_PREPROCESSOR #endif // _OPTIONAL_ diff --git a/stl/inc/ostream b/stl/inc/ostream index 860b8526733..1a679cf019b 100644 --- a/stl/inc/ostream +++ b/stl/inc/ostream @@ -117,7 +117,7 @@ public: const bool _Zero_uncaught_exceptions = !_STD uncaught_exception(); // TRANSITION, ArchivedOS-12000909 #else // ^^^ _HAS_DEPRECATED_UNCAUGHT_EXCEPTION / !_HAS_DEPRECATED_UNCAUGHT_EXCEPTION vvv const bool _Zero_uncaught_exceptions = _STD uncaught_exceptions() == 0; -#endif // !_HAS_DEPRECATED_UNCAUGHT_EXCEPTION +#endif // ^^^ !_HAS_DEPRECATED_UNCAUGHT_EXCEPTION ^^^ if (_Zero_uncaught_exceptions) { this->_Myostr._Osfx(); @@ -184,7 +184,7 @@ public: _Pfn(*this); return *this; } -#endif // _M_CEE_PURE +#endif // defined(_M_CEE_PURE) basic_ostream& __CLR_OR_THIS_CALL operator<<(basic_ostream&(__cdecl* _Pfn)(basic_ostream&) ) { // call basic_ostream manipulator diff --git a/stl/inc/print b/stl/inc/print index dabc8c4a0f1..0e4c090925b 100644 --- a/stl/inc/print +++ b/stl/inc/print @@ -165,6 +165,6 @@ _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) #pragma pack(pop) -#endif // defined(__cpp_lib_print) +#endif // ^^^ defined(__cpp_lib_print) ^^^ #endif // _STL_COMPILER_PREPROCESSOR #endif // _PRINT_ diff --git a/stl/inc/queue b/stl/inc/queue index 4ea1df73500..980fa86e1c2 100644 --- a/stl/inc/queue +++ b/stl/inc/queue @@ -135,9 +135,9 @@ public: decltype(auto) emplace(_Valty&&... _Val) { #if _HAS_CXX17 return c.emplace_back(_STD forward<_Valty>(_Val)...); -#else // ^^^ C++17 or newer / C++14 vvv +#else // ^^^ _HAS_CXX17 / !_HAS_CXX17 vvv c.emplace_back(_STD forward<_Valty>(_Val)...); -#endif // _HAS_CXX17 +#endif // ^^^ !_HAS_CXX17 ^^^ } void pop() noexcept(noexcept(c.pop_front())) /* strengthened */ { @@ -246,40 +246,40 @@ public: : c(), comp(_Pred) {} priority_queue(const _Pr& _Pred, const _Container& _Cont) : c(_Cont), comp(_Pred) { - _STD make_heap(c.begin(), c.end(), comp); + _Make_heap(); } priority_queue(const _Pr& _Pred, _Container&& _Cont) : c(_STD move(_Cont)), comp(_Pred) { - _STD make_heap(c.begin(), c.end(), comp); + _Make_heap(); } template , int> = 0> priority_queue(_InIt _First, _InIt _Last, const _Pr& _Pred, const _Container& _Cont) : c(_Cont), comp(_Pred) { c.insert(c.end(), _First, _Last); - _STD make_heap(c.begin(), c.end(), comp); + _Make_heap(); } template , int> = 0> priority_queue(_InIt _First, _InIt _Last) : c(_First, _Last), comp() { - _STD make_heap(c.begin(), c.end(), comp); + _Make_heap(); } template , int> = 0> priority_queue(_InIt _First, _InIt _Last, const _Pr& _Pred) : c(_First, _Last), comp(_Pred) { - _STD make_heap(c.begin(), c.end(), comp); + _Make_heap(); } template , int> = 0> priority_queue(_InIt _First, _InIt _Last, const _Pr& _Pred, _Container&& _Cont) : c(_STD move(_Cont)), comp(_Pred) { c.insert(c.end(), _First, _Last); - _STD make_heap(c.begin(), c.end(), comp); + _Make_heap(); } #if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 template <_Container_compatible_range<_Ty> _Rng> priority_queue(from_range_t, _Rng&& _Range, const _Pr& _Pred = _Pr()) : c(_RANGES to<_Container>(_STD forward<_Rng>(_Range))), comp(_Pred) { - _STD make_heap(c.begin(), c.end(), comp); + _Make_heap(); } #endif // _HAS_CXX23 && defined(__cpp_lib_concepts) @@ -295,12 +295,12 @@ public: template , int> = 0> priority_queue(const _Pr& _Pred, const _Container& _Cont, const _Alloc& _Al) : c(_Cont, _Al), comp(_Pred) { - _STD make_heap(c.begin(), c.end(), comp); + _Make_heap(); } template , int> = 0> priority_queue(const _Pr& _Pred, _Container&& _Cont, const _Alloc& _Al) : c(_STD move(_Cont), _Al), comp(_Pred) { - _STD make_heap(c.begin(), c.end(), comp); + _Make_heap(); } template , int> = 0> @@ -315,14 +315,14 @@ public: template && uses_allocator_v<_Container, _Alloc>, int> = 0> priority_queue(_InIt _First, _InIt _Last, const _Alloc& _Al) : c(_First, _Last, _Al), comp() { - _STD make_heap(c.begin(), c.end(), comp); + _Make_heap(); } template && uses_allocator_v<_Container, _Alloc>, int> = 0> priority_queue(_InIt _First, _InIt _Last, const _Pr& _Pred, const _Alloc& _Al) : c(_First, _Last, _Al), comp(_Pred) { - _STD make_heap(c.begin(), c.end(), comp); + _Make_heap(); } template , int> = 0> priority_queue(from_range_t, _Rng&& _Range, const _Pr& _Pred, const _Alloc& _Al) : c(_RANGES to<_Container>(_STD forward<_Rng>(_Range), _Al)), comp(_Pred) { - _STD make_heap(c.begin(), c.end(), comp); + _Make_heap(); } template <_Container_compatible_range<_Ty> _Rng, class _Alloc, enable_if_t, int> = 0> priority_queue(from_range_t, _Rng&& _Range, const _Alloc& _Al) : c(_RANGES to<_Container>(_STD forward<_Rng>(_Range), _Al)), comp() { - _STD make_heap(c.begin(), c.end(), comp); + _Make_heap(); } #endif // _HAS_CXX23 && defined(__cpp_lib_concepts) @@ -371,35 +371,47 @@ public: void push(const value_type& _Val) { c.push_back(_Val); - _STD push_heap(c.begin(), c.end(), comp); + _STD push_heap(c.begin(), c.end(), _STD _Pass_fn(comp)); } void push(value_type&& _Val) { c.push_back(_STD move(_Val)); - _STD push_heap(c.begin(), c.end(), comp); + _STD push_heap(c.begin(), c.end(), _STD _Pass_fn(comp)); } #if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 template <_Container_compatible_range<_Ty> _Rng> void push_range(_Rng&& _Range) { + const size_type _Old_size = c.size(); + if constexpr (requires { c.append_range(_Range); }) { c.append_range(_Range); } else { _RANGES copy(_Range, back_insert_iterator{c}); } - _STD make_heap(c.begin(), c.end(), comp); + const size_type _New_size = c.size(); + if (_New_size / 2 > _Old_size) { // threshold chosen for performance + _Make_heap(); + } else { + const auto _Begin = _STD _Get_unwrapped(c.begin()); + auto _Heap_end = _Begin + _Old_size; + const auto _End = _STD _Get_unwrapped(c.end()); + while (_Heap_end != _End) { + _STD push_heap(_Begin, ++_Heap_end, _STD _Pass_fn(comp)); + } + } } #endif // _HAS_CXX23 && defined(__cpp_lib_concepts) template void emplace(_Valty&&... _Val) { c.emplace_back(_STD forward<_Valty>(_Val)...); - _STD push_heap(c.begin(), c.end(), comp); + _STD push_heap(c.begin(), c.end(), _STD _Pass_fn(comp)); } void pop() { - _STD pop_heap(c.begin(), c.end(), comp); + _STD pop_heap(c.begin(), c.end(), _STD _Pass_fn(comp)); c.pop_back(); } @@ -410,6 +422,11 @@ public: swap(comp, _Right.comp); // intentional ADL } +private: + void _Make_heap() { + _STD make_heap(c.begin(), c.end(), _STD _Pass_fn(comp)); + } + protected: _Container c{}; _Pr comp{}; diff --git a/stl/inc/random b/stl/inc/random index 54fa87dd853..ddf08e72236 100644 --- a/stl/inc/random +++ b/stl/inc/random @@ -26,9 +26,9 @@ _STL_DISABLE_CLANG_WARNINGS #ifdef _ALLOW_RANDOM_DISTRIBUTION_CONST_OPERATOR #define _DISTRIBUTION_CONST const -#else // ^^^ _ALLOW_RANDOM_DISTRIBUTION_CONST_OPERATOR / !_ALLOW_RANDOM_DISTRIBUTION_CONST_OPERATOR vvv +#else #define _DISTRIBUTION_CONST -#endif // _ALLOW_RANDOM_DISTRIBUTION_CONST_OPERATOR +#endif _STD_BEGIN #define _RNG_PROHIBIT_CHAR(_CheckedType) \ diff --git a/stl/inc/ranges b/stl/inc/ranges index 280c879dc9a..42dc779d63b 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -99,7 +99,7 @@ namespace ranges { move_constructible<_Ty> #else // ^^^ C++23 / C++20 vvv copy_constructible<_Ty> -#endif // C++20 +#endif // ^^^ C++20 ^^^ && _Destructible_object<_Ty>; template @@ -5720,7 +5720,7 @@ namespace ranges { typename tuple_element_t<_Index, _Tuple>; { _STD get<_Index>(__t) } -> convertible_to&>; }; -#endif // C++20 +#endif // ^^^ C++20 ^^^ template concept _Returnable_element = is_reference_v<_Tuple> || move_constructible>; @@ -9012,11 +9012,7 @@ namespace ranges { template struct _Invoke_result_with_repeated_type_impl<_Fn, _Ty, index_sequence<_Indices...>> { -#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-1761088 using type = invoke_result_t<_Fn, _Repeat_type<_Ty, _Indices>...>; -#else // ^^^ no workaround / workaround vvv - using type = decltype(_STD invoke(_STD declval<_Fn>(), _STD declval<_Repeat_type<_Ty, _Indices>>()...)); -#endif // ^^^ workaround ^^^ }; template @@ -10484,6 +10480,6 @@ _STD_END _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) #pragma pack(pop) -#endif // defined(__cpp_lib_ranges) +#endif // ^^^ defined(__cpp_lib_ranges) ^^^ #endif // _STL_COMPILER_PREPROCESSOR #endif // _RANGES_ diff --git a/stl/inc/regex b/stl/inc/regex index 4d893eee77b..b1bbda55544 100644 --- a/stl/inc/regex +++ b/stl/inc/regex @@ -35,23 +35,23 @@ _STL_DISABLE_CLANG_WARNINGS #ifndef _REGEX_MAX_COMPLEXITY_COUNT #define _REGEX_MAX_COMPLEXITY_COUNT 10000000L // set to 0 to disable -#endif // _REGEX_MAX_COMPLEXITY_COUNT +#endif // !defined(_REGEX_MAX_COMPLEXITY_COUNT) #ifndef _REGEX_MAX_STACK_COUNT #ifdef _WIN64 #define _REGEX_MAX_STACK_COUNT 600L // set to 0 to disable -#else // _WIN64 +#else // ^^^ defined(_WIN64) / !defined(_WIN64) vvv #define _REGEX_MAX_STACK_COUNT 1000L // set to 0 to disable -#endif // _WIN64 -#endif // _REGEX_MAX_STACK_COUNT +#endif // ^^^ !defined(_WIN64) ^^^ +#endif // !defined(_REGEX_MAX_STACK_COUNT) #ifndef _ENHANCED_REGEX_VISUALIZER #ifdef _DEBUG #define _ENHANCED_REGEX_VISUALIZER 1 -#else // _DEBUG +#else // ^^^ defined(_DEBUG) / !defined(_DEBUG) vvv #define _ENHANCED_REGEX_VISUALIZER 0 -#endif // _DEBUG -#endif // _ENHANCED_REGEX_VISUALIZER +#endif // ^^^ !defined(_DEBUG) ^^^ +#endif // !defined(_ENHANCED_REGEX_VISUALIZER) _STD_BEGIN @@ -761,7 +761,7 @@ template _NODISCARD bool operator>=(const sub_match<_BidIt>& _Left, const sub_match<_BidIt>& _Right) { return !(_Left < _Right); } -#endif // !_HAS_CXX20 +#endif // ^^^ !_HAS_CXX20 ^^^ _EXPORT_STD template _NODISCARD bool operator==(const sub_match<_BidIt>& _Left, const _Iter_value_t<_BidIt>* _Right) { @@ -828,7 +828,7 @@ template _NODISCARD bool operator>=(const sub_match<_BidIt>& _Left, const _Iter_value_t<_BidIt>* _Right) { return !(_Left < _Right); } -#endif // !_HAS_CXX20 +#endif // ^^^ !_HAS_CXX20 ^^^ _EXPORT_STD template _NODISCARD bool operator==(const sub_match<_BidIt>& _Left, const _Iter_value_t<_BidIt>& _Right) { @@ -895,7 +895,7 @@ template _NODISCARD bool operator>=(const sub_match<_BidIt>& _Left, const _Iter_value_t<_BidIt>& _Right) { return !(_Left < _Right); } -#endif // !_HAS_CXX20 +#endif // ^^^ !_HAS_CXX20 ^^^ _EXPORT_STD template _NODISCARD bool operator==( @@ -975,7 +975,7 @@ _NODISCARD bool operator>=( const sub_match<_BidIt>& _Left, const basic_string<_Iter_value_t<_BidIt>, _Traits, _Alloc>& _Right) { return !(_Left < _Right); } -#endif // !_HAS_CXX20 +#endif // ^^^ !_HAS_CXX20 ^^^ _EXPORT_STD template basic_ostream<_Elem, _Traits>& operator<<(basic_ostream<_Elem, _Traits>& _Ostr, const sub_match<_BidIt>& _Match) { diff --git a/stl/inc/semaphore b/stl/inc/semaphore index 9f1d11055cb..78e5649f427 100644 --- a/stl/inc/semaphore +++ b/stl/inc/semaphore @@ -52,7 +52,7 @@ _NODISCARD unsigned long _Semaphore_remaining_timeout(const chrono::time_point<_ return static_cast(_Rel_time.count()); } -inline constexpr ptrdiff_t _Semaphore_max = (1ULL << (sizeof(ptrdiff_t) * CHAR_BIT - 1)) - 1; +inline constexpr ptrdiff_t _Semaphore_max = PTRDIFF_MAX; _EXPORT_STD template class counting_semaphore { diff --git a/stl/inc/source_location b/stl/inc/source_location index 649f3443d76..e4e724d6526 100644 --- a/stl/inc/source_location +++ b/stl/inc/source_location @@ -65,6 +65,6 @@ _STD_END _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) #pragma pack(pop) -#endif // _HAS_CXX20 +#endif // ^^^ _HAS_CXX20 ^^^ #endif // _STL_COMPILER_PREPROCESSOR #endif // _SOURCE_LOCATION_ diff --git a/stl/inc/span b/stl/inc/span index 3f8cb1861c9..24980bdc5cd 100644 --- a/stl/inc/span +++ b/stl/inc/span @@ -598,7 +598,7 @@ public: return {_Mydata, _Mydata, _Mydata + _Mysize}; #else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 / _ITERATOR_DEBUG_LEVEL == 0 vvv return {_Mydata}; -#endif // _ITERATOR_DEBUG_LEVEL +#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ } _NODISCARD constexpr iterator end() const noexcept { @@ -607,7 +607,7 @@ public: return {_End, _Mydata, _End}; #else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 / _ITERATOR_DEBUG_LEVEL == 0 vvv return {_End}; -#endif // _ITERATOR_DEBUG_LEVEL +#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ } #if _HAS_CXX23 && defined(__cpp_lib_concepts) @@ -695,6 +695,6 @@ _STD_END _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) #pragma pack(pop) -#endif // _HAS_CXX20 +#endif // ^^^ _HAS_CXX20 ^^^ #endif // _STL_COMPILER_PREPROCESSOR #endif // _SPAN_ diff --git a/stl/inc/spanstream b/stl/inc/spanstream index 3c572019aee..20362eac70d 100644 --- a/stl/inc/spanstream +++ b/stl/inc/spanstream @@ -401,6 +401,6 @@ _STD_END _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) #pragma pack(pop) -#endif // _HAS_CXX23 +#endif // ^^^ _HAS_CXX23 ^^^ #endif // _STL_COMPILER_PREPROCESSOR #endif // _SPANSTREAM_ diff --git a/stl/inc/sstream b/stl/inc/sstream index 9a4aafa910a..2d38233b381 100644 --- a/stl/inc/sstream +++ b/stl/inc/sstream @@ -150,7 +150,7 @@ public: _NODISCARD _Mystr str() const& #else _NODISCARD _Mystr str() const -#endif // _HAS_CXX20 +#endif { _Mystr _Result(_Al); const auto _View = _Get_buffer_view(); @@ -620,7 +620,7 @@ public: _NODISCARD _Mystr str() const& #else _NODISCARD _Mystr str() const -#endif // _HAS_CXX20 +#endif { return _Stringbuffer.str(); } @@ -740,7 +740,7 @@ public: _NODISCARD _Mystr str() const& #else _NODISCARD _Mystr str() const -#endif // _HAS_CXX20 +#endif { return _Stringbuffer.str(); } @@ -866,7 +866,7 @@ public: _NODISCARD _Mystr str() const& #else _NODISCARD _Mystr str() const -#endif // _HAS_CXX20 +#endif { return _Stringbuffer.str(); } diff --git a/stl/inc/stack b/stl/inc/stack index 29c51ea484f..e311d6e72a8 100644 --- a/stl/inc/stack +++ b/stl/inc/stack @@ -125,9 +125,9 @@ public: decltype(auto) emplace(_Valty&&... _Val) { #if _HAS_CXX17 return c.emplace_back(_STD forward<_Valty>(_Val)...); -#else // ^^^ C++17 or newer / C++14 vvv +#else // ^^^ _HAS_CXX17 / !_HAS_CXX17 vvv c.emplace_back(_STD forward<_Valty>(_Val)...); -#endif // _HAS_CXX17 +#endif // ^^^ !_HAS_CXX17 ^^^ } void pop() noexcept(noexcept(c.pop_back())) /* strengthened */ { diff --git a/stl/inc/stop_token b/stl/inc/stop_token index a518805973d..cec4ddc5956 100644 --- a/stl/inc/stop_token +++ b/stl/inc/stop_token @@ -392,6 +392,6 @@ _STD_END _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) #pragma pack(pop) -#endif // _HAS_CXX20 +#endif // ^^^ _HAS_CXX20 ^^^ #endif // _STL_COMPILER_PREPROCESSOR #endif // _STOP_TOKEN_ diff --git a/stl/inc/string b/stl/inc/string index 284942baac3..feded5cb836 100644 --- a/stl/inc/string +++ b/stl/inc/string @@ -444,7 +444,7 @@ _NODISCARD _Elem* _UIntegral_to_buff(_Elem* _RNext, _UTy _UVal) { #ifdef _WIN64 auto _UVal_trunc = _UVal; -#else // ^^^ _WIN64 / !_WIN64 vvv +#else // ^^^ defined(_WIN64) / !defined(_WIN64) vvv constexpr bool _Big_uty = sizeof(_UTy) > 4; if constexpr (_Big_uty) { // For 64-bit numbers, work in chunks to avoid 64-bit divisions. @@ -460,7 +460,7 @@ _NODISCARD _Elem* _UIntegral_to_buff(_Elem* _RNext, _UTy _UVal) { } auto _UVal_trunc = static_cast(_UVal); -#endif // _WIN64 +#endif // ^^^ !defined(_WIN64) ^^^ do { *--_RNext = static_cast<_Elem>('0' + _UVal_trunc % 10); diff --git a/stl/inc/string_view b/stl/inc/string_view index d1fe409b425..f6fe952f223 100644 --- a/stl/inc/string_view +++ b/stl/inc/string_view @@ -12,6 +12,6 @@ _EMIT_STL_WARNING(STL4038, "The contents of are available only with C++17 or later."); #else // ^^^ !_HAS_CXX17 / _HAS_CXX17 vvv #include -#endif // _HAS_CXX17 +#endif // ^^^ _HAS_CXX17 ^^^ #endif // _STL_COMPILER_PREPROCESSOR #endif // _STRING_VIEW_ diff --git a/stl/inc/syncstream b/stl/inc/syncstream index 155e9e96481..8c76ac98d80 100644 --- a/stl/inc/syncstream +++ b/stl/inc/syncstream @@ -380,6 +380,6 @@ _STD_END _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) #pragma pack(pop) -#endif // _HAS_CXX20 +#endif // ^^^ _HAS_CXX20 ^^^ #endif // _STL_COMPILER_PREPROCESSOR #endif // _SYNCSTREAM_ diff --git a/stl/inc/system_error b/stl/inc/system_error index 096447c7c10..dbd47b05a82 100644 --- a/stl/inc/system_error +++ b/stl/inc/system_error @@ -15,7 +15,7 @@ #include #ifndef _M_CEE_PURE #include -#endif // _M_CEE_PURE +#endif // !defined(_M_CEE_PURE) #if _HAS_CXX20 #include @@ -410,7 +410,7 @@ _NODISCARD inline bool operator!=(const error_condition& _Left, const error_cond return !(_Left == _Right); } #endif // !_HAS_CXX20 -#endif // _STL_OPTIMIZE_SYSTEM_ERROR_OPERATORS +#endif // ^^^ !_STL_OPTIMIZE_SYSTEM_ERROR_OPERATORS ^^^ _NODISCARD inline error_condition error_category::default_error_condition(int _Errval) const noexcept { // make error_condition for error code diff --git a/stl/inc/thread b/stl/inc/thread index 0b66acf2964..0d9e5a582bb 100644 --- a/stl/inc/thread +++ b/stl/inc/thread @@ -231,7 +231,7 @@ private: friend strong_ordering operator<=>(thread::id _Left, thread::id _Right) noexcept; #else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv friend bool operator<(thread::id _Left, thread::id _Right) noexcept; -#endif // !_HAS_CXX20 +#endif // ^^^ !_HAS_CXX20 ^^^ template friend basic_ostream<_Ch, _Tr>& operator<<(basic_ostream<_Ch, _Tr>& _Str, thread::id _Id); friend hash; @@ -277,7 +277,7 @@ _NODISCARD inline bool operator>(thread::id _Left, thread::id _Right) noexcept { _NODISCARD inline bool operator>=(thread::id _Left, thread::id _Right) noexcept { return !(_Left < _Right); } -#endif // !_HAS_CXX20 +#endif // ^^^ !_HAS_CXX20 ^^^ _EXPORT_STD template basic_ostream<_Ch, _Tr>& operator<<(basic_ostream<_Ch, _Tr>& _Str, thread::id _Id) { diff --git a/stl/inc/tuple b/stl/inc/tuple index 021c6b057a4..217c4d70308 100644 --- a/stl/inc/tuple +++ b/stl/inc/tuple @@ -1044,7 +1044,7 @@ struct _Tuple_cat2<_Ty, index_sequence<_Kx...>, index_sequence<_Ix...>, _Ix_next template <_Tuple_like... _Tuples> #else // ^^^ C++23 / C++20 vvv template -#endif // C++20 +#endif // ^^^ C++20 ^^^ using _Tuple_cat1 = _Tuple_cat2, index_sequence<>, index_sequence<>, 0, make_index_sequence>>...>; @@ -1057,7 +1057,7 @@ constexpr _Ret _Tuple_cat(index_sequence<_Kx...>, index_sequence<_Ix...>, _Ty _A _EXPORT_STD template <_Tuple_like... _Tuples> #else // ^^^ C++23 / C++20 vvv _EXPORT_STD template -#endif // C++20 +#endif // ^^^ C++20 ^^^ _NODISCARD constexpr typename _Tuple_cat1<_Tuples...>::_Ret tuple_cat(_Tuples&&... _Tpls) { // concatenate tuples using _Cat1 = _Tuple_cat1<_Tuples...>; using _Ret = typename _Cat1::_Ret; @@ -1071,7 +1071,7 @@ _NODISCARD constexpr typename _Tuple_cat1<_Tuples...>::_Ret tuple_cat(_Tuples&&. template #else // ^^^ C++23 / C++20 vvv template -#endif // C++20 +#endif // ^^^ C++20 ^^^ constexpr decltype(auto) _Apply_impl(_Callable&& _Obj, _Tuple&& _Tpl, index_sequence<_Indices...>) noexcept( noexcept(_STD invoke(_STD forward<_Callable>(_Obj), _STD get<_Indices>(_STD forward<_Tuple>(_Tpl))...))) { return _STD invoke(_STD forward<_Callable>(_Obj), _STD get<_Indices>(_STD forward<_Tuple>(_Tpl))...); @@ -1081,7 +1081,7 @@ constexpr decltype(auto) _Apply_impl(_Callable&& _Obj, _Tuple&& _Tpl, index_sequ _EXPORT_STD template #else // ^^^ C++23 / C++20 vvv _EXPORT_STD template -#endif // C++20 +#endif // ^^^ C++20 ^^^ constexpr decltype(auto) apply(_Callable&& _Obj, _Tuple&& _Tpl) noexcept( noexcept(_Apply_impl(_STD forward<_Callable>(_Obj), _STD forward<_Tuple>(_Tpl), make_index_sequence>>{}))) { @@ -1093,7 +1093,7 @@ constexpr decltype(auto) apply(_Callable&& _Obj, _Tuple&& _Tpl) noexcept( template #else // ^^^ C++23 / C++20 vvv template -#endif // C++20 +#endif // ^^^ C++20 ^^^ constexpr _Ty _Make_from_tuple_impl(_Tuple&& _Tpl, index_sequence<_Indices...>) noexcept( is_nothrow_constructible_v<_Ty, decltype(_STD get<_Indices>(_STD forward<_Tuple>(_Tpl)))...>) { // construct _Ty from the elements of _Tpl @@ -1106,7 +1106,7 @@ constexpr _Ty _Make_from_tuple_impl(_Tuple&& _Tpl, index_sequence<_Indices...>) _EXPORT_STD template #else // ^^^ C++23 / C++20 vvv _EXPORT_STD template -#endif // C++20 +#endif // ^^^ C++20 ^^^ _NODISCARD constexpr _Ty make_from_tuple(_Tuple&& _Tpl) noexcept(noexcept(_Make_from_tuple_impl<_Ty>( _STD forward<_Tuple>(_Tpl), make_index_sequence>>{}))) /* strengthened */ { // construct _Ty from the elements of _Tpl diff --git a/stl/inc/type_traits b/stl/inc/type_traits index 42842466e92..9da0dee5a6e 100644 --- a/stl/inc/type_traits +++ b/stl/inc/type_traits @@ -377,31 +377,29 @@ _INLINE_VAR constexpr bool is_compound_v = !is_fundamental_v<_Ty>; #ifdef _M_CEE #define _EMIT_CLRCALL(FUNC, OPT1, OPT2, OPT3) FUNC(__clrcall, OPT1, OPT2, OPT3) -#else // ^^^ defined(_M_CEE) / !defined(_M_CEE) vvv +#else // ^^^ __clrcall supported / __clrcall not supported vvv #define _EMIT_CLRCALL(FUNC, OPT1, OPT2, OPT3) -#endif // ^^^ !defined(_M_CEE) ^^^ +#endif // ^^^ __clrcall not supported ^^^ #if defined(_M_IX86) && !defined(_M_CEE) #define _EMIT_FASTCALL(FUNC, OPT1, OPT2, OPT3) FUNC(__fastcall, OPT1, OPT2, OPT3) - -#else // defined(_M_IX86) && !defined(_M_CEE) +#else // ^^^ __fastcall supported / __fastcall not supported vvv #define _EMIT_FASTCALL(FUNC, OPT1, OPT2, OPT3) -#endif // defined(_M_IX86) && !defined(_M_CEE) +#endif // ^^^ __fastcall not supported ^^^ #ifdef _M_IX86 #define _EMIT_STDCALL(FUNC, OPT1, OPT2, OPT3) FUNC(__stdcall, OPT1, OPT2, OPT3) #define _EMIT_THISCALL(FUNC, OPT1, OPT2, OPT3) FUNC(__thiscall, OPT1, OPT2, OPT3) -#else // ^^^ defined(_M_IX86) / !defined(_M_IX86) vvv +#else // ^^^ __stdcall and __thiscall supported / __stdcall and __thiscall not supported vvv #define _EMIT_STDCALL(FUNC, OPT1, OPT2, OPT3) #define _EMIT_THISCALL(FUNC, OPT1, OPT2, OPT3) -#endif // ^^^ !defined(_M_IX86) ^^^ +#endif // ^^^ __stdcall and __thiscall not supported ^^^ #if ((defined(_M_IX86) && _M_IX86_FP >= 2) || defined(_M_X64)) && !defined(_M_CEE) #define _EMIT_VECTORCALL(FUNC, OPT1, OPT2, OPT3) FUNC(__vectorcall, OPT1, OPT2, OPT3) - -#else // defined(_M_IX86) && _M_IX86_FP >= 2 etc. +#else // ^^^ __vectorcall supported / __vectorcall not supported vvv #define _EMIT_VECTORCALL(FUNC, OPT1, OPT2, OPT3) -#endif // defined(_M_IX86) && _M_IX86_FP >= 2 etc. +#endif // ^^^ __vectorcall not supported ^^^ #define _NON_MEMBER_CALL(FUNC, CV_OPT, REF_OPT, NOEXCEPT_OPT) \ _EMIT_CDECL(FUNC, CV_OPT, REF_OPT, NOEXCEPT_OPT) \ @@ -803,7 +801,7 @@ struct _Is_assignable_no_precondition_check : bool_constant<__is_assignable_no_p #else // ^^^ Use intrinsic / intrinsic not supported vvv template using _Is_assignable_no_precondition_check = is_assignable<_To, _From>; -#endif // defined(_IS_ASSIGNABLE_NOCHECK_SUPPORTED) && !defined(__CUDACC__) +#endif // ^^^ intrinsic not supported ^^^ _EXPORT_STD template struct is_copy_assignable @@ -830,7 +828,7 @@ using _Is_copy_assignable_no_precondition_check = is_copy_assignable<_Ty>; template _INLINE_VAR constexpr bool _Is_copy_assignable_unchecked_v = is_copy_assignable_v<_Ty>; -#endif // defined(_IS_ASSIGNABLE_NOCHECK_SUPPORTED) && !defined(__CUDACC__) +#endif // ^^^ intrinsic not supported ^^^ _EXPORT_STD template struct is_move_assignable : bool_constant<__is_assignable(add_lvalue_reference_t<_Ty>, _Ty)> { @@ -854,7 +852,7 @@ using _Is_move_assignable_no_precondition_check = is_move_assignable<_Ty>; template _INLINE_VAR constexpr bool _Is_move_assignable_unchecked_v = is_move_assignable_v<_Ty>; -#endif // defined(_IS_ASSIGNABLE_NOCHECK_SUPPORTED) && !defined(__CUDACC__) +#endif // ^^^ intrinsic not supported ^^^ _EXPORT_STD template struct is_destructible : bool_constant<__is_destructible(_Ty)> { @@ -1164,7 +1162,7 @@ struct _Aligned<_Len, _Align, double, false> { struct type { alignas(_Align) char _Space[_Len]; }; -#else // ^^^ _ENABLE_EXTENDED_ALIGNED_STORAGE / !_ENABLE_EXTENDED_ALIGNED_STORAGE vvv +#else // ^^^ defined(_ENABLE_EXTENDED_ALIGNED_STORAGE) / !defined(_ENABLE_EXTENDED_ALIGNED_STORAGE) vvv #ifndef _DISABLE_EXTENDED_ALIGNED_STORAGE static_assert(_Always_false<_Aligned>, "You've instantiated std::aligned_storage with an extended alignment (in other " @@ -1175,9 +1173,9 @@ struct _Aligned<_Len, _Align, double, false> { "To suppress this error, please define either " "(1) _ENABLE_EXTENDED_ALIGNED_STORAGE to confirm that you want a type with an extended alignment, or " "(2) _DISABLE_EXTENDED_ALIGNED_STORAGE to get the old non-conforming behavior."); -#endif // !_DISABLE_EXTENDED_ALIGNED_STORAGE +#endif // ^^^ !defined(_DISABLE_EXTENDED_ALIGNED_STORAGE) ^^^ using type = _Align_type; -#endif // _ENABLE_EXTENDED_ALIGNED_STORAGE +#endif // ^^^ !defined(_ENABLE_EXTENDED_ALIGNED_STORAGE) ^^^ }; template @@ -1323,10 +1321,10 @@ struct _Const_lvalue_cond_oper<_Ty1, _Ty2, void_t<_Conditional_type struct _Decayed_cond_oper : _Const_lvalue_cond_oper<_Ty1, _Ty2> {}; -#else // ^^^ >= C++20 / <= C++17 vvv +#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv template struct _Decayed_cond_oper {}; -#endif // _HAS_CXX20 +#endif // ^^^ !_HAS_CXX20 ^^^ template struct _Decayed_cond_oper<_Ty1, _Ty2, void_t<_Conditional_type<_Ty1, _Ty2>>> { @@ -2126,7 +2124,7 @@ struct _Is_nothrow_swappable; _EXPORT_STD template && is_move_assignable_v<_Ty>, int> = 0> #else // ^^^ _HAS_CXX17 / !_HAS_CXX17 vvv template -#endif // _HAS_CXX17 +#endif // ^^^ !_HAS_CXX17 ^^^ _CONSTEXPR20 void swap(_Ty&, _Ty&) noexcept(is_nothrow_move_constructible_v<_Ty>&& is_nothrow_move_assignable_v<_Ty>); _EXPORT_STD template ::value, int> = 0> diff --git a/stl/inc/typeinfo b/stl/inc/typeinfo index 1d761bdeeb2..20c07d5863f 100644 --- a/stl/inc/typeinfo +++ b/stl/inc/typeinfo @@ -61,7 +61,7 @@ class __non_rtti_object : public bad_typeid { // report a non-RTTI object public: __non_rtti_object(const char* _Message) : bad_typeid(_Message) {} }; -#endif // !_HAS_EXCEPTIONS +#endif // ^^^ !_HAS_EXCEPTIONS ^^^ [[noreturn]] inline void _Throw_bad_cast() { _THROW(bad_cast{}); diff --git a/stl/inc/use_ansi.h b/stl/inc/use_ansi.h index 20fa0edad44..573d73df1af 100644 --- a/stl/inc/use_ansi.h +++ b/stl/inc/use_ansi.h @@ -24,23 +24,22 @@ #ifdef _DEBUG #define _DEBUG_AFFIX "d" #define _IDL_DEFAULT 2 -#else +#else // ^^^ defined(_DEBUG) / !defined(_DEBUG) vvv #define _DEBUG_AFFIX "" #define _IDL_DEFAULT 0 -#endif +#endif // ^^^ !defined(_DEBUG) ^^^ #if defined(_DLL) && !defined(_STATIC_CPPLIB) #define _LIB_STEM "msvcprt" -#else +#else // ^^^ defined(_DLL) && !defined(_STATIC_CPPLIB) / !defined(_DLL) || defined(_STATIC_CPPLIB) vvv #define _LIB_STEM "libcpmt" #if _ITERATOR_DEBUG_LEVEL != _IDL_DEFAULT #define _IDL_AFFIX _STRINGIZE(_ITERATOR_DEBUG_LEVEL) -#endif -#endif +#endif // _ITERATOR_DEBUG_LEVEL != _IDL_DEFAULT +#endif // ^^^ !defined(_DLL) || defined(_STATIC_CPPLIB) ^^^ -#ifdef _IDL_AFFIX -#else +#ifndef _IDL_AFFIX #define _IDL_AFFIX "" #endif @@ -51,8 +50,8 @@ #undef _IDL_DEFAULT #undef _LIB_STEM -#endif // _M_CEE_PURE +#endif // !defined(_M_CEE_PURE) -#endif // _CRT_NOPRAGMA_LIBS +#endif // !defined(_CRT_NOPRAGMA_LIBS) #endif // _USE_ANSI_CPP diff --git a/stl/inc/utility b/stl/inc/utility index d3c1f405eee..520ec24b4d4 100644 --- a/stl/inc/utility +++ b/stl/inc/utility @@ -123,7 +123,7 @@ _CONSTEXPR20 void swap(_Ty (&_Left)[_Size], _Ty (&_Right)[_Size]) noexcept(_Is_n _EXPORT_STD template && is_move_assignable_v<_Ty>, int> /* = 0 */> #else // ^^^ _HAS_CXX17 / !_HAS_CXX17 vvv template -#endif // _HAS_CXX17 +#endif // ^^^ !_HAS_CXX17 ^^^ _CONSTEXPR20 void swap(_Ty& _Left, _Ty& _Right) noexcept( is_nothrow_move_constructible_v<_Ty>&& is_nothrow_move_assignable_v<_Ty>) { _Ty _Tmp = _STD move(_Left); diff --git a/stl/inc/variant b/stl/inc/variant index b1da693c42d..051de655b7e 100644 --- a/stl/inc/variant +++ b/stl/inc/variant @@ -1679,7 +1679,7 @@ _NODISCARD constexpr bool operator<=(monostate, monostate) noexcept { _NODISCARD constexpr bool operator>=(monostate, monostate) noexcept { return true; } -#endif // !_HAS_CXX20 +#endif // ^^^ !_HAS_CXX20 ^^^ _EXPORT_STD template ..., is_swappable<_Types>...>, int> = 0> @@ -1732,6 +1732,6 @@ _STD_END _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) #pragma pack(pop) -#endif // _HAS_CXX17 +#endif // ^^^ _HAS_CXX17 ^^^ #endif // _STL_COMPILER_PREPROCESSOR #endif // _VARIANT_ diff --git a/stl/inc/vector b/stl/inc/vector index 8286166d3d2..95ef86aae3b 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -117,7 +117,7 @@ public: if (_Off > 0) { _STL_VERIFY(_Off <= _Mycont->_Mylast - _Ptr, "cannot seek vector iterator after end"); } -#endif // _ITERATOR_DEBUG_LEVEL == 0 +#endif // ^^^ _ITERATOR_DEBUG_LEVEL != 0 ^^^ } _CONSTEXPR20 _Vector_const_iterator& operator+=(const difference_type _Off) noexcept { @@ -188,7 +188,7 @@ public: _NODISCARD bool operator>=(const _Vector_const_iterator& _Right) const noexcept { return !(*this < _Right); } -#endif // !_HAS_CXX20 +#endif // ^^^ !_HAS_CXX20 ^^^ _CONSTEXPR20 void _Compat(const _Vector_const_iterator& _Right) const noexcept { // test for compatible iterator pair @@ -196,7 +196,7 @@ public: (void) _Right; #else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 / _ITERATOR_DEBUG_LEVEL != 0 vvv _STL_VERIFY(this->_Getcont() == _Right._Getcont(), "vector iterators incompatible"); -#endif // _ITERATOR_DEBUG_LEVEL == 0 +#endif // ^^^ _ITERATOR_DEBUG_LEVEL != 0 ^^^ } #if _ITERATOR_DEBUG_LEVEL != 0 @@ -594,7 +594,7 @@ private: #define _ASAN_VECTOR_CREATE_GUARD #define _ASAN_VECTOR_EXTEND_GUARD(n) #define _ASAN_VECTOR_RELEASE_GUARD -#endif // !_INSERT_VECTOR_ANNOTATION +#endif // ^^^ !_INSERT_VECTOR_ANNOTATION ^^^ using _Scary_val = _Vector_val, _Simple_types<_Ty>, _Vec_iter_types<_Ty, size_type, difference_type, pointer, const_pointer>>>; @@ -864,7 +864,7 @@ public: return _Result; #else // ^^^ _HAS_CXX17 / !_HAS_CXX17 vvv (void) _Result; -#endif // _HAS_CXX17 +#endif // ^^^ !_HAS_CXX17 ^^^ } _CONSTEXPR20 void push_back(const _Ty& _Val) { // insert element at end, provide strong guarantee @@ -2183,7 +2183,7 @@ private: } #else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 / _ITERATOR_DEBUG_LEVEL != 2 vvv _CONSTEXPR20 void _Orphan_range(pointer, pointer) const {} -#endif // _ITERATOR_DEBUG_LEVEL != 2 +#endif // ^^^ _ITERATOR_DEBUG_LEVEL != 2 ^^^ _NODISCARD _CONSTEXPR20 _Alty& _Getal() noexcept { return _Mypair._Get_first(); @@ -2636,7 +2636,7 @@ public: _NODISCARD bool operator>=(const _Vb_const_iterator& _Right) const noexcept { return !(*this < _Right); } -#endif // !_HAS_CXX20 +#endif // ^^^ !_HAS_CXX20 ^^^ _CONSTEXPR20 void _Compat(const _Vb_const_iterator& _Right) const noexcept { // test for compatible iterator pair @@ -2983,7 +2983,7 @@ public: this->_Mysize = _STD exchange(_Right._Mysize, size_type{0}); this->_Swap_proxy_and_iterators(_Right); -#endif // _ITERATOR_DEBUG_LEVEL == 0 +#endif // ^^^ _ITERATOR_DEBUG_LEVEL != 0 ^^^ return *this; } @@ -3050,7 +3050,7 @@ public: this->_Myvec = _Right._Myvec; this->_Mysize = _Right._Mysize; -#endif // _ITERATOR_DEBUG_LEVEL == 0 +#endif // ^^^ _ITERATOR_DEBUG_LEVEL != 0 ^^^ return *this; } @@ -3730,6 +3730,173 @@ _NODISCARD _CONSTEXPR20 _Iter_diff_t<_VbIt> _Count_vbool(_VbIt _First, const _Vb }); } +template +_CONSTEXPR20 _OutIt _Copy_vbool(_VbIt _First, _VbIt _Last, _OutIt _Dest) { + // copy [_First, _Last) to [_Dest, ...) + if (_First == _Last) { + return _Dest; + } + + auto _VbFirst = _First._Myptr; + const auto _VbLast = _Last._Myptr; + auto _VbDest = const_cast<_Vbase*>(_Dest._Myptr); + const auto _DestEnd = _Dest + (_Last - _First); + + const auto _FirstSourceMask = static_cast<_Vbase>(-1) << _First._Myoff; + const auto _FirstDestMask = _Dest._Myoff == 0 ? 0 : (static_cast<_Vbase>(-1) >> (_VBITS - _Dest._Myoff)); + const auto _LastSourceMask = static_cast<_Vbase>(-1) >> (_VBITS - _Last._Myoff); + const auto _LastDestMask = static_cast<_Vbase>(-1) << _DestEnd._Myoff; + + const bool _IsSingleBlockSource = _VbFirst == _VbLast; + const bool _IsSingleBlockDest = _VbDest == _DestEnd._Myptr; + const bool _IsRightShift = _Dest._Myoff < _First._Myoff; + if (_IsSingleBlockSource) { + // We already excluded _First == _Last, so here _Last._Myoff > 0 and the shift is safe + const auto _SourceMask = _FirstSourceMask & _LastSourceMask; + const auto _SourceShift = _IsRightShift ? _First._Myoff - _Dest._Myoff : _Dest._Myoff - _First._Myoff; + const auto _SourceVal = _IsRightShift ? (*_VbFirst & _SourceMask) >> _SourceShift // + : (*_VbFirst & _SourceMask) << _SourceShift; + if (_IsSingleBlockDest) { + const auto _DestMask = _FirstDestMask | _LastDestMask; + *_VbDest = (*_VbDest & _DestMask) | _SourceVal; + } else { + *_VbDest = (*_VbDest & _FirstDestMask) | _SourceVal; + ++_VbDest; + + const auto _LastShift = _Last._Myoff - _DestEnd._Myoff; + const auto _LastSourceVal = (*_VbFirst & _SourceMask) >> _LastShift; + *_VbDest = (*_VbDest & _LastDestMask) | _LastSourceVal; + } + + return _DestEnd; + } else if (_IsSingleBlockDest) { + const auto _SourceShift = _IsRightShift ? _First._Myoff - _Dest._Myoff : _Dest._Myoff - _First._Myoff; + const auto _SourceVal = _IsRightShift ? (*_VbFirst & _FirstSourceMask) >> _SourceShift // + : (*_VbFirst & _FirstSourceMask) << _SourceShift; + + const auto _DestMask = _FirstDestMask | _LastDestMask; + if (_Last._Myoff != 0) { + const auto _LastShift = _DestEnd._Myoff - _Last._Myoff; + const auto _LastSourceVal = (*_VbLast & _LastSourceMask) << _LastShift; + *_VbDest = (*_VbDest & _DestMask) | _SourceVal | _LastSourceVal; + } else { + *_VbDest = (*_VbDest & _DestMask) | _SourceVal; + } + + return _DestEnd; + } + +#if _HAS_CXX20 + if (!_STD is_constant_evaluated()) +#endif + { + // If _First and _Dest have matching char alignment, use memmove + const auto _UnalignedFirstBits = _First._Myoff & _Vbase{7}; + const auto _UnalignedDestBits = _Dest._Myoff & _Vbase{7}; + if (_UnalignedFirstBits == _UnalignedDestBits) { + const auto _UnalignedLastBits = _Last._Myoff & _Vbase{7}; + + auto _VbFirst_ch = reinterpret_cast(_VbFirst) + (_First._Myoff - _UnalignedFirstBits) / 8; + const auto _VbLast_ch = reinterpret_cast(_VbLast) + (_Last._Myoff - _UnalignedLastBits) / 8; + auto _VbDest_ch = reinterpret_cast(_VbDest) + (_Dest._Myoff - _UnalignedDestBits) / 8; + + // Copy bits until the next char alignment + if (_UnalignedFirstBits != 0) { + const auto _SourceBitMask = static_cast(UCHAR_MAX << _UnalignedFirstBits); + const auto _DestBitMask = static_cast(UCHAR_MAX >> (8 - _UnalignedFirstBits)); + *_VbDest_ch = (*_VbDest_ch & _DestBitMask) | (*_VbFirst_ch & _SourceBitMask); + ++_VbFirst_ch; + ++_VbDest_ch; + } + + _VbDest_ch = _Copy_unchecked(_VbFirst_ch, _VbLast_ch, _VbDest_ch); + + // Copy remaining last bits + if (_UnalignedLastBits != 0) { + const auto _SourceBitMask = static_cast(UCHAR_MAX >> (8 - _UnalignedLastBits)); + const auto _DestBitMask = static_cast(UCHAR_MAX << _UnalignedLastBits); + *_VbDest_ch = (*_VbDest_ch & _DestBitMask) | (*_VbLast_ch & _SourceBitMask); + } + + return _DestEnd; + } + } + + // Unaligned _VbFirst and _VbLast require a two step copy with carry + if (_IsRightShift) { + const auto _SourceShift = _First._Myoff - _Dest._Myoff; + const auto _CarryShift = _VBITS - _SourceShift; + const auto _CarryMask = static_cast<_Vbase>(-1) >> _SourceShift; + const auto _DestMask = ~_CarryMask; + + const auto _FirstSourceVal = (*_VbFirst & _FirstSourceMask) >> _SourceShift; + *_VbDest = (*_VbDest & _FirstDestMask) | _FirstSourceVal; + + ++_VbFirst; + for (; _VbFirst != _VbLast; ++_VbFirst) { + const auto _CarryVal = *_VbFirst << _CarryShift; + *_VbDest = (*_VbDest & _CarryMask) | _CarryVal; + + ++_VbDest; + const auto _SourceVal = *_VbFirst >> _SourceShift; + *_VbDest = (*_VbDest & _DestMask) | _SourceVal; + } + + const auto _CarryVal = (*_VbFirst & _LastSourceMask) << _CarryShift; + if (_Last._Myoff >= _SourceShift) { + *_VbDest = (*_VbDest & _CarryMask) | _CarryVal; + + // We have more bits remaining than the final block has left + if (_Last._Myoff != _SourceShift) { + ++_VbDest; + const auto _SourceVal = (*_VbFirst & _LastSourceMask) >> _SourceShift; + *_VbDest = (*_VbDest & _LastDestMask) | _SourceVal; + } + } else if (_Last._Myoff != 0) { + // There are not enough bits to fill the final block so we need to mask both ends + const auto _FinalMask = _CarryMask | _LastDestMask; + *_VbDest = (*_VbDest & _FinalMask) | _CarryVal; + } + } else { + const auto _SourceShift = _Dest._Myoff - _First._Myoff; + const auto _CarryShift = _VBITS - _SourceShift; + + const auto _FirstSourceVal = (*_VbFirst & _FirstSourceMask) << _SourceShift; + *_VbDest = (*_VbDest & _FirstDestMask) | _FirstSourceVal; + auto _CarryVal = *_VbFirst >> _CarryShift; + + ++_VbFirst; + ++_VbDest; + for (; _VbFirst != _VbLast; ++_VbFirst, ++_VbDest) { + const auto _SourceVal = *_VbFirst << _SourceShift; + *_VbDest = _CarryVal | _SourceVal; + _CarryVal = *_VbFirst >> _CarryShift; + } + + if (_Last._Myoff >= _CarryShift) { + const auto _SourceVal = *_VbFirst << _SourceShift; + *_VbDest = _CarryVal | _SourceVal; + _CarryVal = *_VbFirst >> _CarryShift; + + // We have more bits remaining than the final block has left + if (_Last._Myoff != _CarryShift) { + ++_VbDest; + const auto _LastCarryMask = ~_LastDestMask; + *_VbDest = (*_VbDest & _LastDestMask) | (_CarryVal & _LastCarryMask); + } + } else if (_Last._Myoff != 0) { + // There are not enough bits to fill the final block so we need to mask both ends + const auto _LastSourceVal = (*_VbFirst & _LastSourceMask) << _SourceShift; + *_VbDest = (*_VbDest & _LastDestMask) | _CarryVal | _LastSourceVal; + } else { + // No new bits, just copy the carry + *_VbDest = (*_VbDest & _LastDestMask) | _CarryVal; + } + } + + return _DestEnd; +} + #undef _ASAN_VECTOR_MODIFY #undef _ASAN_VECTOR_REMOVE #undef _ASAN_VECTOR_CREATE diff --git a/stl/inc/xbit_ops.h b/stl/inc/xbit_ops.h index e899114f78f..f80c8214f38 100644 --- a/stl/inc/xbit_ops.h +++ b/stl/inc/xbit_ops.h @@ -30,7 +30,7 @@ _NODISCARD inline unsigned long _Floor_of_log_2(size_t _Value) noexcept { // ret _Result = 63; #else // ^^^ 64-bit / 32-bit vvv _Result = 31; -#endif // 64 vs. 32-bit +#endif // ^^^ 32-bit ^^^ while ((size_t{1} << _Result) > _Value) { --_Result; @@ -41,7 +41,7 @@ _NODISCARD inline unsigned long _Floor_of_log_2(size_t _Value) noexcept { // ret _BitScanReverse64(&_Result, _Value); // lgtm [cpp/conditionallyuninitializedvariable] #else // ^^^ 64-bit / 32-bit vvv _BitScanReverse(&_Result, _Value); // lgtm [cpp/conditionallyuninitializedvariable] -#endif // 64 vs. 32-bit +#endif // ^^^ 32-bit ^^^ #endif // ^^^ !defined(_M_CEE_PURE) ^^^ return _Result; diff --git a/stl/inc/xhash b/stl/inc/xhash index 3b7cf67778b..1e07e3ffdf1 100644 --- a/stl/inc/xhash +++ b/stl/inc/xhash @@ -1017,7 +1017,7 @@ private: _Mylist& _List; const _Nodeptr _Predecessor; _Nodeptr _Next; -#endif +#endif // ^^^ _ITERATOR_DEBUG_LEVEL != 2 ^^^ }; _Nodeptr _Unchecked_erase(_Nodeptr _First, const _Nodeptr _Last) noexcept(_Nothrow_hash<_Traits, key_type>) { diff --git a/stl/inc/xlocinfo b/stl/inc/xlocinfo index 54e55501126..e1d8a3b1b4c 100644 --- a/stl/inc/xlocinfo +++ b/stl/inc/xlocinfo @@ -227,7 +227,7 @@ public: __CLR_OR_THIS_CALL _Locinfo(const char* _Pch = "C") #ifndef _M_CEE_PURE : _Lock(_LOCK_LOCALE) -#endif // _M_CEE_PURE +#endif // !defined(_M_CEE_PURE) { if (_Pch) { _Locinfo_ctor(this, _Pch); @@ -240,7 +240,7 @@ public: __CLR_OR_THIS_CALL _Locinfo(int _Cat, const char* _Pch) #ifndef _M_CEE_PURE : _Lock(_LOCK_LOCALE) -#endif // _M_CEE_PURE +#endif // !defined(_M_CEE_PURE) { if (_Pch) { _Locinfo_ctor(this, _Cat, _Pch); diff --git a/stl/inc/xlocnum b/stl/inc/xlocnum index 86c19b22c9c..30e53bdcbcb 100644 --- a/stl/inc/xlocnum +++ b/stl/inc/xlocnum @@ -614,7 +614,9 @@ protected: virtual _InIt __CLR_OR_THIS_CALL do_get(_InIt _First, _InIt _Last, ios_base& _Iosbase, ios_base::iostate& _State, long double& _Val) const { // get long double from [_First, _Last) into _Val - static_assert(sizeof(double) == sizeof(long double), "Bad assumption: sizeof(double) == sizeof(long double)."); + // Assumes sizeof(double) == sizeof(long double). + // For 80-bit long double (which is not supported by MSVC in general), this will compile + // but will not attempt to handle the increased precision at runtime. double _Result; _First = num_get::do_get(_First, _Last, _Iosbase, _State, _Result); // avoid virtual call for perf _Val = _Result; diff --git a/stl/inc/xmemory b/stl/inc/xmemory index a612d99d103..16525adce1f 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -1261,7 +1261,7 @@ public: } #else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 / _ITERATOR_DEBUG_LEVEL != 2 vvv _Myproxy = _Right._Myproxy; -#endif // _ITERATOR_DEBUG_LEVEL != 2 +#endif // ^^^ _ITERATOR_DEBUG_LEVEL != 2 ^^^ return *this; } @@ -1295,7 +1295,7 @@ public: _Myproxy = nullptr; } } -#endif // _ITERATOR_DEBUG_LEVEL != 2 +#endif // ^^^ _ITERATOR_DEBUG_LEVEL != 2 ^^^ _CONSTEXPR20 const _Container_base12* _Getcont() const noexcept { return _Myproxy ? _Myproxy->_Mycont : nullptr; @@ -1420,7 +1420,7 @@ _CONSTEXPR20 void _Container_base12::_Swap_proxy_and_iterators(_Container_base12 } #else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 / _ITERATOR_DEBUG_LEVEL != 2 vvv _Swap_proxy_and_iterators_unlocked(_Right); -#endif // _ITERATOR_DEBUG_LEVEL != 2 +#endif // ^^^ _ITERATOR_DEBUG_LEVEL != 2 ^^^ } #if _ITERATOR_DEBUG_LEVEL == 0 diff --git a/stl/inc/xpolymorphic_allocator.h b/stl/inc/xpolymorphic_allocator.h index 334cd44aaab..d6b34b3d146 100644 --- a/stl/inc/xpolymorphic_allocator.h +++ b/stl/inc/xpolymorphic_allocator.h @@ -195,9 +195,9 @@ namespace pmr { #if _HAS_CXX20 && defined(__cpp_lib_byte) _EXPORT_STD template -#else +#else // ^^^ _HAS_CXX20 && defined(__cpp_lib_byte) / !_HAS_CXX20 || !defined(__cpp_lib_byte) vvv _EXPORT_STD template -#endif // _HAS_CXX20 && defined(__cpp_lib_byte) +#endif // ^^^ !_HAS_CXX20 || !defined(__cpp_lib_byte) ^^^ class polymorphic_allocator { public: template diff --git a/stl/inc/xstring b/stl/inc/xstring index ae566f24af1..8b7fc948540 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -918,7 +918,7 @@ private: : _Mydata(_Data), _Mysize(_Size), _Myoff(_Off) {} #else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 / _ITERATOR_DEBUG_LEVEL == 0 vvv constexpr explicit _String_view_iterator(const pointer _Ptr) noexcept : _Myptr(_Ptr) {} -#endif // _ITERATOR_DEBUG_LEVEL +#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ public: _NODISCARD constexpr reference operator*() const noexcept { @@ -928,7 +928,7 @@ public: return _Mydata[_Myoff]; #else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 / _ITERATOR_DEBUG_LEVEL == 0 vvv return *_Myptr; -#endif // _ITERATOR_DEBUG_LEVEL +#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ } _NODISCARD constexpr pointer operator->() const noexcept { @@ -938,7 +938,7 @@ public: return _Mydata + _Myoff; #else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 / _ITERATOR_DEBUG_LEVEL == 0 vvv return _Myptr; -#endif // _ITERATOR_DEBUG_LEVEL +#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ } constexpr _String_view_iterator& operator++() noexcept { @@ -948,7 +948,7 @@ public: ++_Myoff; #else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 / _ITERATOR_DEBUG_LEVEL == 0 vvv ++_Myptr; -#endif // _ITERATOR_DEBUG_LEVEL +#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ return *this; } @@ -965,7 +965,7 @@ public: --_Myoff; #else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 / _ITERATOR_DEBUG_LEVEL == 0 vvv --_Myptr; -#endif // _ITERATOR_DEBUG_LEVEL +#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ return *this; } @@ -991,7 +991,7 @@ public: } #else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 / _ITERATOR_DEBUG_LEVEL == 0 vvv (void) _Off; -#endif // _ITERATOR_DEBUG_LEVEL >= 1 +#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ } constexpr _String_view_iterator& operator+=(const difference_type _Off) noexcept { @@ -1000,7 +1000,7 @@ public: _Myoff += static_cast(_Off); #else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 / _ITERATOR_DEBUG_LEVEL == 0 vvv _Myptr += _Off; -#endif // _ITERATOR_DEBUG_LEVEL +#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ return *this; } @@ -1035,7 +1035,7 @@ public: _Myoff -= static_cast(_Off); #else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 / _ITERATOR_DEBUG_LEVEL == 0 vvv _Myptr -= _Off; -#endif // _ITERATOR_DEBUG_LEVEL +#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ return *this; } @@ -1053,7 +1053,7 @@ public: return static_cast(_Myoff - _Right._Myoff); #else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 / _ITERATOR_DEBUG_LEVEL == 0 vvv return _Myptr - _Right._Myptr; -#endif // _ITERATOR_DEBUG_LEVEL +#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ } _NODISCARD constexpr reference operator[](const difference_type _Off) const noexcept { @@ -1067,7 +1067,7 @@ public: return _Myoff == _Right._Myoff; #else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 / _ITERATOR_DEBUG_LEVEL == 0 vvv return _Myptr == _Right._Myptr; -#endif // _ITERATOR_DEBUG_LEVEL +#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ } #if _HAS_CXX20 @@ -1078,7 +1078,7 @@ public: return _Myoff <=> _Right._Myoff; #else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 / _ITERATOR_DEBUG_LEVEL == 0 vvv return _Myptr <=> _Right._Myptr; -#endif // _ITERATOR_DEBUG_LEVEL +#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ } #else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv _NODISCARD constexpr bool operator!=(const _String_view_iterator& _Right) const noexcept { @@ -1092,7 +1092,7 @@ public: return _Myoff < _Right._Myoff; #else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 / _ITERATOR_DEBUG_LEVEL == 0 vvv return _Myptr < _Right._Myptr; -#endif // _ITERATOR_DEBUG_LEVEL +#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ } _NODISCARD constexpr bool operator>(const _String_view_iterator& _Right) const noexcept { @@ -1123,7 +1123,7 @@ public: return _Mydata + _Myoff; #else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 / _ITERATOR_DEBUG_LEVEL == 0 vvv return _Myptr; -#endif // _ITERATOR_DEBUG_LEVEL +#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ } static constexpr bool _Unwrap_when_unverified = _ITERATOR_DEBUG_LEVEL == 0; @@ -1133,7 +1133,7 @@ public: _Myoff = static_cast(_It - _Mydata); #else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 / _ITERATOR_DEBUG_LEVEL == 0 vvv _Myptr = _It; -#endif // _ITERATOR_DEBUG_LEVEL +#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ } private: @@ -1143,7 +1143,7 @@ private: size_t _Myoff = 0; #else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 / _ITERATOR_DEBUG_LEVEL == 0 vvv pointer _Myptr = nullptr; -#endif // _ITERATOR_DEBUG_LEVEL +#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ }; #if _HAS_CXX20 @@ -1239,7 +1239,7 @@ public: return const_iterator(_Mydata, _Mysize, 0); #else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 / _ITERATOR_DEBUG_LEVEL == 0 vvv return const_iterator(_Mydata); -#endif // _ITERATOR_DEBUG_LEVEL +#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ } _NODISCARD constexpr const_iterator end() const noexcept { @@ -1247,7 +1247,7 @@ public: return const_iterator(_Mydata, _Mysize, _Mysize); #else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 / _ITERATOR_DEBUG_LEVEL == 0 vvv return const_iterator(_Mydata + _Mysize); -#endif // _ITERATOR_DEBUG_LEVEL +#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ } _NODISCARD constexpr const_iterator cbegin() const noexcept { @@ -1934,7 +1934,7 @@ public: } #else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 / _ITERATOR_DEBUG_LEVEL == 0 vvv (void) _Off; -#endif // _ITERATOR_DEBUG_LEVEL >= 1 +#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ } _CONSTEXPR20 _String_const_iterator& operator+=(const difference_type _Off) noexcept { @@ -2016,7 +2016,7 @@ public: " point to different string instances)"); #else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 / _ITERATOR_DEBUG_LEVEL == 0 vvv (void) _Right; -#endif // _ITERATOR_DEBUG_LEVEL +#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ } #if _ITERATOR_DEBUG_LEVEL >= 1 @@ -2479,7 +2479,7 @@ private: #define _ASAN_STRING_REMOVE(_Str) #define _ASAN_STRING_CREATE(_Str) #define _ASAN_STRING_MODIFY(_Str, _Old_size, _New_size) -#endif // !_INSERT_STRING_ANNOTATION +#endif // ^^^ !_INSERT_STRING_ANNOTATION ^^^ public: _CONSTEXPR20 @@ -2666,15 +2666,14 @@ private: _Traits::copy(_My_data._Bx._Buf, _Arg, _Count + 1); #else // ^^^ _INSERT_STRING_ANNOTATION / !_INSERT_STRING_ANNOTATION vvv _Traits::copy(_My_data._Bx._Buf, _Arg, _BUF_SIZE); -#endif // !_INSERT_STRING_ANNOTATION +#endif // ^^^ !_INSERT_STRING_ANNOTATION ^^^ } _Proxy._Release(); return; } - _My_data._Myres = _Small_string_capacity; - size_type _New_capacity = _Calculate_growth(_Count); + size_type _New_capacity = _Calculate_growth(_Count, _Small_string_capacity, max_size()); const pointer _New_ptr = _Allocate_for_capacity(_Al, _New_capacity); // throws _Construct_in_place(_My_data._Bx._Ptr, _New_ptr); @@ -2731,7 +2730,7 @@ private: } _Elem* const _Old_ptr = _My_data._Myptr(); - size_type _New_capacity = _Calculate_growth(_My_data._Mysize); + size_type _New_capacity = _Calculate_growth(_My_data._Mysize + 1); const pointer _New_ptr = _Allocate_for_capacity(_Al, _New_capacity); // throws _Traits::copy(_Unfancy(_New_ptr), _Old_ptr, _My_data._Mysize); @@ -3010,15 +3009,6 @@ public: } private: - void _Memcpy_val_from(const basic_string& _Right) noexcept { - _STL_INTERNAL_CHECK(_Can_memcpy_val); - const auto _My_data_mem = - reinterpret_cast(_STD addressof(_Mypair._Myval2)) + _Memcpy_val_offset; - const auto _Right_data_mem = - reinterpret_cast(_STD addressof(_Right._Mypair._Myval2)) + _Memcpy_val_offset; - _CSTD memcpy(_My_data_mem, _Right_data_mem, _Memcpy_val_size); - } - _CONSTEXPR20 void _Take_contents(basic_string& _Right) noexcept { // assign by stealing _Right's buffer // pre: this != &_Right @@ -3043,7 +3033,11 @@ private: } #endif // _ITERATOR_DEBUG_LEVEL != 0 - _Memcpy_val_from(_Right); + const auto _My_data_mem = + reinterpret_cast(_STD addressof(_Mypair._Myval2)) + _Memcpy_val_offset; + const auto _Right_data_mem = + reinterpret_cast(_STD addressof(_Right._Mypair._Myval2)) + _Memcpy_val_offset; + _CSTD memcpy(_My_data_mem, _Right_data_mem, _Memcpy_val_size); _Right._Tidy_init(); return; } @@ -3052,8 +3046,9 @@ private: if (_Right_data._Large_mode_engaged()) { // steal buffer _Construct_in_place(_My_data._Bx._Ptr, _Right_data._Bx._Ptr); - _Right_data._Bx._Ptr = nullptr; _Swap_proxy_and_iterators(_Right); + + _Destroy_in_place(_Right_data._Bx._Ptr); } else { // copy small string buffer _My_data._Activate_SSO_buffer(); _Traits::copy(_My_data._Bx._Buf, _Right_data._Bx._Buf, _Right_data._Mysize + 1); @@ -3075,12 +3070,12 @@ private: const auto _Right_ptr = _Right_data._Myptr(); auto& _Al = _Getal(); if (_Allocators_equal(_Al, _Right._Getal()) && _Result_size > _Small_string_capacity) { + _Mypair._Myval2._Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alty, _Al)); + if (_Roff != 0) { _Traits::move(_Right_ptr, _Right_ptr + _Roff, _Result_size); } _Right._Eos(_Result_size); - - _Mypair._Myval2._Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alty, _Al)); _Take_contents(_Right); } else { _Construct<_Construct_strategy::_From_ptr>(_Right_ptr + _Roff, _Result_size); @@ -3091,11 +3086,7 @@ private: public: _CONSTEXPR20 basic_string(initializer_list<_Elem> _Ilist, const _Alloc& _Al = allocator_type()) : _Mypair(_One_then_variadic_args_t{}, _Al) { - auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); - _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _Mypair._Myval2); - _Tidy_init(); - assign(_Ilist.begin(), _Convert_size(_Ilist.size())); - _Proxy._Release(); + _Construct<_Construct_strategy::_From_ptr>(_Ilist.begin(), _Convert_size(_Ilist.size())); } _CONSTEXPR20 basic_string& operator=(initializer_list<_Elem> _Ilist) { @@ -3166,12 +3157,13 @@ public: size_type _New_capacity = _Calculate_growth(_Right_size, _Small_string_capacity, _Right.max_size()); auto _Right_al_non_const = _Right_al; const pointer _New_ptr = _Allocate_for_capacity(_Right_al_non_const, _New_capacity); // throws - _Traits::copy(_Unfancy(_New_ptr), _Right_ptr, _Right_size + 1); + _Tidy_deallocate(); - _Mypair._Myval2._Bx._Ptr = _New_ptr; - _Mypair._Myval2._Mysize = _Right_size; - _Mypair._Myval2._Myres = _New_capacity; + _Construct_in_place(_Mypair._Myval2._Bx._Ptr, _New_ptr); + _Mypair._Myval2._Mysize = _Right_size; + _Mypair._Myval2._Myres = _New_capacity; + _ASAN_STRING_CREATE(*this); } else { _Tidy_deallocate(); _Traits::copy(_Mypair._Myval2._Bx._Buf, _Right_ptr, _Right_size + 1); @@ -3493,7 +3485,7 @@ public: const bool _Check_overlap = _Count <= _Mypair._Myval2._Myres - _Old_size && !_STD is_constant_evaluated(); #else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv const bool _Check_overlap = _Count <= _Mypair._Myval2._Myres - _Old_size; -#endif // _HAS_CXX20 +#endif // ^^^ !_HAS_CXX20 ^^^ if (_Check_overlap) { _ASAN_STRING_MODIFY(*this, _Old_size, _Old_size + _Count); @@ -4274,9 +4266,6 @@ public: auto& _My_data = _Mypair._Myval2; auto& _Right_data = _Right._Mypair._Myval2; - const bool _My_large = _My_data._Large_mode_engaged(); - const bool _Right_large = _Right_data._Large_mode_engaged(); - #if !defined(_INSERT_STRING_ANNOTATION) if constexpr (_Can_memcpy_val) { #if _HAS_CXX20 @@ -4297,6 +4286,9 @@ public: } #endif // !defined(_INSERT_STRING_ANNOTATION) + const bool _My_large = _My_data._Large_mode_engaged(); + const bool _Right_large = _Right_data._Large_mode_engaged(); + if (_My_large && _Right_large) { // swap buffers, iterators preserved swap(_My_data._Bx._Ptr, _Right_data._Bx._Ptr); // intentional ADL } else if (_My_large) { // swap large with small @@ -4801,7 +4793,7 @@ private: return *this; } - _CONSTEXPR20 void _Become_small() { + _CONSTEXPR20 void _Become_small() noexcept { // release any held storage and return to small string mode auto& _My_data = _Mypair._Myval2; _STL_INTERNAL_CHECK(_My_data._Large_mode_engaged()); @@ -5021,7 +5013,7 @@ _NODISCARD _CONSTEXPR20 bool operator==( _EXPORT_STD template _NODISCARD _CONSTEXPR20 bool operator==( - const basic_string<_Elem, _Traits, _Alloc>& _Left, _In_z_ const _Elem* const _Right) { + const basic_string<_Elem, _Traits, _Alloc>& _Left, _In_z_ const _Elem* const _Right) noexcept /* strengthened */ { return _Left._Equal(_Right); } @@ -5034,12 +5026,13 @@ _NODISCARD constexpr _Get_comparison_category_t<_Traits> operator<=>( _EXPORT_STD template _NODISCARD constexpr _Get_comparison_category_t<_Traits> operator<=>( - const basic_string<_Elem, _Traits, _Alloc>& _Left, _In_z_ const _Elem* const _Right) { + const basic_string<_Elem, _Traits, _Alloc>& _Left, _In_z_ const _Elem* const _Right) noexcept /* strengthened */ { return static_cast<_Get_comparison_category_t<_Traits>>(_Left.compare(_Right) <=> 0); } #else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv template -_NODISCARD bool operator==(_In_z_ const _Elem* const _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) { +_NODISCARD bool operator==(_In_z_ const _Elem* const _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) noexcept +/* strengthened */ { return _Right._Equal(_Left); } @@ -5050,12 +5043,14 @@ _NODISCARD bool operator!=( } template -_NODISCARD bool operator!=(_In_z_ const _Elem* const _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) { +_NODISCARD bool operator!=(_In_z_ const _Elem* const _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) noexcept +/* strengthened */ { return !(_Left == _Right); } template -_NODISCARD bool operator!=(const basic_string<_Elem, _Traits, _Alloc>& _Left, _In_z_ const _Elem* const _Right) { +_NODISCARD bool operator!=(const basic_string<_Elem, _Traits, _Alloc>& _Left, _In_z_ const _Elem* const _Right) noexcept +/* strengthened */ { return !(_Left == _Right); } @@ -5066,12 +5061,14 @@ _NODISCARD bool operator<( } template -_NODISCARD bool operator<(_In_z_ const _Elem* const _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) { +_NODISCARD bool operator<(_In_z_ const _Elem* const _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) noexcept +/* strengthened */ { return _Right.compare(_Left) > 0; } template -_NODISCARD bool operator<(const basic_string<_Elem, _Traits, _Alloc>& _Left, _In_z_ const _Elem* const _Right) { +_NODISCARD bool operator<(const basic_string<_Elem, _Traits, _Alloc>& _Left, _In_z_ const _Elem* const _Right) noexcept +/* strengthened */ { return _Left.compare(_Right) < 0; } @@ -5082,12 +5079,14 @@ _NODISCARD bool operator>( } template -_NODISCARD bool operator>(_In_z_ const _Elem* const _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) { +_NODISCARD bool operator>(_In_z_ const _Elem* const _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) noexcept +/* strengthened */ { return _Right < _Left; } template -_NODISCARD bool operator>(const basic_string<_Elem, _Traits, _Alloc>& _Left, _In_z_ const _Elem* const _Right) { +_NODISCARD bool operator>(const basic_string<_Elem, _Traits, _Alloc>& _Left, _In_z_ const _Elem* const _Right) noexcept +/* strengthened */ { return _Right < _Left; } @@ -5098,12 +5097,14 @@ _NODISCARD bool operator<=( } template -_NODISCARD bool operator<=(_In_z_ const _Elem* const _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) { +_NODISCARD bool operator<=(_In_z_ const _Elem* const _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) noexcept +/* strengthened */ { return !(_Right < _Left); } template -_NODISCARD bool operator<=(const basic_string<_Elem, _Traits, _Alloc>& _Left, _In_z_ const _Elem* const _Right) { +_NODISCARD bool operator<=(const basic_string<_Elem, _Traits, _Alloc>& _Left, _In_z_ const _Elem* const _Right) noexcept +/* strengthened */ { return !(_Right < _Left); } @@ -5114,12 +5115,14 @@ _NODISCARD bool operator>=( } template -_NODISCARD bool operator>=(_In_z_ const _Elem* const _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) { +_NODISCARD bool operator>=(_In_z_ const _Elem* const _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) noexcept +/* strengthened */ { return !(_Left < _Right); } template -_NODISCARD bool operator>=(const basic_string<_Elem, _Traits, _Alloc>& _Left, _In_z_ const _Elem* const _Right) { +_NODISCARD bool operator>=(const basic_string<_Elem, _Traits, _Alloc>& _Left, _In_z_ const _Elem* const _Right) noexcept +/* strengthened */ { return !(_Left < _Right); } #endif // ^^^ !_HAS_CXX20 ^^^ diff --git a/stl/inc/xtr1common b/stl/inc/xtr1common index ea61a5aab5c..0709e650366 100644 --- a/stl/inc/xtr1common +++ b/stl/inc/xtr1common @@ -172,7 +172,7 @@ _INLINE_VAR constexpr bool _Is_any_of_v = // true if and only if _Ty is in _Type (is_same_v<_Ty, _Types> || ...); #else // ^^^ _HAS_CXX17 / !_HAS_CXX17 vvv disjunction_v...>; -#endif // _HAS_CXX17 +#endif // ^^^ !_HAS_CXX17 ^^^ _NODISCARD constexpr bool _Is_constant_evaluated() noexcept { // Internal function for any standard mode return __builtin_is_constant_evaluated(); diff --git a/stl/inc/xtree b/stl/inc/xtree index 5016220213f..d03a13d1d4e 100644 --- a/stl/inc/xtree +++ b/stl/inc/xtree @@ -213,7 +213,7 @@ public: _STL_VERIFY(_Ptrsav != this->_Ptr, "cannot decrement begin map/set iterator"); #else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 / _ITERATOR_DEBUG_LEVEL != 2 vvv _Mybase::operator--(); -#endif // _ITERATOR_DEBUG_LEVEL == 2 +#endif // ^^^ _ITERATOR_DEBUG_LEVEL != 2 ^^^ return *this; } @@ -726,7 +726,7 @@ public: } #else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 / _ITERATOR_DEBUG_LEVEL != 2 vvv (void) _Ptr; -#endif // _ITERATOR_DEBUG_LEVEL == 2 +#endif // ^^^ _ITERATOR_DEBUG_LEVEL != 2 ^^^ } template diff --git a/stl/inc/xutility b/stl/inc/xutility index 880293a0d71..351138b4716 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -540,8 +540,11 @@ struct less_equal { template struct _Ref_fn { // pass function object by value as a reference + // _Ref_fn is an aggregate so it can be enregistered, unlike reference_wrapper + template - constexpr decltype(auto) operator()(_Args&&... _Vals) { // forward function call operator + constexpr decltype(auto) operator()(_Args&&... _Vals) noexcept( + _Select_invoke_traits<_Fx&, _Args...>::_Is_nothrow_invocable::value) { // forward function call operator if constexpr (is_member_pointer_v<_Fx>) { return _STD invoke(_Fn, _STD forward<_Args>(_Vals)...); } else { @@ -1296,7 +1299,7 @@ using _Guide_key_t = remove_const_t::value_type>>; #else // ^^^ C++23 / C++20 vvv remove_const_t::value_type::first_type>; -#endif // C++20 +#endif // ^^^ C++20 ^^^ template using _Guide_val_t = @@ -1304,7 +1307,7 @@ using _Guide_val_t = tuple_element_t<1, typename iterator_traits<_Iter>::value_type>; #else // ^^^ C++23 / C++20 vvv typename iterator_traits<_Iter>::value_type::second_type; -#endif // C++20 +#endif // ^^^ C++20 ^^^ template using _Guide_pair_t = @@ -1314,7 +1317,7 @@ using _Guide_pair_t = #else // ^^^ C++23 / C++20 vvv pair::value_type::first_type>, typename iterator_traits<_Iter>::value_type::second_type>; -#endif // C++20 +#endif // ^^^ C++20 ^^^ _EXPORT_STD template struct is_execution_policy : false_type {}; @@ -2708,7 +2711,7 @@ namespace ranges { { return _RANGES begin(static_cast<_CTy&&>(_Val)); } -#endif // C++20 +#endif // ^^^ C++20 ^^^ }; inline namespace _Cpos { @@ -2738,7 +2741,7 @@ namespace ranges { { return _RANGES end(static_cast<_CTy&&>(_Val)); } -#endif // C++20 +#endif // ^^^ C++20 ^^^ }; inline namespace _Cpos { @@ -2905,7 +2908,7 @@ namespace ranges { { return _RANGES rbegin(static_cast<_CTy&&>(_Val)); } -#endif // C++20 +#endif // ^^^ C++20 ^^^ }; inline namespace _Cpos { @@ -2935,7 +2938,7 @@ namespace ranges { { return _RANGES rend(static_cast<_CTy&&>(_Val)); } -#endif // C++20 +#endif // ^^^ C++20 ^^^ }; inline namespace _Cpos { @@ -3160,7 +3163,7 @@ namespace ranges { { return _RANGES data(static_cast<_CTy&&>(_Val)); } -#endif // C++20 +#endif // ^^^ C++20 ^^^ }; inline namespace _Cpos { @@ -4576,30 +4579,34 @@ template _CONSTEXPR20 _OutIt _Copy_unchecked(_InIt _First, _Sent _Last, _OutIt _Dest) { // copy [_First, _Last) to [_Dest, ...) // note: _Copy_unchecked has callers other than the copy family - if constexpr (_Sent_copy_cat<_InIt, _Sent, _OutIt>::_Bitcopy_assignable) { + if constexpr (_Is_vb_iterator<_InIt> && _Is_vb_iterator<_OutIt, true>) { + return _Copy_vbool(_First, _Last, _Dest); + } else { + if constexpr (_Sent_copy_cat<_InIt, _Sent, _OutIt>::_Bitcopy_assignable) { #if _HAS_CXX20 - if (!_STD is_constant_evaluated()) + if (!_STD is_constant_evaluated()) #endif // _HAS_CXX20 - { + { #ifdef __cpp_lib_concepts - if constexpr (is_same_v<_InIt, _Sent>) + if constexpr (is_same_v<_InIt, _Sent>) #endif // defined(__cpp_lib_concepts) - { - return _Copy_memmove(_First, _Last, _Dest); - } + { + return _Copy_memmove(_First, _Last, _Dest); + } #ifdef __cpp_lib_concepts - else { - return _Copy_memmove_n(_First, static_cast(_Last - _First), _Dest); - } + else { + return _Copy_memmove_n(_First, static_cast(_Last - _First), _Dest); + } #endif // defined(__cpp_lib_concepts) + } } - } - for (; _First != _Last; ++_Dest, (void) ++_First) { - *_Dest = *_First; - } + for (; _First != _Last; ++_Dest, (void) ++_First) { + *_Dest = *_First; + } - return _Dest; + return _Dest; + } } _EXPORT_STD template @@ -4774,32 +4781,36 @@ _CONSTEXPR20 _OutIt copy_n(_InIt _First, _Diff _Count_raw, _OutIt _Dest) { // copy [_First, _First + _Count) to [_Dest, ...) _Algorithm_int_t<_Diff> _Count = _Count_raw; if (0 < _Count) { - auto _UFirst = _Get_unwrapped_n(_First, _Count); - auto _UDest = _Get_unwrapped_n(_Dest, _Count); - if constexpr (_Iter_copy_cat::_Bitcopy_assignable) { + if constexpr (_Is_vb_iterator<_InIt> && _Is_vb_iterator<_OutIt, true>) { + return _Copy_vbool(_First, _First + _Count, _Dest); + } else { + auto _UFirst = _Get_unwrapped_n(_First, _Count); + auto _UDest = _Get_unwrapped_n(_Dest, _Count); + if constexpr (_Iter_copy_cat::_Bitcopy_assignable) { #if _HAS_CXX20 - if (!_STD is_constant_evaluated()) + if (!_STD is_constant_evaluated()) #endif // _HAS_CXX20 - { - _UDest = _Copy_memmove_n(_UFirst, static_cast(_Count), _UDest); - _Seek_wrapped(_Dest, _UDest); - return _Dest; + { + _UDest = _Copy_memmove_n(_UFirst, static_cast(_Count), _UDest); + _Seek_wrapped(_Dest, _UDest); + return _Dest; + } } - } - for (;;) { - *_UDest = *_UFirst; - ++_UDest; - --_Count; - if (_Count == 0) { // note that we avoid an extra ++_First here to allow istream_iterator to work, - // see LWG-2471 - break; + for (;;) { + *_UDest = *_UFirst; + ++_UDest; + --_Count; + // note that we avoid an extra ++_First here to allow istream_iterator to work, see LWG-2471 + if (_Count == 0) { + break; + } + + ++_UFirst; } - ++_UFirst; + _Seek_wrapped(_Dest, _UDest); } - - _Seek_wrapped(_Dest, _UDest); } return _Dest; @@ -4873,20 +4884,24 @@ template _CONSTEXPR20 _OutIt _Move_unchecked(_InIt _First, _InIt _Last, _OutIt _Dest) { // move [_First, _Last) to [_Dest, ...) // note: _Move_unchecked has callers other than the move family - if constexpr (_Iter_move_cat<_InIt, _OutIt>::_Bitcopy_assignable) { + if constexpr (_Is_vb_iterator<_InIt> && _Is_vb_iterator<_OutIt, true>) { + return _Copy_vbool(_First, _Last, _Dest); + } else { + if constexpr (_Iter_move_cat<_InIt, _OutIt>::_Bitcopy_assignable) { #if _HAS_CXX20 - if (!_STD is_constant_evaluated()) + if (!_STD is_constant_evaluated()) #endif // _HAS_CXX20 - { - return _Copy_memmove(_First, _Last, _Dest); + { + return _Copy_memmove(_First, _Last, _Dest); + } } - } - for (; _First != _Last; ++_Dest, (void) ++_First) { - *_Dest = _STD move(*_First); - } + for (; _First != _Last; ++_Dest, (void) ++_First) { + *_Dest = _STD move(*_First); + } - return _Dest; + return _Dest; + } } _EXPORT_STD template diff --git a/stl/inc/yvals.h b/stl/inc/yvals.h index 9f337dad050..03d40d869bc 100644 --- a/stl/inc/yvals.h +++ b/stl/inc/yvals.h @@ -15,7 +15,7 @@ #ifdef _ENFORCE_ONLY_CORE_HEADERS _EMIT_STL_ERROR( STL1005, "Tried to include a non-core C++ Standard Library header file with _ENFORCE_ONLY_CORE_HEADERS defined."); -#endif // _ENFORCE_ONLY_CORE_HEADERS +#endif // defined(_ENFORCE_ONLY_CORE_HEADERS) #include #include @@ -47,15 +47,15 @@ _STL_DISABLE_CLANG_WARNINGS #else #define _CRT_MSVCP_CURRENT "msvcp_win.dll" #endif -#else +#else // ^^^ defined(_CRT_WINDOWS) / !defined(_CRT_WINDOWS) vvv // Visual Studio #ifdef _DEBUG #define _CRT_MSVCP_CURRENT "msvcp140d.dll" #else #define _CRT_MSVCP_CURRENT "msvcp140.dll" #endif -#endif -#endif +#endif // ^^^ !defined(_CRT_WINDOWS) ^^^ +#endif // !defined(_CRT_MSVCP_CURRENT) #ifdef _ITERATOR_DEBUG_LEVEL // A. _ITERATOR_DEBUG_LEVEL is already defined. @@ -79,7 +79,7 @@ _STL_DISABLE_CLANG_WARNINGS #else #define _HAS_ITERATOR_DEBUGGING 0 #endif -#endif // _HAS_ITERATOR_DEBUGGING +#endif // ^^^ !defined(_HAS_ITERATOR_DEBUGGING) ^^^ // A3. Inspect _SECURE_SCL. #ifdef _SECURE_SCL // A3i. _SECURE_SCL is already defined, validate it. @@ -111,7 +111,7 @@ _STL_DISABLE_CLANG_WARNINGS #else #define _HAS_ITERATOR_DEBUGGING 0 #endif -#endif // _HAS_ITERATOR_DEBUGGING +#endif // ^^^ !defined(_HAS_ITERATOR_DEBUGGING) ^^^ // B2. Inspect _SECURE_SCL. #ifdef _SECURE_SCL // B2i. _SECURE_SCL is already defined, validate it. @@ -131,19 +131,19 @@ _STL_DISABLE_CLANG_WARNINGS #define _ITERATOR_DEBUG_LEVEL 2 #elif _SECURE_SCL #define _ITERATOR_DEBUG_LEVEL 1 -#else +#else // ^^^ _SECURE_SCL / !_SECURE_SCL vvv #define _ITERATOR_DEBUG_LEVEL 0 -#endif +#endif // ^^^ !_HAS_ITERATOR_DEBUGGING && !_SECURE_SCL ^^^ #endif // ^^^ !defined(_ITERATOR_DEBUG_LEVEL) ^^^ #ifndef _ALLOW_MSC_VER_MISMATCH #pragma detect_mismatch("_MSC_VER", "1900") -#endif // _ALLOW_MSC_VER_MISMATCH +#endif // !defined(_ALLOW_MSC_VER_MISMATCH) #ifndef _ALLOW_ITERATOR_DEBUG_LEVEL_MISMATCH #pragma detect_mismatch("_ITERATOR_DEBUG_LEVEL", _STRINGIZE(_ITERATOR_DEBUG_LEVEL)) -#endif // _ALLOW_ITERATOR_DEBUG_LEVEL_MISMATCH +#endif // !defined(_ALLOW_ITERATOR_DEBUG_LEVEL_MISMATCH) #ifndef _ALLOW_RUNTIME_LIBRARY_MISMATCH #if !defined(_DLL) && !defined(_DEBUG) @@ -155,7 +155,7 @@ _STL_DISABLE_CLANG_WARNINGS #elif defined(_DLL) && defined(_DEBUG) #pragma detect_mismatch("RuntimeLibrary", "MDd_DynamicDebug") #endif // defined(_DLL) etc. -#endif // _ALLOW_RUNTIME_LIBRARY_MISMATCH +#endif // !defined(_ALLOW_RUNTIME_LIBRARY_MISMATCH) #ifndef _CONTAINER_DEBUG_LEVEL #if _ITERATOR_DEBUG_LEVEL == 0 @@ -163,7 +163,7 @@ _STL_DISABLE_CLANG_WARNINGS #else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 / _ITERATOR_DEBUG_LEVEL != 0 vvv #define _CONTAINER_DEBUG_LEVEL 1 #endif // _ITERATOR_DEBUG_LEVEL == 0 -#endif // _CONTAINER_DEBUG_LEVEL +#endif // !defined(_CONTAINER_DEBUG_LEVEL) #if _ITERATOR_DEBUG_LEVEL != 0 && _CONTAINER_DEBUG_LEVEL == 0 #error _ITERATOR_DEBUG_LEVEL != 0 must imply _CONTAINER_DEBUG_LEVEL == 1. @@ -177,7 +177,7 @@ _STL_DISABLE_CLANG_WARNINGS #else // ^^^ defined(_DEBUG) / !defined(_DEBUG) vvv #define _STL_CRT_SECURE_INVALID_PARAMETER(expr) _CRT_SECURE_INVALID_PARAMETER(expr) #endif // ^^^ !defined(_DEBUG) ^^^ -#endif // _STL_CRT_SECURE_INVALID_PARAMETER +#endif // !defined(_STL_CRT_SECURE_INVALID_PARAMETER) #define _STL_REPORT_ERROR(mesg) \ do { \ @@ -217,9 +217,9 @@ _STL_DISABLE_CLANG_WARNINGS #ifdef _ENABLE_STL_INTERNAL_CHECK #define _STL_INTERNAL_CHECK(...) _STL_VERIFY(__VA_ARGS__, "STL internal check: " #__VA_ARGS__) -#else // ^^^ _ENABLE_STL_INTERNAL_CHECK / !_ENABLE_STL_INTERNAL_CHECK vvv +#else // ^^^ defined(_ENABLE_STL_INTERNAL_CHECK) / !defined(_ENABLE_STL_INTERNAL_CHECK) vvv #define _STL_INTERNAL_CHECK(...) _Analysis_assume_(__VA_ARGS__) -#endif // _ENABLE_STL_INTERNAL_CHECK +#endif // ^^^ !defined(_ENABLE_STL_INTERNAL_CHECK) ^^^ #ifndef _ENABLE_ATOMIC_REF_ALIGNMENT_CHECK #ifdef _DEBUG @@ -227,7 +227,7 @@ _STL_DISABLE_CLANG_WARNINGS #else // ^^^ defined(_DEBUG) / !defined(_DEBUG) vvv #define _ENABLE_ATOMIC_REF_ALIGNMENT_CHECK 0 #endif // ^^^ !defined(_DEBUG) ^^^ -#endif // _ENABLE_ATOMIC_REF_ALIGNMENT_CHECK +#endif // !defined(_ENABLE_ATOMIC_REF_ALIGNMENT_CHECK) #if _ENABLE_ATOMIC_REF_ALIGNMENT_CHECK #define _ATOMIC_REF_CHECK_ALIGNMENT(cond, mesg) _STL_VERIFY(cond, mesg) @@ -245,11 +245,11 @@ _EMIT_STL_WARNING(STL4000, "_STATIC_CPPLIB is deprecated and will be REMOVED."); #ifdef _M_CEE_MIXED #error _STATIC_CPPLIB is not supported while building with /clr #endif -#endif // !_DISABLE_DEPRECATE_STATIC_CPPLIB +#endif // !defined(_DISABLE_DEPRECATE_STATIC_CPPLIB) #ifdef _M_CEE_PURE #error _STATIC_CPPLIB cannot be used with /clr:pure (the resulting assembly would not be pure) #endif -#endif // _STATIC_CPPLIB +#endif // defined(_STATIC_CPPLIB) #if defined(_M_CEE_PURE) && !defined(_SILENCE_CLR_PURE_DEPRECATION_WARNING) _EMIT_STL_WARNING(STL4001, "/clr:pure is deprecated and will be REMOVED."); @@ -261,7 +261,7 @@ _EMIT_STL_WARNING(STL4001, "/clr:pure is deprecated and will be REMOVED."); #else #define _MRTIMP2_PURE _MRTIMP2 #endif -#endif // _MRTIMP2_PURE +#endif // !defined(_MRTIMP2_PURE) #if defined(_DLL) && !defined(_STATIC_CPPLIB) && !defined(_M_CEE_PURE) #define _DLL_CPPLIB @@ -273,17 +273,17 @@ _EMIT_STL_WARNING(STL4001, "/clr:pure is deprecated and will be REMOVED."); #else #define _CRTIMP2_PURE _CRTIMP2 #endif -#endif // _CRTIMP2_PURE +#endif // !defined(_CRTIMP2_PURE) #ifndef _CRTIMP2_IMPORT #if defined(CRTDLL2) && defined(_CRTBLD) #define _CRTIMP2_IMPORT __declspec(dllexport) #elif defined(_DLL) && !defined(_STATIC_CPPLIB) #define _CRTIMP2_IMPORT __declspec(dllimport) -#else +#else // ^^^ defined(_DLL) && !defined(_STATIC_CPPLIB) / !defined(_DLL) || defined(_STATIC_CPPLIB) vvv #define _CRTIMP2_IMPORT -#endif -#endif // _CRTIMP2_IMPORT +#endif // ^^^ !defined(_DLL) || defined(_STATIC_CPPLIB) ^^^ +#endif // !defined(_CRTIMP2_IMPORT) #ifndef _CRTIMP2_PURE_IMPORT #ifdef _M_CEE_PURE @@ -291,7 +291,7 @@ _EMIT_STL_WARNING(STL4001, "/clr:pure is deprecated and will be REMOVED."); #else #define _CRTIMP2_PURE_IMPORT _CRTIMP2_IMPORT #endif -#endif // _CRTIMP2_PURE_IMPORT +#endif // !defined(_CRTIMP2_PURE_IMPORT) #ifndef _CRTIMP2_PURE_IMPORT_UNLESS_CODECVT_ID_SATELLITE #ifdef _BUILDING_SATELLITE_CODECVT_IDS @@ -299,7 +299,7 @@ _EMIT_STL_WARNING(STL4001, "/clr:pure is deprecated and will be REMOVED."); #else #define _CRTIMP2_PURE_IMPORT_UNLESS_CODECVT_ID_SATELLITE _CRTIMP2_PURE_IMPORT #endif -#endif // _CRTIMP2_PURE_IMPORT_UNLESS_CODECVT_ID_SATELLITE +#endif // !defined(_CRTIMP2_PURE_IMPORT_UNLESS_CODECVT_ID_SATELLITE) #ifndef _CRTDATA2_IMPORT #if defined(MRTDLL) && defined(_CRTBLD) @@ -307,7 +307,7 @@ _EMIT_STL_WARNING(STL4001, "/clr:pure is deprecated and will be REMOVED."); #else #define _CRTDATA2_IMPORT _CRTIMP2_IMPORT #endif -#endif // _CRTDATA2_IMPORT +#endif // !defined(_CRTDATA2_IMPORT) #define _LOCK_LOCALE 0 #define _LOCK_MALLOC 1 @@ -321,7 +321,7 @@ _EMIT_STL_WARNING(STL4001, "/clr:pure is deprecated and will be REMOVED."); #else // ^^^ modern 64-bit / less modern or 32-bit vvv #define _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B 0 #endif // _STL_WIN32_WINNT >= _STL_WIN32_WINNT_WINBLUE && defined(_WIN64) -#endif // _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B +#endif // !defined(_STD_ATOMIC_ALWAYS_USE_CMPXCHG16B) #if _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B == 0 && defined(_M_ARM64) #error ARM64 requires _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B to be 1. @@ -378,16 +378,16 @@ class _CRTIMP2_PURE_IMPORT _EmptyLockit { // empty lock class used for bin compa private: int _Locktype; }; -#endif // _M_CEE_PURE +#endif // defined(_M_CEE_PURE) #ifdef _M_CEE #ifndef _PREPARE_CONSTRAINED_REGIONS #ifdef _M_CEE_PURE #define _PREPARE_CONSTRAINED_REGIONS 1 -#else // _M_CEE_PURE +#else // ^^^ defined(_M_CEE_PURE) / !defined(_M_CEE_PURE) vvv #define _PREPARE_CONSTRAINED_REGIONS 0 -#endif // _M_CEE_PURE -#endif // _PREPARE_CONSTRAINED_REGIONS +#endif // ^^^ !defined(_M_CEE_PURE) ^^^ +#endif // !defined(_PREPARE_CONSTRAINED_REGIONS) #if _PREPARE_CONSTRAINED_REGIONS #define _BEGIN_LOCK(_Kind) \ diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 98a044cae12..46310c21a4a 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -14,7 +14,7 @@ #else #define _STL_COMPILER_PREPROCESSOR 1 #endif -#endif // _STL_COMPILER_PREPROCESSOR +#endif // !defined(_STL_COMPILER_PREPROCESSOR) #if _STL_COMPILER_PREPROCESSOR @@ -521,7 +521,7 @@ #else // defined(_MSVC_WARNING_LEVEL) && _MSVC_WARNING_LEVEL >= 4 #define _STL_WARNING_LEVEL 3 #endif // defined(_MSVC_WARNING_LEVEL) && _MSVC_WARNING_LEVEL >= 4 -#endif // _STL_WARNING_LEVEL +#endif // !defined(_STL_WARNING_LEVEL) #if _STL_WARNING_LEVEL < 3 #error _STL_WARNING_LEVEL cannot be less than 3. @@ -573,16 +573,16 @@ #elif __has_cpp_attribute(nodiscard) >= 201907L #define _NODISCARD_CTOR _NODISCARD #define _NODISCARD_CTOR_MSG(_Msg) _NODISCARD_MSG(_Msg) -#else +#else // ^^^ __has_cpp_attribute(nodiscard) >= 201907L / __has_cpp_attribute(nodiscard) < 201907L vvv #define _NODISCARD_CTOR #define _NODISCARD_CTOR_MSG(_Msg) -#endif +#endif // ^^^ defined(__has_cpp_attribute) && __has_cpp_attribute(nodiscard) < 201907L ^^^ #if defined(__CUDACC__) && !defined(__clang__) // TRANSITION, VSO-568006 #define _NODISCARD_FRIEND friend #else // ^^^ workaround / no workaround vvv #define _NODISCARD_FRIEND _NODISCARD friend -#endif // TRANSITION, VSO-568006 +#endif // ^^^ no workaround ^^^ #define _NODISCARD_REMOVE_ALG \ _NODISCARD_MSG("The 'remove' and 'remove_if' algorithms return the iterator past the last element " \ @@ -772,7 +772,7 @@ #ifndef _STL_EXTRA_DISABLED_WARNINGS #define _STL_EXTRA_DISABLED_WARNINGS -#endif // _STL_EXTRA_DISABLED_WARNINGS +#endif // !defined(_STL_EXTRA_DISABLED_WARNINGS) // warning C4180: qualifier applied to function type has no meaning; ignored // warning C4412: function signature contains type 'meow'; C++ objects are unsafe to pass between pure code @@ -813,7 +813,7 @@ _STL_DISABLED_WARNING_C5053 \ _STL_EXTRA_DISABLED_WARNINGS // clang-format on -#endif // _STL_DISABLED_WARNINGS +#endif // !defined(_STL_DISABLED_WARNINGS) // warning: constexpr if is a C++17 extension [-Wc++17-extensions] // warning: explicit(bool) is a C++20 extension [-Wc++20-extensions] @@ -837,7 +837,7 @@ #else // ^^^ defined(__clang__) / !defined(__clang__) vvv #define _STL_DISABLE_CLANG_WARNINGS #endif // ^^^ !defined(__clang__) ^^^ -#endif // _STL_DISABLE_CLANG_WARNINGS +#endif // !defined(_STL_DISABLE_CLANG_WARNINGS) #ifndef _STL_RESTORE_CLANG_WARNINGS #ifdef __clang__ @@ -845,7 +845,7 @@ #else // ^^^ defined(__clang__) / !defined(__clang__) vvv #define _STL_RESTORE_CLANG_WARNINGS #endif // ^^^ !defined(__clang__) ^^^ -#endif // _STL_RESTORE_CLANG_WARNINGS +#endif // !defined(_STL_RESTORE_CLANG_WARNINGS) // clang-format off #ifndef _STL_DISABLE_DEPRECATED_WARNING @@ -873,7 +873,7 @@ #else // vvv MSVC vvv #define _STL_RESTORE_DEPRECATED_WARNING _Pragma("warning(pop)") #endif // ^^^ MSVC ^^^ -#endif // _STL_RESTORE_DEPRECATED_WARNING +#endif // !defined(_STL_RESTORE_DEPRECATED_WARNING) #define _CPPLIB_VER 650 #define _MSVC_STL_VERSION 143 @@ -891,13 +891,13 @@ _EMIT_STL_ERROR(STL1002, "Unexpected compiler version, expected CUDA 11.6 or new _EMIT_STL_ERROR(STL1000, "Unexpected compiler version, expected Clang 16.0.0 or newer."); #endif // ^^^ old Clang ^^^ #elif defined(_MSC_VER) -#if _MSC_VER < 1936 // Coarse-grained, not inspecting _MSC_FULL_VER -_EMIT_STL_ERROR(STL1001, "Unexpected compiler version, expected MSVC 19.36 or newer."); +#if _MSC_VER < 1938 // Coarse-grained, not inspecting _MSC_FULL_VER +_EMIT_STL_ERROR(STL1001, "Unexpected compiler version, expected MSVC 19.38 or newer."); #endif // ^^^ old MSVC ^^^ #else // vvv other compilers vvv // not attempting to detect other compilers #endif // ^^^ other compilers ^^^ -#endif // _ALLOW_COMPILER_AND_STL_VERSION_MISMATCH +#endif // !defined(_ALLOW_COMPILER_AND_STL_VERSION_MISMATCH) #ifndef _HAS_STATIC_RTTI #define _HAS_STATIC_RTTI 1 @@ -951,12 +951,12 @@ _EMIT_STL_ERROR(STL1001, "Unexpected compiler version, expected MSVC 19.36 or ne // N4190 Removing auto_ptr, random_shuffle(), And Old Stuff #ifndef _HAS_AUTO_PTR_ETC #define _HAS_AUTO_PTR_ETC (!_HAS_CXX17) -#endif // _HAS_AUTO_PTR_ETC +#endif // !defined(_HAS_AUTO_PTR_ETC) // P0003R5 Removing Dynamic Exception Specifications #ifndef _HAS_UNEXPECTED #define _HAS_UNEXPECTED (!_HAS_CXX17) -#endif // _HAS_UNEXPECTED +#endif // !defined(_HAS_UNEXPECTED) #if _HAS_UNEXPECTED && _HAS_CXX23 _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpected."); @@ -965,12 +965,12 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect // P0004R1 Removing Deprecated Iostreams Aliases #ifndef _HAS_OLD_IOSTREAMS_MEMBERS #define _HAS_OLD_IOSTREAMS_MEMBERS (!_HAS_CXX17) -#endif // _HAS_OLD_IOSTREAMS_MEMBERS +#endif // !defined(_HAS_OLD_IOSTREAMS_MEMBERS) // P0298R3 std::byte #ifndef _HAS_STD_BYTE #define _HAS_STD_BYTE _HAS_CXX17 // inspected by GSL, do not remove -#endif // _HAS_STD_BYTE +#endif // !defined(_HAS_STD_BYTE) // P0302R1 Removing Allocator Support In std::function // LWG-2385 function::assign allocator argument doesn't make sense @@ -978,12 +978,12 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect // LWG-2976 Dangling uses_allocator specialization for packaged_task #ifndef _HAS_FUNCTION_ALLOCATOR_SUPPORT #define _HAS_FUNCTION_ALLOCATOR_SUPPORT (!_HAS_CXX17) -#endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT +#endif // !defined(_HAS_FUNCTION_ALLOCATOR_SUPPORT) // The non-Standard std::tr1 namespace and TR1-only machinery #ifndef _HAS_TR1_NAMESPACE #define _HAS_TR1_NAMESPACE (!_HAS_CXX17) -#endif // _HAS_TR1_NAMESPACE +#endif // !defined(_HAS_TR1_NAMESPACE) // STL4000 is "_STATIC_CPPLIB is deprecated", currently in yvals.h // STL4001 is "/clr:pure is deprecated", currently in yvals.h @@ -1005,7 +1005,7 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect // Enforcement of matching allocator value_types #ifndef _ENFORCE_MATCHING_ALLOCATORS #define _ENFORCE_MATCHING_ALLOCATORS _HAS_CXX17 -#endif // _ENFORCE_MATCHING_ALLOCATORS +#endif // !defined(_ENFORCE_MATCHING_ALLOCATORS) #define _MISMATCHED_ALLOCATOR_MESSAGE(_CONTAINER, _VALUE_TYPE) \ _CONTAINER " requires that Allocator's value_type match " _VALUE_TYPE " (See N4950 [container.alloc.reqmts]/5)" \ @@ -1015,7 +1015,7 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect // Enforcement of Standard facet specializations #ifndef _ENFORCE_FACET_SPECIALIZATIONS #define _ENFORCE_FACET_SPECIALIZATIONS 0 -#endif // _ENFORCE_FACET_SPECIALIZATIONS +#endif // !defined(_ENFORCE_FACET_SPECIALIZATIONS) #define _FACET_SPECIALIZATION_MESSAGE \ "Unsupported facet specialization; see N4950 [locale.category]. " \ @@ -1026,7 +1026,7 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect // depicted in the Standard. #ifndef _STL_OPTIMIZE_SYSTEM_ERROR_OPERATORS #define _STL_OPTIMIZE_SYSTEM_ERROR_OPERATORS 1 -#endif // _STL_OPTIMIZE_SYSTEM_ERROR_OPERATORS +#endif // !defined(_STL_OPTIMIZE_SYSTEM_ERROR_OPERATORS) // Controls whether the STL will force /fp:fast to enable vectorization of algorithms defined // in the standard as special cases; such as reduce, transform_reduce, inclusive_scan, exclusive_scan @@ -1035,8 +1035,8 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #define _STD_VECTORIZE_WITH_FLOAT_CONTROL 0 #else // ^^^ floating-point exceptions enabled / floating-point exceptions disabled (default) vvv #define _STD_VECTORIZE_WITH_FLOAT_CONTROL 1 -#endif // _M_FP_EXCEPT -#endif // _STD_VECTORIZE_WITH_FLOAT_CONTROL +#endif // ^^^ floating-point exceptions disabled (default) ^^^ +#endif // !defined(_STD_VECTORIZE_WITH_FLOAT_CONTROL) // P0174R2 Deprecating Vestigial Library Parts // P0521R0 Deprecating shared_ptr::unique() @@ -1528,47 +1528,47 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect // P0619R4 Removing C++17-Deprecated Features #ifndef _HAS_FEATURES_REMOVED_IN_CXX20 #define _HAS_FEATURES_REMOVED_IN_CXX20 (!_HAS_CXX20) -#endif // _HAS_FEATURES_REMOVED_IN_CXX20 +#endif // !defined(_HAS_FEATURES_REMOVED_IN_CXX20) #ifndef _HAS_DEPRECATED_ADAPTOR_TYPEDEFS #define _HAS_DEPRECATED_ADAPTOR_TYPEDEFS (_HAS_FEATURES_REMOVED_IN_CXX20) -#endif // _HAS_DEPRECATED_ADAPTOR_TYPEDEFS +#endif // !defined(_HAS_DEPRECATED_ADAPTOR_TYPEDEFS) #ifndef _HAS_DEPRECATED_ALLOCATOR_MEMBERS #define _HAS_DEPRECATED_ALLOCATOR_MEMBERS (_HAS_FEATURES_REMOVED_IN_CXX20) -#endif // _HAS_DEPRECATED_ALLOCATOR_MEMBERS +#endif // !defined(_HAS_DEPRECATED_ALLOCATOR_MEMBERS) #ifndef _HAS_DEPRECATED_ALLOCATOR_VOID #define _HAS_DEPRECATED_ALLOCATOR_VOID (_HAS_FEATURES_REMOVED_IN_CXX20) -#endif // _HAS_DEPRECATED_ALLOCATOR_VOID +#endif // !defined(_HAS_DEPRECATED_ALLOCATOR_VOID) #ifndef _HAS_DEPRECATED_IS_LITERAL_TYPE #define _HAS_DEPRECATED_IS_LITERAL_TYPE (_HAS_FEATURES_REMOVED_IN_CXX20) -#endif // _HAS_DEPRECATED_IS_LITERAL_TYPE +#endif // !defined(_HAS_DEPRECATED_IS_LITERAL_TYPE) #ifndef _HAS_DEPRECATED_NEGATORS #define _HAS_DEPRECATED_NEGATORS (_HAS_FEATURES_REMOVED_IN_CXX20) -#endif // _HAS_DEPRECATED_NEGATORS +#endif // !defined(_HAS_DEPRECATED_NEGATORS) #ifndef _HAS_DEPRECATED_RAW_STORAGE_ITERATOR #define _HAS_DEPRECATED_RAW_STORAGE_ITERATOR (_HAS_FEATURES_REMOVED_IN_CXX20) -#endif // _HAS_DEPRECATED_RAW_STORAGE_ITERATOR +#endif // !defined(_HAS_DEPRECATED_RAW_STORAGE_ITERATOR) #ifndef _HAS_DEPRECATED_RESULT_OF #define _HAS_DEPRECATED_RESULT_OF (_HAS_FEATURES_REMOVED_IN_CXX20) -#endif // _HAS_DEPRECATED_RESULT_OF +#endif // !defined(_HAS_DEPRECATED_RESULT_OF) #ifndef _HAS_DEPRECATED_SHARED_PTR_UNIQUE #define _HAS_DEPRECATED_SHARED_PTR_UNIQUE (_HAS_FEATURES_REMOVED_IN_CXX20) -#endif // _HAS_DEPRECATED_SHARED_PTR_UNIQUE +#endif // !defined(_HAS_DEPRECATED_SHARED_PTR_UNIQUE) #ifndef _HAS_DEPRECATED_TEMPORARY_BUFFER #define _HAS_DEPRECATED_TEMPORARY_BUFFER (_HAS_FEATURES_REMOVED_IN_CXX20) -#endif // _HAS_DEPRECATED_TEMPORARY_BUFFER +#endif // !defined(_HAS_DEPRECATED_TEMPORARY_BUFFER) #ifndef _HAS_DEPRECATED_UNCAUGHT_EXCEPTION #define _HAS_DEPRECATED_UNCAUGHT_EXCEPTION (_HAS_FEATURES_REMOVED_IN_CXX20) -#endif // _HAS_DEPRECATED_UNCAUGHT_EXCEPTION +#endif // !defined(_HAS_DEPRECATED_UNCAUGHT_EXCEPTION) #if _HAS_DEPRECATED_ADAPTOR_TYPEDEFS #define _ARGUMENT_TYPE_NAME argument_type @@ -1580,22 +1580,22 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #define _FIRST_ARGUMENT_TYPE_NAME _Unnameable_first_argument #define _SECOND_ARGUMENT_TYPE_NAME _Unnameable_second_argument #define _RESULT_TYPE_NAME _Unnameable_result -#endif // !_HAS_DEPRECATED_ADAPTOR_TYPEDEFS +#endif // ^^^ !_HAS_DEPRECATED_ADAPTOR_TYPEDEFS ^^^ // P1423R3 char8_t Backward Compatibility Remediation // Controls whether we allow the stream insertions this proposal forbids #ifndef _HAS_STREAM_INSERTION_OPERATORS_DELETED_IN_CXX20 #define _HAS_STREAM_INSERTION_OPERATORS_DELETED_IN_CXX20 (_HAS_FEATURES_REMOVED_IN_CXX20) -#endif // _HAS_STREAM_INSERTION_OPERATORS_DELETED_IN_CXX20 +#endif // !defined(_HAS_STREAM_INSERTION_OPERATORS_DELETED_IN_CXX20) #ifndef _HAS_FEATURES_REMOVED_IN_CXX23 #define _HAS_FEATURES_REMOVED_IN_CXX23 (!_HAS_CXX23) -#endif // _HAS_FEATURES_REMOVED_IN_CXX23 +#endif // !defined(_HAS_FEATURES_REMOVED_IN_CXX23) // P2186R2 Removing Garbage Collection Support #ifndef _HAS_GARBAGE_COLLECTION_SUPPORT_DELETED_IN_CXX23 #define _HAS_GARBAGE_COLLECTION_SUPPORT_DELETED_IN_CXX23 (_HAS_FEATURES_REMOVED_IN_CXX23) -#endif // _HAS_GARBAGE_COLLECTION_SUPPORT_DELETED_IN_CXX23 +#endif // !defined(_HAS_GARBAGE_COLLECTION_SUPPORT_DELETED_IN_CXX23) // C++14 #define __cpp_lib_chrono_udls 201304L @@ -1627,7 +1627,7 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #define __cpp_lib_robust_nonmodifying_seq_ops 201304L #ifndef _M_CEE_PURE #define __cpp_lib_shared_timed_mutex 201402L -#endif // _M_CEE_PURE +#endif // !defined(_M_CEE_PURE) #define __cpp_lib_string_udls 201304L #define __cpp_lib_transformation_trait_aliases 201304L #define __cpp_lib_tuple_element_t 201402L @@ -1679,7 +1679,7 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #define __cpp_lib_not_fn 201603L #ifndef _M_CEE_PURE #define __cpp_lib_parallel_algorithm 201603L -#endif // _M_CEE_PURE +#endif // !defined(_M_CEE_PURE) #define __cpp_lib_raw_memory_algorithms 201606L #define __cpp_lib_sample 201603L #define __cpp_lib_scoped_lock 201703L @@ -1693,11 +1693,11 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #ifdef __cpp_char8_t #define __cpp_lib_char8_t 201907L -#endif // __cpp_char8_t +#endif // defined(__cpp_char8_t) #ifdef __cpp_impl_coroutine #define __cpp_lib_coroutine 201902L -#endif // __cpp_impl_coroutine +#endif // defined(__cpp_impl_coroutine) #if _HAS_CXX20 #if !defined(__EDG__) || defined(__INTELLISENSE__) // TRANSITION, GH-395 @@ -1758,13 +1758,13 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #ifndef __clang__ // TRANSITION, LLVM-48860 #define __cpp_lib_is_layout_compatible 201907L -#endif // __clang__ +#endif // !defined(__clang__) #define __cpp_lib_is_nothrow_convertible 201806L #ifndef __clang__ // TRANSITION, LLVM-48860 #define __cpp_lib_is_pointer_interconvertible 201907L -#endif // __clang__ +#endif // !defined(__clang__) #define __cpp_lib_jthread 201911L #define __cpp_lib_latch 201907L @@ -1891,7 +1891,7 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #elif _HAS_CXX17 #define __cpp_lib_execution 201603L // P0024R2 Parallel Algorithms #endif // language mode -#endif // _M_CEE_PURE +#endif // !defined(_M_CEE_PURE) #if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 #define __cpp_lib_optional 202110L // P0798R8 Monadic Operations For optional @@ -1934,8 +1934,8 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #ifndef _ALLOW_RTCc_IN_STL #error /RTCc rejects conformant code, so it is not supported by the C++ Standard Library. Either remove this \ compiler option, or define _ALLOW_RTCc_IN_STL to suppress this error. -#endif // _ALLOW_RTCc_IN_STL -#endif // _RTC_CONVERSION_CHECKS_ENABLED +#endif // !defined(_ALLOW_RTCc_IN_STL) +#endif // defined(_RTC_CONVERSION_CHECKS_ENABLED) #define _STRINGIZEX(x) #x #define _STRINGIZE(x) _STRINGIZEX(x) @@ -1991,27 +1991,27 @@ compiler option, or define _ALLOW_RTCc_IN_STL to suppress this error. // The earliest Windows supported by this implementation is Windows 7 #define _STL_WIN32_WINNT _STL_WIN32_WINNT_WIN7 #endif // ^^^ !defined(_M_ARM) && !defined(_M_ARM64) && !defined(_ONECORE) && !defined(_CRT_APP) ^^^ -#endif // _STL_WIN32_WINNT +#endif // !defined(_STL_WIN32_WINNT) #ifdef __cpp_noexcept_function_type #define _NOEXCEPT_FNPTR noexcept -#else +#else // ^^^ defined(__cpp_noexcept_function_type) / !defined(__cpp_noexcept_function_type) vvv #define _NOEXCEPT_FNPTR -#endif // __cpp_noexcept_function_type +#endif // ^^^ !defined(__cpp_noexcept_function_type) ^^^ #ifdef __clang__ #define _STL_INTRIN_HEADER #define _STL_UNREACHABLE __builtin_unreachable() -#else // ^^^ clang / other vvv +#else // ^^^ defined(__clang__) / !defined(__clang__) vvv #define _STL_INTRIN_HEADER #define _STL_UNREACHABLE __assume(false) -#endif // __clang__ +#endif // ^^^ !defined(__clang__) ^^^ #ifdef _ENABLE_STL_INTERNAL_CHECK #define _STL_INTERNAL_STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) -#else // ^^^ _ENABLE_STL_INTERNAL_CHECK / !_ENABLE_STL_INTERNAL_CHECK vvv +#else // ^^^ defined(_ENABLE_STL_INTERNAL_CHECK) / !defined(_ENABLE_STL_INTERNAL_CHECK) vvv #define _STL_INTERNAL_STATIC_ASSERT(...) -#endif // _ENABLE_STL_INTERNAL_CHECK +#endif // ^^^ !defined(_ENABLE_STL_INTERNAL_CHECK) ^^^ #endif // _STL_COMPILER_PREPROCESSOR #endif // _YVALS_CORE_H_ diff --git a/stl/src/atomic_wait.cpp b/stl/src/atomic_wait.cpp index b503c902c6d..3abc008af5a 100644 --- a/stl/src/atomic_wait.cpp +++ b/stl/src/atomic_wait.cpp @@ -94,7 +94,7 @@ namespace { #else // ^^^ _STL_WIN32_WINNT >= _STL_WIN32_WINNT_WIN8 / _STL_WIN32_WINNT < _STL_WIN32_WINNT_WIN8 vvv #define _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE 0 #endif // ^^^ _STL_WIN32_WINNT < _STL_WIN32_WINNT_WIN8 ^^^ -#endif // _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE +#endif // !defined(_ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE) #if _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE diff --git a/stl/src/dllmain.cpp b/stl/src/dllmain.cpp index 9cf64d30fa5..23968536e81 100644 --- a/stl/src/dllmain.cpp +++ b/stl/src/dllmain.cpp @@ -8,7 +8,7 @@ #ifdef _CRT_APP // free static resource used by causality extern "C" void __cdecl __crtCleanupCausalityStaticFactories(); -#endif // _CRT_APP +#endif // defined(_CRT_APP) extern "C" BOOL APIENTRY DllMain(HMODULE /* hModule */, DWORD ul_reason_for_call, [[maybe_unused]] LPVOID lpReserved) { if (ul_reason_for_call == DLL_PROCESS_DETACH) { @@ -16,7 +16,7 @@ extern "C" BOOL APIENTRY DllMain(HMODULE /* hModule */, DWORD ul_reason_for_call if (lpReserved == nullptr) { // only when the process is not terminating __crtCleanupCausalityStaticFactories(); } -#endif // _CRT_APP +#endif // defined(_CRT_APP) } return TRUE; } diff --git a/stl/src/excptptr.cpp b/stl/src/excptptr.cpp index 5cfc8406419..b36a2cf6999 100644 --- a/stl/src/excptptr.cpp +++ b/stl/src/excptptr.cpp @@ -8,7 +8,7 @@ #ifndef _VCRT_ALLOW_INTERNALS #define _VCRT_ALLOW_INTERNALS -#endif // _VCRT_ALLOW_INTERNALS +#endif // !defined(_VCRT_ALLOW_INTERNALS) #include #include // for abort @@ -171,7 +171,7 @@ namespace { const auto _CopyFunc = reinterpret_cast(_ThrowImageBase + _PType->copyFunction); #else // ^^^ _EH_RELATIVE_TYPEINFO / !_EH_RELATIVE_TYPEINFO vvv const auto _CopyFunc = _PType->copyFunction; -#endif // _EH_RELATIVE_TYPEINFO +#endif // ^^^ !_EH_RELATIVE_TYPEINFO ^^^ const auto _Adjusted = __AdjustPointer(const_cast(_Src), _PType->thisDisplacement); if (_PType->properties & CT_HasVirtualBase) { @@ -270,7 +270,7 @@ namespace { static_cast(_CatchableTypeArray->arrayOfCatchableTypes[0]) + _ThrowImageBase); #else // ^^^ _EH_RELATIVE_TYPEINFO / !_EH_RELATIVE_TYPEINFO vvv const auto _PType = _PThrow->pCatchableTypeArray->arrayOfCatchableTypes[0]; -#endif // _EH_RELATIVE_TYPEINFO +#endif // ^^^ !_EH_RELATIVE_TYPEINFO ^^^ if (_PThrow->pmfnUnwind) { // The exception was a user defined type with a nontrivial destructor, call it @@ -281,7 +281,7 @@ namespace { reinterpret_cast(_PThrow->pmfnUnwind + _ThrowImageBase)); #else // ^^^ _EH_RELATIVE_TYPEINFO && !defined(_M_CEE_PURE) / !_EH_RELATIVE_TYPEINFO && !defined(_M_CEE_PURE) vvv _CallMemberFunction0(_CppEhRecord.params.pExceptionObject, _PThrow->pmfnUnwind); -#endif +#endif // ^^^ !_EH_RELATIVE_TYPEINFO && !defined(_M_CEE_PURE) ^^^ } else if (_PType->properties & CT_IsWinRTHandle) { const auto _PUnknown = *static_cast(_CppEhRecord.params.pExceptionObject); if (_PUnknown) { @@ -337,7 +337,7 @@ namespace { static_cast(_CatchableTypeArray->arrayOfCatchableTypes[0]) + _ThrowImageBase); #else // ^^^ _EH_RELATIVE_TYPEINFO / !_EH_RELATIVE_TYPEINFO vvv const auto _PType = _PThrow->pCatchableTypeArray->arrayOfCatchableTypes[0]; -#endif // _EH_RELATIVE_TYPEINFO +#endif // ^^^ !_EH_RELATIVE_TYPEINFO ^^^ const auto _ExceptionObjectSize = static_cast(_PType->sizeOrOffset); const auto _AllocSize = sizeof(_ExceptionPtr_normal) + _ExceptionObjectSize; @@ -386,7 +386,7 @@ namespace { static_cast(_InnerCatchableTypeArray->arrayOfCatchableTypes[0]) + _InnerThrowImageBase); #else // ^^^ _EH_RELATIVE_TYPEINFO / !_EH_RELATIVE_TYPEINFO vvv const auto _PInnerType = _PInnerThrow->pCatchableTypeArray->arrayOfCatchableTypes[0]; -#endif // _EH_RELATIVE_TYPEINFO +#endif // ^^^ !_EH_RELATIVE_TYPEINFO ^^^ const auto _InnerExceptionSize = static_cast(_PInnerType->sizeOrOffset); const auto _InnerAllocSize = sizeof(_ExceptionPtr_normal) + _InnerExceptionSize; @@ -496,9 +496,9 @@ _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL __ExceptionPtrCurrentException(void* const auto _ThrowImageBase = reinterpret_cast(_CppRecord.params.pThrowImageBase); const auto _CatchableTypeArray = reinterpret_cast(_ThrowImageBase + _PThrow->pCatchableTypeArray); -#else +#else // ^^^ _EH_RELATIVE_TYPEINFO / !_EH_RELATIVE_TYPEINFO vvv const auto _CatchableTypeArray = _PThrow->pCatchableTypeArray; -#endif // _EH_RELATIVE_TYPEINFO +#endif // ^^^ !_EH_RELATIVE_TYPEINFO ^^^ if (_CatchableTypeArray->nCatchableTypes <= 0) { // Ditto corrupted. @@ -511,7 +511,7 @@ _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL __ExceptionPtrCurrentException(void* static_cast(_CatchableTypeArray->arrayOfCatchableTypes[0]) + _ThrowImageBase); #else // ^^^ _EH_RELATIVE_TYPEINFO / !_EH_RELATIVE_TYPEINFO vvv const auto _PType = _PThrow->pCatchableTypeArray->arrayOfCatchableTypes[0]; -#endif // _EH_RELATIVE_TYPEINFO +#endif // ^^^ !_EH_RELATIVE_TYPEINFO ^^^ // Alloc memory on stack for exception object. This might cause a stack overflow SEH exception, or another C++ // exception when copying the C++ exception object. In that case, we just let that become the thrown exception. diff --git a/stl/src/ppltasks.cpp b/stl/src/ppltasks.cpp index e5253e86229..c0bbdad466a 100644 --- a/stl/src/ppltasks.cpp +++ b/stl/src/ppltasks.cpp @@ -204,7 +204,7 @@ namespace Concurrency { } } -#else +#else // ^^^ defined(_CRT_APP) / !defined(_CRT_APP) vvv _CRTIMP2 void __thiscall _TaskEventLogger::_LogScheduleTask(bool) {} _CRTIMP2 void __thiscall _TaskEventLogger::_LogTaskCompleted() {} @@ -216,7 +216,7 @@ namespace Concurrency { _CRTIMP2 void __thiscall _TaskEventLogger::_LogWorkItemStarted() {} _CRTIMP2 void __thiscall _TaskEventLogger::_LogWorkItemCompleted() {} -#endif +#endif // ^^^ !defined(_CRT_APP) ^^^ #if defined(_CRT_APP) || defined(UNDOCKED_WINDOWS_UCRT) using namespace ABI::Windows::Foundation; @@ -317,7 +317,8 @@ namespace Concurrency { return false; } -#else +#else // ^^^ defined(_CRT_APP) || defined(UNDOCKED_WINDOWS_UCRT) + // / !defined(_CRT_APP) && !defined(UNDOCKED_WINDOWS_UCRT) vvv _CRTIMP2 void __thiscall _ContextCallback::_CallInContext(_CallbackFunction _Func, bool) const { _Func(); } @@ -335,16 +336,16 @@ namespace Concurrency { _CRTIMP2 bool __cdecl _Task_impl_base::_IsNonBlockingThread() { return false; } -#endif +#endif // ^^^ !defined(_CRT_APP) && !defined(UNDOCKED_WINDOWS_UCRT) ^^^ } // namespace details #ifdef _CRT_APP _CRTIMP2 __thiscall task_continuation_context::task_continuation_context() : _ContextCallback(true), _M_RunInline(false) {} -#else +#else // ^^^ defined(_CRT_APP) / !defined(_CRT_APP) vvv _CRTIMP2 __thiscall task_continuation_context::task_continuation_context() : _ContextCallback(false), _M_RunInline(false) {} -#endif +#endif // ^^^ !defined(_CRT_APP) ^^^ } // namespace Concurrency diff --git a/stl/src/taskscheduler.cpp b/stl/src/taskscheduler.cpp index 8a7e5385c45..1386a66a25e 100644 --- a/stl/src/taskscheduler.cpp +++ b/stl/src/taskscheduler.cpp @@ -55,7 +55,7 @@ namespace Concurrency { _STL_host_status _Get_STL_host_status() { #ifdef CRTDLL2 return _STL_host_status::_Dll; -#else // ^^^ CRTDLL2 / !CRTDLL2 vvv +#else // ^^^ defined(CRTDLL2) / !defined(CRTDLL2) vvv HANDLE _HExe = _Call_get_module_handle_ex(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, nullptr); if (_HExe == nullptr) { return _STL_host_status::_Unknown; @@ -64,7 +64,7 @@ namespace Concurrency { } else { return _STL_host_status::_Dll; } -#endif // CRTDLL2 +#endif // ^^^ !defined(CRTDLL2) ^^^ } #ifdef CRTDLL2 @@ -73,7 +73,7 @@ namespace Concurrency { // code is sufficient. void _Increment_outstanding() {} void _Decrement_outstanding() {} -#else // ^^^ CRTDLL2 / !CRTDLL2 vvv +#else // ^^^ defined(CRTDLL2) / !defined(CRTDLL2) vvv size_t _Outstanding_tasks = 0; _STD mutex _Task_cv_mutex; _STD condition_variable _Task_cv; @@ -114,7 +114,7 @@ namespace Concurrency { } }; _Task_scheduler_main_block _Task_scheduler_main_block_instance; -#endif // CRTDLL2 +#endif // ^^^ !defined(CRTDLL2) ^^^ void CALLBACK _Task_scheduler_callback(PTP_CALLBACK_INSTANCE _Pci, PVOID _Args, PTP_WORK) noexcept { _Increment_outstanding(); diff --git a/stl/src/ushiostr.cpp b/stl/src/ushiostr.cpp index 6dd6a65f39a..220aa1678f0 100644 --- a/stl/src/ushiostr.cpp +++ b/stl/src/ushiostr.cpp @@ -27,7 +27,7 @@ __PURE_APPDOMAIN_GLOBAL extern wostream* _Ptr_wcout = nullptr; __PURE_APPDOMAIN_GLOBAL extern wostream* _Ptr_wcerr = nullptr; __PURE_APPDOMAIN_GLOBAL extern wostream* _Ptr_wclog = nullptr; _STD_END -#else +#else // ^^^ defined(_M_CEE_PURE) / !defined(_M_CEE_PURE) vvv _STD_BEGIN __PURE_APPDOMAIN_GLOBAL extern _CRTDATA2_IMPORT wistream* _Ptr_wcin = nullptr; __PURE_APPDOMAIN_GLOBAL extern _CRTDATA2_IMPORT wostream* _Ptr_wcout = nullptr; @@ -35,4 +35,4 @@ __PURE_APPDOMAIN_GLOBAL extern _CRTDATA2_IMPORT wostream* _Ptr_wcerr = nullptr; __PURE_APPDOMAIN_GLOBAL extern _CRTDATA2_IMPORT wostream* _Ptr_wclog = nullptr; _STD_END #include "wiostrea.cpp" -#endif +#endif // ^^^ !defined(_M_CEE_PURE) ^^^ diff --git a/stl/src/vector_algorithms.cpp b/stl/src/vector_algorithms.cpp index 0827f9da68f..9f9e43fab1a 100644 --- a/stl/src/vector_algorithms.cpp +++ b/stl/src/vector_algorithms.cpp @@ -15,7 +15,7 @@ extern "C" long __isa_enabled; #ifndef _DEBUG #pragma optimize("t", on) // Override /Os with /Ot for this TU -#endif // !_DEBUG +#endif // !defined(_DEBUG) namespace { bool _Use_avx2() noexcept { diff --git a/stl/src/winapisupp.cpp b/stl/src/winapisupp.cpp index 4510f38958e..9949df6eb9a 100644 --- a/stl/src/winapisupp.cpp +++ b/stl/src/winapisupp.cpp @@ -138,7 +138,7 @@ extern "C" int __crt_IsPackagedAppHelper() { extern "C" _CRTIMP2 BOOL __cdecl __crtIsPackagedApp() { #ifdef _CRT_APP return TRUE; -#else +#else // ^^^ defined(_CRT_APP) / !defined(_CRT_APP) vvv static int isPackaged = -1; // Initialize to undefined state // If we've already made this check, just return the prev result @@ -147,7 +147,7 @@ extern "C" _CRTIMP2 BOOL __cdecl __crtIsPackagedApp() { } return (isPackaged > 0) ? TRUE : FALSE; -#endif +#endif // ^^^ !defined(_CRT_APP) ^^^ } #endif // !defined(_CRT_WINDOWS) && !defined(UNDOCKED_WINDOWS_UCRT) diff --git a/stl/src/xmbtowc.cpp b/stl/src/xmbtowc.cpp index 4b97b53e590..bcfb7d78144 100644 --- a/stl/src/xmbtowc.cpp +++ b/stl/src/xmbtowc.cpp @@ -158,6 +158,6 @@ _MRTIMP2 _Success_(return >= 0) int __cdecl _Mbrtowc( _MRTIMP2 int __cdecl _Mbrtowc(unsigned short* pwc, const char* s, size_t n, mbstate_t* pst, const _Cvtvec* ploc) { return _Mbrtowc(reinterpret_cast(pwc), s, n, pst, ploc); } -#endif // MRTDLL +#endif // defined(MRTDLL) _END_EXTERN_C_UNLESS_PURE diff --git a/stl/src/xwcscoll.cpp b/stl/src/xwcscoll.cpp index 160f1110323..ab3fb060f78 100644 --- a/stl/src/xwcscoll.cpp +++ b/stl/src/xwcscoll.cpp @@ -71,6 +71,6 @@ _CRTIMP2_PURE int __CLRCALL_PURE_OR_CDECL _Wcscoll(const unsigned short* string1 return _Wcscoll(reinterpret_cast(string1), reinterpret_cast(end1), reinterpret_cast(string2), reinterpret_cast(end2), ploc); } -#endif // MRTDLL +#endif // defined(MRTDLL) _END_EXTERN_C_UNLESS_PURE diff --git a/stl/src/xwcsxfrm.cpp b/stl/src/xwcsxfrm.cpp index 1a1cc5be915..f103ca79872 100644 --- a/stl/src/xwcsxfrm.cpp +++ b/stl/src/xwcsxfrm.cpp @@ -104,6 +104,6 @@ _CRTIMP2_PURE size_t __CLRCALL_PURE_OR_CDECL _Wcsxfrm(unsigned short* string1, u return _Wcsxfrm(reinterpret_cast(string1), reinterpret_cast(end1), reinterpret_cast(string2), reinterpret_cast(end2), ploc); } -#endif // MRTDLL +#endif // defined(MRTDLL) _END_EXTERN_C_UNLESS_PURE diff --git a/stl/src/xwctomb.cpp b/stl/src/xwctomb.cpp index e53bc0ff551..1e1b339a3e9 100644 --- a/stl/src/xwctomb.cpp +++ b/stl/src/xwctomb.cpp @@ -89,7 +89,7 @@ _CRTIMP2_PURE _Success_(return != -1) int __CLRCALL_PURE_OR_CDECL _CRTIMP2_PURE int __CLRCALL_PURE_OR_CDECL _Wcrtomb(char* s, unsigned short wchar, mbstate_t* pst, const _Cvtvec* ploc) { return _Wcrtomb(s, static_cast(wchar), pst, ploc); } -#endif // MRTDLL +#endif // defined(MRTDLL) // TRANSITION, ABI: __Wcrtomb_lk() is preserved for binary compatibility _CRTIMP2_PURE int __CLRCALL_PURE_OR_CDECL __Wcrtomb_lk(char* s, wchar_t wchar, mbstate_t* pst, const _Cvtvec* ploc) { diff --git a/stl/src/xxstod.hpp b/stl/src/xxstod.hpp index 58c81be89aa..80c8bfda4c4 100644 --- a/stl/src/xxstod.hpp +++ b/stl/src/xxstod.hpp @@ -13,9 +13,9 @@ #define NLONG 1 // 7 * NLONG == max hexadecimal digits #elif FBITS == 53 #define NLONG 3 -#else // FBITS +#else // ^^^ FBITS == 53 / FBITS != 24 && FBITS != 53 vvv #error Unexpected value for FBITS -#endif // FBITS +#endif // ^^^ FBITS != 24 && FBITS != 53 ^^^ // FTYPE _Stodx(const CTYPE *s, CTYPE **endptr, long pten, int *perr) { // convert string to FTYPE, with checking diff --git a/stl/src/xxxdtent.hpp b/stl/src/xxxdtent.hpp index d4272282673..88c5ff4290b 100644 --- a/stl/src/xxxdtent.hpp +++ b/stl/src/xxxdtent.hpp @@ -37,9 +37,9 @@ static const FTYPE tenth[] = { static_cast(FLIT(2457.0) / FRAC_BITS_2 / FRAC_BITS_2), }; -#else // FBITS +#else // ^^^ FBITS == 24 / FBITS != 24 && FBITS != 53 vvv #error Unexpected value for FBITS -#endif // FBITS +#endif // ^^^ FBITS != 24 && FBITS != 53 ^^^ FTYPE FNAME(Dtento)(FTYPE* xpx, long n, int* perr) { // compute *px * 10**n FTYPE xpf[ACSIZE]; diff --git a/stl/src/xxxprec.hpp b/stl/src/xxxprec.hpp index 5f17437e26b..31b6d3661f3 100644 --- a/stl/src/xxxprec.hpp +++ b/stl/src/xxxprec.hpp @@ -288,9 +288,9 @@ FTYPE* FNAME(Xp_setn)(FTYPE* p, int n, long x) noexcept { // load a long integer FNAME(Xp_setw)(p, n, static_cast(x / 10000)); FNAME(Xp_mulh)(p, n, static_cast(10000)); FNAME(Xp_addh)(p, n, static_cast(x % 10000)); -#else // FBITS +#else // ^^^ FBITS == 24 / FBITS != 24 && FBITS != 53 vvv #error Unexpected value for FBITS -#endif // FBITS +#endif // ^^^ FBITS != 24 && FBITS != 53 ^^^ return p; } diff --git a/tests/std/include/test_format_support.hpp b/tests/std/include/test_format_support.hpp index 969f6f57bb0..c8b2a218f45 100644 --- a/tests/std/include/test_format_support.hpp +++ b/tests/std/include/test_format_support.hpp @@ -26,6 +26,10 @@ struct choose_literal { static constexpr char choose(char c, wchar_t) { return c; } + + static constexpr std::string_view choose(std::string_view sv, std::wstring_view) { + return sv; + } }; template <> @@ -37,6 +41,10 @@ struct choose_literal { static constexpr wchar_t choose(char, wchar_t c) { return c; } + + static constexpr std::wstring_view choose(std::string_view, std::wstring_view sv) { + return sv; + } }; #define TYPED_LITERAL(CharT, Literal) (choose_literal::choose(Literal, L##Literal)) diff --git a/tests/std/test.lst b/tests/std/test.lst index a6ba5720f59..b0783f0730a 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -231,6 +231,7 @@ tests\GH_003676_format_large_hh_mm_ss_values tests\GH_003735_char_traits_signatures tests\GH_003840_tellg_when_reading_lf_file_in_text_mode tests\GH_003867_output_nan +tests\GH_004023_mdspan_fwd_prod_overflow tests\LWG2381_num_get_floating_point tests\LWG2597_complex_branch_cut tests\LWG3018_shared_ptr_function @@ -593,9 +594,10 @@ tests\P2278R4_const_span tests\P2278R4_ranges_const_iterator_machinery tests\P2278R4_ranges_const_range_machinery tests\P2278R4_views_as_const -tests\P2286R8_formatting_ranges -tests\P2286R8_formatting_ranges_legacy_text_encoding -tests\P2286R8_formatting_ranges_utf8 +tests\P2286R8_text_formatting_debug_enabled_specializations +tests\P2286R8_text_formatting_escaping +tests\P2286R8_text_formatting_escaping_legacy_text_encoding +tests\P2286R8_text_formatting_escaping_utf8 tests\P2302R4_ranges_alg_contains tests\P2302R4_ranges_alg_contains_subrange tests\P2321R2_proxy_reference diff --git a/tests/std/tests/Dev10_860421_deque_push_back_pop_front/test.cpp b/tests/std/tests/Dev10_860421_deque_push_back_pop_front/test.cpp index 3a9e78d92c6..72ff7bd48c4 100644 --- a/tests/std/tests/Dev10_860421_deque_push_back_pop_front/test.cpp +++ b/tests/std/tests/Dev10_860421_deque_push_back_pop_front/test.cpp @@ -1,15 +1,16 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#include #include #include +#include +#include #include using namespace std; -void test_391805(); - -int main() { +void test_push_back_pop_front() { deque d; for (int n = 0; n < 1000; ++n) { @@ -31,8 +32,6 @@ int main() { assert(d[i] == *v[i]); } } - - test_391805(); } // Also test Dev10-391805 "STL: Prefast error in deque". @@ -47,3 +46,224 @@ void test_391805() { assert(d.size() == 4 && d[0] == 40 && d[1] == 30 && d[2] == 10 && d[3] == 20); } + +// Also test GH-1023 ": std::deque::insert performance" +// - support for single-element insertion of non-swappable type, and +// - exception safety for single-element insertion. + +struct ThrowingConstructionTag { + explicit ThrowingConstructionTag() = default; +}; + +struct UniqueError { + explicit UniqueError() = default; +}; + +class NonswappableMovable { +public: + NonswappableMovable() = default; + NonswappableMovable(NonswappableMovable&& other) noexcept : payload{exchange(other.payload, -1)} {} + NonswappableMovable(const NonswappableMovable&) = default; + + explicit NonswappableMovable(int n) noexcept : payload{n} {} + explicit NonswappableMovable(ThrowingConstructionTag) { + throw UniqueError{}; + } + + NonswappableMovable& operator=(NonswappableMovable&& other) noexcept { + payload = exchange(other.payload, -1); + return *this; + } + NonswappableMovable& operator=(const NonswappableMovable&) = default; + +#if _HAS_CXX20 + friend bool operator==(const NonswappableMovable&, const NonswappableMovable&) = default; +#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv + friend bool operator==(const NonswappableMovable& lhs, const NonswappableMovable& rhs) noexcept { + return lhs.payload == rhs.payload; + } + + friend bool operator!=(const NonswappableMovable& lhs, const NonswappableMovable& rhs) noexcept { + return lhs.payload != rhs.payload; + } +#endif // ^^^ !_HAS_CXX20 ^^^ + + friend void swap(NonswappableMovable&, NonswappableMovable&) = delete; + +private: + int payload = -1; +}; + +#if _HAS_CXX17 +static_assert(!is_swappable_v); +#endif // _HAS_CXX17 + +void test_exception_safety_for_nonswappable_movable() { + using Diff = deque::difference_type; + + deque d; + for (int i = 0; i < 10; ++i) { + d.emplace_back(i); + } + + { + auto it = d.emplace(d.begin(), 33); + assert(it == d.begin()); + assert(d.front() == NonswappableMovable{33}); + } + { + auto it = d.emplace(d.begin() + Diff{3}, 42); + assert(it == d.begin() + Diff{3}); + assert(d[3] == NonswappableMovable{42}); + } + { + auto it = d.emplace(d.end() - Diff{3}, 1729); + assert(it == d.end() - Diff{4}); + assert(d[d.size() - 4] == NonswappableMovable{1729}); + } + { + auto it = d.emplace(d.end(), 2023); + assert(it == d.end() - Diff{1}); + assert(d.back() == NonswappableMovable{2023}); + } + { + static constexpr int correct[] = {33, 0, 1, 42, 2, 3, 4, 5, 6, 1729, 7, 8, 9, 2023}; + auto comp = [](const NonswappableMovable& lhs, const int rhs) { return lhs == NonswappableMovable{rhs}; }; + assert(equal(d.begin(), d.end(), begin(correct), end(correct), comp)); + } + + const auto d_orig = d; + try { + d.emplace_front(ThrowingConstructionTag{}); + assert(false); + } catch (const UniqueError&) { + } + assert(d == d_orig); + + try { + d.emplace_back(ThrowingConstructionTag{}); + assert(false); + } catch (const UniqueError&) { + } + assert(d == d_orig); + + try { + d.emplace(d.begin(), ThrowingConstructionTag{}); + assert(false); + } catch (const UniqueError&) { + } + assert(d == d_orig); + + try { + d.emplace(d.begin() + Diff{2}, ThrowingConstructionTag{}); + assert(false); + } catch (const UniqueError&) { + } + assert(d == d_orig); + + try { + d.emplace(d.end() - Diff{2}, ThrowingConstructionTag{}); + assert(false); + } catch (const UniqueError&) { + } + assert(d == d_orig); + + try { + d.emplace(d.end(), ThrowingConstructionTag{}); + assert(false); + } catch (const UniqueError&) { + } + assert(d == d_orig); +} + +class ThrowingMovable { +public: + ThrowingMovable() = default; + ThrowingMovable(ThrowingMovable&&) { + throw UniqueError{}; + } + ThrowingMovable(const ThrowingMovable&) = default; + + explicit ThrowingMovable(int n) noexcept : payload{n} {} + + ThrowingMovable& operator=(ThrowingMovable&&) { + throw UniqueError{}; + } + ThrowingMovable& operator=(const ThrowingMovable&) = default; + +#if _HAS_CXX20 + friend bool operator==(const ThrowingMovable&, const ThrowingMovable&) = default; +#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv + friend bool operator==(const ThrowingMovable& lhs, const ThrowingMovable& rhs) noexcept { + return lhs.payload == rhs.payload; + } + + friend bool operator!=(const ThrowingMovable& lhs, const ThrowingMovable& rhs) noexcept { + return lhs.payload != rhs.payload; + } +#endif // ^^^ !_HAS_CXX20 ^^^ + +private: + int payload = -1; +}; + +void test_exception_safety_for_throwing_movable() { + using Diff = deque::difference_type; + + deque d; + for (int i = 0; i < 10; ++i) { + d.emplace_back(i); + } + + const auto d_orig = d; + try { + d.emplace_front(ThrowingMovable{}); + assert(false); + } catch (const UniqueError&) { + } + assert(d == d_orig); + + try { + d.emplace_back(ThrowingMovable{}); + assert(false); + } catch (const UniqueError&) { + } + assert(d == d_orig); + + try { + d.emplace(d.begin(), ThrowingMovable{}); + assert(false); + } catch (const UniqueError&) { + } + assert(d == d_orig); + + try { + d.emplace(d.begin() + Diff{2}, ThrowingMovable{}); + assert(false); + } catch (const UniqueError&) { + } + assert(d == d_orig); + + try { + d.emplace(d.end() - Diff{2}, ThrowingMovable{}); + assert(false); + } catch (const UniqueError&) { + } + assert(d == d_orig); + + try { + d.emplace(d.end(), ThrowingMovable{}); + assert(false); + } catch (const UniqueError&) { + } + assert(d == d_orig); +} + +int main() { + test_push_back_pop_front(); + + test_391805(); + + test_exception_safety_for_nonswappable_movable(); + test_exception_safety_for_throwing_movable(); +} diff --git a/tests/std/tests/GH_000625_vector_bool_optimization/test.cpp b/tests/std/tests/GH_000625_vector_bool_optimization/test.cpp index 27d9393ce68..c96ea1bbafd 100644 --- a/tests/std/tests/GH_000625_vector_bool_optimization/test.cpp +++ b/tests/std/tests/GH_000625_vector_bool_optimization/test.cpp @@ -3,16 +3,45 @@ #include #include +#include #include +#include #include +#include #include +#include #include +#pragma warning(disable : 4365) // conversion from 'unsigned __int64' to 'const __int64', signed/unsigned mismatch + using namespace std; constexpr int blockSize = 32; static_assert(blockSize == _VBITS, "Invalid block size"); +// This test data is not random, but irregular enough to ensure confidence in the tests +// clang-format off +const vector source = { true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false + }; +// clang-format on + + void test_fill_helper(const size_t length) { // No offset { @@ -152,30 +181,9 @@ bool test_find() { } void test_count_helper(const ptrdiff_t length) { - // This test data is not random, but irregular enough to ensure confidence in the tests - // clang-format off - vector source = { true, false, true, false, true, true, true, false, - true, false, true, false, true, true, true, false, - true, false, true, false, true, true, true, false, - true, false, true, false, true, true, true, false, - true, false, true, false, true, true, true, false, - true, false, true, false, true, true, true, false, - true, false, true, false, true, true, true, false, - true, false, true, false, true, true, true, false, - true, false, true, false, true, true, true, false, - true, false, true, false, true, true, true, false, - true, false, true, false, true, true, true, false, - true, false, true, false, true, true, true, false, - true, false, true, false, true, true, true, false, - true, false, true, false, true, true, true, false, - true, false, true, false, true, true, true, false, - true, false, true, false, true, true, true, false, - true, false, true, false, true, true, true, false - }; - const int counts_true[8] = { 0, 1, 1, 2, 2, 3, 4, 5 }; - const int counts_false[8] = { 0, 0, 1, 1, 2, 2, 2, 2 }; - // clang-format on - const auto expected = div(static_cast(length), 8); + const int counts_true[] = {0, 1, 1, 2, 2, 3, 4, 5}; + const int counts_false[] = {0, 0, 1, 1, 2, 2, 2, 2}; + const auto expected = div(static_cast(length), 8); // No offset { const auto result_true = static_cast(count(source.cbegin(), next(source.cbegin(), length), true)); @@ -253,10 +261,1058 @@ void test_huge_vector_bool() { assert(count(v.begin(), v.end(), false) == large_bit_diff - 3); } +void test_copy_no_offset(const size_t length) { + vector result; + // clang-format off + switch (length) { + case 3: + result = { true, false, true }; + break; + case 8: + result = { true, false, true, false, true, true, true, false }; + break; + case 22: + result = { true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true }; + break; + case 31: + result = { true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true }; + break; + case 32: + result = { true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false }; + break; + case 67: + result = { true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true }; + break; + default: + assert(false); + } + // clang-format on + + { + vector dest(length, false); + const auto res_copy = copy(source.begin(), next(source.begin(), length), dest.begin()); + assert(dest == result); + assert(res_copy == dest.end()); + } + + { + vector dest_n(length, false); + const auto res_copy_n = copy_n(source.begin(), length, dest_n.begin()); + assert(dest_n == result); + assert(res_copy_n == dest_n.end()); + } + + { + vector dest_backward(length, false); + const auto res_copy_backward = copy_backward(source.begin(), next(source.begin(), length), dest_backward.end()); + assert(dest_backward == result); + assert(res_copy_backward == dest_backward.begin()); + } + + { + vector dest_move(length, false); + const auto res_move = move(source.begin(), next(source.begin(), length), dest_move.begin()); + assert(dest_move == result); + assert(res_move == dest_move.end()); + } + + { + vector dest_move_backward(length, false); + const auto res_move_backward = + move_backward(source.begin(), next(source.begin(), length), dest_move_backward.end()); + assert(dest_move_backward == result); + assert(res_move_backward == dest_move_backward.begin()); + } +} + +void test_copy_offset_source(const size_t length) { + vector result; + // clang-format off + switch (length) { + case 3: + result = { false, true, false}; + break; + case 8: + result = { false, true, false, true, true, true, false, + true }; + break; + case 22: + result = { false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true }; + break; + case 31: + result = { false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false }; + break; + case 32: + result = { false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true}; + break; + case 67: + result = { false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false }; + break; + default: + assert(false); + } + // clang-format on + + { + vector dest(length, false); + const auto res_copy = copy(next(source.begin()), next(source.begin(), length + 1), dest.begin()); + assert(dest == result); + assert(res_copy == dest.end()); + } + + { + vector dest_n(length, false); + const auto res_copy_n = copy_n(next(source.begin()), length, dest_n.begin()); + assert(dest_n == result); + assert(res_copy_n == dest_n.end()); + } + + { + vector dest_backward(length, false); + const auto res_copy_backward = + copy_backward(next(source.begin()), next(source.begin(), length + 1), dest_backward.end()); + assert(dest_backward == result); + assert(res_copy_backward == dest_backward.begin()); + } + + { + vector dest_move(length, false); + const auto res_move = move(next(source.begin()), next(source.begin(), length + 1), dest_move.begin()); + assert(dest_move == result); + assert(res_move == dest_move.end()); + } + + { + vector dest_move_backward(length, false); + const auto res_move_backward = + move_backward(next(source.begin()), next(source.begin(), length + 1), dest_move_backward.end()); + assert(dest_move_backward == result); + assert(res_move_backward == dest_move_backward.begin()); + } +} + +void test_copy_offset_dest(const size_t length) { + vector result; + // clang-format off + switch (length) { + case 3: + result = { false, + true, false, true }; + break; + case 8: + result = { false, + true, false, true, false, true, true, true, false }; + break; + case 22: + result = { false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true }; + break; + case 31: + result = { false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true }; + break; + case 32: + result = { false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false }; + break; + case 67: + result = { false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true }; + break; + default: + assert(false); + } + // clang-format on + + { + vector dest(length + 1, false); + const auto res_copy = copy(source.begin(), next(source.begin(), length), next(dest.begin())); + assert(dest == result); + assert(res_copy == dest.end()); + } + + { + vector dest_n(length + 1, false); + const auto res_copy_n = copy_n(source.begin(), length, next(dest_n.begin())); + assert(dest_n == result); + assert(res_copy_n == dest_n.end()); + } + + { + vector dest_backward(length + 1, false); + const auto res_copy_backward = copy_backward(source.begin(), next(source.begin(), length), dest_backward.end()); + assert(dest_backward == result); + assert(res_copy_backward == next(dest_backward.begin())); + } + + { + vector dest_move(length + 1, false); + const auto res_move = move(source.begin(), next(source.begin(), length), next(dest_move.begin())); + assert(dest_move == result); + assert(res_move == dest_move.end()); + } + + { + vector dest_move_backward(length + 1, false); + const auto res_move_backward = + move_backward(source.begin(), next(source.begin(), length), dest_move_backward.end()); + assert(dest_move_backward == result); + assert(res_move_backward == next(dest_move_backward.begin())); + } +} + +void test_copy_offset_match(const size_t length) { + vector result; + // clang-format off + switch (length) { + case 3: + result = { false, + false, true }; + break; + case 8: + result = { false, + false, true, false, true, true, true, false }; + break; + case 22: + result = { false, + false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true }; + break; + case 31: + result = { false, + false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true }; + break; + case 32: + result = { false, + false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false }; + break; + case 67: + result = { false, + false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true }; + break; + default: + assert(false); + } + // clang-format on + + { + vector dest(length, false); + const auto res_copy = copy(next(source.begin()), next(source.begin(), length), next(dest.begin())); + assert(dest == result); + assert(res_copy == dest.end()); + } + + { + vector dest_n(length, false); + const auto res_copy_n = copy_n(next(source.begin()), length - 1, next(dest_n.begin())); + assert(dest_n == result); + assert(res_copy_n == dest_n.end()); + } + + { + vector dest_backward(length, false); + const auto res_copy_backward = + copy_backward(next(source.begin()), next(source.begin(), length), dest_backward.end()); + assert(dest_backward == result); + assert(res_copy_backward == next(dest_backward.begin())); + } + + { + vector dest_move(length, false); + const auto res_move = move(next(source.begin()), next(source.begin(), length), next(dest_move.begin())); + assert(dest_move == result); + assert(res_move == dest_move.end()); + } + + { + vector dest_move_backward(length, false); + const auto res_move_backward = + move_backward(next(source.begin()), next(source.begin(), length), dest_move_backward.end()); + assert(dest_move_backward == result); + assert(res_move_backward == next(dest_move_backward.begin())); + } +} + +void test_copy_offset_mismatch_leftshift(const size_t length) { + vector result; + // clang-format off + switch (length) { + case 3: + result = { false, false, + false, true }; + break; + case 8: + result = { false, false, + false, true, false, true, true, true, false }; + break; + case 22: + result = { false, false, + false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true }; + break; + case 31: + result = { false, false, + false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true }; + break; + case 32: + result = { false, false, + false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false }; + break; + case 67: + result = { false, false, + false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true }; + break; + default: + assert(false); + } + // clang-format on + + { + vector dest(length + 1, false); + const auto res_copy = copy(next(source.begin()), next(source.begin(), length), next(dest.begin(), 2)); + assert(dest == result); + assert(res_copy == dest.end()); + } + + { + vector dest_n(length + 1, false); + const auto res_copy_n = copy_n(next(source.begin()), length - 1, next(dest_n.begin(), 2)); + assert(dest_n == result); + assert(res_copy_n == dest_n.end()); + } + + { + vector dest_backward(length + 1, false); + const auto res_copy_backward = + copy_backward(next(source.begin()), next(source.begin(), length), dest_backward.end()); + assert(dest_backward == result); + assert(res_copy_backward == next(dest_backward.begin(), 2)); + } + + { + vector dest_move(length + 1, false); + const auto res_move = move(next(source.begin()), next(source.begin(), length), next(dest_move.begin(), 2)); + assert(dest_move == result); + assert(res_move == dest_move.end()); + } + + { + vector dest_move_backward(length + 1, false); + const auto res_move_backward = + move_backward(next(source.begin()), next(source.begin(), length), dest_move_backward.end()); + assert(dest_move_backward == result); + assert(res_move_backward == next(dest_move_backward.begin(), 2)); + } +} + +void test_copy_offset_mismatch_rightshift(const size_t length) { + vector result; + // clang-format off + switch (length) { + case 3: + result = { false, + true, false }; + break; + case 8: + result = { false, + true, false, true, true, true, false, + true }; + break; + case 22: + result = { false, + true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true }; + break; + case 31: + result = { false, + true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false }; + break; + case 32: + result = { false, + true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true }; + break; + case 67: + result = { false, + true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false }; + break; + default: + assert(false); + } + // clang-format on + + { + vector dest(length, false); + const auto res_copy = copy(next(source.begin(), 2), next(source.begin(), length + 1), next(dest.begin())); + assert(dest == result); + assert(res_copy == dest.end()); + } + + { + vector dest_n(length, false); + const auto res_copy_n = copy_n(next(source.begin(), 2), length - 1, next(dest_n.begin())); + assert(dest_n == result); + assert(res_copy_n == dest_n.end()); + } + + { + vector dest_backward(length, false); + const auto res_copy_backward = + copy_backward(next(source.begin(), 2), next(source.begin(), length + 1), dest_backward.end()); + assert(dest_backward == result); + assert(res_copy_backward == next(dest_backward.begin())); + } + + { + vector dest_move(length, false); + const auto res_move = move(next(source.begin(), 2), next(source.begin(), length + 1), next(dest_move.begin())); + assert(dest_move == result); + assert(res_move == dest_move.end()); + } + + { + vector dest_move_backward(length, false); + const auto res_move_backward = + move_backward(next(source.begin(), 2), next(source.begin(), length + 1), dest_move_backward.end()); + assert(dest_move_backward == result); + assert(res_move_backward == next(dest_move_backward.begin())); + } +} + +void test_copy_offset_aligned(const size_t length) { + vector result; + // clang-format off + switch (length) { + case 3: + result = { false, + false, true }; + break; + case 8: + result = { false, + false, true, false, true, true, true, false }; + break; + case 22: + result = { false, + false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true }; + break; + case 31: + result = { false, + false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true }; + break; + case 32: + result = { false, + false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false }; + break; + case 67: + result = { false, + false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true, false, true, true, true, false, + true, false, true }; + break; + default: + assert(false); + } + // clang-format on + + { + vector dest(length, false); + const auto res_copy = copy(next(source.begin(), 9), next(source.begin(), length + 8), next(dest.begin())); + assert(dest == result); + assert(res_copy == dest.end()); + } + + { + vector dest_n(length, false); + const auto res_copy_n = copy_n(next(source.begin(), 9), length - 1, next(dest_n.begin())); + assert(dest_n == result); + assert(res_copy_n == dest_n.end()); + } + + { + vector dest_backward(length, false); + const auto res_copy_backward = + copy_backward(next(source.begin(), 9), next(source.begin(), length + 8), dest_backward.end()); + assert(dest_backward == result); + assert(res_copy_backward == next(dest_backward.begin())); + } + + { + vector dest_move(length, false); + const auto res_move = move(next(source.begin(), 9), next(source.begin(), length + 8), next(dest_move.begin())); + assert(dest_move == result); + assert(res_move == dest_move.end()); + } + + { + vector dest_move_backward(length, false); + const auto res_move_backward = + move_backward(next(source.begin(), 9), next(source.begin(), length + 8), dest_move_backward.end()); + assert(dest_move_backward == result); + assert(res_move_backward == next(dest_move_backward.begin())); + } +} + +void test_copy_sub_char() { + { // sub char copy unaligned + const vector result = {false, false, true, false, true, false, false, false}; + + { + vector dest(8, false); + const auto res_copy = copy(source.begin(), next(source.begin(), 3), next(dest.begin(), 2)); + assert(dest == result); + assert(res_copy == next(dest.begin(), 5)); + } + + { + vector dest_n(8, false); + const auto res_copy_n = copy_n(source.begin(), 3, next(dest_n.begin(), 2)); + assert(dest_n == result); + assert(res_copy_n == next(dest_n.begin(), 5)); + } + + { + vector dest_backward(8, false); + const auto res_copy_backward = + copy_backward(source.begin(), next(source.begin(), 3), next(dest_backward.begin(), 5)); + assert(dest_backward == result); + assert(res_copy_backward == next(dest_backward.begin(), 2)); + } + + { + vector dest_move(8, false); + const auto res_move = move(source.begin(), next(source.begin(), 3), next(dest_move.begin(), 2)); + assert(dest_move == result); + assert(res_move == next(dest_move.begin(), 5)); + } + + { + vector dest_move_backward(8, false); + const auto res_move_backward = + move_backward(source.begin(), next(source.begin(), 3), next(dest_move_backward.begin(), 5)); + assert(dest_move_backward == result); + assert(res_move_backward == next(dest_move_backward.begin(), 2)); + } + } + + { // sub char copy until char alignment source + const vector result = {false, false, true, true, false, false, false, false}; + + { + vector dest(8, false); + const auto res_copy = copy(next(source.begin(), 5), next(source.begin(), 8), next(dest.begin(), 2)); + assert(dest == result); + assert(res_copy == next(dest.begin(), 5)); + } + + { + vector dest_n(8, false); + const auto res_copy_n = copy_n(next(source.begin(), 5), 3, next(dest_n.begin(), 2)); + assert(dest_n == result); + assert(res_copy_n == next(dest_n.begin(), 5)); + } + + { + vector dest_backward(8, false); + const auto res_copy_backward = + copy_backward(next(source.begin(), 5), next(source.begin(), 8), next(dest_backward.begin(), 5)); + assert(dest_backward == result); + assert(res_copy_backward == next(dest_backward.begin(), 2)); + } + + { + vector dest_move(8, false); + const auto res_move = move(next(source.begin(), 5), next(source.begin(), 8), next(dest_move.begin(), 2)); + assert(dest_move == result); + assert(res_move == next(dest_move.begin(), 5)); + } + + { + vector dest_move_backward(8, false); + const auto res_move_backward = + move_backward(next(source.begin(), 5), next(source.begin(), 8), next(dest_move_backward.begin(), 5)); + assert(dest_move_backward == result); + assert(res_move_backward == next(dest_move_backward.begin(), 2)); + } + } + + { // sub char copy until char alignment dest + const vector result = {false, false, false, false, false, true, false, true, false, false, false, false, + false, false, false, false}; + + { + vector dest(16, false); + const auto res_copy = copy(source.begin(), next(source.begin(), 3), next(dest.begin(), 5)); + assert(dest == result); + assert(res_copy == next(dest.begin(), 8)); + } + + { + vector dest_n(16, false); + const auto res_copy_n = copy_n(source.begin(), 3, next(dest_n.begin(), 5)); + assert(dest_n == result); + assert(res_copy_n == next(dest_n.begin(), 8)); + } + + { + vector dest_backward(16, false); + const auto res_copy_backward = + copy_backward(source.begin(), next(source.begin(), 3), next(dest_backward.begin(), 8)); + assert(dest_backward == result); + assert(res_copy_backward == next(dest_backward.begin(), 5)); + } + + { + vector dest_move(16, false); + const auto res_move = move(source.begin(), next(source.begin(), 3), next(dest_move.begin(), 5)); + assert(dest_move == result); + assert(res_move == next(dest_move.begin(), 8)); + } + + { + vector dest_move_backward(16, false); + const auto res_move_backward = + move_backward(source.begin(), next(source.begin(), 3), next(dest_move_backward.begin(), 8)); + assert(dest_move_backward == result); + assert(res_move_backward == next(dest_move_backward.begin(), 5)); + } + } + + { // sub char copy over char alignment source + const vector result = {false, false, false, true, false, false, false, false}; + + { + vector dest(8, false); + const auto res_copy = copy(next(source.begin(), 7), next(source.begin(), 10), next(dest.begin(), 2)); + assert(dest == result); + assert(res_copy == next(dest.begin(), 5)); + } + + { + vector dest_n(8, false); + const auto res_copy_n = copy_n(next(source.begin(), 7), 3, next(dest_n.begin(), 2)); + assert(dest_n == result); + assert(res_copy_n == next(dest_n.begin(), 5)); + } + + { + vector dest_backward(8, false); + const auto res_copy_backward = + copy_backward(next(source.begin(), 7), next(source.begin(), 10), next(dest_backward.begin(), 5)); + assert(dest_backward == result); + assert(res_copy_backward == next(dest_backward.begin(), 2)); + } + + { + vector dest_move(8, false); + const auto res_move = move(next(source.begin(), 7), next(source.begin(), 10), next(dest_move.begin(), 2)); + assert(dest_move == result); + assert(res_move == next(dest_move.begin(), 5)); + } + + { + vector dest_move_backward(8, false); + const auto res_move_backward = + move_backward(next(source.begin(), 7), next(source.begin(), 10), next(dest_move_backward.begin(), 5)); + assert(dest_move_backward == result); + assert(res_move_backward == next(dest_move_backward.begin(), 2)); + } + } + + { // sub char copy over char alignment dest + const vector result = {false, false, false, false, false, false, false, true, false, true, false, false, + false, false, false, false}; + + { + vector dest(16, false); + const auto res_copy = copy(source.begin(), next(source.begin(), 3), next(dest.begin(), 7)); + assert(dest == result); + assert(res_copy == next(dest.begin(), 10)); + } + + { + vector dest_n(16, false); + const auto res_copy_n = copy_n(source.begin(), 3, next(dest_n.begin(), 7)); + assert(dest_n == result); + assert(res_copy_n == next(dest_n.begin(), 10)); + } + + { + vector dest_backward(16, false); + const auto res_copy_backward = + copy_backward(source.begin(), next(source.begin(), 3), next(dest_backward.begin(), 10)); + assert(dest_backward == result); + assert(res_copy_backward == next(dest_backward.begin(), 7)); + } + + { + vector dest_move(16, false); + const auto res_move = move(source.begin(), next(source.begin(), 3), next(dest_move.begin(), 7)); + assert(dest_move == result); + assert(res_move == next(dest_move.begin(), 10)); + } + + { + vector dest_move_backward(16, false); + const auto res_move_backward = + move_backward(source.begin(), next(source.begin(), 3), next(dest_move_backward.begin(), 10)); + assert(dest_move_backward == result); + assert(res_move_backward == next(dest_move_backward.begin(), 7)); + } + } +} + +void test_copy_regression() { + // This specific case was found by the randomized coverage below. + const vector src = {0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, + 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0}; + + vector dst = {0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1}; + + const int src_prefix = 24; + const int dst_prefix = 7; + const int copy_len = 48; + + copy(src.begin() + src_prefix, src.begin() + src_prefix + copy_len, dst.begin() + dst_prefix); + + const vector correct = {0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1}; + + assert(dst == correct); +} + +bool test_copy() { + test_copy_no_offset(3); + test_copy_no_offset(8); + test_copy_no_offset(22); + test_copy_no_offset(31); + test_copy_no_offset(32); + test_copy_no_offset(67); + + test_copy_offset_source(3); + test_copy_offset_source(8); + test_copy_offset_source(22); + test_copy_offset_source(31); + test_copy_offset_source(32); + test_copy_offset_source(67); + + test_copy_offset_dest(3); + test_copy_offset_dest(8); + test_copy_offset_dest(22); + test_copy_offset_dest(31); + test_copy_offset_dest(32); + test_copy_offset_dest(67); + + test_copy_offset_match(3); + test_copy_offset_match(8); + test_copy_offset_match(22); + test_copy_offset_match(31); + test_copy_offset_match(32); + test_copy_offset_match(67); + + test_copy_offset_mismatch_leftshift(3); + test_copy_offset_mismatch_leftshift(8); + test_copy_offset_mismatch_leftshift(22); + test_copy_offset_mismatch_leftshift(31); + test_copy_offset_mismatch_leftshift(32); + test_copy_offset_mismatch_leftshift(67); + + test_copy_offset_mismatch_rightshift(3); + test_copy_offset_mismatch_rightshift(8); + test_copy_offset_mismatch_rightshift(22); + test_copy_offset_mismatch_rightshift(31); + test_copy_offset_mismatch_rightshift(32); + test_copy_offset_mismatch_rightshift(67); + + test_copy_offset_aligned(3); + test_copy_offset_aligned(8); + test_copy_offset_aligned(22); + test_copy_offset_aligned(31); + test_copy_offset_aligned(32); + test_copy_offset_aligned(67); + + test_copy_sub_char(); + + test_copy_regression(); + + return true; +} + +void initialize_randomness(mt19937_64& gen) { + constexpr size_t n = mt19937_64::state_size; + constexpr size_t w = mt19937_64::word_size; + static_assert(w % 32 == 0, "w should be evenly divisible by 32"); + constexpr size_t k = w / 32; + + vector vec(n * k); + + random_device rd; + generate(vec.begin(), vec.end(), ref(rd)); + + printf("This is a randomized test.\n"); + printf("DO NOT IGNORE/RERUN ANY FAILURES.\n"); + printf("You must report them to the STL maintainers.\n\n"); + + seed_seq seq(vec.cbegin(), vec.cend()); + gen.seed(seq); +} + +template +void print_vec(const char* const name, const vector& v) { + printf("%s: ", name); + for (const auto& e : v) { + printf("%d", static_cast(e)); + } + printf("\n"); +} + +void randomized_test_copy(mt19937_64& gen) { + uniform_int_distribution affix_dist{0, 2 * blockSize - 1}; // from nothing to a partial then whole block + uniform_int_distribution copy_len_dist{1, 3 * blockSize}; // from 1 bit to leading/middle/trailing blocks + auto bool_dist = [&gen] { return static_cast(gen() & 1); }; + + constexpr int repetitions = 10'000; // tune the number of tests to balance coverage vs. execution time + + for (int k = 0; k < repetitions; ++k) { + const int src_prefix = affix_dist(gen); + const int dst_prefix = affix_dist(gen); + const int copy_len = copy_len_dist(gen); + const int src_suffix = affix_dist(gen); + const int dst_suffix = affix_dist(gen); + + // src vector: + // dst vector: + + vector vb_src(src_prefix + copy_len + src_suffix); + vector vb_dst(dst_prefix + copy_len + dst_suffix); + + generate(vb_src.begin(), vb_src.end(), bool_dist); + generate(vb_dst.begin(), vb_dst.end(), bool_dist); + + const vector v8_src(vb_src.cbegin(), vb_src.cend()); + vector v8_dst(vb_dst.cbegin(), vb_dst.cend()); + + const vector orig_v8_dst = v8_dst; + + copy(vb_src.cbegin() + src_prefix, vb_src.cbegin() + src_prefix + copy_len, vb_dst.begin() + dst_prefix); + copy(v8_src.cbegin() + src_prefix, v8_src.cbegin() + src_prefix + copy_len, v8_dst.begin() + dst_prefix); + + if (!equal(vb_dst.cbegin(), vb_dst.cend(), v8_dst.cbegin(), v8_dst.cend(), equal_to{})) { + printf("src_prefix: %d\n", src_prefix); + printf("dst_prefix: %d\n", dst_prefix); + printf(" copy_len: %d\n", copy_len); + printf("src_suffix: %d\n", src_suffix); + printf("dst_suffix: %d\n", dst_suffix); + + print_vec(" Src", v8_src); + print_vec("Original", orig_v8_dst); + print_vec(" Got", vb_dst); + print_vec("Expected", v8_dst); + + assert(false); + } + } + + // Overlapping is permitted when the dst range starts before the src range. + for (int k = 0; k < repetitions; ++k) { + const int prefix = affix_dist(gen); + const int copy_len = copy_len_dist(gen); + const int overhang = uniform_int_distribution{1, copy_len + 30}(gen); + const int suffix = affix_dist(gen); + + // An overhang of 1 results in the maximum possible overlap. + // An overhang of copy_len results in non-overlapping but adjacent ranges. + // An overhang of copy_len + 30 is the maximum value where the dst and src ranges could share a block. + + // Vector diagram: + // + // ^ + // + + vector vb(prefix + overhang + copy_len + suffix); + + generate(vb.begin(), vb.end(), bool_dist); + + vector v8(vb.cbegin(), vb.cend()); + + const vector orig_v8 = v8; + + copy(vb.cbegin() + prefix + overhang, vb.cbegin() + prefix + overhang + copy_len, vb.begin() + prefix); + copy(v8.cbegin() + prefix + overhang, v8.cbegin() + prefix + overhang + copy_len, v8.begin() + prefix); + + if (!equal(vb.cbegin(), vb.cend(), v8.cbegin(), v8.cend(), equal_to{})) { + printf(" prefix: %d\n", prefix); + printf("copy_len: %d\n", copy_len); + printf("overhang: %d\n", overhang); + printf(" suffix: %d\n", suffix); + + print_vec("Original", orig_v8); + print_vec("Got", vb); + print_vec("Expected", v8); + + assert(false); + } + } + + uniform_int_distribution gap_dist{0, 30}; // 0 gap is adjacent; 30 is the max gap between 2 bits in a block + + // One more interesting case: when the src range is before the dst range, + // and they're non-overlapping but close enough that they could share a block. + for (int k = 0; k < repetitions; ++k) { + const int prefix = affix_dist(gen); + const int copy_len = copy_len_dist(gen); + const int gap = gap_dist(gen); + const int suffix = affix_dist(gen); + + // Vector diagram: + // + + vector vb(prefix + copy_len + gap + copy_len + suffix); + + generate(vb.begin(), vb.end(), bool_dist); + + vector v8(vb.cbegin(), vb.cend()); + + const vector orig_v8 = v8; + + copy(vb.cbegin() + prefix, vb.cbegin() + prefix + copy_len, vb.begin() + prefix + copy_len + gap); + copy(v8.cbegin() + prefix, v8.cbegin() + prefix + copy_len, v8.begin() + prefix + copy_len + gap); + + if (!equal(vb.cbegin(), vb.cend(), v8.cbegin(), v8.cend(), equal_to{})) { + printf(" prefix: %d\n", prefix); + printf("copy_len: %d\n", copy_len); + printf(" gap: %d\n", gap); + printf(" suffix: %d\n", suffix); + + print_vec("Original", orig_v8); + print_vec("Got", vb); + print_vec("Expected", v8); + + assert(false); + } + } +} + int main() { test_fill(); test_find(); test_count(); + test_copy(); test_huge_vector_bool(); + + mt19937_64 gen; + initialize_randomness(gen); + randomized_test_copy(gen); } diff --git a/tests/std/tests/GH_003570_allocate_at_least/test.cpp b/tests/std/tests/GH_003570_allocate_at_least/test.cpp index 1814ff4e2bd..37408cf4782 100644 --- a/tests/std/tests/GH_003570_allocate_at_least/test.cpp +++ b/tests/std/tests/GH_003570_allocate_at_least/test.cpp @@ -51,7 +51,7 @@ struct signalling_allocator { allocation_result allocate_at_least(size_t count) { allocate_at_least_signal.set(); - return {allocate(count * 2), count * 2}; + return {allocate(count * 2 + 1), count * 2 + 1}; } void deallocate(T* ptr, size_t) noexcept { @@ -72,10 +72,15 @@ void test_container() { } void test_deque() { - deque> d; - d.resize(100); + deque> d; + for (size_t i = 0; i < 100; ++i) { + d.push_back(i); + } assert(allocate_at_least_signal.consume()); assert(d.size() == 100); + for (size_t i = 0; i < 100; ++i) { + assert(d[i] == i); + } } void test_stream_overflow(auto& stream) { diff --git a/tests/std/tests/P2286R8_formatting_ranges/env.lst b/tests/std/tests/GH_004023_mdspan_fwd_prod_overflow/env.lst similarity index 100% rename from tests/std/tests/P2286R8_formatting_ranges/env.lst rename to tests/std/tests/GH_004023_mdspan_fwd_prod_overflow/env.lst diff --git a/tests/std/tests/GH_004023_mdspan_fwd_prod_overflow/test.compile.pass.cpp b/tests/std/tests/GH_004023_mdspan_fwd_prod_overflow/test.compile.pass.cpp new file mode 100644 index 00000000000..48095f66fe1 --- /dev/null +++ b/tests/std/tests/GH_004023_mdspan_fwd_prod_overflow/test.compile.pass.cpp @@ -0,0 +1,79 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include + +using namespace std; + +struct layout_packed_upper { // LAPACK packed storage, VERY INCOMPLETE + template + class mapping { + public: + using extents_type = Extents; + using index_type = extents_type::index_type; + using size_type = extents_type::size_type; + using rank_type = extents_type::rank_type; + using layout_type = layout_packed_upper; + + constexpr mapping() noexcept = default; + constexpr mapping(const extents_type& ex_) : ex{ex_} {} + + constexpr const extents_type& extents() const { + return ex; + } + + constexpr index_type required_span_size() const { + if (dim % 2 == 0) { + return (dim / 2) * (dim + 1); + } else { + return ((dim + 1) / 2) * dim; + } + } + + private: + extents_type ex = extents_type(); + index_type dim = ex.extent(0); + }; +}; + +int main() { + constexpr int32_t dim = 47'000; // sqrt(2^32) > dim > sqrt(2^31), dim assumed even below + constexpr auto expected_size = [] { + int32_t unused; + bool overflow = _Mul_overflow(dim, dim, unused); + assert(overflow); + + using UType = remove_cv_t>; + const auto udim = static_cast(dim); + UType result{}; + overflow = _Mul_overflow(udim, udim, result); + assert(!overflow); + return result; + }(); + + constexpr auto expected_req_size = [] { + int32_t result{}; + const bool overflow = _Mul_overflow(dim / 2, dim + 1, result); + assert(!overflow); + return result; + }(); + + { + using E = extents; + constexpr mdspan m(nullptr); + static_assert(m.size() == expected_size); + static_assert(m.mapping().required_span_size() == expected_req_size); + } + + { + using E = dextents; + constexpr mdspan m(nullptr, dim, dim); + static_assert(m.size() == expected_size); + static_assert(m.mapping().required_span_size() == expected_req_size); + } + + return 0; +} diff --git a/tests/std/tests/P0220R1_any/test.cpp b/tests/std/tests/P0220R1_any/test.cpp index 6d3d25e3552..23b1a93fb57 100644 --- a/tests/std/tests/P0220R1_any/test.cpp +++ b/tests/std/tests/P0220R1_any/test.cpp @@ -2570,21 +2570,41 @@ namespace msvc { // empty any a; a = std::move(a); + assertEmpty(a); + + a = std::make_any(); + a = any_cast(std::move(a)); // extract inner any + assertEmpty(a); } { // small any a{small{42}}; a = std::move(a); + assertContains(a, 42); + + a = std::make_any(small{42}); + a = any_cast(std::move(a)); // extract inner any + assertContains(a, 42); } { // large any a{large{42}}; a = std::move(a); + assertContains(a, 42); + + a = std::make_any(large{42}); + a = any_cast(std::move(a)); // extract inner any + assertContains(a, 42); } { // trivial any a{int{42}}; a = std::move(a); + assertContains(a, 42); + + a = std::make_any(int{42}); + a = any_cast(std::move(a)); // extract inner any + assertContains(a, 42); } } #ifdef __clang__ @@ -3160,6 +3180,40 @@ namespace msvc { } #pragma warning(pop) } // namespace trivial + +#ifndef _M_CEE // TRANSITION, VSO-1659496 + namespace gh_140_robust_against_adl { + struct incomplete; + + template + struct wrapper { + T t; + }; + + template + void test_for() { + any a; + a = any{Type()}; + a = any{std::in_place_type}; + a = Type(); + a = std::make_any(); + a.emplace(); + assert(any_cast(&a) != nullptr); + } + + void run_test() { + using _trivial = wrapper*; + using _small = std::pair<_trivial, small>; + using _large = std::pair<_trivial, large>; + + globalMemCounter.disable_allocations = true; + test_for<_trivial>(); + test_for<_small>(); + globalMemCounter.disable_allocations = false; + test_for<_large>(); + } + } // namespace gh_140_robust_against_adl +#endif // _M_CEE } // namespace msvc int main() { @@ -3196,4 +3250,7 @@ int main() { msvc::size_and_alignment::run_test(); msvc::small_type::run_test(); msvc::trivial::run_test(); +#ifndef _M_CEE // TRANSITION, VSO-1659496 + msvc::gh_140_robust_against_adl::run_test(); +#endif // _M_CEE } diff --git a/tests/std/tests/P2286R8_text_formatting_debug_enabled_specializations/env.lst b/tests/std/tests/P2286R8_text_formatting_debug_enabled_specializations/env.lst new file mode 100644 index 00000000000..18e2d7c71ec --- /dev/null +++ b/tests/std/tests/P2286R8_text_formatting_debug_enabled_specializations/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\concepts_latest_matrix.lst diff --git a/tests/std/tests/P2286R8_text_formatting_debug_enabled_specializations/test.cpp b/tests/std/tests/P2286R8_text_formatting_debug_enabled_specializations/test.cpp new file mode 100644 index 00000000000..d5ac1fad875 --- /dev/null +++ b/tests/std/tests/P2286R8_text_formatting_debug_enabled_specializations/test.cpp @@ -0,0 +1,211 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define STR(Str) TYPED_LITERAL(CharT, Str) + +using namespace std; + +template +concept DebugEnabledSpecialization = is_default_constructible_v && requires(F& fmt) { + { fmt.set_debug_format() } noexcept -> same_as; +}; + +template +consteval bool check_debug_enabled_specializations() { + static_assert(DebugEnabledSpecialization>); + static_assert(DebugEnabledSpecialization>); + static_assert(DebugEnabledSpecialization>); + static_assert(DebugEnabledSpecialization>); + static_assert(DebugEnabledSpecialization>); + static_assert(DebugEnabledSpecialization, CharT>>); + static_assert(DebugEnabledSpecialization, CharT>>); + static_assert(DebugEnabledSpecialization, CharT>>); + + static_assert(!DebugEnabledSpecialization>); + static_assert(!DebugEnabledSpecialization>); + static_assert(!DebugEnabledSpecialization>); + static_assert(!DebugEnabledSpecialization>); + static_assert(!DebugEnabledSpecialization>); + + static_assert(!DebugEnabledSpecialization>); + // NB: formatter is special case, see below + static_assert(!DebugEnabledSpecialization>); + static_assert(!DebugEnabledSpecialization>); + static_assert(!DebugEnabledSpecialization>); + + static_assert(!DebugEnabledSpecialization>); + static_assert(!DebugEnabledSpecialization>); + static_assert(!DebugEnabledSpecialization>); + static_assert(!DebugEnabledSpecialization>); + + // NB: wchar_t might be defined as a typedef for unsigned short (with '/Zc:wchar_t-') + static_assert(DebugEnabledSpecialization> == same_as); + + return true; +} + +template +struct Holder { + char narrow_ch; + CharT ch; + const CharT* const_ptr; + basic_string str; + CharT* non_const_ptr; + basic_string_view str_view; + CharT arr[11]; +}; + +// holder-format-specs: +// member debug-format(opt) +// member: +// 0 1 2 ... N (index of member object, single digit) +// debug-format: +// $ (use debug format) +template +struct std::formatter, CharT> { +public: + constexpr auto parse(basic_format_parse_context& ctx) { + auto it = ctx.begin(); + if (it == ctx.end() || *it == STR('}')) { + throw format_error{"Invalid holder-format-specs."}; + } + + if (STR('0') <= *it && *it <= STR('9')) { + member_index = *it - STR('0'); + } else { + throw format_error{"Expected member index in holder-format-specs."}; + } + + ++it; + if (it == ctx.end() || *it == STR('}')) { + return it; + } + + if (*it == '$') { + switch (member_index) { + case 0: + fmt0.set_debug_format(); + break; + case 1: + fmt1.set_debug_format(); + break; + case 2: + fmt2.set_debug_format(); + break; + case 3: + fmt3.set_debug_format(); + break; + case 4: + fmt4.set_debug_format(); + break; + case 5: + fmt5.set_debug_format(); + break; + case 6: + fmt6.set_debug_format(); + break; + } + } else { + throw format_error{"Unexpected symbols in holder-format-specs."}; + } + + ++it; + if (it != ctx.end() && *it != STR('}')) { + throw format_error{"Expected '}' at the end of holder-format-specs."}; + } + + return it; + } + + template + auto format(const Holder& val, FormatContext& ctx) const { + switch (member_index) { + case 0: + return fmt0.format(val.narrow_ch, ctx); + case 1: + return fmt1.format(val.ch, ctx); + case 2: + return fmt2.format(val.const_ptr, ctx); + case 3: + return fmt3.format(val.str, ctx); + case 4: + return fmt4.format(val.non_const_ptr, ctx); + case 5: + return fmt5.format(val.str_view, ctx); + case 6: + return fmt6.format(val.arr, ctx); + } + + unreachable(); + } + +private: + int member_index{-1}; + + formatter fmt0; + formatter fmt1; + formatter fmt2; + formatter, CharT> fmt3; + formatter fmt4; + formatter, CharT> fmt5; + formatter fmt6; +}; + +template +void check_set_debug_format_function() { + Holder val; + + val.narrow_ch = '\t'; + val.ch = STR('\t'); + val.const_ptr = STR("const\tCharT\t*"); + val.str = STR("basic\tstring"); + val.non_const_ptr = val.str.data(); + val.str_view = STR("basic\tstring\tview"); + ranges::copy(STR("CharT\t[11]\0"sv), val.arr); + + assert(format(STR("{:0}"), val) == STR("\t")); + assert(format(STR("{:1}"), val) == STR("\t")); + assert(format(STR("{:2}"), val) == STR("const\tCharT\t*")); + assert(format(STR("{:3}"), val) == STR("basic\tstring")); + assert(format(STR("{:4}"), val) == STR("basic\tstring")); + assert(format(STR("{:5}"), val) == STR("basic\tstring\tview")); + assert(format(STR("{:6}"), val) == STR("CharT\t[11]")); + + assert(format(STR("{:0$}"), val) == STR(R"('\t')")); + assert(format(STR("{:1$}"), val) == STR(R"('\t')")); + assert(format(STR("{:2$}"), val) == STR(R"("const\tCharT\t*")")); + assert(format(STR("{:3$}"), val) == STR(R"("basic\tstring")")); + assert(format(STR("{:4$}"), val) == STR(R"("basic\tstring")")); + assert(format(STR("{:5$}"), val) == STR(R"("basic\tstring\tview")")); + assert(format(STR("{:6$}"), val) == STR(R"("CharT\t[11]")")); +} + +void set_debug_format(auto&) {} + +struct name_lookup_in_formatter_checker : formatter { + auto parse(auto& ctx) { // COMPILE-ONLY + set_debug_format(*this); + return ctx.begin(); + } +}; + +int main() { + static_assert(check_debug_enabled_specializations()); + static_assert(check_debug_enabled_specializations()); + + check_set_debug_format_function(); + check_set_debug_format_function(); +} diff --git a/tests/std/tests/P2286R8_text_formatting_escaping/env.lst b/tests/std/tests/P2286R8_text_formatting_escaping/env.lst new file mode 100644 index 00000000000..18e2d7c71ec --- /dev/null +++ b/tests/std/tests/P2286R8_text_formatting_escaping/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\concepts_latest_matrix.lst diff --git a/tests/std/tests/P2286R8_formatting_ranges/test.cpp b/tests/std/tests/P2286R8_text_formatting_escaping/test.cpp similarity index 100% rename from tests/std/tests/P2286R8_formatting_ranges/test.cpp rename to tests/std/tests/P2286R8_text_formatting_escaping/test.cpp diff --git a/tests/std/tests/P2286R8_formatting_ranges_legacy_text_encoding/env.lst b/tests/std/tests/P2286R8_text_formatting_escaping_legacy_text_encoding/env.lst similarity index 100% rename from tests/std/tests/P2286R8_formatting_ranges_legacy_text_encoding/env.lst rename to tests/std/tests/P2286R8_text_formatting_escaping_legacy_text_encoding/env.lst diff --git a/tests/std/tests/P2286R8_formatting_ranges_legacy_text_encoding/test.cpp b/tests/std/tests/P2286R8_text_formatting_escaping_legacy_text_encoding/test.cpp similarity index 100% rename from tests/std/tests/P2286R8_formatting_ranges_legacy_text_encoding/test.cpp rename to tests/std/tests/P2286R8_text_formatting_escaping_legacy_text_encoding/test.cpp diff --git a/tests/std/tests/P2286R8_formatting_ranges_utf8/env.lst b/tests/std/tests/P2286R8_text_formatting_escaping_utf8/env.lst similarity index 100% rename from tests/std/tests/P2286R8_formatting_ranges_utf8/env.lst rename to tests/std/tests/P2286R8_text_formatting_escaping_utf8/env.lst diff --git a/tests/std/tests/P2286R8_formatting_ranges_utf8/test.cpp b/tests/std/tests/P2286R8_text_formatting_escaping_utf8/test.cpp similarity index 100% rename from tests/std/tests/P2286R8_formatting_ranges_utf8/test.cpp rename to tests/std/tests/P2286R8_text_formatting_escaping_utf8/test.cpp diff --git a/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp b/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp index d697fc595a2..9585dca3ea9 100644 --- a/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp +++ b/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp @@ -34,6 +34,160 @@ _CONSTEXPR20 void assert_is_permutation(const Container& cont, initializer_list< assert(is_permutation(cont.begin(), cont.end(), il.begin(), il.end())); } +class test_leak { +private: + char* res; + +public: + test_leak(const test_leak&) = delete; + test_leak& operator=(const test_leak&) = delete; + + _CONSTEXPR20 test_leak() noexcept /* terminates */ : res(allocator{}.allocate(1)) {} + _CONSTEXPR20 ~test_leak() { + allocator{}.deallocate(res, 1); + } +}; + +template +class nontrivial_pointer : private test_leak { +public: + T* ptr; + _CONSTEXPR20 nontrivial_pointer() noexcept : ptr(nullptr) {} + _CONSTEXPR20 explicit nontrivial_pointer(T* ptr_) noexcept : ptr(ptr_) {} + _CONSTEXPR20 /*implicit*/ nontrivial_pointer(nullptr_t) noexcept : ptr(nullptr) {} + + _CONSTEXPR20 nontrivial_pointer(const nontrivial_pointer& other) noexcept : ptr(other.ptr) {} + template , int> = 0> + _CONSTEXPR20 nontrivial_pointer(const nontrivial_pointer& other) noexcept : ptr(other.ptr) {} + _CONSTEXPR20 nontrivial_pointer& operator=(const nontrivial_pointer& other) noexcept { + ptr = other.ptr; + return *this; + } + + _CONSTEXPR20 ~nontrivial_pointer() = default; + + _CONSTEXPR20 explicit operator bool() const noexcept { +#ifdef __EDG__ // TRANSITION, VSO-1888157 + return static_cast(ptr); +#else // ^^^ workaround / no workaround vvv + return ptr != nullptr; +#endif // ^^^ no workaround ^^^ + } + _CONSTEXPR20 add_lvalue_reference_t operator*() const noexcept { + return *ptr; + } + _CONSTEXPR20 T* operator->() const noexcept { + return ptr; + } + template , int> = 0> + _CONSTEXPR20 add_lvalue_reference_t operator[](I off) const noexcept { + return ptr[off]; + } + + _CONSTEXPR20 nontrivial_pointer& operator++() noexcept { + ++ptr; + return *this; + } + _CONSTEXPR20 nontrivial_pointer operator++(int) noexcept { + return nontrivial_pointer(ptr++); + } + _CONSTEXPR20 nontrivial_pointer& operator--() noexcept { + --ptr; + return *this; + } + _CONSTEXPR20 nontrivial_pointer operator--(int) noexcept { + return nontrivial_pointer(ptr--); + } + template , int> = 0> + _CONSTEXPR20 nontrivial_pointer& operator+=(I diff) noexcept { + ptr += diff; + return *this; + } + template , int> = 0> + _CONSTEXPR20 nontrivial_pointer& operator-=(I diff) noexcept { + ptr -= diff; + return *this; + } + + template , int> = 0> + friend _CONSTEXPR20 nontrivial_pointer operator+(nontrivial_pointer ptr, I diff) noexcept { + return ptr += diff; + } + template , int> = 0> + friend _CONSTEXPR20 nontrivial_pointer operator+(I diff, nontrivial_pointer ptr) noexcept { + return ptr += diff; + } + friend _CONSTEXPR20 ptrdiff_t operator-(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { + return lhs.ptr - rhs.ptr; + } + template , int> = 0> + friend _CONSTEXPR20 nontrivial_pointer operator-(nontrivial_pointer ptr, I diff) noexcept { + return ptr -= diff; + } + + friend _CONSTEXPR20 bool operator==(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { + return lhs.ptr == rhs.ptr; + } + friend _CONSTEXPR20 bool operator==(nontrivial_pointer ptr, nullptr_t) noexcept { + return !ptr; + } + friend _CONSTEXPR20 bool operator==(nullptr_t, nontrivial_pointer ptr) noexcept { + return !ptr; + } + friend _CONSTEXPR20 bool operator!=(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { + return lhs.ptr != rhs.ptr; + } + friend _CONSTEXPR20 bool operator!=(nontrivial_pointer ptr, nullptr_t) noexcept { + return static_cast(ptr); + } + friend _CONSTEXPR20 bool operator!=(nullptr_t, nontrivial_pointer ptr) noexcept { + return static_cast(ptr); + } + friend _CONSTEXPR20 bool operator<(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { + return lhs.ptr < rhs.ptr; + } + friend _CONSTEXPR20 bool operator<=(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { + return lhs.ptr <= rhs.ptr; + } + friend _CONSTEXPR20 bool operator>(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { + return lhs.ptr > rhs.ptr; + } + friend _CONSTEXPR20 bool operator>=(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { + return lhs.ptr >= rhs.ptr; + } +}; + +template > +struct impl_pointer_to { + // no pointer_to for void +}; + +template +struct impl_pointer_to { + static constexpr nontrivial_pointer pointer_to(T& r) noexcept { + return nontrivial_pointer(addressof(r)); + } +}; + +template +struct std::pointer_traits> : impl_pointer_to { + using pointer = nontrivial_pointer; + using element_type = T; + using difference_type = ptrdiff_t; + + template + using rebind = nontrivial_pointer; +}; + +template +struct std::iterator_traits> { + using iterator_category = random_access_iterator_tag; + using difference_type = ptrdiff_t; + using value_type = remove_const_t; + using reference = add_lvalue_reference_t; + using pointer = nontrivial_pointer; +}; + template class MyAlloc { private: @@ -49,6 +203,7 @@ class MyAlloc { } using value_type = T; + using pointer = nontrivial_pointer; using propagate_on_container_copy_assignment = POCCA; using propagate_on_container_move_assignment = POCMA; @@ -70,12 +225,12 @@ class MyAlloc { return equal_id() != other.equal_id(); } - [[nodiscard]] constexpr T* allocate(const size_t numElements) { - return allocator{}.allocate(numElements + equal_id()) + equal_id(); + [[nodiscard]] constexpr pointer allocate(const size_t numElements) { + return pointer(allocator{}.allocate(numElements + equal_id()) + equal_id()); } - constexpr void deallocate(T* const first, const size_t numElements) noexcept { - allocator{}.deallocate(first - equal_id(), numElements + equal_id()); + constexpr void deallocate(pointer const first, const size_t numElements) noexcept { + allocator{}.deallocate(_Unfancy(first - equal_id()), numElements + equal_id()); } }; @@ -307,7 +462,12 @@ _CONSTEXPR20 bool test_sequence() { test_sequence_copy_assign>(11, 22, 11); // POCCA, non-equal allocators test_sequence_copy_assign>(11, 22, 11); // POCCA, always-equal allocators - test_sequence_move_ctor(); +#if _HAS_CXX20 && !defined(__clang__) && !defined(__EDG__) // TRANSITION, VSO-1888462 + if (!is_constant_evaluated()) +#endif // ^^^ workaround ^^^ + { + test_sequence_move_ctor(); + } test_sequence_move_alloc_ctor(11, 11); // equal allocators test_sequence_move_alloc_ctor(11, 22); // non-equal allocators @@ -559,7 +719,7 @@ void test_flist() { // NOTE: Having 4 elements of type char32_t bypasses the Small String Optimization. -void test_string_copy_ctor() { +_CONSTEXPR20 void test_string_copy_ctor() { basic_string, StationaryAlloc> src( {5, 10, 20, 30}, StationaryAlloc(11)); auto src_it = src.begin(); @@ -583,7 +743,7 @@ void test_string_copy_ctor() { assert(dst.get_allocator().id() == 11); } -void test_string_copy_alloc_ctor(const size_t id1, const size_t id2) { +_CONSTEXPR20 void test_string_copy_alloc_ctor(const size_t id1, const size_t id2) { basic_string, StationaryAlloc> src( {5, 10, 20, 30}, StationaryAlloc(id1)); auto src_it = src.begin(); @@ -608,7 +768,7 @@ void test_string_copy_alloc_ctor(const size_t id1, const size_t id2) { } template -void test_string_copy_assign(const size_t id1, const size_t id2, const size_t id3) { +_CONSTEXPR20 void test_string_copy_assign(const size_t id1, const size_t id2, const size_t id3) { basic_string, Alloc> src({5, 10, 20, 30}, Alloc(id1)); basic_string, Alloc> dst({0, 0, 0, 0}, Alloc(id2)); @@ -636,7 +796,7 @@ void test_string_copy_assign(const size_t id1, const size_t id2, const size_t id assert(dst.get_allocator().id() == id3); } -void test_string_copy_assign_pocca_sso() { +_CONSTEXPR20 void test_string_copy_assign_pocca_sso() { // GH-3862 fixed a bug where the POCCA codepath in basic_string's copy assignment operator mishandled // the scenario where the string on the right hand side has a large capacity but a small size - so while // the RHS has dynamically allocated memory, the LHS should activate the Small String Optimization. @@ -661,7 +821,7 @@ void test_string_copy_assign_pocca_sso() { assert(right == "yyyyyyy"); } -void test_string_move_ctor() { +_CONSTEXPR20 void test_string_move_ctor() { basic_string, StationaryAlloc> src( {5, 10, 20, 30}, StationaryAlloc(11)); auto it1 = src.begin(); @@ -690,7 +850,7 @@ void test_string_move_ctor() { assert(dst.get_allocator().id() == 11); } -void test_string_move_alloc_ctor(const size_t id1, const size_t id2) { +_CONSTEXPR20 void test_string_move_alloc_ctor(const size_t id1, const size_t id2) { basic_string, StationaryAlloc> src( {5, 10, 20, 30}, StationaryAlloc(id1)); auto it1 = src.begin(); @@ -721,7 +881,7 @@ void test_string_move_alloc_ctor(const size_t id1, const size_t id2) { } template -void test_string_move_assign(const size_t id1, const size_t id2, const size_t id3) { +_CONSTEXPR20 void test_string_move_assign(const size_t id1, const size_t id2, const size_t id3) { basic_string, Alloc> src({5, 10, 20, 30}, Alloc(id1)); basic_string, Alloc> dst({0, 0, 0, 0}, Alloc(id2)); @@ -755,7 +915,7 @@ void test_string_move_assign(const size_t id1, const size_t id2, const size_t id } template -void test_string_swap(const size_t id1, const size_t id2) { +_CONSTEXPR20 void test_string_swap(const size_t id1, const size_t id2) { basic_string, Alloc> src({5, 10, 20, 30}, Alloc(id1)); basic_string, Alloc> dst({6, 40, 50, 60}, Alloc(id2)); @@ -784,7 +944,7 @@ void test_string_swap(const size_t id1, const size_t id2) { assert(dst.get_allocator().id() == id1); } -void test_string() { +_CONSTEXPR20 bool test_string() { test_string_copy_ctor(); test_string_copy_alloc_ctor(11, 11); // equal allocators @@ -814,6 +974,8 @@ void test_string() { test_string_swap>(11, 11); // POCS, equal allocators test_string_swap>(11, 22); // POCS, non-equal allocators test_string_swap>(11, 22); // POCS, always-equal allocators + + return true; } @@ -1680,8 +1842,11 @@ int main() { test_sequence(); test_sequence(); test_sequence(); + #if _HAS_CXX20 static_assert(test_sequence()); + + static_assert(test_string()); #endif // _HAS_CXX20 test_flist();