diff --git a/stl/inc/memory_resource b/stl/inc/memory_resource index bb47641ee..3aebab8a6 100644 --- a/stl/inc/memory_resource +++ b/stl/inc/memory_resource @@ -661,7 +661,7 @@ namespace pmr { } protected: - virtual void* do_allocate(const size_t _Bytes, const size_t _Align) override { + virtual void* do_allocate(size_t _Bytes, size_t _Align) override { // TRANSITION, DevCom-1159869 // allocate from the current buffer or a new larger buffer from upstream if (!_STD align(_Align, _Bytes, _Current_buffer, _Space_available)) { _Increase_capacity(_Bytes, _Align); diff --git a/tests/std/test.lst b/tests/std/test.lst index 2ac454e53..72a031644 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -365,6 +365,7 @@ tests\P1135R6_latch tests\P1135R6_semaphore tests\P1165R1_consistently_propagating_stateful_allocators tests\P1423R3_char8_t_remediation +tests\P1502R1_standard_library_header_units tests\P1645R1_constexpr_numeric tests\VSO_0000000_allocator_propagation tests\VSO_0000000_any_calling_conventions diff --git a/tests/std/tests/P1502R1_standard_library_header_units/__init__.py b/tests/std/tests/P1502R1_standard_library_header_units/__init__.py new file mode 100644 index 000000000..2ac2a854c --- /dev/null +++ b/tests/std/tests/P1502R1_standard_library_header_units/__init__.py @@ -0,0 +1,2 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception diff --git a/tests/std/tests/P1502R1_standard_library_header_units/custom_format.py b/tests/std/tests/P1502R1_standard_library_header_units/custom_format.py new file mode 100644 index 000000000..4338a1186 --- /dev/null +++ b/tests/std/tests/P1502R1_standard_library_header_units/custom_format.py @@ -0,0 +1,126 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +from pathlib import Path + +from stl.test.format import STLTestFormat, TestStep + + +class CustomTestFormat(STLTestFormat): + def getBuildSteps(self, test, lit_config, shared): + shared.exec_dir = test.getExecDir() + output_base = test.getOutputBaseName() + output_dir = test.getOutputDir() + source_path = Path(test.getSourcePath()) + + stl_headers = [ + 'algorithm', + 'any', + 'array', + 'atomic', + 'barrier', + 'bit', + 'bitset', + 'charconv', + 'chrono', + 'codecvt', + 'compare', + 'complex', + 'concepts', + 'condition_variable', + 'coroutine', + 'deque', + 'exception', + 'execution', + 'filesystem', + # 'format', + 'forward_list', + 'fstream', + 'functional', + 'future', + 'initializer_list', + 'iomanip', + 'ios', + 'iosfwd', + 'iostream', + 'istream', + 'iterator', + 'latch', + 'limits', + 'list', + 'locale', + 'map', + 'memory_resource', + 'memory', + 'mutex', + 'new', + 'numbers', + 'numeric', + 'optional', + 'ostream', + 'queue', + 'random', + 'ranges', + 'ratio', + 'regex', + 'scoped_allocator', + 'semaphore', + 'set', + 'shared_mutex', + # 'source_location', + 'span', + 'sstream', + 'stack', + 'stdexcept', + 'stop_token', + 'streambuf', + 'string_view', + 'string', + 'strstream', + # 'syncstream', + 'system_error', + 'thread', + 'tuple', + 'type_traits', + 'typeindex', + 'typeinfo', + 'unordered_map', + 'unordered_set', + 'utility', + 'valarray', + 'variant', + 'vector', + 'version', + ] + + compile_test_cpp_with_edg = test.cxx.flags.count('/BE') == 1 + + if compile_test_cpp_with_edg: + test.cxx.flags.remove('/BE') + + header_unit_options = [] + + for header in stl_headers: + header_obj_path = output_dir / (header + '.obj') + + header_unit_options.append('/headerUnit') + header_unit_options.append('{0}/{1}={1}.ifc'.format(test.config.cxx_headers, header)) + + if not compile_test_cpp_with_edg: + header_unit_options.append(str(header_obj_path)) + + cmd, out_files = test.cxx._basicCmd(source_files = [], out = None, + flags = ['/exportHeader', '<{}>'.format(header), '/Fo{}'.format(str(header_obj_path))], + skip_mode_flags = True) + yield TestStep(cmd, shared.exec_dir, [], test.cxx.compile_env) + + if compile_test_cpp_with_edg: + test.cxx.flags.append('/BE') + + cmd, out_files, shared.exec_file = \ + test.cxx.executeBasedOnFlagsCmd([source_path], + output_dir, shared.exec_dir, + output_base, header_unit_options, [], []) + + yield TestStep(cmd, shared.exec_dir, [source_path], + test.cxx.compile_env) diff --git a/tests/std/tests/P1502R1_standard_library_header_units/custombuild.pl b/tests/std/tests/P1502R1_standard_library_header_units/custombuild.pl new file mode 100644 index 000000000..403af1be0 --- /dev/null +++ b/tests/std/tests/P1502R1_standard_library_header_units/custombuild.pl @@ -0,0 +1,105 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +use Run; + +sub CustomBuildHook() +{ + my $cwd = Run::GetCWDName(); + my $stl_include_dir = $ENV{STL_INCLUDE_DIR}; + + my @stl_headers = ( + "algorithm", + "any", + "array", + "atomic", + "barrier", + "bit", + "bitset", + "charconv", + "chrono", + "codecvt", + "compare", + "complex", + "concepts", + "condition_variable", + "coroutine", + "deque", + "exception", + "execution", + "filesystem", + # "format", + "forward_list", + "fstream", + "functional", + "future", + "initializer_list", + "iomanip", + "ios", + "iosfwd", + "iostream", + "istream", + "iterator", + "latch", + "limits", + "list", + "locale", + "map", + "memory_resource", + "memory", + "mutex", + "new", + "numbers", + "numeric", + "optional", + "ostream", + "queue", + "random", + "ranges", + "ratio", + "regex", + "scoped_allocator", + "semaphore", + "set", + "shared_mutex", + # "source_location", + "span", + "sstream", + "stack", + "stdexcept", + "stop_token", + "streambuf", + "string_view", + "string", + "strstream", + # "syncstream", + "system_error", + "thread", + "tuple", + "type_traits", + "typeindex", + "typeinfo", + "unordered_map", + "unordered_set", + "utility", + "valarray", + "variant", + "vector", + "version", + ); + + my $header_unit_options = ""; + + foreach (@stl_headers) { + $header_unit_options .= " /headerUnit"; + $header_unit_options .= " $stl_include_dir/$_=$_.ifc"; + $header_unit_options .= " $_.obj"; + + # TRANSITION, remove /DMSVC_INTERNAL_TESTING after all compiler bugs are fixed + Run::ExecuteCL("/DMSVC_INTERNAL_TESTING /exportHeader \"<$_>\" /Fo$_.obj"); + } + + # TRANSITION, remove /DMSVC_INTERNAL_TESTING after all compiler bugs are fixed + Run::ExecuteCL("/DMSVC_INTERNAL_TESTING test.cpp /Fe$cwd.exe $header_unit_options"); +} +1 diff --git a/tests/std/tests/P1502R1_standard_library_header_units/env.lst b/tests/std/tests/P1502R1_standard_library_header_units/env.lst new file mode 100644 index 000000000..792b7aab9 --- /dev/null +++ b/tests/std/tests/P1502R1_standard_library_header_units/env.lst @@ -0,0 +1,19 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\..\..\universal_prefix.lst +RUNALL_CROSSLIST +PM_CL="/w14365 /D_ENFORCE_FACET_SPECIALIZATIONS=1" +RUNALL_CROSSLIST +PM_CL="/w14640 /Zc:threadSafeInit- /EHsc /std:c++latest" +RUNALL_CROSSLIST +PM_CL="/Zc:preprocessor /D_SILENCE_CXX17_STRSTREAM_DEPRECATION_WARNING" +RUNALL_CROSSLIST +PM_CL="/MD" +PM_CL="/MDd" +PM_CL="/MT" +PM_CL="/MTd" +# RUNALL_CROSSLIST +# PM_CL="" +# PM_CL="/analyze:only" # TRANSITION, works correctly but slowly +# PM_CL="/BE" # TRANSITION, VSO-1232145 "EDG ICEs when consuming Standard Library Header Units" diff --git a/tests/std/tests/P1502R1_standard_library_header_units/lit.local.cfg b/tests/std/tests/P1502R1_standard_library_header_units/lit.local.cfg new file mode 100644 index 000000000..504df778c --- /dev/null +++ b/tests/std/tests/P1502R1_standard_library_header_units/lit.local.cfg @@ -0,0 +1,10 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +import P1502R1_standard_library_header_units.custom_format + +config.test_format = \ + P1502R1_standard_library_header_units.custom_format.CustomTestFormat(config.test_format.cxx, + config.test_format.execute_external, + config.test_format.build_executor, + config.test_format.test_executor) diff --git a/tests/std/tests/P1502R1_standard_library_header_units/test.cpp b/tests/std/tests/P1502R1_standard_library_header_units/test.cpp new file mode 100644 index 000000000..2a086ef1e --- /dev/null +++ b/tests/std/tests/P1502R1_standard_library_header_units/test.cpp @@ -0,0 +1,1020 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// N4868 [headers]/4: +// "The headers listed in Table 21 [...] are collectively known as the importable C++ library headers. +// [Note 1: Importable C++ library headers can be imported as module units (10.3). - end note]" +// [tab:headers.cpp]: "Table 21: C++ library headers" + +// This EXCLUDES the headers in: +// [tab:headers.cpp.c]: "Table 22: C++ headers for C library facilities" + +// clang-format off +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +// import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +// import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +// import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +import ; +// clang-format on + +#include +#include +#include +using namespace std; + +int main() { + { + puts("Testing ."); + constexpr int arr[]{11, 0, 22, 0, 33, 0, 44, 0, 55}; + assert(count(begin(arr), end(arr), 0) == 4); + assert(ranges::count(arr, 0) == 4); + static_assert(count(begin(arr), end(arr), 0) == 4); + static_assert(ranges::count(arr, 0) == 4); + } + + { + puts("Testing ."); + any a1{1729}; + any a2{7.5}; + a1.swap(a2); + assert(any_cast(a1) == 7.5); + assert(any_cast(a2) == 1729); + } + + { + puts("Testing ."); +#if 0 // TRANSITION, VSO-1088552 (deduction guides) + constexpr array arr{10, 20, 30, 40, 50}; +#else // ^^^ no workaround / workaround vvv + constexpr array arr{10, 20, 30, 40, 50}; +#endif // ^^^ workaround ^^^ + assert(arr[2] == 30); + static_assert(arr[2] == 30); + } + + { + puts("Testing ."); + atomic atom{1729}; + assert(atom.load() == 1729); + ++atom; + assert(atom.load() == 1730); + static_assert(atomic::is_always_lock_free); // implementation-defined + } + + { + puts("Testing ."); + static_assert(barrier<>::max() >= 5); + barrier b{2}; + atomic atom{0}; + thread t1{[&] { + for (int i = 0; i < 5; ++i) { + auto token = b.arrive(); + b.wait(move(token)); + atom.fetch_add(1, memory_order_relaxed); + } + }}; + thread t2{[&] { + for (int i = 0; i < 3; ++i) { + b.arrive_and_wait(); + atom.fetch_add(1, memory_order_relaxed); + } + b.arrive_and_drop(); + }}; + t1.join(); + t2.join(); + assert(atom.load(memory_order_relaxed) == 8); + } + + { + puts("Testing ."); + assert(popcount(0x1234ABCDu) == 15); + static_assert(popcount(0x1234ABCDu) == 15); + } + + { + puts("Testing ."); + constexpr bitset<32> b{0x1234ABCDu}; + assert(b[3] && b[2] && !b[1] && b[0]); + static_assert(b[3] && b[2] && !b[1] && b[0]); + } + + { + puts("Testing ."); + char buf[4]{}; + const to_chars_result result = to_chars(buf, end(buf), 3.14); + assert(result.ec == errc{}); + assert(result.ptr == end(buf)); +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1224512 (char_traits) + const string_view sv{buf, size(buf)}; + assert(sv == "3.14"); +#else // ^^^ no workaround / workaround vvv + assert(buf[0] == '3' && buf[1] == '.' && buf[2] == '1' && buf[3] == '4'); +#endif // ^^^ workaround ^^^ + } + + { + puts("Testing ."); +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1159995 (UDLs) + constexpr chrono::seconds dur = 3min; +#else // ^^^ no workaround / workaround vvv + constexpr chrono::seconds dur = chrono::minutes{3}; +#endif // ^^^ workaround ^^^ + assert(dur.count() == 180); + static_assert(dur.count() == 180); + } + + { + puts("Testing ."); +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1161187 (access control), VSO-1236034 (error LNK2005: _Yarn) + const string utf8_koshka_cat{"\xD0\xBA\xD0\xBE\xD1\x88\xD0\xBA\xD0\xB0_\xF0\x9F\x90\x88"}; + const wstring utf16_koshka_cat{L"\x043A\x043E\x0448\x043A\x0430_\xD83D\xDC08"}; + wstring_convert> conv; + assert(conv.from_bytes(utf8_koshka_cat) == utf16_koshka_cat); + assert(conv.to_bytes(utf16_koshka_cat) == utf8_koshka_cat); +#endif // ^^^ no workaround ^^^ + + static_assert(static_cast(codecvt_mode::consume_header) == 4); // TRANSITION, DevCom-1160041 (deprecated) + } + + { + puts("Testing ."); + assert(is_lt(10 <=> 20)); + static_assert(is_lt(10 <=> 20)); + } + + { + puts("Testing ."); + constexpr complex c{3.0, 4.0}; + assert(norm(c) == 25.0); + static_assert(norm(c) == 25.0); + } + + { + puts("Testing ."); + static_assert(signed_integral); + static_assert(!signed_integral); + static_assert(!signed_integral); + } + + { + puts("Testing ."); + condition_variable cv; + mutex mut; + vector vec = {5}; + + thread odd{[&cv, &mut, &vec] { + unique_lock lk{mut}; + + while (vec.size() < 6) { + cv.wait(lk, [&vec] { return vec.size() % 2 == 1; }); + const int n = vec.back(); + vec.push_back(n * 10 + 1); + cv.notify_one(); + } + }}; + + thread even{[&cv, &mut, &vec] { + unique_lock lk{mut}; + + while (vec.size() < 7) { + cv.wait(lk, [&vec] { return vec.size() % 2 == 0; }); + const int n = vec.back(); + vec.push_back(n * 10 + 2); + cv.notify_one(); + } + }}; + + odd.join(); + even.join(); + + const vector expected = {5, 51, 512, 5121, 51212, 512121, 5121212}; + assert(vec == expected); + + static_assert(static_cast(cv_status::no_timeout) == 0); + static_assert(static_cast(cv_status::timeout) == 1); + } + + { + puts("Testing ."); + constexpr coroutine_handle<> handle{}; + assert(handle.address() == nullptr); + static_assert(handle.address() == nullptr); + } + + { + puts("Testing ."); +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1160260 (partial specialization) + const deque d{10, 20, 30, 40, 50}; + assert(d[2] == 30); +#endif // ^^^ no workaround ^^^ + } + + { + puts("Testing ."); + assert(uncaught_exceptions() == 0); + const exception_ptr ep = current_exception(); + assert(!ep); + } + + { + puts("Testing ."); + constexpr int arr[]{11, 0, 22, 0, 33, 0, 44, 0, 55}; + assert(count(execution::par, begin(arr), end(arr), 0) == 4); + } + + { + puts("Testing ."); +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1224512 (char_traits) + constexpr wstring_view dot{L"."}; + error_code ec{}; + const filesystem::space_info info = filesystem::space(dot, ec); + assert(!ec); + assert(info.capacity > 0); + assert(info.capacity != static_cast(-1)); +#endif // ^^^ no workaround ^^^ + } + + { + puts("Testing ."); + puts("(TRANSITION, not yet implemented.)"); + } + + { + puts("Testing ."); +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1160260 (partial specialization) + const forward_list fl{10, 20, 30, 40, 50}; + assert(*next(fl.begin(), 2) == 30); +#endif // ^^^ no workaround ^^^ + } + + { + puts("Testing ."); +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1224512 (char_traits) + const ifstream f{}; + assert(!f.is_open()); +#endif // ^^^ no workaround ^^^ + } + + { + puts("Testing ."); + function f{multiplies{}}; + assert(f(3, 5) == 15); + f = [](int x, int y) { return x * 100 + y * 10; }; + assert(f(3, 5) == 350); + constexpr auto b = bind(multiplies{}, placeholders::_1, 11); + assert(b(3) == 33); + static_assert(b(3) == 33); + } + + { + puts("Testing ."); + promise p{}; + future f{p.get_future()}; + assert(f.wait_for(chrono::seconds{0}) == future_status::timeout); + p.set_value(1729); + assert(f.wait_for(chrono::seconds{0}) == future_status::ready); + assert(f.get() == 1729); + } + + { + puts("Testing ."); + const initializer_list il{10, 20, 30, 40, 50}; + assert(il.begin()[2] == 30); + } + + { + puts("Testing ."); +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1224512 (char_traits) + ostringstream oss; + oss << "I have " << setfill('.') << setw(7) << 9 * 9 * 9 + 10 * 10 * 10 << " cute fluffy kittens."; + assert(oss.str() == "I have ...1729 cute fluffy kittens."); + oss.str(""); + oss << quoted(R"(Read "C:\Temp\Cat Names.txt" for more info.)"); + const char* const expected_quoted = R"("Read \"C:\\Temp\\Cat Names.txt\" for more info.")"; + assert(oss.str() == expected_quoted); +#endif // ^^^ no workaround ^^^ + } + + { + puts("Testing ."); +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1224512 (char_traits) + ios b{nullptr}; + assert(b.rdbuf() == nullptr); + assert(b.rdstate() == ios_base::badbit); + assert(b.precision() == 6); + static_assert(ios_base::floatfield == (ios_base::fixed | ios_base::scientific)); +#endif // ^^^ no workaround ^^^ + } + + { + puts("Testing ."); + static_assert(is_same_v>); + static_assert(is_same_v>); + } + + { + puts("Testing ."); +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1224512 (char_traits) + cout << "Testing P1502R1_standard_library_header_units.\n"; + assert(cin.tie() == &cout); +#endif // ^^^ no workaround ^^^ + } + + { + puts("Testing ."); +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1224512 (char_traits) + const istream is{nullptr}; + assert(is.gcount() == 0); +#endif // ^^^ no workaround ^^^ + } + + { + puts("Testing ."); + constexpr int arr[]{10, 20, 30, 40, 50}; + constexpr reverse_iterator ri{end(arr)}; + assert(*ri == 50); + assert(*next(ri) == 40); + static_assert(*ri == 50); + static_assert(*next(ri) == 40); + } + + { + puts("Testing ."); + static_assert(latch::max() >= 5); + for (const auto& release_wait : {true, false}) { + latch l{5}; + thread t1{[&] { l.wait(); }}; + thread t2{[&] { l.arrive_and_wait(2); }}; + l.count_down(); + if (release_wait) { + l.arrive_and_wait(2); + } else { + l.count_down(2); + } + t1.join(); + t2.join(); + } + } + + { + puts("Testing ."); + static_assert(numeric_limits::min() == -32768); + static_assert(numeric_limits::max() == 32767); + } + + { + puts("Testing ."); +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1160260 (partial specialization) + const list l{10, 20, 30, 40, 50}; + assert(*next(l.begin(), 2) == 30); +#endif // ^^^ no workaround ^^^ + } + + { + puts("Testing ."); + locale loc{}; + assert(isdigit('1', loc)); + assert(!isdigit('a', loc)); + using L = locale; + static_assert((L::collate | L::ctype | L::monetary | L::numeric | L::time | L::messages | L::all) == L::all); + } + + { + puts("Testing ."); +#if 0 // TRANSITION, DevCom-1160260 (partial specialization), VSO-1236041 (error LNK2019 pair piecewise_construct_t) + map m{{10, 11}, {20, 22}, {30, 33}, {40, 44}, {50, 55}}; + assert(m[30] == 33); +#endif // ^^^ no workaround ^^^ + } + + { + puts("Testing ."); + pmr::monotonic_buffer_resource mbr{}; + pmr::polymorphic_allocator al{&mbr}; + pmr::vector v({10, 20, 30, 40, 50}, al); + assert(v[2] == 30); + v.push_back(60); + assert(v[5] == 60); + } + + { + puts("Testing ."); + unique_ptr up = make_unique(1729); + assert(*up == 1729); + shared_ptr sp{move(up)}; + assert(!up); + assert(*sp == 1729); + weak_ptr wp{sp}; + assert(!wp.expired()); + shared_ptr other = wp.lock(); + assert(*other == 1729); + ++*sp; + assert(*other == 1730); + } + + { + puts("Testing ."); + // see above, tested with + int n = 10; + auto lambda = [&n] { ++n; }; + once_flag flag; + assert(n == 10); + call_once(flag, lambda); + assert(n == 11); + call_once(flag, lambda); + assert(n == 11); + } + + { + puts("Testing ."); + bool caught_bad_alloc = false; + + try { + throw bad_array_new_length{}; + } catch (const bad_alloc&) { + caught_bad_alloc = true; + } catch (...) { + assert(false); + } + + assert(caught_bad_alloc); + + const int* const ptr = new (nothrow) int{1729}; + assert(ptr); + assert(*ptr == 1729); + delete ptr; + + static_assert(hardware_constructive_interference_size == 64); // implementation-defined + static_assert(hardware_destructive_interference_size == 64); // implementation-defined + } + + { + puts("Testing ."); + static_assert(3.14 < numbers::pi && numbers::pi < 3.15); + static_assert(2.71828f < numbers::e_v && numbers::e_v < 2.71829f); + } + + { + puts("Testing ."); + constexpr int arr[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + assert(accumulate(begin(arr), end(arr), 0) == 55); + static_assert(accumulate(begin(arr), end(arr), 0) == 55); + } + + { + puts("Testing ."); + constexpr optional opt{in_place, 1729}; + assert(opt.has_value()); + assert(opt.value() == 1729); + static_assert(opt.has_value()); + static_assert(opt.value() == 1729); + + constexpr optional empty{nullopt}; + assert(!empty.has_value()); + assert(empty.value_or(-1) == -1); + static_assert(!empty.has_value()); + static_assert(empty.value_or(-1) == -1); + } + + { + puts("Testing ."); +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1224512 (char_traits) + const ostream os{nullptr}; + assert(os.rdbuf() == nullptr); +#endif // ^^^ no workaround ^^^ + } + + { + puts("Testing ."); +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1160260 (partial specialization) + queue q; + q.push(10); + q.push(20); + q.push(30); + assert(q.size() == 3); + assert(q.front() == 10); + q.pop(); + assert(q.front() == 20); + q.pop(); + assert(q.front() == 30); + q.pop(); + assert(q.empty()); + + priority_queue pq; + pq.push(50); + pq.push(10); + pq.push(1729); + pq.push(200); + assert(pq.size() == 4); + assert(pq.top() == 1729); + pq.pop(); + assert(pq.top() == 200); + pq.pop(); + assert(pq.top() == 50); + pq.pop(); + assert(pq.top() == 10); + pq.pop(); + assert(pq.empty()); +#endif // ^^^ no workaround ^^^ + } + + { + puts("Testing ."); + minstd_rand0 lcg; + + for (int i = 0; i < 9999; ++i) { + (void) lcg(); + } + + assert(lcg() == 1043618065); // N4868 [rand.predef]/1 + } + + { + puts("Testing ."); + constexpr int arr[]{11, 0, 22, 0, 33, 0, 44, 0, 55}; +#if 0 // TRANSITION, VSO-1088552 (deduction guides) + assert(ranges::distance(views::filter(arr, [](int x) { return x == 0; })) == 4); + static_assert(ranges::distance(views::filter(arr, [](int x) { return x != 0; })) == 5); +#elif 0 // TRANSITION, VSO-1237145 (trailing requires clause) + auto is_zero = [](int x) { return x == 0; }; + using FV1 = ranges::filter_view, decltype(is_zero)>; + assert(ranges::distance(FV1{arr, is_zero}) == 4); + constexpr auto not_zero = [](int x) { return x != 0; }; + using FV2 = ranges::filter_view, remove_const_t>; + static_assert(ranges::distance(FV2{arr, not_zero}) == 5); +#endif // ^^^ workaround ^^^ + } + + { + puts("Testing ."); + static_assert(ratio_equal_v, deci>); + } + + { + puts("Testing ."); +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1224512 (char_traits) + const regex r{R"(\w+)"}; + const string s{"cute! fluffy? kittens."}; + vector v; + + for (sregex_token_iterator it{s.begin(), s.end(), r}, end; it != end; ++it) { + v.push_back(it->str()); + } + + const vector expected{"cute", "fluffy", "kittens"}; + assert(v == expected); +#endif // ^^^ no workaround ^^^ + } + + { + puts("Testing ."); +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1162644 (deprecated warning) + vector>> v; + v.push_back(11); + v.push_back(22); + v.push_back(33); + constexpr int expected[]{11, 22, 33}; + assert(equal(v.begin(), v.end(), begin(expected), end(expected))); +#endif // ^^^ no workaround ^^^ + } + + { + puts("Testing ."); + static_assert(binary_semaphore::max() >= 1); + binary_semaphore s{1}; + int val{0}; + s.acquire(); + thread t1{[&] { + for (int i = 0; i < 17; ++i) { + s.acquire(); + val += 100; + s.release(); + } + }}; + thread t2{[&] { + for (int i = 0; i < 29; ++i) { + s.acquire(); + ++val; + s.release(); + } + }}; + s.release(); + t1.join(); + t2.join(); + assert(val == 1729); + } + + { + puts("Testing ."); +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1160260 (partial specialization) + const set s{10, 20, 30, 40, 50}; + assert(*next(s.begin(), 2) == 30); + + const multiset ms{10, 20, 20, 30, 30, 30, 40, 40, 40, 40}; + const auto p = ms.equal_range(30); + assert(distance(p.first, p.second) == 3); +#endif // ^^^ no workaround ^^^ + } + + { + puts("Testing ."); + condition_variable_any cv; + shared_mutex mut; + vector vec = {5}; + + thread odd{[&cv, &mut, &vec] { + unique_lock lk{mut}; + + while (vec.size() < 6) { + cv.wait(lk, [&vec] { return vec.size() % 2 == 1; }); + const int n = vec.back(); + vec.push_back(n * 10 + 1); + cv.notify_one(); + } + }}; + + thread even{[&cv, &mut, &vec] { + unique_lock lk{mut}; + + while (vec.size() < 7) { + cv.wait(lk, [&vec] { return vec.size() % 2 == 0; }); + const int n = vec.back(); + vec.push_back(n * 10 + 2); + cv.notify_one(); + } + }}; + + odd.join(); + even.join(); + + const vector expected = {5, 51, 512, 5121, 51212, 512121, 5121212}; + assert(vec == expected); + } + + { + puts("Testing ."); + puts("(TRANSITION, not yet implemented.)"); + } + + { + puts("Testing ."); + constexpr int arr[]{11, 22, 33, 44, 55}; + constexpr span whole{arr}; + constexpr span mid = whole.subspan<1, 3>(); + assert(mid[0] == 22 && mid[1] == 33 && mid[2] == 44); + static_assert(mid[0] == 22 && mid[1] == 33 && mid[2] == 44); + } + + { + puts("Testing ."); +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1224512 (char_traits) + ostringstream oss; + oss << "I have " << 9 * 9 * 9 + 10 * 10 * 10 << " cute fluffy kittens."; + assert(oss.str() == "I have 1729 cute fluffy kittens."); +#endif // ^^^ no workaround ^^^ + } + + { + puts("Testing ."); +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1160260 (partial specialization) + stack s; + s.push(10); + s.push(20); + s.push(30); + assert(s.size() == 3); + assert(s.top() == 30); + s.pop(); + assert(s.top() == 20); + s.pop(); + assert(s.top() == 10); + s.pop(); + assert(s.empty()); +#endif // ^^^ no workaround ^^^ + } + + { + puts("Testing ."); +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1224512 (char_traits) + bool caught_puppies = false; + + try { + throw overflow_error{"too many puppies"}; + } catch (const runtime_error& e) { + caught_puppies = e.what() == string_view{"too many puppies"}; + } catch (...) { + assert(false); + } + + assert(caught_puppies); +#endif // ^^^ no workaround ^^^ + } + + { + puts("Testing ."); + vector vec; + { + latch l{1}; + jthread jt{[&](const stop_token& token) { + int val{1729}; + // Generate the Collatz sequence for 1729. + // main() shouldn't ask us to stop early; if it does, the sequence will be truncated. + while (!token.stop_requested()) { + vec.push_back(val); + if (val == 1) { + break; + } else if (val % 2 == 0) { + val /= 2; + } else { + val = 3 * val + 1; + } + } + l.count_down(); // tell main() that we're done + while (!token.stop_requested()) { +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1159995 (UDLs) + this_thread::sleep_for(10ms); // not a timing assumption; avoids spinning furiously +#else // ^^^ no workaround / workaround vvv + this_thread::sleep_for(chrono::milliseconds{10}); // not a timing assumption +#endif // ^^^ workaround ^^^ + } + vec.push_back(-1000); // indicate that token.stop_requested() returned true + }}; + l.wait(); // wait for jt to generate the sequence + } // destroying jt will ask it to stop + static constexpr int expected[]{1729, 5188, 2594, 1297, 3892, 1946, 973, 2920, 1460, 730, 365, 1096, 548, 274, + 137, 412, 206, 103, 310, 155, 466, 233, 700, 350, 175, 526, 263, 790, 395, 1186, 593, 1780, 890, 445, 1336, + 668, 334, 167, 502, 251, 754, 377, 1132, 566, 283, 850, 425, 1276, 638, 319, 958, 479, 1438, 719, 2158, + 1079, 3238, 1619, 4858, 2429, 7288, 3644, 1822, 911, 2734, 1367, 4102, 2051, 6154, 3077, 9232, 4616, 2308, + 1154, 577, 1732, 866, 433, 1300, 650, 325, 976, 488, 244, 122, 61, 184, 92, 46, 23, 70, 35, 106, 53, 160, + 80, 40, 20, 10, 5, 16, 8, 4, 2, 1, -1000}; +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1160260 (partial specialization) + assert(equal(vec.begin(), vec.end(), begin(expected), end(expected))); +#else // ^^^ no workaround / workaround vvv + assert(vec.size() == size(expected)); + for (size_t i = 0; i < vec.size(); ++i) { + assert(vec[i] == expected[i]); + } +#endif // ^^^ workaround ^^^ + } + + { + puts("Testing ."); +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1224512 (char_traits) + istringstream iss{"kittens"}; + assert(iss.rdbuf()->in_avail() == 7); +#endif // ^^^ no workaround ^^^ + } + + { + puts("Testing ."); +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1224512 (char_traits) + constexpr string_view catenary{"catenary"}; + assert(catenary.starts_with("cat")); + assert(!catenary.starts_with("dog")); + static_assert(catenary.starts_with("cat")); + static_assert(!catenary.starts_with("dog")); +#endif // ^^^ no workaround ^^^ + } + + { + puts("Testing ."); +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1224512 (char_traits) + const string small_string{"homeowner"}; + const string large_string{"Cute fluffy kittens are so adorable when they meow and purr."}; + assert(small_string.find("meow") == 2); + assert(large_string.find("meow") == 46); +#endif // ^^^ no workaround ^^^ + } + + { + puts("Testing ."); +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1224512 (char_traits) + istrstream istr{"1729"}; + int n = -1; + istr >> n; + assert(n == 1729); +#endif // ^^^ no workaround ^^^ + } + + { + puts("Testing ."); + puts("(TRANSITION, not yet implemented.)"); + } + + { + puts("Testing ."); + const error_code code = make_error_code(errc::value_too_large); + assert(code.value() == static_cast(errc::value_too_large)); + assert(code.category() == generic_category()); + assert(code); + } + + { + puts("Testing ."); + // see above, tested with + assert(this_thread::get_id() != thread::id{}); + } + + { + puts("Testing ."); + constexpr tuple t{1729, 'c', 1.25}; + assert(get(t) == 1729); + assert(get(t) == 'c'); + assert(get(t) == 1.25); + static_assert(get(t) == 1729); + static_assert(get(t) == 'c'); + static_assert(get(t) == 1.25); + } + + { + puts("Testing ."); + static_assert(is_void_v); + static_assert(!is_void_v); + static_assert(is_same_v, int[20][30]>); + static_assert(is_same_v, double>); + + constexpr auto compiletime_10_or_runtime_20 = [] { + if (is_constant_evaluated()) { + return 10; + } else { + return 20; + } + }; + + assert(compiletime_10_or_runtime_20() == 20); + static_assert(compiletime_10_or_runtime_20() == 10); + } + + { + puts("Testing ."); + const type_index ti_int{typeid(int)}; + type_index ti{typeid(double)}; + assert(ti != ti_int); + ti = ti_int; + assert(ti == ti_int); + } + + { + puts("Testing ."); + const type_info& t1 = typeid(int); + const type_info& t2 = typeid(const int&); + const type_info& t3 = typeid(double); + assert(t1 == t2); + assert(t1 != t3); + } + + { + puts("Testing ."); +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1160260 (partial specialization) + unordered_map um{{1, 1}, {2, 4}, {3, 9}, {4, 16}, {5, 25}}; + for (const auto& p : um) { + assert(p.first * p.first == p.second); + } +#endif // ^^^ no workaround ^^^ + } + + { + puts("Testing ."); +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, DevCom-1160260 (partial specialization) + unordered_set us{10, 20, 30, 40, 50}; + for (const auto& elem : us) { + assert(elem % 10 == 0); + } +#endif // ^^^ no workaround ^^^ + } + + { + puts("Testing ."); + constexpr pair p{44, 5.5}; + assert(p.first == 44); + assert(p.second == 5.5); + static_assert(p.first == 44); + static_assert(p.second == 5.5); + + assert(in_range(200)); + assert(!in_range(300)); + static_assert(in_range(200)); + static_assert(!in_range(300)); + + static_assert(is_same_v, integer_sequence>); + static_assert(is_same_v() + declval()), int>); + } + + { + puts("Testing ."); + valarray val{1, 2, 3}; + val *= 10; + assert(val[0] == 10 && val[1] == 20 && val[2] == 30); + } + + { + puts("Testing ."); + constexpr const char* cats = "CATS"; +#if 0 // TRANSITION, DevCom-1162647 (constexpr variant stores wrong pointer) + constexpr variant var{in_place_type, cats}; + static_assert(var.index() == 1); + static_assert(holds_alternative(var)); + static_assert(get(var) == cats); +#else // ^^^ no workaround / workaround vvv + const variant var{in_place_type, cats}; +#endif // ^^^ workaround ^^^ + assert(var.index() == 1); + assert(holds_alternative(var)); + assert(get(var) == cats); + + constexpr variant var2{in_place_type, 2.5}; + assert(var2.index() == 2); + assert(holds_alternative(var2)); + assert(get(var2) == 2.5); + static_assert(var2.index() == 2); + static_assert(holds_alternative(var2)); + static_assert(get(var2) == 2.5); + } + + { + puts("Testing ."); + const vector v{10, 20, 30, 40, 50}; + assert(v[2] == 30); + +#ifdef MSVC_INTERNAL_TESTING // TRANSITION, should work with VS 2019 16.9 Preview 1 + const vector vb{true, true, false, true}; + assert(vb[0] && vb[1] && !vb[2] && vb[3]); +#endif // ^^^ no workaround ^^^ + } + + { + puts("Testing ."); + static_assert(__cpp_lib_make_unique >= 201304L); + } +}