Fix basic_string_view typedefs and enforce preconditions

The basic_string_view::pointer and basic_string_view::reference typedefs
are supposed to refer to the non-const value type.

In previous standards having traits_type::char_type different to
value_type was simply undefined, but in the C++2a draft it's ill-formed,
as changed by P1148R0. For std::basic_string and iostreams we might
want to only enforce this conditionally for __cplusplus > 201703L but
for std::basic_string_view we don't have backwards compatibility
concerns. Also add assertions to verify the _CharT argument is a
"char-like" type (non-array, trivial, standard layout type).

Also remove the non-standard basic_string_view::_M_check and
basic_string_view::_M_limit member functions, replacing them with
non-member functions that will still exist even if basic_string_view is
specialized by the program.

	* include/experimental/string_view (basic_string_view::pointer)
	(basic_string_view::reference): Fix to refer to non-const value_type.
	* include/bits/basic_string.h (basic_string): Use __sv_check and
	__sv_limit instead of basic_string_view::_M_check and
	basic_string_view::_M_limit.
	* include/std/string_view (__sv_check, __sv_limit): New
	helper functions to replace basic_string_view::_M_check and
	basic_string_view::_M_limit.
	(basic_string_view): Add static assertions to enforce ill-formed
	requirement for traits_type::char_type from P1148R0, and to enforce
	required properties of char-like types.
	(basic_string_view::pointer, basic_string_view::reference): Fix to
	refer to non-const value_type.
	(basic_string_view::operator[], basic_string_view::at)
	(basic_string_view::front, basic_string_view::back)
	(basic_string_view::data): Use const_reference and const_pointer
	typedefs for return types.
	(basic_string_view::_M_check, basic_string_view::_M_limit): Remove.
	(hash<wstring_view>): Fix argument_type typedef.
	* testsuite/21_strings/basic_string_view/modifiers/remove_prefix/
	char/1.cc: Fix expected return type of basic_string_view::data().
	* testsuite/21_strings/basic_string_view/modifiers/remove_prefix/
	wchar_t/1.cc: Likewise.
	* testsuite/21_strings/basic_string_view/modifiers/remove_suffix/
	char/1.cc: Likewise.
	* testsuite/21_strings/basic_string_view/modifiers/remove_suffix/
	wchar_t/1.cc: Likewise.
	* testsuite/21_strings/basic_string_view/requirements/traits_neg.cc:
	New test.
	* testsuite/21_strings/basic_string_view/requirements/typedefs.cc:
	Check reference and pointer typedefs.
	* testsuite/experimental/string_view/requirements/typedefs.cc:
	Likewise.
	* testsuite/experimental/string_view/modifiers/remove_prefix/char/1.cc:
	Fix expected return type of basic_string_view::data().
	* testsuite/experimental/string_view/modifiers/remove_prefix/wchar_t/
	1.cc: Likewise.
	* testsuite/experimental/string_view/modifiers/remove_suffix/char/1.cc:
	Likewise.
	* testsuite/experimental/string_view/modifiers/remove_suffix/wchar_t/
	1.cc: Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@270548 138bc75d-0d04-0410-961f-82ee72b054a4
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 2ab686b..5e8a09a 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,5 +1,47 @@
 2019-04-24  Jonathan Wakely  <jwakely@redhat.com>
 
+	* include/experimental/string_view (basic_string_view::pointer)
+	(basic_string_view::reference): Fix to refer to non-const value_type.
+	* include/bits/basic_string.h (basic_string): Use __sv_check and
+	__sv_limit instead of basic_string_view::_M_check and
+	basic_string_view::_M_limit.
+	* include/std/string_view (__sv_check, __sv_limit): New
+	helper functions to replace basic_string_view::_M_check and
+	basic_string_view::_M_limit.
+	(basic_string_view): Add static assertions to enforce ill-formed
+	requirement for traits_type::char_type from P1148R0, and to enforce
+	required properties of char-like types.
+	(basic_string_view::pointer, basic_string_view::reference): Fix to
+	refer to non-const value_type.
+	(basic_string_view::operator[], basic_string_view::at)
+	(basic_string_view::front, basic_string_view::back)
+	(basic_string_view::data): Use const_reference and const_pointer
+	typedefs for return types.
+	(basic_string_view::_M_check, basic_string_view::_M_limit): Remove.
+	(hash<wstring_view>): Fix argument_type typedef.
+	* testsuite/21_strings/basic_string_view/modifiers/remove_prefix/
+	char/1.cc: Fix expected return type of basic_string_view::data().
+	* testsuite/21_strings/basic_string_view/modifiers/remove_prefix/
+	wchar_t/1.cc: Likewise.
+	* testsuite/21_strings/basic_string_view/modifiers/remove_suffix/
+	char/1.cc: Likewise.
+	* testsuite/21_strings/basic_string_view/modifiers/remove_suffix/
+	wchar_t/1.cc: Likewise.
+	* testsuite/21_strings/basic_string_view/requirements/traits_neg.cc:
+	New test.
+	* testsuite/21_strings/basic_string_view/requirements/typedefs.cc:
+	Check reference and pointer typedefs.
+	* testsuite/experimental/string_view/requirements/typedefs.cc:
+	Likewise.
+	* testsuite/experimental/string_view/modifiers/remove_prefix/char/1.cc:
+	Fix expected return type of basic_string_view::data().
+	* testsuite/experimental/string_view/modifiers/remove_prefix/wchar_t/
+	1.cc: Likewise.
+	* testsuite/experimental/string_view/modifiers/remove_suffix/char/1.cc:
+	Likewise.
+	* testsuite/experimental/string_view/modifiers/remove_suffix/wchar_t/
+	1.cc: Likewise.
+
 	PR libstdc++/90220
 	* include/std/any (__any_caster): Use remove_cv_t instead of decay_t.
 	Avoid a runtime check for types that can never be stored in std::any.
diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index 9225369..40ef875 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -1336,8 +1336,8 @@
 	{
 	  __sv_type __sv = __svt;
 	  return _M_append(__sv.data()
-			   + __sv._M_check(__pos, "basic_string::append"),
-			   __sv._M_limit(__pos, __n));
+	      + std::__sv_check(__sv.size(), __pos, "basic_string::append"),
+	      std::__sv_limit(__sv.size(), __pos, __n));
 	}
 #endif // C++17
 
@@ -1507,9 +1507,10 @@
 	assign(const _Tp& __svt, size_type __pos, size_type __n = npos)
 	{
 	  __sv_type __sv = __svt;
-	  return _M_replace(size_type(0), this->size(), __sv.data()
-			    + __sv._M_check(__pos, "basic_string::assign"),
-			    __sv._M_limit(__pos, __n));
+	  return _M_replace(size_type(0), this->size(),
+	      __sv.data()
+	      + std::__sv_check(__sv.size(), __pos, "basic_string::assign"),
+	      std::__sv_limit(__sv.size(), __pos, __n));
 	}
 #endif // C++17
 
@@ -1780,9 +1781,10 @@
 	       size_type __pos2, size_type __n = npos)
 	{
 	  __sv_type __sv = __svt;
-	  return this->replace(__pos1, size_type(0), __sv.data()
-			       + __sv._M_check(__pos2, "basic_string::insert"),
-			       __sv._M_limit(__pos2, __n));
+	  return this->replace(__pos1, size_type(0),
+	      __sv.data()
+	      + std::__sv_check(__sv.size(), __pos2, "basic_string::insert"),
+	      std::__sv_limit(__sv.size(), __pos2, __n));
 	}
 #endif // C++17
 
@@ -2212,9 +2214,10 @@
 		size_type __pos2, size_type __n2 = npos)
 	{
 	  __sv_type __sv = __svt;
-	  return this->replace(__pos1, __n1, __sv.data()
-			       + __sv._M_check(__pos2, "basic_string::replace"),
-			       __sv._M_limit(__pos2, __n2));
+	  return this->replace(__pos1, __n1,
+	      __sv.data()
+	      + std::__sv_check(__sv.size(), __pos2, "basic_string::replace"),
+	      std::__sv_limit(__sv.size(), __pos2, __n2));
 	}
 
       /**
@@ -4303,8 +4306,8 @@
 	{
 	  __sv_type __sv = __svt;
 	  return append(__sv.data()
-			+ __sv._M_check(__pos, "basic_string::append"),
-			__sv._M_limit(__pos, __n));
+	      + std::__sv_check(__sv.size(), __pos, "basic_string::append"),
+	      std::__sv_limit(__sv.size(), __pos, __n));
 	}
 #endif // C++17
 
@@ -4460,8 +4463,8 @@
 	{
 	  __sv_type __sv = __svt;
 	  return assign(__sv.data()
-			+ __sv._M_check(__pos, "basic_string::assign"),
-			__sv._M_limit(__pos, __n));
+	      + std::__sv_check(__sv.size(), __pos, "basic_string::assign"),
+	      std::__sv_limit(__sv.size(), __pos, __n));
 	}
 #endif // C++17
 
@@ -4671,8 +4674,8 @@
 	{
 	  __sv_type __sv = __svt;
 	  return this->replace(__pos1, size_type(0), __sv.data()
-			       + __sv._M_check(__pos2, "basic_string::insert"),
-			       __sv._M_limit(__pos2, __n));
+	      + std::__sv_check(__sv.size(), __pos2, "basic_string::insert"),
+	      std::__sv_limit(__sv.size(), __pos2, __n));
 	}
 #endif // C++17
 
@@ -5062,8 +5065,9 @@
 	{
 	  __sv_type __sv = __svt;
 	  return this->replace(__pos1, __n1,
-	      __sv.data() + __sv._M_check(__pos2, "basic_string::replace"),
-	      __sv._M_limit(__pos2, __n2));
+	      __sv.data()
+	      + std::__sv_check(__sv.size(), __pos2, "basic_string::replace"),
+	      std::__sv_limit(__sv.size(), __pos2, __n2));
 	}
 
       /**
diff --git a/libstdc++-v3/include/experimental/string_view b/libstdc++-v3/include/experimental/string_view
index ce2c14c..9e810de 100644
--- a/libstdc++-v3/include/experimental/string_view
+++ b/libstdc++-v3/include/experimental/string_view
@@ -78,9 +78,9 @@
       // types
       using traits_type = _Traits;
       using value_type = _CharT;
-      using pointer = const _CharT*;
+      using pointer = _CharT*;
       using const_pointer = const _CharT*;
-      using reference = const _CharT&;
+      using reference = _CharT&;
       using const_reference = const _CharT&;
       using const_iterator = const _CharT*;
       using iterator = const_iterator;
diff --git a/libstdc++-v3/include/std/string_view b/libstdc++-v3/include/std/string_view
index 844cfb1..42822cc 100644
--- a/libstdc++-v3/include/std/string_view
+++ b/libstdc++-v3/include/std/string_view
@@ -49,6 +49,25 @@
 
 #define __cpp_lib_string_view 201603
 
+  // Helper for basic_string and basic_string_view members.
+  constexpr size_t
+  __sv_check(size_t __size, size_t __pos, const char* __s)
+  {
+    if (__pos > __size)
+      __throw_out_of_range_fmt(__N("%s: __pos (which is %zu) > __size "
+				   "(which is %zu)"), __s, __pos, __size);
+    return __pos;
+  }
+
+  // Helper for basic_string members.
+  // NB: __sv_limit doesn't check for a bad __pos value.
+  constexpr size_t
+  __sv_limit(size_t __size, size_t __pos, size_t __off) noexcept
+  {
+   const bool __testoff =  __off < __size - __pos;
+   return __testoff ? __off : __size - __pos;
+  }
+
   /**
    *  @class basic_string_view <string_view>
    *  @brief  A non-owning reference to a string.
@@ -70,24 +89,28 @@
   template<typename _CharT, typename _Traits = std::char_traits<_CharT>>
     class basic_string_view
     {
+      static_assert(!is_array_v<_CharT>);
+      static_assert(is_trivial_v<_CharT> && is_standard_layout_v<_CharT>);
+      static_assert(is_same_v<_CharT, typename _Traits::char_type>);
+
     public:
 
       // types
-      using traits_type = _Traits;
-      using value_type = _CharT;
-      using pointer = const _CharT*;
-      using const_pointer = const _CharT*;
-      using reference = const _CharT&;
-      using const_reference = const _CharT&;
-      using const_iterator = const _CharT*;
-      using iterator = const_iterator;
+      using traits_type		= _Traits;
+      using value_type		= _CharT;
+      using pointer		= value_type*;
+      using const_pointer	= const value_type*;
+      using reference		= value_type&;
+      using const_reference	= const value_type&;
+      using const_iterator	= const value_type*;
+      using iterator		= const_iterator;
       using const_reverse_iterator = std::reverse_iterator<const_iterator>;
-      using reverse_iterator = const_reverse_iterator;
-      using size_type = size_t;
-      using difference_type = ptrdiff_t;
+      using reverse_iterator	= const_reverse_iterator;
+      using size_type		= size_t;
+      using difference_type	= ptrdiff_t;
       static constexpr size_type npos = size_type(-1);
 
-      // [string.view.cons], construct/copy
+      // [string.view.cons], construction and assignment
 
       constexpr
       basic_string_view() noexcept
@@ -110,7 +133,7 @@
       constexpr basic_string_view&
       operator=(const basic_string_view&) noexcept = default;
 
-      // [string.view.iterators], iterators
+      // [string.view.iterators], iterator support
 
       constexpr const_iterator
       begin() const noexcept
@@ -167,7 +190,7 @@
 
       // [string.view.access], element access
 
-      constexpr const _CharT&
+      constexpr const_reference
       operator[](size_type __pos) const noexcept
       {
 	// TODO: Assert to restore in a way compatible with the constexpr.
@@ -175,7 +198,7 @@
 	return *(this->_M_str + __pos);
       }
 
-      constexpr const _CharT&
+      constexpr const_reference
       at(size_type __pos) const
       {
 	if (__pos >= _M_len)
@@ -185,7 +208,7 @@
 	return *(this->_M_str + __pos);
       }
 
-      constexpr const _CharT&
+      constexpr const_reference
       front() const noexcept
       {
 	// TODO: Assert to restore in a way compatible with the constexpr.
@@ -193,7 +216,7 @@
 	return *this->_M_str;
       }
 
-      constexpr const _CharT&
+      constexpr const_reference
       back() const noexcept
       {
 	// TODO: Assert to restore in a way compatible with the constexpr.
@@ -201,7 +224,7 @@
 	return *(this->_M_str + this->_M_len - 1);
       }
 
-      constexpr const _CharT*
+      constexpr const_pointer
       data() const noexcept
       { return this->_M_str; }
 
@@ -233,7 +256,7 @@
       copy(_CharT* __str, size_type __n, size_type __pos = 0) const
       {
 	__glibcxx_requires_string_len(__str, __n);
-	__pos = _M_check(__pos, "basic_string_view::copy");
+	__pos = std::__sv_check(size(), __pos, "basic_string_view::copy");
 	const size_type __rlen = std::min(__n, _M_len - __pos);
 	// _GLIBCXX_RESOLVE_LIB_DEFECTS
 	// 2777. basic_string_view::copy should use char_traits::copy
@@ -244,7 +267,7 @@
       constexpr basic_string_view
       substr(size_type __pos = 0, size_type __n = npos) const noexcept(false)
       {
-	__pos = _M_check(__pos, "basic_string_view::substr");
+	__pos = std::__sv_check(size(), __pos, "basic_string_view::substr");
 	const size_type __rlen = std::min(__n, _M_len - __pos);
 	return basic_string_view{_M_str + __pos, __rlen};
       }
@@ -286,6 +309,37 @@
 		   .compare(basic_string_view(__str, __n2));
       }
 
+#if __cplusplus > 201703L
+      constexpr bool
+      starts_with(basic_string_view __x) const noexcept
+      { return this->substr(0, __x.size()) == __x; }
+
+      constexpr bool
+      starts_with(_CharT __x) const noexcept
+      { return !this->empty() && traits_type::eq(this->front(), __x); }
+
+      constexpr bool
+      starts_with(const _CharT* __x) const noexcept
+      { return this->starts_with(basic_string_view(__x)); }
+
+      constexpr bool
+      ends_with(basic_string_view __x) const noexcept
+      {
+	return this->size() >= __x.size()
+	    && this->compare(this->size() - __x.size(), npos, __x) == 0;
+      }
+
+      constexpr bool
+      ends_with(_CharT __x) const noexcept
+      { return !this->empty() && traits_type::eq(this->back(), __x); }
+
+      constexpr bool
+      ends_with(const _CharT* __x) const noexcept
+      { return this->ends_with(basic_string_view(__x)); }
+#endif // C++20
+
+      // [string.view.find], searching
+
       constexpr size_type
       find(basic_string_view __str, size_type __pos = 0) const noexcept
       { return this->find(__str._M_str, __pos, __str._M_len); }
@@ -386,53 +440,6 @@
 				      traits_type::length(__str));
       }
 
-#if __cplusplus > 201703L
-      constexpr bool
-      starts_with(basic_string_view __x) const noexcept
-      { return this->substr(0, __x.size()) == __x; }
-
-      constexpr bool
-      starts_with(_CharT __x) const noexcept
-      { return !this->empty() && traits_type::eq(this->front(), __x); }
-
-      constexpr bool
-      starts_with(const _CharT* __x) const noexcept
-      { return this->starts_with(basic_string_view(__x)); }
-
-      constexpr bool
-      ends_with(basic_string_view __x) const noexcept
-      {
-	return this->size() >= __x.size()
-	    && this->compare(this->size() - __x.size(), npos, __x) == 0;
-      }
-
-      constexpr bool
-      ends_with(_CharT __x) const noexcept
-      { return !this->empty() && traits_type::eq(this->back(), __x); }
-
-      constexpr bool
-      ends_with(const _CharT* __x) const noexcept
-      { return this->ends_with(basic_string_view(__x)); }
-#endif // C++20
-
-      constexpr size_type
-      _M_check(size_type __pos, const char* __s) const noexcept(false)
-      {
-	if (__pos > this->size())
-	  __throw_out_of_range_fmt(__N("%s: __pos (which is %zu) > "
-				       "this->size() (which is %zu)"),
-				   __s, __pos, this->size());
-	return __pos;
-      }
-
-      // NB: _M_limit doesn't check for a bad __pos value.
-      constexpr size_type
-      _M_limit(size_type __pos, size_type __off) const noexcept
-      {
-	const bool __testoff =  __off < this->size() - __pos;
-	return __testoff ? __off : this->size() - __pos;
-      }
-      
     private:
 
       static constexpr int
@@ -610,7 +617,7 @@
 #ifdef _GLIBCXX_USE_WCHAR_T
   template<>
     struct hash<wstring_view>
-    : public __hash_base<size_t, wstring>
+    : public __hash_base<size_t, wstring_view>
     {
       size_t
       operator()(const wstring_view& __s) const noexcept
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/modifiers/remove_prefix/char/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/modifiers/remove_prefix/char/1.cc
index eedc6b9..9442606 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string_view/modifiers/remove_prefix/char/1.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/modifiers/remove_prefix/char/1.cc
@@ -26,7 +26,7 @@
   using std::string_view;
 
   string_view str0{"olympus mons"};
-  string_view::pointer p = str0.data();
+  string_view::const_pointer p = str0.data();
   str0.remove_prefix(4);
   VERIFY( str0.data() == p + 4);
   VERIFY( str0.length() == 8 );
@@ -39,7 +39,7 @@
   using std::string_view;
 
   string_view str0{"olympus mons"};
-  string_view::pointer p = str0.data();
+  string_view::const_pointer p = str0.data();
   str0.remove_prefix(4);
   if ( str0.data() != p + 4)
     return false;
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/modifiers/remove_prefix/wchar_t/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/modifiers/remove_prefix/wchar_t/1.cc
index e017751..c8ad552 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string_view/modifiers/remove_prefix/wchar_t/1.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/modifiers/remove_prefix/wchar_t/1.cc
@@ -26,7 +26,7 @@
   using std::wstring_view;
 
   wstring_view str0{L"olympus mons"};
-  wstring_view::pointer p = str0.data();
+  wstring_view::const_pointer p = str0.data();
   str0.remove_prefix(4);
   VERIFY( str0.data() == p + 4);
   VERIFY( str0.length() == 8 );
@@ -39,7 +39,7 @@
   using std::wstring_view;
 
   wstring_view str0{L"olympus mons"};
-  wstring_view::pointer p = str0.data();
+  wstring_view::const_pointer p = str0.data();
   str0.remove_prefix(4);
   if ( str0.data() != p + 4)
     return false;
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/modifiers/remove_suffix/char/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/modifiers/remove_suffix/char/1.cc
index 67a8a58..d4d5d7d 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string_view/modifiers/remove_suffix/char/1.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/modifiers/remove_suffix/char/1.cc
@@ -26,7 +26,7 @@
   using std::string_view;
 
   string_view str0{"olympus mons"};
-  string_view::pointer p = str0.data();
+  string_view::const_pointer p = str0.data();
   str0.remove_suffix(2);
   VERIFY( str0.data() == p);
   VERIFY( str0.length() == 10 );
@@ -39,7 +39,7 @@
   using std::string_view;
 
   string_view str0{"olympus mons"};
-  string_view::pointer p = str0.data();
+  string_view::const_pointer p = str0.data();
   str0.remove_suffix(2);
   if ( str0.data() != p)
     return false;
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/modifiers/remove_suffix/wchar_t/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/modifiers/remove_suffix/wchar_t/1.cc
index 81ccb91..deccc25 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string_view/modifiers/remove_suffix/wchar_t/1.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/modifiers/remove_suffix/wchar_t/1.cc
@@ -26,7 +26,7 @@
   using std::wstring_view;
 
   wstring_view str0{L"olympus mons"};
-  wstring_view::pointer p = str0.data();
+  wstring_view::const_pointer p = str0.data();
   str0.remove_suffix(2);
   VERIFY( str0.data() == p);
   VERIFY( str0.length() == 10 );
@@ -39,7 +39,7 @@
   using std::wstring_view;
 
   wstring_view str0{L"olympus mons"};
-  wstring_view::pointer p = str0.data();
+  wstring_view::const_pointer p = str0.data();
   str0.remove_suffix(2);
   if ( str0.data() != p)
     return false;
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/requirements/traits_neg.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/requirements/traits_neg.cc
new file mode 100644
index 0000000..93ea808
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/requirements/traits_neg.cc
@@ -0,0 +1,37 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++17 } }
+
+#include <string_view>
+
+// C++98 21.1 [lib.char.traits] p3
+// C++03 21.1 [lib.char.traits] p3
+// C++11 21.2 [char.traits] p3
+// C++14 21.2 [char.traits] p3
+// C++17 24.2 [char.traits] p3
+// "Traits::char_type shall be the same as CharT."
+// C++17 24.4.2 [string.view.template] p1
+// "the type traits::char_type shall name the same type as charT"
+// C++2a 21.2 [char.traits] p3 (post-P1148R0)
+// "If X::char_type is not the same type as C, the program is ill-formed."
+
+std::basic_string_view<char, std::char_traits<char16_t>> s1; // { dg-error "here" }
+std::basic_string_view<char32_t, std::char_traits<char>> s2; // { dg-error "here" }
+
+// { dg-prune-output "static assertion failed" }
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/requirements/typedefs.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/requirements/typedefs.cc
index 41b8f56..b11ef57 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string_view/requirements/typedefs.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/requirements/typedefs.cc
@@ -45,3 +45,12 @@
 __gnu_test::reversible_types<std::wstring_view> t2r;
 typedef typename std::wstring_view::traits_type traits_type2;
 #endif
+
+static_assert(std::is_same<std::string_view::pointer, char*>(),
+    "pointer should be value_type*");
+static_assert(std::is_same<std::string_view::const_pointer, const char*>(),
+    "const_pointer should be const value_type*");
+static_assert(std::is_same<std::string_view::reference, char&>(),
+    "reference should be value_type&");
+static_assert(std::is_same<std::string_view::const_reference, const char&>(),
+    "const_reference should be const value_type&");
diff --git a/libstdc++-v3/testsuite/experimental/string_view/modifiers/remove_prefix/char/1.cc b/libstdc++-v3/testsuite/experimental/string_view/modifiers/remove_prefix/char/1.cc
index 12a4078..8a7b6b8 100644
--- a/libstdc++-v3/testsuite/experimental/string_view/modifiers/remove_prefix/char/1.cc
+++ b/libstdc++-v3/testsuite/experimental/string_view/modifiers/remove_prefix/char/1.cc
@@ -26,7 +26,7 @@
   using namespace std::experimental;
 
   string_view str0{"olympus mons"};
-  string_view::pointer p = str0.data();
+  string_view::const_pointer p = str0.data();
   str0.remove_prefix(4);
   VERIFY( str0.data() == p + 4);
   VERIFY( str0.length() == 8 );
diff --git a/libstdc++-v3/testsuite/experimental/string_view/modifiers/remove_prefix/wchar_t/1.cc b/libstdc++-v3/testsuite/experimental/string_view/modifiers/remove_prefix/wchar_t/1.cc
index e92d6d9..153349f 100644
--- a/libstdc++-v3/testsuite/experimental/string_view/modifiers/remove_prefix/wchar_t/1.cc
+++ b/libstdc++-v3/testsuite/experimental/string_view/modifiers/remove_prefix/wchar_t/1.cc
@@ -26,7 +26,7 @@
   using namespace std::experimental;
 
   wstring_view str0{L"olympus mons"};
-  wstring_view::pointer p = str0.data();
+  wstring_view::const_pointer p = str0.data();
   str0.remove_prefix(4);
   VERIFY( str0.data() == p + 4);
   VERIFY( str0.length() == 8 );
diff --git a/libstdc++-v3/testsuite/experimental/string_view/modifiers/remove_suffix/char/1.cc b/libstdc++-v3/testsuite/experimental/string_view/modifiers/remove_suffix/char/1.cc
index ab990cb..612a62c 100644
--- a/libstdc++-v3/testsuite/experimental/string_view/modifiers/remove_suffix/char/1.cc
+++ b/libstdc++-v3/testsuite/experimental/string_view/modifiers/remove_suffix/char/1.cc
@@ -26,7 +26,7 @@
   using namespace std::experimental;
 
   string_view str0{"olympus mons"};
-  string_view::pointer p = str0.data();
+  string_view::const_pointer p = str0.data();
   str0.remove_suffix(2);
   VERIFY( str0.data() == p);
   VERIFY( str0.length() == 10 );
diff --git a/libstdc++-v3/testsuite/experimental/string_view/modifiers/remove_suffix/wchar_t/1.cc b/libstdc++-v3/testsuite/experimental/string_view/modifiers/remove_suffix/wchar_t/1.cc
index 7c7c63e..b1114d1 100644
--- a/libstdc++-v3/testsuite/experimental/string_view/modifiers/remove_suffix/wchar_t/1.cc
+++ b/libstdc++-v3/testsuite/experimental/string_view/modifiers/remove_suffix/wchar_t/1.cc
@@ -26,7 +26,7 @@
   using namespace std::experimental;
 
   wstring_view str0{L"olympus mons"};
-  wstring_view::pointer p = str0.data();
+  wstring_view::const_pointer p = str0.data();
   str0.remove_suffix(2);
   VERIFY( str0.data() == p);
   VERIFY( str0.length() == 10 );
diff --git a/libstdc++-v3/testsuite/experimental/string_view/requirements/typedefs.cc b/libstdc++-v3/testsuite/experimental/string_view/requirements/typedefs.cc
index 269633b..38e20e1 100644
--- a/libstdc++-v3/testsuite/experimental/string_view/requirements/typedefs.cc
+++ b/libstdc++-v3/testsuite/experimental/string_view/requirements/typedefs.cc
@@ -43,3 +43,16 @@
 __gnu_test::reversible_types<std::experimental::wstring_view> t2r;
 typedef typename std::experimental::wstring_view::traits_type traits_type2;
 #endif
+
+static_assert(
+    std::is_same<std::experimental::string_view::pointer, char*>(),
+    "pointer should be value_type*");
+static_assert(
+    std::is_same<std::experimental::string_view::const_pointer, const char*>(),
+    "const_pointer should be const value_type*");
+static_assert(
+    std::is_same<std::experimental::string_view::reference, char&>(),
+    "reference should be value_type&");
+static_assert(
+    std::is_same<std::experimental::string_view::const_reference, const char&>(),
+    "const_reference should be const value_type&");