[libc++] Move preferred_name declarations into the forward declaring headers and add pmr preferred names

We currently define the preferred names in multiple places. `basic_string` and `basic_string_view` also have a lot of aliases, which makes the declarations quite long. So let's only add the preferred names in forward-declaring headers to make the implementation more readable and have all the preferred names in one place.

Reviewed By: ldionne

Spies: EricWF, krytarowski, libcxx-commits

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

NOKEYCHECK=True
GitOrigin-RevId: 627465cf9fa71ac1933986c20b32d6842a5b2678
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
index 99a1529..7603b37 100644
--- a/include/CMakeLists.txt
+++ b/include/CMakeLists.txt
@@ -342,8 +342,10 @@
   __fwd/array.h
   __fwd/get.h
   __fwd/hash.h
+  __fwd/memory_resource.h
   __fwd/pair.h
   __fwd/span.h
+  __fwd/string.h
   __fwd/string_view.h
   __fwd/tuple.h
   __hash_table
diff --git a/include/__fwd/memory_resource.h b/include/__fwd/memory_resource.h
new file mode 100644
index 0000000..718a907
--- /dev/null
+++ b/include/__fwd/memory_resource.h
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___FWD_MEMORY_RESOURCE_H
+#define _LIBCPP___FWD_MEMORY_RESOURCE_H
+
+#include <__config>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+namespace pmr {
+template <class _ValueType>
+class _LIBCPP_TEMPLATE_VIS polymorphic_allocator;
+} // namespace pmr
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___FWD_MEMORY_RESOURCE_H
diff --git a/include/__fwd/string.h b/include/__fwd/string.h
new file mode 100644
index 0000000..7ab5561
--- /dev/null
+++ b/include/__fwd/string.h
@@ -0,0 +1,110 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___FWD_STRING_H
+#define _LIBCPP___FWD_STRING_H
+
+#include <__config>
+#include <__fwd/memory_resource.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template <class _CharT>
+struct _LIBCPP_TEMPLATE_VIS char_traits;
+template <>
+struct char_traits<char>;
+
+#ifndef _LIBCPP_HAS_NO_CHAR8_T
+template <>
+struct char_traits<char8_t>;
+#endif
+
+template <>
+struct char_traits<char16_t>;
+template <>
+struct char_traits<char32_t>;
+
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
+template <>
+struct char_traits<wchar_t>;
+#endif
+
+template <class _Tp>
+class _LIBCPP_TEMPLATE_VIS allocator;
+
+template <class _CharT, class _Traits = char_traits<_CharT>, class _Allocator = allocator<_CharT> >
+class _LIBCPP_TEMPLATE_VIS basic_string;
+
+using string = basic_string<char>;
+
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
+using wstring = basic_string<wchar_t>;
+#endif
+
+#ifndef _LIBCPP_HAS_NO_CHAR8_T
+using u8string = basic_string<char8_t>;
+#endif
+
+using u16string = basic_string<char16_t>;
+using u32string = basic_string<char32_t>;
+
+#if _LIBCPP_STD_VER >= 17
+
+namespace pmr {
+template <class _CharT, class _Traits = char_traits<_CharT>>
+using basic_string = std::basic_string<_CharT, _Traits, polymorphic_allocator<_CharT>>;
+
+using string = basic_string<char>;
+
+#  ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
+using wstring = basic_string<wchar_t>;
+#  endif
+
+#  ifndef _LIBCPP_HAS_NO_CHAR8_T
+using u8string = basic_string<char8_t>;
+#  endif
+
+using u16string = basic_string<char16_t>;
+using u32string = basic_string<char32_t>;
+
+} // namespace pmr
+
+#endif // _LIBCPP_STD_VER >= 17
+
+// clang-format off
+template <class _CharT, class _Traits, class _Allocator>
+class _LIBCPP_PREFERRED_NAME(string)
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
+      _LIBCPP_PREFERRED_NAME(wstring)
+#endif
+#ifndef _LIBCPP_HAS_NO_CHAR8_T
+      _LIBCPP_PREFERRED_NAME(u8string)
+#endif
+      _LIBCPP_PREFERRED_NAME(u16string)
+      _LIBCPP_PREFERRED_NAME(u32string)
+#if _LIBCPP_STD_VER >= 17
+      _LIBCPP_PREFERRED_NAME(pmr::string)
+#  ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
+      _LIBCPP_PREFERRED_NAME(pmr::wstring)
+#  endif
+#  ifndef _LIBCPP_HAS_NO_CHAR8_T
+      _LIBCPP_PREFERRED_NAME(pmr::u8string)
+#  endif
+      _LIBCPP_PREFERRED_NAME(pmr::u16string)
+      _LIBCPP_PREFERRED_NAME(pmr::u32string)
+#endif
+      basic_string;
+// clang-format on
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___FWD_STRING_H
diff --git a/include/__fwd/string_view.h b/include/__fwd/string_view.h
index 4324c9f..4818990 100644
--- a/include/__fwd/string_view.h
+++ b/include/__fwd/string_view.h
@@ -32,6 +32,19 @@
 typedef basic_string_view<wchar_t>  wstring_view;
 #endif
 
+// clang-format off
+template <class _CharT, class _Traits>
+class _LIBCPP_PREFERRED_NAME(string_view)
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
+      _LIBCPP_PREFERRED_NAME(wstring_view)
+#endif
+#ifndef _LIBCPP_HAS_NO_CHAR8_T
+      _LIBCPP_PREFERRED_NAME(u8string_view)
+#endif
+      _LIBCPP_PREFERRED_NAME(u16string_view)
+      _LIBCPP_PREFERRED_NAME(u32string_view)
+      basic_string_view;
+// clang-format on
 _LIBCPP_END_NAMESPACE_STD
 
 #endif // _LIBCPP___FWD_STRING_VIEW_H
diff --git a/include/iosfwd b/include/iosfwd
index 9cd9450..7948606 100644
--- a/include/iosfwd
+++ b/include/iosfwd
@@ -96,6 +96,7 @@
 
 #include <__assert> // all public C++ headers provide the assertion handler
 #include <__config>
+#include <__fwd/string.h>
 #include <__mbstate_t.h>
 #include <version>
 
@@ -107,19 +108,6 @@
 
 class _LIBCPP_TYPE_VIS ios_base;
 
-template<class _CharT>  struct _LIBCPP_TEMPLATE_VIS char_traits;
-template<> struct char_traits<char>;
-#ifndef _LIBCPP_HAS_NO_CHAR8_T
-template<> struct char_traits<char8_t>;
-#endif
-template<> struct char_traits<char16_t>;
-template<> struct char_traits<char32_t>;
-#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
-template<> struct char_traits<wchar_t>;
-#endif
-
-template<class _Tp>     class _LIBCPP_TEMPLATE_VIS allocator;
-
 template <class _CharT, class _Traits = char_traits<_CharT> >
     class _LIBCPP_TEMPLATE_VIS basic_ios;
 
@@ -242,18 +230,6 @@
 typedef long long streamoff;        // for char_traits in <string>
 #endif
 
-template <class _CharT,             // for <stdexcept>
-          class _Traits = char_traits<_CharT>,
-          class _Allocator = allocator<_CharT> >
-    class _LIBCPP_TEMPLATE_VIS basic_string;
-typedef basic_string<char, char_traits<char>, allocator<char> > string;
-#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
-typedef basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> > wstring;
-#endif
-
-template <class _CharT, class _Traits, class _Allocator>
-    class _LIBCPP_PREFERRED_NAME(string) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wstring)) basic_string;
-
 // Include other forward declarations here
 template <class _Tp, class _Alloc = allocator<_Tp> >
 class _LIBCPP_TEMPLATE_VIS vector;
diff --git a/include/module.modulemap.in b/include/module.modulemap.in
index a7e3ff0..c33f5a8 100644
--- a/include/module.modulemap.in
+++ b/include/module.modulemap.in
@@ -988,6 +988,7 @@
 
     module __memory_resource {
       module memory_resource              { private header "__memory_resource/memory_resource.h" }
+      module memory_resource_fwd          { private header "__fwd/memory_resource.h" }
       module monotonic_buffer_resource    { private header "__memory_resource/monotonic_buffer_resource.h" }
       module polymorphic_allocator        { private header "__memory_resource/polymorphic_allocator.h" }
       module pool_options                 { private header "__memory_resource/pool_options.h" }
@@ -1218,6 +1219,7 @@
     module __string {
       module char_traits           { private header "__string/char_traits.h" }
       module extern_template_lists { private header "__string/extern_template_lists.h" }
+      module string_fwd            { private header "__fwd/string.h" }
     }
     export *
   }
diff --git a/include/regex b/include/regex
index d45f6c1..91a10fe 100644
--- a/include/regex
+++ b/include/regex
@@ -6845,9 +6845,12 @@
 using match_results = std::match_results<_BidirT, polymorphic_allocator<std::sub_match<_BidirT>>>;
 
 using cmatch  = match_results<const char*>;
-using wcmatch = match_results<const wchar_t*>;
 using smatch  = match_results<std::pmr::string::const_iterator>;
+
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
+using wcmatch = match_results<const wchar_t*>;
 using wsmatch = match_results<std::pmr::wstring::const_iterator>;
+#endif
 } // namespace pmr
 _LIBCPP_END_NAMESPACE_STD
 #endif
diff --git a/include/string b/include/string
index 652fa32..8eb1d30 100644
--- a/include/string
+++ b/include/string
@@ -539,6 +539,7 @@
 #include <__format/enable_insertable.h>
 #include <__functional/hash.h>
 #include <__functional/unary_function.h>
+#include <__fwd/string.h>
 #include <__ios/fpos.h>
 #include <__iterator/distance.h>
 #include <__iterator/iterator_traits.h>
@@ -565,7 +566,6 @@
 #include <cstdio>  // EOF
 #include <cstdlib>
 #include <cstring>
-#include <iosfwd>
 #include <limits>
 #include <stdexcept>
 #include <string_view>
@@ -646,23 +646,10 @@
      !is_convertible<const _Tp&, const _CharT*>::value
     > {};
 
-#ifndef _LIBCPP_HAS_NO_CHAR8_T
-typedef basic_string<char8_t> u8string;
-#endif
-typedef basic_string<char16_t> u16string;
-typedef basic_string<char32_t> u32string;
-
 struct __uninitialized_size_tag {};
 
 template<class _CharT, class _Traits, class _Allocator>
-class
-    _LIBCPP_TEMPLATE_VIS
-#ifndef _LIBCPP_HAS_NO_CHAR8_T
-    _LIBCPP_PREFERRED_NAME(u8string)
-#endif
-    _LIBCPP_PREFERRED_NAME(u16string)
-    _LIBCPP_PREFERRED_NAME(u32string)
-    basic_string
+class basic_string
 {
 public:
     typedef basic_string                                 __self;
@@ -4674,20 +4661,6 @@
 
 _LIBCPP_END_NAMESPACE_STD
 
-#if _LIBCPP_STD_VER > 14
-_LIBCPP_BEGIN_NAMESPACE_STD
-namespace pmr {
-template <class _CharT, class _TraitsT = std::char_traits<_CharT>>
-using basic_string = std::basic_string<_CharT, _TraitsT, polymorphic_allocator<_CharT>>;
-
-using string    = basic_string<char>;
-using u16string = basic_string<char16_t>;
-using u32string = basic_string<char32_t>;
-using wstring   = basic_string<wchar_t>;
-} // namespace pmr
-_LIBCPP_END_NAMESPACE_STD
-#endif
-
 _LIBCPP_POP_MACROS
 
 #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
diff --git a/include/string_view b/include/string_view
index 2941f71..2c4f306 100644
--- a/include/string_view
+++ b/include/string_view
@@ -256,15 +256,7 @@
 }
 
 template<class _CharT, class _Traits>
-class
-    _LIBCPP_PREFERRED_NAME(string_view)
-#ifndef _LIBCPP_HAS_NO_CHAR8_T
-    _LIBCPP_PREFERRED_NAME(u8string_view)
-#endif
-    _LIBCPP_PREFERRED_NAME(u16string_view)
-    _LIBCPP_PREFERRED_NAME(u32string_view)
-    _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wstring_view))
-    basic_string_view {
+class basic_string_view {
 public:
     // types
     typedef _Traits                                    traits_type;