Index: libcxx/test/std/concepts/concepts.callable/concept.invocable/invocable.compile.pass.cpp =================================================================== --- libcxx/test/std/concepts/concepts.callable/concept.invocable/invocable.compile.pass.cpp +++ libcxx/test/std/concepts/concepts.callable/concept.invocable/invocable.compile.pass.cpp @@ -229,12 +229,18 @@ static_assert(std::invocable); static_assert(std::invocable); static_assert(std::invocable); +#ifndef _MSC_VER static_assert(!std::invocable); +#endif +static_assert(!std::invocable); static_assert(std::invocable); static_assert(std::invocable); static_assert(std::invocable); static_assert(std::invocable); +#ifndef _MSC_VER static_assert(!std::invocable); +#endif +static_assert(!std::invocable); static_assert(std::invocable); static_assert(std::invocable); } // namespace function_objects Index: libcxx/test/std/concepts/concepts.callable/concept.regularinvocable/regular_invocable.pass.cpp =================================================================== --- libcxx/test/std/concepts/concepts.callable/concept.regularinvocable/regular_invocable.pass.cpp +++ libcxx/test/std/concepts/concepts.callable/concept.regularinvocable/regular_invocable.pass.cpp @@ -255,12 +255,18 @@ static_assert(std::regular_invocable); static_assert(std::regular_invocable); static_assert(std::regular_invocable); +#ifndef _MSC_VER static_assert(!std::regular_invocable); +#endif +static_assert(!std::regular_invocable); static_assert(std::regular_invocable); static_assert(std::regular_invocable); static_assert(std::regular_invocable); static_assert(std::regular_invocable); +#ifndef _MSC_VER static_assert(!std::regular_invocable); +#endif +static_assert(!std::regular_invocable); static_assert(std::regular_invocable); static_assert(std::regular_invocable); } // namespace function_objects Index: libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/path.pass.cpp =================================================================== --- libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/path.pass.cpp +++ libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/path.pass.cpp @@ -8,8 +8,6 @@ // UNSUPPORTED: c++03 -// XFAIL: LIBCXX-WINDOWS-FIXME - // // class directory_entry @@ -155,7 +153,8 @@ // reading directories; test using a special inaccessible directory // instead. const path dir = GetWindowsInaccessibleDir(); - TEST_REQUIRE(!dir.empty()); + if (dir.empty()) + TEST_UNSUPPORTED(); const path file = dir / "file"; { std::error_code ec = GetTestEC(); Index: libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/ctor.pass.cpp =================================================================== --- libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/ctor.pass.cpp +++ libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/ctor.pass.cpp @@ -8,8 +8,6 @@ // UNSUPPORTED: c++03 -// XFAIL: LIBCXX-WINDOWS-FIXME - // // class directory_iterator @@ -94,7 +92,8 @@ // reading directories; test using a special inaccessible directory // instead. const path testDir = GetWindowsInaccessibleDir(); - TEST_REQUIRE(!testDir.empty()); + if (testDir.empty()) + TEST_UNSUPPORTED(); #else scoped_test_env env; path const testDir = env.make_env_path("dir1"); Index: libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp =================================================================== --- libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp +++ libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp @@ -8,8 +8,6 @@ // UNSUPPORTED: c++03 -// XFAIL: LIBCXX-WINDOWS-FIXME - // // class directory_iterator @@ -95,7 +93,8 @@ // reading directories; test using a special inaccessible directory // instead. const path testDir = GetWindowsInaccessibleDir(); - TEST_REQUIRE(!testDir.empty()); + if (testDir.empty()) + TEST_UNSUPPORTED(); #else scoped_test_env env; path const testDir = env.make_env_path("dir1"); Index: libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.exists/exists.pass.cpp =================================================================== --- libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.exists/exists.pass.cpp +++ libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.exists/exists.pass.cpp @@ -8,8 +8,6 @@ // UNSUPPORTED: c++03 -// XFAIL: LIBCXX-WINDOWS-FIXME - // // bool exists(file_status s) noexcept @@ -91,7 +89,8 @@ // reading directories; test using a special inaccessible directory // instead. const path p = GetWindowsInaccessibleDir(); - TEST_REQUIRE(!p.empty()); + if (p.empty()) + TEST_UNSUPPORTED(); #else scoped_test_env env; const path dir = env.create_dir("dir"); Index: libcxx/test/std/language.support/support.dynamic/alloc.errors/set.new.handler/set_new_handler.pass.cpp =================================================================== --- libcxx/test/std/language.support/support.dynamic/alloc.errors/set.new.handler/set_new_handler.pass.cpp +++ libcxx/test/std/language.support/support.dynamic/alloc.errors/set.new.handler/set_new_handler.pass.cpp @@ -8,8 +8,6 @@ // test set_new_handler -// XFAIL: LIBCXX-WINDOWS-FIXME - #include #include Index: libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t.pass.cpp =================================================================== --- libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t.pass.cpp +++ libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t.pass.cpp @@ -22,11 +22,6 @@ // XFAIL: with_system_cxx_lib=macosx10.10 // XFAIL: with_system_cxx_lib=macosx10.9 -// On Windows libc++ doesn't provide its own definitions for new/delete -// but instead depends on the ones in VCRuntime. However VCRuntime does not -// yet provide aligned new/delete definitions so this test fails to link. -// XFAIL: LIBCXX-WINDOWS-FIXME - // test operator new #include Index: libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t_nothrow.pass.cpp =================================================================== --- libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t_nothrow.pass.cpp +++ libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t_nothrow.pass.cpp @@ -22,11 +22,6 @@ // XFAIL: with_system_cxx_lib=macosx10.10 // XFAIL: with_system_cxx_lib=macosx10.9 -// On Windows libc++ doesn't provide its own definitions for new/delete -// but instead depends on the ones in VCRuntime. However VCRuntime does not -// yet provide aligned new/delete definitions so this test fails to compile/link. -// XFAIL: LIBCXX-WINDOWS-FIXME - // test operator new (nothrow) #include Index: libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array.pass.cpp =================================================================== --- libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array.pass.cpp +++ libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array.pass.cpp @@ -9,7 +9,6 @@ // test operator new[] // NOTE: asan and msan will not call the new handler. // UNSUPPORTED: sanitizer-new-delete -// XFAIL: LIBCXX-WINDOWS-FIXME #include Index: libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_nothrow.pass.cpp =================================================================== --- libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_nothrow.pass.cpp +++ libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_nothrow.pass.cpp @@ -9,7 +9,6 @@ // test operator new [] (nothrow) // NOTE: asan and msan will not call the new handler. // UNSUPPORTED: sanitizer-new-delete -// XFAIL: LIBCXX-WINDOWS-FIXME #include Index: libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.pass.cpp =================================================================== --- libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.pass.cpp +++ libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.pass.cpp @@ -10,7 +10,6 @@ // asan and msan will not call the new handler. // UNSUPPORTED: sanitizer-new-delete -// XFAIL: LIBCXX-WINDOWS-FIXME #include #include Index: libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t.pass.cpp =================================================================== --- libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t.pass.cpp +++ libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t.pass.cpp @@ -22,11 +22,6 @@ // asan and msan will not call the new handler. // UNSUPPORTED: sanitizer-new-delete -// On Windows libc++ doesn't provide its own definitions for new/delete -// but instead depends on the ones in VCRuntime. However VCRuntime does not -// yet provide aligned new/delete definitions so this test fails to compile/link. -// XFAIL: LIBCXX-WINDOWS-FIXME - // test operator new #include Index: libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t_nothrow.pass.cpp =================================================================== --- libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t_nothrow.pass.cpp +++ libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t_nothrow.pass.cpp @@ -22,11 +22,6 @@ // asan and msan will not call the new handler. // UNSUPPORTED: sanitizer-new-delete -// On Windows libc++ doesn't provide its own definitions for new/delete -// but instead depends on the ones in VCRuntime. However VCRuntime does not -// yet provide aligned new/delete definitions so this test fails to compile/link. -// XFAIL: LIBCXX-WINDOWS-FIXME - // test operator new (nothrow) #include Index: libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_nothrow.pass.cpp =================================================================== --- libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_nothrow.pass.cpp +++ libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_nothrow.pass.cpp @@ -10,7 +10,6 @@ // asan and msan will not call the new handler. // UNSUPPORTED: sanitizer-new-delete -// XFAIL: LIBCXX-WINDOWS-FIXME #include #include Index: libcxx/test/std/thread/thread.condition/thread.condition.condvar/wait_for.pass.cpp =================================================================== --- libcxx/test/std/thread/thread.condition/thread.condition.condvar/wait_for.pass.cpp +++ libcxx/test/std/thread/thread.condition/thread.condition.condvar/wait_for.pass.cpp @@ -44,9 +44,12 @@ test1 = 1; cv.notify_one(); Clock::time_point t0 = Clock::now(); - while (test2 == 0 && - cv.wait_for(lk, milliseconds(250)) == std::cv_status::no_timeout) - ; + Clock::time_point wait_end = t0 + milliseconds(250); + Clock::time_point now; + do { + now = Clock::now(); + if (now >= wait_end) break; + } while (test2 == 0 && cv.wait_for(lk, wait_end - now) == std::cv_status::no_timeout); Clock::time_point t1 = Clock::now(); if (runs == 0) { Index: libcxx/test/std/thread/thread.condition/thread.condition.condvarany/wait_for.pass.cpp =================================================================== --- libcxx/test/std/thread/thread.condition/thread.condition.condvarany/wait_for.pass.cpp +++ libcxx/test/std/thread/thread.condition/thread.condition.condvarany/wait_for.pass.cpp @@ -47,9 +47,12 @@ test1 = 1; cv.notify_one(); Clock::time_point t0 = Clock::now(); - while (test2 == 0 && - cv.wait_for(lk, milliseconds(250)) == std::cv_status::no_timeout) - ; + Clock::time_point wait_end = t0 + milliseconds(250); + Clock::time_point now; + do { + now = Clock::now(); + if (now >= wait_end) break; + } while (test2 == 0 && cv.wait_for(lk, wait_end - now) == std::cv_status::no_timeout); Clock::time_point t1 = Clock::now(); if (runs == 0) { Index: libcxx/test/std/utilities/time/time.clock/time.clock.file/now.pass.cpp =================================================================== --- libcxx/test/std/utilities/time/time.clock/time.clock.file/now.pass.cpp +++ libcxx/test/std/utilities/time/time.clock/time.clock.file/now.pass.cpp @@ -17,8 +17,6 @@ // UNSUPPORTED: with_system_cxx_lib=macosx10.10 // UNSUPPORTED: with_system_cxx_lib=macosx10.9 -// XFAIL: LIBCXX-WINDOWS-FIXME - // // file_clock Index: libcxx/test/support/filesystem_test_helper.h =================================================================== --- libcxx/test/support/filesystem_test_helper.h +++ libcxx/test/support/filesystem_test_helper.h @@ -678,22 +678,28 @@ const fs::path dir("C:\\System Volume Information"); std::error_code ec; const fs::path root("C:\\"); - fs::directory_iterator it(root, ec); - if (ec) - return fs::path(); - const fs::directory_iterator endIt{}; - while (it != endIt) { - const fs::directory_entry &ent = *it; - if (ent == dir) { - // Basic sanity checks on the directory_entry - if (!ent.exists()) - return fs::path(); - if (!ent.is_directory()) - return fs::path(); - return ent; + for (const auto &ent : fs::directory_iterator(root, ec)) { + if (ent != dir) + continue; + // Basic sanity checks on the directory_entry + if (!ent.exists() || !ent.is_directory()) { + fprintf(stderr, "The expected inaccessible directory \"%s\" was found " + "but doesn't behave as expected, skipping tests " + "regarding it\n", dir.string().c_str()); + return fs::path(); } - ++it; + // Check that it indeed is inaccessible as expected + (void)fs::exists(ent, ec); + if (!ec) { + fprintf(stderr, "The expected inaccessible directory \"%s\" was found " + "but seems to be accessible, skipping tests " + "regarding it\n", dir.string().c_str()); + return fs::path(); + } + return ent; } + fprintf(stderr, "No inaccessible directory \"%s\" found, skipping tests " + "regarding it\n", dir.string().c_str()); return fs::path(); } Index: libcxx/utils/ci/buildkite-pipeline.yml =================================================================== --- libcxx/utils/ci/buildkite-pipeline.yml +++ libcxx/utils/ci/buildkite-pipeline.yml @@ -299,6 +299,21 @@ - exit_status: -1 # Agent was lost limit: 2 + - label: "Windows" + # TODO: The CI runner doesn't have bash in the path currently. Once it + # has that, remove the absolute path and just call 'bash' here. + command: "\"\\Program Files\\Git\\usr\\bin\\bash\" libcxx/utils/ci/run-buildbot generic-win" + artifact_paths: + - "**/test-results.xml" + agents: + queue: "windows" + retry: + automatic: + - exit_status: -1 # Agent was lost + limit: 2 + soft_fail: + - exit_status: 1 + # All jobs defined before this `wait` will run whenever a CI job is started. # Jobs defined after the `wait` will run only if all the jobs above succeeded. # We use this to reduce the load on testers that have more constrained resources Index: libcxx/utils/ci/run-buildbot =================================================================== --- libcxx/utils/ci/run-buildbot +++ libcxx/utils/ci/run-buildbot @@ -451,6 +451,49 @@ generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Armv7Thumb-noexceptions.cmake" check-cxx-cxxabi ;; +generic-win) + clean + # TODO: The CI runner doesn't have bash in the path currently, and it's + # needed for running tests. Once it's available out of the box, remove this. + export PATH="$PATH:/c/Program Files/Git/usr/bin" + + # TODO: Clang-cl in MSVC configurations don't have access to compiler_rt + # builtins helpers for int128 division. See + # https://reviews.llvm.org/D91139#2429595 for a comment about longterm + # intent for handling the issue. In the meantime, define + # -D_LIBCPP_HAS_NO_INT128 (both when building the library itself and + # when building tests) to allow enabling filesystem for running tests, + # even if it uses a non-permanent ABI. + + # TODO: The CI runner currently uses Clang 11, which doesn't implicitly + # link in oldnames.lib (which is needed for some tests) when compiling + # with the plain "clang" driver, as the tests do (as opposed to using + # the "clang-cl" driver for compiling). When the CI runner runs + # Clang 12, the "-loldnames" option can be dropped. + + # TODO: Currently, building with the experimental library breaks running + # tests (the test linking look for the c++experimental library with the + # wrong name, and the statically linked c++experimental can't be linked + # correctly when libc++ visibility attributes indicate dllimport linkage + # anyway), thus just disable the experimental library. Remove this + # setting when cmake and the test driver does the right thing automatically. + + echo "--- Generating CMake" + cmake -S "${MONOREPO_ROOT}/libcxx" \ + -B "${BUILD_DIR}" \ + -GNinja -DCMAKE_MAKE_PROGRAM="${NINJA}" \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DCMAKE_C_COMPILER=clang-cl \ + -DCMAKE_CXX_COMPILER=clang-cl \ + -DLLVM_LIT_ARGS="-sv --show-unsupported --xunit-xml-output test-results.xml" \ + -DLIBCXX_ENABLE_EXPERIMENTAL_LIBRARY=NO \ + -DLIBCXX_ENABLE_FILESYSTEM=YES \ + -DCMAKE_CXX_FLAGS="-D_LIBCPP_HAS_NO_INT128" \ + -DLIBCXX_TEST_COMPILER_FLAGS="-D_LIBCPP_HAS_NO_INT128" \ + -DLIBCXX_TEST_LINKER_FLAGS="-loldnames" + echo "+++ Running the libc++ tests" + ${NINJA} -vC "${BUILD_DIR}" check-cxx +;; *) echo "${BUILDER} is not a known configuration" exit 1 Index: libcxx/utils/libcxx/test/config.py =================================================================== --- libcxx/utils/libcxx/test/config.py +++ libcxx/utils/libcxx/test/config.py @@ -457,7 +457,7 @@ elif cxx_abi == 'vcruntime': debug_suffix = 'd' if self.debug_build else '' self.cxx.link_flags += ['-l%s%s' % (lib, debug_suffix) for lib in - ['vcruntime', 'ucrt', 'msvcrt']] + ['vcruntime', 'ucrt', 'msvcrt', 'msvcprt']] elif cxx_abi == 'none' or cxx_abi == 'default': if self.target_info.is_windows(): debug_suffix = 'd' if self.debug_build else ''