[libc++] Implement `operator<=>` for `filesystem::path`

Implements part of P1614R2 "The Mothership has Landed"

Differential Revision: https://reviews.llvm.org/D130859

NOKEYCHECK=True
GitOrigin-RevId: b3ab3bece0bf1d441518b7d3b1294cb72445cb0f
diff --git a/include/filesystem b/include/filesystem
index aa0cd56..8b81e10 100644
--- a/include/filesystem
+++ b/include/filesystem
@@ -14,29 +14,150 @@
 
     namespace std::filesystem {
 
-    class path;
+    // `class path` from http://eel.is/c++draft/fs.class.path.general#6
+    class path {
+      public:
+        using value_type  = see below;
+        using string_type = basic_string<value_type>;
+        static constexpr value_type preferred_separator = see below;
+
+        enum format;
+
+        path() noexcept;
+        path(const path& p);
+        path(path&& p) noexcept;
+        path(string_type&& source, format fmt = auto_format);
+        template<class Source>
+          path(const Source& source, format fmt = auto_format);
+        template<class InputIterator>
+          path(InputIterator first, InputIterator last, format fmt = auto_format);
+        template<class Source>
+          path(const Source& source, const locale& loc, format fmt = auto_format);
+        template<class InputIterator>
+          path(InputIterator first, InputIterator last, const locale& loc, format fmt = auto_format);
+        ~path();
+
+        path& operator=(const path& p);
+        path& operator=(path&& p) noexcept;
+        path& operator=(string_type&& source);
+        path& assign(string_type&& source);
+        template<class Source>
+          path& operator=(const Source& source);
+        template<class Source>
+          path& assign(const Source& source);
+        template<class InputIterator>
+          path& assign(InputIterator first, InputIterator last);
+
+        path& operator/=(const path& p);
+        template<class Source>
+          path& operator/=(const Source& source);
+        template<class Source>
+          path& append(const Source& source);
+        template<class InputIterator>
+          path& append(InputIterator first, InputIterator last);
+
+        path& operator+=(const path& x);
+        path& operator+=(const string_type& x);
+        path& operator+=(basic_string_view<value_type> x);
+        path& operator+=(const value_type* x);
+        path& operator+=(value_type x);
+        template<class Source>
+          path& operator+=(const Source& x);
+        template<class EcharT>
+          path& operator+=(EcharT x);
+        template<class Source>
+          path& concat(const Source& x);
+        template<class InputIterator>
+          path& concat(InputIterator first, InputIterator last);
+
+        void  clear() noexcept;
+        path& make_preferred();
+        path& remove_filename();
+        path& replace_filename(const path& replacement);
+        path& replace_extension(const path& replacement = path());
+        void  swap(path& rhs) noexcept;
+
+        friend bool operator==(const path& lhs, const path& rhs) noexcept;
+        friend bool operator!=(const path& lhs, const path& rhs) noexcept;             // removed in C++20
+        friend bool operator< (const path& lhs, const path& rhs) noexcept;             // removed in C++20
+        friend bool operator<=(const path& lhs, const path& rhs) noexcept;             // removed in C++20
+        friend bool operator> (const path& lhs, const path& rhs) noexcept;             // removed in C++20
+        friend bool operator>=(const path& lhs, const path& rhs) noexcept;             // removed in C++20
+        friend strong_ordering operator<=>(const path& lhs, const path& rhs) noexcept; // C++20
+
+        friend path operator/(const path& lhs, const path& rhs);
+
+        const string_type& native() const noexcept;
+        const value_type*  c_str() const noexcept;
+        operator string_type() const;
+
+        template<class EcharT, class traits = char_traits<EcharT>,
+                 class Allocator = allocator<EcharT>>
+          basic_string<EcharT, traits, Allocator>
+            string(const Allocator& a = Allocator()) const;
+        std::string    string() const;
+        std::wstring   wstring() const;
+        std::u8string  u8string() const;
+        std::u16string u16string() const;
+        std::u32string u32string() const;
+
+        template<class EcharT, class traits = char_traits<EcharT>,
+                 class Allocator = allocator<EcharT>>
+          basic_string<EcharT, traits, Allocator>
+            generic_string(const Allocator& a = Allocator()) const;
+        std::string    generic_string() const;
+        std::wstring   generic_wstring() const;
+        std::u8string  generic_u8string() const;
+        std::u16string generic_u16string() const;
+        std::u32string generic_u32string() const;
+
+        int compare(const path& p) const noexcept;
+        int compare(const string_type& s) const;
+        int compare(basic_string_view<value_type> s) const;
+        int compare(const value_type* s) const;
+
+        path root_name() const;
+        path root_directory() const;
+        path root_path() const;
+        path relative_path() const;
+        path parent_path() const;
+        path filename() const;
+        path stem() const;
+        path extension() const;
+
+        [[nodiscard]] bool empty() const noexcept;
+        bool has_root_name() const;
+        bool has_root_directory() const;
+        bool has_root_path() const;
+        bool has_relative_path() const;
+        bool has_parent_path() const;
+        bool has_filename() const;
+        bool has_stem() const;
+        bool has_extension() const;
+        bool is_absolute() const;
+        bool is_relative() const;
+
+        path lexically_normal() const;
+        path lexically_relative(const path& base) const;
+        path lexically_proximate(const path& base) const;
+
+        class iterator;
+        using const_iterator = iterator;
+
+        iterator begin() const;
+        iterator end() const;
+
+        template<class charT, class traits>
+          friend basic_ostream<charT, traits>&
+            operator<<(basic_ostream<charT, traits>& os, const path& p);
+        template<class charT, class traits>
+          friend basic_istream<charT, traits>&
+            operator>>(basic_istream<charT, traits>& is, path& p);
+    };
 
     void swap(path& lhs, path& rhs) noexcept;
     size_t hash_value(const path& p) noexcept;
 
-    bool operator==(const path& lhs, const path& rhs) noexcept;
-    bool operator!=(const path& lhs, const path& rhs) noexcept;
-    bool operator< (const path& lhs, const path& rhs) noexcept;
-    bool operator<=(const path& lhs, const path& rhs) noexcept;
-    bool operator> (const path& lhs, const path& rhs) noexcept;
-    bool operator>=(const path& lhs, const path& rhs) noexcept;
-
-    path operator/ (const path& lhs, const path& rhs);
-
-    // fs.path.io operators are friends of path.
-    template <class charT, class traits>
-    friend basic_ostream<charT, traits>&
-    operator<<(basic_ostream<charT, traits>& os, const path& p);
-
-    template <class charT, class traits>
-    friend basic_istream<charT, traits>&
-    operator>>(basic_istream<charT, traits>& is, path& p);
-
     template <class Source>
       path u8path(const Source& source);
     template <class InputIterator>