[PATCH] D41830: [libc++] Fix PR#35780 - make std::experimental::filesystem::remove return false if the file doesn't exist
TyanNN created this revision. TyanNN added a reviewer: EricWF. Herald added a subscriber: cfe-commits. Previously it thrown an error if the file didn't exist. PR#35780 Repository: rCXX libc++ https://reviews.llvm.org/D41830 Files: src/experimental/filesystem/operations.cpp test/libcxx/experimental/filesystem/class.path/path.remove/remove_should_not_throw.pass.cpp Index: test/libcxx/experimental/filesystem/class.path/path.remove/remove_should_not_throw.pass.cpp === --- test/libcxx/experimental/filesystem/class.path/path.remove/remove_should_not_throw.pass.cpp +++ test/libcxx/experimental/filesystem/class.path/path.remove/remove_should_not_throw.pass.cpp @@ -0,0 +1,42 @@ +//===--===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===--===// + +// UNSUPPORTED: c++98, c++03 + +// + +// class path + +#define _LIBCPP_DEBUG 0 +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : (void)::AssertCount++) +int AssertCount = 0; + +#include +#include +#include + +namespace fs = std::experimental::filesystem; + +int main() +{ +using namespace fs; + +path nFile("nonexistant.file"); +assert(remove(nFile) == false); + +path tempFilePath = temp_directory_path(); +tempFilePath += path("existingFile"); + +std::ofstream theTempFile(tempFilePath); +theTempFile.close(); + +assert(remove(tempFilePath) == true); + +return 0; +} Index: src/experimental/filesystem/operations.cpp === --- src/experimental/filesystem/operations.cpp +++ src/experimental/filesystem/operations.cpp @@ -661,8 +661,9 @@ bool __remove(const path& p, std::error_code *ec) { if (ec) ec->clear(); + if (::remove(p.c_str()) == -1) { -set_or_throw(ec, "remove", p); +if (errno != ENOENT) set_or_throw(ec, "remove", p); return false; } return true; Index: test/libcxx/experimental/filesystem/class.path/path.remove/remove_should_not_throw.pass.cpp === --- test/libcxx/experimental/filesystem/class.path/path.remove/remove_should_not_throw.pass.cpp +++ test/libcxx/experimental/filesystem/class.path/path.remove/remove_should_not_throw.pass.cpp @@ -0,0 +1,42 @@ +//===--===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===--===// + +// UNSUPPORTED: c++98, c++03 + +// + +// class path + +#define _LIBCPP_DEBUG 0 +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : (void)::AssertCount++) +int AssertCount = 0; + +#include +#include +#include + +namespace fs = std::experimental::filesystem; + +int main() +{ +using namespace fs; + +path nFile("nonexistant.file"); +assert(remove(nFile) == false); + +path tempFilePath = temp_directory_path(); +tempFilePath += path("existingFile"); + +std::ofstream theTempFile(tempFilePath); +theTempFile.close(); + +assert(remove(tempFilePath) == true); + +return 0; +} Index: src/experimental/filesystem/operations.cpp === --- src/experimental/filesystem/operations.cpp +++ src/experimental/filesystem/operations.cpp @@ -661,8 +661,9 @@ bool __remove(const path& p, std::error_code *ec) { if (ec) ec->clear(); + if (::remove(p.c_str()) == -1) { -set_or_throw(ec, "remove", p); +if (errno != ENOENT) set_or_throw(ec, "remove", p); return false; } return true; ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D41830: [libc++] Fix PR#35780 - make std::experimental::filesystem::remove and remove_all return false or 0 if the file doesn't exist
TyanNN updated this revision to Diff 129115. TyanNN retitled this revision from "[libc++] Fix PR#35780 - make std::experimental::filesystem::remove return false if the file doesn't exist" to "[libc++] Fix PR#35780 - make std::experimental::filesystem::remove and remove_all return false or 0 if the file doesn't exist". TyanNN edited the summary of this revision. TyanNN added a comment. Fix remove_all too. Use std error codes instead of those from C https://reviews.llvm.org/D41830 Files: src/experimental/filesystem/operations.cpp test/libcxx/experimental/filesystem/class.path/path.remove/remove_should_not_throw_on_nonexistant.pass.cpp Index: test/libcxx/experimental/filesystem/class.path/path.remove/remove_should_not_throw_on_nonexistant.pass.cpp === --- test/libcxx/experimental/filesystem/class.path/path.remove/remove_should_not_throw_on_nonexistant.pass.cpp +++ test/libcxx/experimental/filesystem/class.path/path.remove/remove_should_not_throw_on_nonexistant.pass.cpp @@ -0,0 +1,52 @@ +//===--===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===--===// + +// UNSUPPORTED: c++98, c++03 + +// + +// class path + +#define _LIBCPP_DEBUG 0 +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : (void)::AssertCount++) +int AssertCount = 0; + +#include +#include +#include + +namespace fs = std::experimental::filesystem; + +int main() +{ +using namespace fs; + +// filesystem::remove test + +path nFile("nonexistant.file"); +assert(remove(nFile) == false); + +path tempFilePath = temp_directory_path(); +tempFilePath += path("existingFile"); + +std::ofstream theTempFile(tempFilePath); +theTempFile.close(); + +assert(remove(tempFilePath) == true); + +// filesystem::remove_all + +assert(remove_all(nFile) == 0); + +std::ofstream theTempFile2(tempFilePath); +theTempFile2.close(); +assert(remove_all(tempFilePath) == 1); + +return 0; +} Index: src/experimental/filesystem/operations.cpp === --- src/experimental/filesystem/operations.cpp +++ src/experimental/filesystem/operations.cpp @@ -661,8 +661,10 @@ bool __remove(const path& p, std::error_code *ec) { if (ec) ec->clear(); + if (::remove(p.c_str()) == -1) { -set_or_throw(ec, "remove", p); +if (ec != nullptr && *ec != errc::no_such_file_or_directory) +set_or_throw(ec, "remove", p); return false; } return true; @@ -695,8 +697,12 @@ std::error_code mec; auto count = remove_all_impl(p, mec); if (mec) { -set_or_throw(mec, ec, "remove_all", p); -return static_cast(-1); +if (mec != errc::no_such_file_or_directory) { +set_or_throw(mec, ec, "remove_all", p); +return static_cast(-1); +} else { +return static_cast(0); +} } if (ec) ec->clear(); return count; Index: test/libcxx/experimental/filesystem/class.path/path.remove/remove_should_not_throw_on_nonexistant.pass.cpp === --- test/libcxx/experimental/filesystem/class.path/path.remove/remove_should_not_throw_on_nonexistant.pass.cpp +++ test/libcxx/experimental/filesystem/class.path/path.remove/remove_should_not_throw_on_nonexistant.pass.cpp @@ -0,0 +1,52 @@ +//===--===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===--===// + +// UNSUPPORTED: c++98, c++03 + +// + +// class path + +#define _LIBCPP_DEBUG 0 +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : (void)::AssertCount++) +int AssertCount = 0; + +#include +#include +#include + +namespace fs = std::experimental::filesystem; + +int main() +{ +using namespace fs; + +// filesystem::remove test + +path nFile("nonexistant.file"); +assert(remove(nFile) == false); + +path tempFilePath = temp_directory_path(); +tempFilePath += path("existingFile"); + +std::ofstream theTempFile(tempFilePath); +theTempFile.close(); + +assert(remove(tempFilePath) == true); + +// filesystem::remove_all + +assert(remove_all(nFile) == 0); + +std::ofstream theTempFile2(tempFilePath); +theTempFile2.close(); +assert(remove_all(tempFilePath) == 1); + +return 0; +} Index: src/experimental/filesystem/operations.cpp ===
[PATCH] D41830: [libc++] Fix PR#35780 - make std::experimental::filesystem::remove and remove_all return false or 0 if the file doesn't exist
TyanNN updated this revision to Diff 129280. TyanNN added a comment. Fix remove and remove_all error resetting. Move test to the appropriate files and fix old tests. https://reviews.llvm.org/D41830 Files: src/experimental/filesystem/operations.cpp test/std/experimental/filesystem/fs.op.funcs/fs.op.remove/remove.pass.cpp test/std/experimental/filesystem/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp Index: test/std/experimental/filesystem/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp === --- test/std/experimental/filesystem/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp +++ test/std/experimental/filesystem/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp @@ -65,14 +65,18 @@ const path testCases[] = { env.make_env_path("dne"), -file_in_bad_dir +//file_in_bad_dir }; const auto BadRet = static_cast(-1); for (auto& p : testCases) { std::error_code ec; -TEST_CHECK(fs::remove_all(p, ec) == BadRet); -TEST_CHECK(ec); -TEST_CHECK(checkThrow(p, ec)); +if (exists(p)) { +TEST_CHECK(fs::remove_all(p, ec) == BadRet); +TEST_CHECK(ec); +TEST_CHECK(checkThrow(p, ec)); +} else { +TEST_CHECK(fs::remove_all(p, ec) == 0); +} } } Index: test/std/experimental/filesystem/fs.op.funcs/fs.op.remove/remove.pass.cpp === --- test/std/experimental/filesystem/fs.op.funcs/fs.op.remove/remove.pass.cpp +++ test/std/experimental/filesystem/fs.op.funcs/fs.op.remove/remove.pass.cpp @@ -64,13 +64,16 @@ "", env.make_env_path("dne"), non_empty_dir, -file_in_bad_dir, +// file_in_bad_dir, // produces "St13exception_ptruncaught_exceptions not yet implemented" }; for (auto& p : testCases) { std::error_code ec; + TEST_CHECK(!fs::remove(p, ec)); -TEST_CHECK(ec); -TEST_CHECK(checkThrow(p, ec)); +if (exists(p)) { +TEST_CHECK(ec); +TEST_CHECK(checkThrow(p, ec)); +} } } Index: src/experimental/filesystem/operations.cpp === --- src/experimental/filesystem/operations.cpp +++ src/experimental/filesystem/operations.cpp @@ -661,8 +661,10 @@ bool __remove(const path& p, std::error_code *ec) { if (ec) ec->clear(); + if (::remove(p.c_str()) == -1) { -set_or_throw(ec, "remove", p); +if (errno != ENOENT) +set_or_throw(ec, "remove", p); return false; } return true; @@ -692,13 +694,18 @@ } // end namespace std::uintmax_t __remove_all(const path& p, std::error_code *ec) { +if (ec) ec->clear(); + std::error_code mec; auto count = remove_all_impl(p, mec); if (mec) { -set_or_throw(mec, ec, "remove_all", p); -return static_cast(-1); +if (mec == errc::no_such_file_or_directory) { +return 0; +} else { +set_or_throw(mec, ec, "remove_all", p); +return static_cast(-1); +} } -if (ec) ec->clear(); return count; } Index: test/std/experimental/filesystem/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp === --- test/std/experimental/filesystem/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp +++ test/std/experimental/filesystem/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp @@ -65,14 +65,18 @@ const path testCases[] = { env.make_env_path("dne"), -file_in_bad_dir +//file_in_bad_dir }; const auto BadRet = static_cast(-1); for (auto& p : testCases) { std::error_code ec; -TEST_CHECK(fs::remove_all(p, ec) == BadRet); -TEST_CHECK(ec); -TEST_CHECK(checkThrow(p, ec)); +if (exists(p)) { +TEST_CHECK(fs::remove_all(p, ec) == BadRet); +TEST_CHECK(ec); +TEST_CHECK(checkThrow(p, ec)); +} else { +TEST_CHECK(fs::remove_all(p, ec) == 0); +} } } Index: test/std/experimental/filesystem/fs.op.funcs/fs.op.remove/remove.pass.cpp === --- test/std/experimental/filesystem/fs.op.funcs/fs.op.remove/remove.pass.cpp +++ test/std/experimental/filesystem/fs.op.funcs/fs.op.remove/remove.pass.cpp @@ -64,13 +64,16 @@ "", env.make_env_path("dne"), non_empty_dir, -file_in_bad_dir, +// file_in_bad_dir, // produces "St13exception_ptruncaught_exceptions not yet implemented" }; for (auto& p : testCases) { std::error_code ec; + TEST_CHECK(!fs::remove(p, ec)); -TEST_CHECK(ec); -TEST_CHECK(checkThrow(p, ec)); +if (exists(p)) { +TEST_CHECK(ec); +TES
[PATCH] D41830: [libc++] Fix PR#35780 - make std::experimental::filesystem::remove and remove_all return false or 0 if the file doesn't exist
TyanNN added inline comments. Comment at: test/std/experimental/filesystem/fs.op.funcs/fs.op.remove/remove.pass.cpp:67 non_empty_dir, -file_in_bad_dir, +// file_in_bad_dir, // produces "St13exception_ptruncaught_exceptions not yet implemented" }; This error is quite strange: it is not inherited from std::exception, one can only really find our the error with std::current_exception, and it happens when you use the path in fs::remove and fs::remove_all. Any idea about this? @mclow.lists https://reviews.llvm.org/D41830 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D41830: [libc++] Fix PR#35780 - make std::experimental::filesystem::remove and remove_all return false or 0 if the file doesn't exist
TyanNN marked 2 inline comments as done. TyanNN added inline comments. Comment at: test/std/experimental/filesystem/fs.op.funcs/fs.op.remove/remove.pass.cpp:67 non_empty_dir, -file_in_bad_dir, +// file_in_bad_dir, // produces "St13exception_ptruncaught_exceptions not yet implemented" }; mclow.lists wrote: > TyanNN wrote: > > This error is quite strange: it is not inherited from std::exception, one > > can only really find our the error with std::current_exception, and it > > happens when you use the path in fs::remove and fs::remove_all. Any idea > > about this? @mclow.lists > I'm not seeing this error on my system (nor are any of the bots reporting it > AFAIK). > > That looks like "`uncaught_exceptions` is not yet implemented", and that > comes from the ABI library. > > What are you using for an ABI library? Is it libc++abi? > Yes, I use libc++abi from trunk that I've built in llvm tree with libc++. I don't have a system wide installation of libc++abi so that must be it. Does uncommenting the line really work on your system? For the tests report an uncaught exception and fail. https://reviews.llvm.org/D41830 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D41830: [libc++] Fix PR#35780 - make std::experimental::filesystem::remove and remove_all return false or 0 if the file doesn't exist
TyanNN updated this revision to Diff 129453. TyanNN added a comment. Fix tests https://reviews.llvm.org/D41830 Files: src/experimental/filesystem/operations.cpp test/std/experimental/filesystem/fs.op.funcs/fs.op.remove/remove.pass.cpp test/std/experimental/filesystem/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp Index: test/std/experimental/filesystem/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp === --- test/std/experimental/filesystem/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp +++ test/std/experimental/filesystem/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp @@ -64,16 +64,28 @@ permissions(bad_perms_file, perms::none); const path testCases[] = { -env.make_env_path("dne"), file_in_bad_dir }; const auto BadRet = static_cast(-1); for (auto& p : testCases) { std::error_code ec; + TEST_CHECK(fs::remove_all(p, ec) == BadRet); TEST_CHECK(ec); TEST_CHECK(checkThrow(p, ec)); } + +// PR#35780 +const path testCasesNonexistant[] = { +"", +env.make_env_path("dne") +}; +for (auto &p : testCasesNonexistant) { +std::error_code ec; + +TEST_CHECK(fs::remove_all(p) == 0); +TEST_CHECK(!ec); +} } TEST_CASE(basic_remove_all_test) Index: test/std/experimental/filesystem/fs.op.funcs/fs.op.remove/remove.pass.cpp === --- test/std/experimental/filesystem/fs.op.funcs/fs.op.remove/remove.pass.cpp +++ test/std/experimental/filesystem/fs.op.funcs/fs.op.remove/remove.pass.cpp @@ -61,17 +61,29 @@ const path file_in_bad_dir = env.create_file(bad_perms_dir / "file", 42); permissions(bad_perms_dir, perms::none); const path testCases[] = { -"", -env.make_env_path("dne"), non_empty_dir, file_in_bad_dir, }; for (auto& p : testCases) { std::error_code ec; + TEST_CHECK(!fs::remove(p, ec)); TEST_CHECK(ec); TEST_CHECK(checkThrow(p, ec)); } + +// PR#35780 +const path testCasesNonexistant[] = { +"", +env.make_env_path("dne") +}; + +for (auto& p : testCasesNonexistant) { +std::error_code ec; + +TEST_CHECK(!fs::remove(p, ec)); +TEST_CHECK(!ec); +} } TEST_CASE(basic_remove_test) Index: src/experimental/filesystem/operations.cpp === --- src/experimental/filesystem/operations.cpp +++ src/experimental/filesystem/operations.cpp @@ -661,8 +661,10 @@ bool __remove(const path& p, std::error_code *ec) { if (ec) ec->clear(); + if (::remove(p.c_str()) == -1) { -set_or_throw(ec, "remove", p); +if (errno != ENOENT) +set_or_throw(ec, "remove", p); return false; } return true; @@ -692,13 +694,18 @@ } // end namespace std::uintmax_t __remove_all(const path& p, std::error_code *ec) { +if (ec) ec->clear(); + std::error_code mec; auto count = remove_all_impl(p, mec); if (mec) { -set_or_throw(mec, ec, "remove_all", p); -return static_cast(-1); +if (mec == errc::no_such_file_or_directory) { +return 0; +} else { +set_or_throw(mec, ec, "remove_all", p); +return static_cast(-1); +} } -if (ec) ec->clear(); return count; } ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D41830: [libc++] Fix PR#35780 - make std::experimental::filesystem::remove and remove_all return false or 0 if the file doesn't exist
TyanNN added inline comments. Comment at: test/std/experimental/filesystem/fs.op.funcs/fs.op.remove/remove.pass.cpp:67 non_empty_dir, -file_in_bad_dir, +// file_in_bad_dir, // produces "St13exception_ptruncaught_exceptions not yet implemented" }; mclow.lists wrote: > mclow.lists wrote: > > TyanNN wrote: > > > mclow.lists wrote: > > > > TyanNN wrote: > > > > > This error is quite strange: it is not inherited from std::exception, > > > > > one can only really find our the error with std::current_exception, > > > > > and it happens when you use the path in fs::remove and > > > > > fs::remove_all. Any idea about this? @mclow.lists > > > > I'm not seeing this error on my system (nor are any of the bots > > > > reporting it AFAIK). > > > > > > > > That looks like "`uncaught_exceptions` is not yet implemented", and > > > > that comes from the ABI library. > > > > > > > > What are you using for an ABI library? Is it libc++abi? > > > > > > > Yes, I use libc++abi from trunk that I've built in llvm tree with libc++. > > > I don't have a system wide installation of libc++abi so that must be it. > > > Does uncommenting the line really work on your system? For the tests > > > report an uncaught exception and fail. > > It's definitely not commented out on my system. > > (or on the trunk) > > > I see the message "uncaught_exceptions not yet implemented" in > src/support/runtime/exception_fallback.ipp - but only in an #ifdef block for > `__EMSCRIPTEN__` Well, it somehow got fixed after moving tests for nonexistant files into a separate loop, so that's good. https://reviews.llvm.org/D41830 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D41830: [libc++] Fix PR#35780 - make std::experimental::filesystem::remove and remove_all return false or 0 if the file doesn't exist
TyanNN added a comment. In https://reviews.llvm.org/D41830#973419, @mclow.lists wrote: > LGTM. > > Do you need me to commit this? Nope, i can do it myself https://reviews.llvm.org/D41830 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D41830: [libc++] Fix PR#35780 - make std::experimental::filesystem::remove and remove_all return false or 0 if the file doesn't exist
TyanNN added inline comments. Comment at: libcxx/trunk/test/std/experimental/filesystem/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp:86 + +TEST_CHECK(fs::remove_all(p) == 0); +TEST_CHECK(!ec); EricWF wrote: > This test is incorrect. `ec` isn't passed to the function. Indeed it isn't. I will fix it later today and commit. Repository: rL LLVM https://reviews.llvm.org/D41830 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits