diff --git a/libcxx/docs/Status/SpaceshipProjects.csv b/libcxx/docs/Status/SpaceshipProjects.csv --- a/libcxx/docs/Status/SpaceshipProjects.csv +++ b/libcxx/docs/Status/SpaceshipProjects.csv @@ -76,6 +76,6 @@ | chrono::time_zone_link",A ```` implementation,Unassigned,|Not Started| | `[fs.filesystem.syn] `_,| `filesystem::space_info `_,None,Adrian Vogelsgesang,|Complete| | `[fs.path.nonmember] `_,| `filesystem::path `_,None,Adrian Vogelsgesang,|Complete| -| `[fs.dir.entry.obs] `_,| `filesystem::directory_entry `_,None,Adrian Vogelsgesang,|In Progress| +| `[fs.dir.entry.obs] `_,| `filesystem::directory_entry `_,None,Adrian Vogelsgesang,|Complete| | `[re.submatch.op] `_,| sub_match,None,Mark de Wever,|In Progress| | `[thread.thread.id] `_,| `thread::id `_,None,Adrian Vogelsgesang,|Complete| diff --git a/libcxx/include/__filesystem/directory_entry.h b/libcxx/include/__filesystem/directory_entry.h --- a/libcxx/include/__filesystem/directory_entry.h +++ b/libcxx/include/__filesystem/directory_entry.h @@ -215,21 +215,23 @@ return __get_symlink_status(&__ec); } - _LIBCPP_INLINE_VISIBILITY - bool operator<(directory_entry const& __rhs) const noexcept { - return __p_ < __rhs.__p_; - } _LIBCPP_INLINE_VISIBILITY bool operator==(directory_entry const& __rhs) const noexcept { return __p_ == __rhs.__p_; } +#if _LIBCPP_STD_VER <= 17 _LIBCPP_INLINE_VISIBILITY bool operator!=(directory_entry const& __rhs) const noexcept { return __p_ != __rhs.__p_; } + _LIBCPP_INLINE_VISIBILITY + bool operator<(directory_entry const& __rhs) const noexcept { + return __p_ < __rhs.__p_; + } + _LIBCPP_INLINE_VISIBILITY bool operator<=(directory_entry const& __rhs) const noexcept { return __p_ <= __rhs.__p_; @@ -245,6 +247,15 @@ return __p_ >= __rhs.__p_; } +#else // _LIBCPP_STD_VER <= 17 + + _LIBCPP_HIDE_FROM_ABI + strong_ordering operator<=>(const directory_entry& __rhs) const noexcept { + return __p_ <=> __rhs.__p_; + } + +#endif // _LIBCPP_STD_VER <= 17 + template _LIBCPP_INLINE_VISIBILITY friend basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const directory_entry& __d) { diff --git a/libcxx/include/filesystem b/libcxx/include/filesystem --- a/libcxx/include/filesystem +++ b/libcxx/include/filesystem @@ -164,7 +164,74 @@ path u8path(InputIterator first, InputIterator last); class filesystem_error; - class directory_entry; + + class directory_entry { + public: + directory_entry() noexcept = default; + directory_entry(const directory_entry&) = default; + directory_entry(directory_entry&&) noexcept = default; + explicit directory_entry(const filesystem::path& p); + directory_entry(const filesystem::path& p, error_code& ec); + ~directory_entry(); + + directory_entry& operator=(const directory_entry&) = default; + directory_entry& operator=(directory_entry&&) noexcept = default; + + void assign(const filesystem::path& p); + void assign(const filesystem::path& p, error_code& ec); + void replace_filename(const filesystem::path& p); + void replace_filename(const filesystem::path& p, error_code& ec); + void refresh(); + void refresh(error_code& ec) noexcept; + + const filesystem::path& path() const noexcept; + operator const filesystem::path&() const noexcept; + bool exists() const; + bool exists(error_code& ec) const noexcept; + bool is_block_file() const; + bool is_block_file(error_code& ec) const noexcept; + bool is_character_file() const; + bool is_character_file(error_code& ec) const noexcept; + bool is_directory() const; + bool is_directory(error_code& ec) const noexcept; + bool is_fifo() const; + bool is_fifo(error_code& ec) const noexcept; + bool is_other() const; + bool is_other(error_code& ec) const noexcept; + bool is_regular_file() const; + bool is_regular_file(error_code& ec) const noexcept; + bool is_socket() const; + bool is_socket(error_code& ec) const noexcept; + bool is_symlink() const; + bool is_symlink(error_code& ec) const noexcept; + uintmax_t file_size() const; + uintmax_t file_size(error_code& ec) const noexcept; + uintmax_t hard_link_count() const; + uintmax_t hard_link_count(error_code& ec) const noexcept; + file_time_type last_write_time() const; + file_time_type last_write_time(error_code& ec) const noexcept; + file_status status() const; + file_status status(error_code& ec) const noexcept; + file_status symlink_status() const; + file_status symlink_status(error_code& ec) const noexcept; + + // XXX + bool operator==(const directory_entry& rhs) const noexcept; + bool operator!=(const directory_entry& rhs) const noexcept; // removed in C++20 + bool operator< (const directory_entry& rhs) const noexcept; // removed in C++20 + bool operator<=(const directory_entry& rhs) const noexcept; // removed in C++20 + bool operator> (const directory_entry& rhs) const noexcept; // removed in C++20 + bool operator>=(const directory_entry& rhs) const noexcept; // removed in C++20 + strong_ordering operator<=>(const directory_entry& rhs) const noexcept; // since C++20 + + template + friend basic_ostream& + operator<<(basic_ostream& os, const directory_entry& d); + + private: + filesystem::path pathobject; // exposition only + friend class directory_iterator; // exposition only + }; class directory_iterator; diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/comparisons.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/comparisons.pass.cpp --- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/comparisons.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/comparisons.pass.cpp @@ -18,6 +18,7 @@ // bool operator<=(directory_entry const&) const noexcept; // bool operator> (directory_entry const&) const noexcept; // bool operator>=(directory_entry const&) const noexcept; +// strong_ordering operator<=>(directory_entry const&) const noexcept; #include "filesystem_include.h" #include @@ -25,61 +26,28 @@ #include #include "test_macros.h" - - -#define CHECK_OP(Op) \ - static_assert(std::is_same::value, ""); \ - static_assert(noexcept(ce Op ce), "Operation must be noexcept" ) - -void test_comparison_signatures() { - using namespace fs; - path const p("foo/bar/baz"); - // Check that the operators are valid, yield bool, and are not - // potentially-throwing. - { - directory_entry const ce(p); - CHECK_OP(==); - CHECK_OP(!=); - CHECK_OP(< ); - CHECK_OP(<=); - CHECK_OP(> ); - CHECK_OP(>=); - } -} -#undef CHECK_OP - -// The actual semantics of the comparisons are testing via paths operators. -void test_comparisons_simple() { - using namespace fs; - typedef std::pair TestType; - TestType TestCases[] = - { - {"", ""}, - {"", "a"}, - {"a", "a"}, - {"a", "b"}, - {"foo/bar/baz", "foo/bar/baz/"} - }; - auto TestFn = [](path const& LHS, const directory_entry& LHSE, - path const& RHS, const directory_entry& RHSE) { - assert((LHS == RHS) == (LHSE == RHSE)); - assert((LHS != RHS) == (LHSE != RHSE)); - assert((LHS < RHS) == (LHSE < RHSE)); - assert((LHS <= RHS) == (LHSE <= RHSE)); - assert((LHS > RHS) == (LHSE > RHSE)); - assert((LHS >= RHS) == (LHSE >= RHSE)); - }; - for (auto const& TC : TestCases) { - const directory_entry L(TC.first); - const directory_entry R(TC.second); - TestFn(TC.first, L, TC.second, R); - TestFn(TC.second, R, TC.first, L); - } -} +#include "test_comparisons.h" int main(int, char**) { - test_comparison_signatures(); - test_comparisons_simple(); + using namespace fs; + + AssertComparisonsAreNoexcept(); + AssertComparisonsReturnBool(); +#if TEST_STD_VER > 17 + AssertOrderAreNoexcept(); + AssertOrderReturn(); +#endif + + typedef std::pair TestType; + TestType TestCases[] = {{"", ""}, {"", "a"}, {"a", "a"}, {"a", "b"}, {"foo/bar/baz", "foo/bar/baz/"}}; + for (auto const& TC : TestCases) { + assert(testComparisonsValues(TC.first, TC.second)); + assert(testComparisonsValues(TC.second, TC.first)); +#if TEST_STD_VER > 17 + assert(testOrderValues(TC.first, TC.second)); + assert(testOrderValues(TC.second, TC.first)); +#endif + } return 0; }