[v2,3/5] Add gdb::string_view

Message ID 20180330214647.485-3-simon.marchi@polymtl.ca
State New, archived
Headers

Commit Message

Simon Marchi March 30, 2018, 9:46 p.m. UTC
  We had a few times the need for a data structure that does essentially
what C++17's std::string_view does, which is to give an std::string-like
interface (only the read-only operations) to an arbitrary character
buffer.

This patch adapts the files copied from libstdc++ by the previous patch
to integrate them with GDB.  Here's a summary of the changes:

  * Remove things related to wstring_view, u16string_view and
  u32string_view (I don't think we need them, but we can always add them
  later).

  * Remove usages of _GLIBCXX_BEGIN_NAMESPACE_VERSION and
  _GLIBCXX_END_NAMESPACE_VERSION.

  * Put the code in the gdb namespace.  I had to add a few "std::" in
  front of std type usages.

  * Add a constructor that builds a string_view from an std::string, so
  that we can pass strings to string_view parameters seamlessly.
  Normally, that's handled by "operator __sv_type" in the std::string
  declaration, but it only exists when building with c++17.

  * Change __throw_out_of_range_fmt() for error().

  * Make gdb::string_view and alias of std::string_view when building
  with >= c++17.

  * Remove a bunch of constexpr, because they are not valid in c++11
  (e.g. they are not a single return line).

  * Use std::common_type<_Tp>::type instead of std::common_type_t<_Tp>,
  because c++11 doesn't have the later.

  * Remove the #pragma GCC system_header, since that silences some
  warnings that we might want to have if we're doing something not
  correctly.

  * GCC complains about us defining the ""sv user-defined literal,
  because user code is supposed to use suffixes that begin with _.
  However, we only use that code with c++ < 17, where we know the sv
  literal is not defined.  Recent GCCs allow turning off the warning
  (-Wliteral-suffix), but gcc 4.8.4 (what the GCC compile farm ARM
  builders have) don't have a way to silence this warning.  The only way
  I found was to add back #pragma GCC system_header, but at least I
  could add it at the very end of the file.  The pragma only makes the
  rest of the file (what follows it) part of a system header, so the
  code above should not be considered a system header.

The string_view class in cli/cli-script.c is removed and its usage
replaced with the new gdb::string_view.

gdb/ChangeLog:

	* common/string_view.h: Remove libstdc++ implementation details,
	adjust to gdb reality.
	* common/string_view.tcc: Likewise.
	* cli/cli-script.c (struct string_view): Remove.
	(user_args) <m_args>: Change element type to gdb::string_view.
	(user_args::insert_args): Adjust.
---
 gdb/cli/cli-script.c       |  17 +---
 gdb/common/string_view.h   | 188 +++++++++++++++------------------------------
 gdb/common/string_view.tcc |  43 +++++------
 3 files changed, 82 insertions(+), 166 deletions(-)
  

Comments

Pedro Alves April 6, 2018, 6:08 p.m. UTC | #1
On 03/30/2018 10:46 PM, Simon Marchi wrote:
> We had a few times the need for a data structure that does essentially
> what C++17's std::string_view does, which is to give an std::string-like
> interface (only the read-only operations) to an arbitrary character
> buffer.
> 
> This patch adapts the files copied from libstdc++ by the previous patch
> to integrate them with GDB.  Here's a summary of the changes:
> 
>   * Remove things related to wstring_view, u16string_view and
>   u32string_view (I don't think we need them, but we can always add them
>   later).

Yeah, I don't think we'll ever need them.

> 
>   * Remove usages of _GLIBCXX_BEGIN_NAMESPACE_VERSION and
>   _GLIBCXX_END_NAMESPACE_VERSION.
> 
>   * Put the code in the gdb namespace.  I had to add a few "std::" in
>   front of std type usages.
> 
>   * Add a constructor that builds a string_view from an std::string, so
>   that we can pass strings to string_view parameters seamlessly.
>   Normally, that's handled by "operator __sv_type" in the std::string
>   declaration, but it only exists when building with c++17.

Yeah, that's how it was done when string_view was still part of 
the C++ Library Fundamentals TS:

  http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html#string.view.cons

I'd suggest taking a look at the diff between gcc/libstdc++'s:

 src/libstdc++-v3/include/experimental/string_view
 src/libstdc++-v3/include/std/string_view

> 
>   * Change __throw_out_of_range_fmt() for error().
> 
>   * Make gdb::string_view and alias of std::string_view when building
>   with >= c++17.

s/and/an

> 
>   * Remove a bunch of constexpr, because they are not valid in c++11
>   (e.g. they are not a single return line).

You could instead pick the versions of those functions from the experimental
string_view instead, which is written in C++11 constexpr form.  E.g.:

       constexpr basic_string_view
-      substr(size_type __pos, size_type __n=npos) const
+      substr(size_type __pos, size_type __n = npos) const noexcept(false)
       {
-       return __pos <= this->_M_len
-            ? basic_string_view{this->_M_str + __pos,
-                               std::min(__n, size_type{this->_M_len  - __pos})}
-            : (__throw_out_of_range_fmt(__N("basic_string_view::substr: __pos "
-                                            "(which is %zu) > this->size() "
-                                            "(which is %zu)"),
-                                    __pos, this->size()), basic_string_view{});
+       __pos = _M_check(__pos, "basic_string_view::substr");
+       const size_type __rlen = std::min(__n, _M_len - __pos);
+       return basic_string_view{_M_str + __pos, __rlen};
       }




>   * GCC complains about us defining the ""sv user-defined literal,
>   because user code is supposed to use suffixes that begin with _.
>   However, we only use that code with c++ < 17, where we know the sv
>   literal is not defined.  Recent GCCs allow turning off the warning
>   (-Wliteral-suffix), but gcc 4.8.4 (what the GCC compile farm ARM
>   builders have) don't have a way to silence this warning.  The only way
>   I found was to add back #pragma GCC system_header, but at least I
>   could add it at the very end of the file.  The pragma only makes the
>   rest of the file (what follows it) part of a system header, so the
>   code above should not be considered a system header.
> 
> The string_view class in cli/cli-script.c is removed and its usage
> replaced with the new gdb::string_view.

Eheh, I knew that day would come when I added that little class.  :-)

>      private:
>  
> -      static constexpr int
> +      static int
>        _S_compare(size_type __n1, size_type __n2) noexcept
>        {
>  	const difference_type __diff = __n1 - __n2;
> @@ -428,11 +434,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      // argument participates in template argument deduction and the other
>      // argument gets implicitly converted to the deduced type. See n3766.html.
>      template<typename _Tp>
> -      using __idt = common_type_t<_Tp>;
> +      using __idt = typename std::common_type<_Tp>::type;
>    }
>  
>    template<typename _CharT, typename _Traits>
> -    constexpr bool
> +    bool
>      operator==(basic_string_view<_CharT, _Traits> __x,
>                 basic_string_view<_CharT, _Traits> __y) noexcept
>      { return __x.size() == __y.size() && __x.compare(__y) == 0; }
> @@ -541,8 +547,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  
>    // [string.view.io], Inserters and extractors
>    template<typename _CharT, typename _Traits>
> -    inline basic_ostream<_CharT, _Traits>&
> -    operator<<(basic_ostream<_CharT, _Traits>& __os,
> +    inline std::basic_ostream<_CharT, _Traits>&
> +    operator<<(std::basic_ostream<_CharT, _Traits>& __os,
>  	       basic_string_view<_CharT,_Traits> __str)
>      { return __ostream_insert(__os, __str.data(), __str.size()); }
>  
> @@ -550,13 +556,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>    // basic_string_view typedef names
>  
>    using string_view = basic_string_view<char>;
> -#ifdef _GLIBCXX_USE_WCHAR_T
> -  using wstring_view = basic_string_view<wchar_t>;
> -#endif
> -#ifdef _GLIBCXX_USE_C99_STDINT_TR1
> -  using u16string_view = basic_string_view<char16_t>;
> -  using u32string_view = basic_string_view<char32_t>;
> -#endif
>  
>    // [string.view.hash], hash support:
>  
> @@ -565,97 +564,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  
>    template<>
>      struct hash<string_view>
> -    : public __hash_base<size_t, string_view>
> +    : public std::__hash_base<size_t, string_view>

This looks suspiciously like using an internal implementation
detail of libstdc++.  Where is std::__hash_base defined?
Does this compile with clang + libc++ ?

Thanks,
Pedro Alves
  
Simon Marchi April 6, 2018, 8:37 p.m. UTC | #2
Thanks for the comments.

On 2018-04-06 14:08, Pedro Alves wrote:
> On 03/30/2018 10:46 PM, Simon Marchi wrote:
>> We had a few times the need for a data structure that does essentially
>> what C++17's std::string_view does, which is to give an 
>> std::string-like
>> interface (only the read-only operations) to an arbitrary character
>> buffer.
>> 
>> This patch adapts the files copied from libstdc++ by the previous 
>> patch
>> to integrate them with GDB.  Here's a summary of the changes:
>> 
>>   * Remove things related to wstring_view, u16string_view and
>>   u32string_view (I don't think we need them, but we can always add 
>> them
>>   later).
> 
> Yeah, I don't think we'll ever need them.
> 
>> 
>>   * Remove usages of _GLIBCXX_BEGIN_NAMESPACE_VERSION and
>>   _GLIBCXX_END_NAMESPACE_VERSION.
>> 
>>   * Put the code in the gdb namespace.  I had to add a few "std::" in
>>   front of std type usages.
>> 
>>   * Add a constructor that builds a string_view from an std::string, 
>> so
>>   that we can pass strings to string_view parameters seamlessly.
>>   Normally, that's handled by "operator __sv_type" in the std::string
>>   declaration, but it only exists when building with c++17.
> 
> Yeah, that's how it was done when string_view was still part of
> the C++ Library Fundamentals TS:
> 
> 
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html#string.view.cons
> 
> I'd suggest taking a look at the diff between gcc/libstdc++'s:
> 
>  src/libstdc++-v3/include/experimental/string_view
>  src/libstdc++-v3/include/std/string_view
> 
>> 
>>   * Change __throw_out_of_range_fmt() for error().
>> 
>>   * Make gdb::string_view and alias of std::string_view when building
>>   with >= c++17.
> 
> s/and/an
> 
>> 
>>   * Remove a bunch of constexpr, because they are not valid in c++11
>>   (e.g. they are not a single return line).
> 
> You could instead pick the versions of those functions from the 
> experimental
> string_view instead, which is written in C++11 constexpr form.  E.g.:
> 
>        constexpr basic_string_view
> -      substr(size_type __pos, size_type __n=npos) const
> +      substr(size_type __pos, size_type __n = npos) const 
> noexcept(false)
>        {
> -       return __pos <= this->_M_len
> -            ? basic_string_view{this->_M_str + __pos,
> -                               std::min(__n, size_type{this->_M_len  - 
> __pos})}
> -            : 
> (__throw_out_of_range_fmt(__N("basic_string_view::substr: __pos "
> -                                            "(which is %zu) > 
> this->size() "
> -                                            "(which is %zu)"),
> -                                    __pos, this->size()), 
> basic_string_view{});
> +       __pos = _M_check(__pos, "basic_string_view::substr");
> +       const size_type __rlen = std::min(__n, _M_len - __pos);
> +       return basic_string_view{_M_str + __pos, __rlen};
>        }


Ah, from the name I thought that experimental version contained the code 
implementing future standards, before they were official... so I'll 
start from scratch using the version from experimental, does that sounds 
good?

>>      private:
>> 
>> -      static constexpr int
>> +      static int
>>        _S_compare(size_type __n1, size_type __n2) noexcept
>>        {
>>  	const difference_type __diff = __n1 - __n2;
>> @@ -428,11 +434,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>>      // argument participates in template argument deduction and the 
>> other
>>      // argument gets implicitly converted to the deduced type. See 
>> n3766.html.
>>      template<typename _Tp>
>> -      using __idt = common_type_t<_Tp>;
>> +      using __idt = typename std::common_type<_Tp>::type;
>>    }
>> 
>>    template<typename _CharT, typename _Traits>
>> -    constexpr bool
>> +    bool
>>      operator==(basic_string_view<_CharT, _Traits> __x,
>>                 basic_string_view<_CharT, _Traits> __y) noexcept
>>      { return __x.size() == __y.size() && __x.compare(__y) == 0; }
>> @@ -541,8 +547,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>> 
>>    // [string.view.io], Inserters and extractors
>>    template<typename _CharT, typename _Traits>
>> -    inline basic_ostream<_CharT, _Traits>&
>> -    operator<<(basic_ostream<_CharT, _Traits>& __os,
>> +    inline std::basic_ostream<_CharT, _Traits>&
>> +    operator<<(std::basic_ostream<_CharT, _Traits>& __os,
>>  	       basic_string_view<_CharT,_Traits> __str)
>>      { return __ostream_insert(__os, __str.data(), __str.size()); }
>> 
>> @@ -550,13 +556,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>>    // basic_string_view typedef names
>> 
>>    using string_view = basic_string_view<char>;
>> -#ifdef _GLIBCXX_USE_WCHAR_T
>> -  using wstring_view = basic_string_view<wchar_t>;
>> -#endif
>> -#ifdef _GLIBCXX_USE_C99_STDINT_TR1
>> -  using u16string_view = basic_string_view<char16_t>;
>> -  using u32string_view = basic_string_view<char32_t>;
>> -#endif
>> 
>>    // [string.view.hash], hash support:
>> 
>> @@ -565,97 +564,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>> 
>>    template<>
>>      struct hash<string_view>
>> -    : public __hash_base<size_t, string_view>
>> +    : public std::__hash_base<size_t, string_view>
> 
> This looks suspiciously like using an internal implementation
> detail of libstdc++.  Where is std::__hash_base defined?
> Does this compile with clang + libc++ ?

Hmm indeed.  Well, it looks like building with clang + libstdcxx fails.  
I'll make sure to test both of these combinations in the next iteration.

Simon
  
Pedro Alves April 6, 2018, 10:01 p.m. UTC | #3
On 04/06/2018 09:37 PM, Simon Marchi wrote:

> Ah, from the name I thought that experimental version contained the code implementing future standards, before they were official... so I'll start from scratch using the version from experimental, does that sounds good?

It does.  However, there may have been other enhancements, small API changes, and
bugfixes to string_view when it was merged to the standard proper (and subsequent
DRs), so I'd still recommend perusing the diff a bit.  Though if the tests still
pass, it'll likely the differences won't matter much.

>>>    template<>
>>>      struct hash<string_view>
>>> -    : public __hash_base<size_t, string_view>
>>> +    : public std::__hash_base<size_t, string_view>
>>
>> This looks suspiciously like using an internal implementation
>> detail of libstdc++.  Where is std::__hash_base defined?
>> Does this compile with clang + libc++ ?
> 
> Hmm indeed.  Well, it looks like building with clang + libstdcxx fails.  I'll make sure to test both of these combinations in the next iteration.

Thanks.

Pedro Alves
  

Patch

diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c
index 366c42227c62..e705b7a8da70 100644
--- a/gdb/cli/cli-script.c
+++ b/gdb/cli/cli-script.c
@@ -32,6 +32,7 @@ 
 #include "extension.h"
 #include "interps.h"
 #include "compile/compile.h"
+#include "common/string_view.h"
 
 #include <vector>
 
@@ -54,18 +55,6 @@  static int command_nest_depth = 1;
 /* This is to prevent certain commands being printed twice.  */
 static int suppress_next_print_command_trace = 0;
 
-/* A non-owning slice of a string.  */
-
-struct string_view
-{
-  string_view (const char *str_, size_t len_)
-    : str (str_), len (len_)
-  {}
-
-  const char *str;
-  size_t len;
-};
-
 /* Structure for arguments to user defined functions.  */
 
 class user_args
@@ -91,7 +80,7 @@  private:
   std::string m_command_line;
 
   /* The arguments.  Each element points inside M_COMMAND_LINE.  */
-  std::vector<string_view> m_args;
+  std::vector<gdb::string_view> m_args;
 };
 
 /* The stack of arguments passed to user defined functions.  We need a
@@ -827,7 +816,7 @@  user_args::insert_args (const char *line) const
 	    error (_("Missing argument %ld in user function."), i);
 	  else
 	    {
-	      new_line.append (m_args[i].str, m_args[i].len);
+	      new_line.append (m_args[i].data (), m_args[i].length ());
 	      line = tmp;
 	    }
 	}
diff --git a/gdb/common/string_view.h b/gdb/common/string_view.h
index 9f39df853e8d..06bf1ca293df 100644
--- a/gdb/common/string_view.h
+++ b/gdb/common/string_view.h
@@ -1,5 +1,8 @@ 
 // Components for manipulating non-owning sequences of characters -*- C++ -*-
 
+// Note: This file has been stolen from the gcc repo
+// (libstdc++-v3/include/std/string_view) and has local modifications.
+
 // Copyright (C) 2013-2018 Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
@@ -22,33 +25,31 @@ 
 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 // <http://www.gnu.org/licenses/>.
 
-/** @file string_view
- *  This is a Standard C++ Library header.
- */
 
 //
 // N3762 basic_string_view library
 //
 
-#ifndef _GLIBCXX_STRING_VIEW
-#define _GLIBCXX_STRING_VIEW 1
-
-#pragma GCC system_header
+#ifndef STRING_VIEW_H
+#define STRING_VIEW_H 1
 
 #if __cplusplus >= 201703L
 
+#include <string_view>
+
+namespace gdb {
+  using string_view = std::string_view;
+} /* namespace gdb */
+
+#else /* __cplusplus < 201703L */
+
 #include <limits>
 #include <iosfwd>
 #include <bits/char_traits.h>
 #include <bits/functional_hash.h>
 #include <bits/range_access.h>
 
-namespace std _GLIBCXX_VISIBILITY(default)
-{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
-#define __cpp_lib_string_view 201603
-
+namespace gdb {
   /**
    *  @class basic_string_view <string_view>
    *  @brief  A non-owning reference to a string.
@@ -96,7 +97,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       constexpr basic_string_view(const basic_string_view&) noexcept = default;
 
-      constexpr basic_string_view(const _CharT* __str) noexcept
+      basic_string_view(const _CharT* __str) noexcept
       : _M_len{__str == nullptr ? 0 : traits_type::length(__str)},
 	_M_str{__str}
       { }
@@ -106,7 +107,12 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       : _M_len{__len}, _M_str{__str}
       { }
 
-      constexpr basic_string_view&
+      constexpr
+      basic_string_view(const std::string &__str) noexcept
+      : _M_len{__str.length()}, _M_str{__str.c_str()}
+      { }
+
+      basic_string_view&
       operator=(const basic_string_view&) noexcept = default;
 
       // [string.view.iterators], iterators
@@ -160,7 +166,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		/ sizeof(value_type) / 4;
       }
 
-      [[nodiscard]] constexpr bool
+      constexpr bool
       empty() const noexcept
       { return this->_M_len == 0; }
 
@@ -174,13 +180,13 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	return *(this->_M_str + __pos);
       }
 
-      constexpr const _CharT&
+      const _CharT&
       at(size_type __pos) const
       {
 	if (__pos >= _M_len)
-	  __throw_out_of_range_fmt(__N("basic_string_view::at: __pos "
-				       "(which is %zu) >= this->size() "
-				       "(which is %zu)"), __pos, this->size());
+	  error (_("basic_string_view::at: __pos "
+		   "(which is %zu) >= this->size() "
+		   "(which is %zu)"), __pos, this->size());
 	return *(this->_M_str + __pos);
       }
 
@@ -206,7 +212,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       // [string.view.modifiers], modifiers:
 
-      constexpr void
+      void
       remove_prefix(size_type __n) noexcept
       {
 	__glibcxx_assert(this->_M_len >= __n);
@@ -214,11 +220,11 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	this->_M_len -= __n;
       }
 
-      constexpr void
+      void
       remove_suffix(size_type __n) noexcept
       { this->_M_len -= __n; }
 
-      constexpr void
+      void
       swap(basic_string_view& __sv) noexcept
       {
 	auto __tmp = *this;
@@ -241,7 +247,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	return __rlen;
       }
 
-      constexpr basic_string_view
+      basic_string_view
       substr(size_type __pos, size_type __n = npos) const noexcept(false)
       {
 	__pos = _M_check(__pos, "basic_string_view::substr");
@@ -249,7 +255,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	return basic_string_view{_M_str + __pos, __rlen};
       }
 
-      constexpr int
+      int
       compare(basic_string_view __str) const noexcept
       {
 	const size_type __rlen = std::min(this->_M_len, __str._M_len);
@@ -263,14 +269,14 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       compare(size_type __pos1, size_type __n1, basic_string_view __str) const
       { return this->substr(__pos1, __n1).compare(__str); }
 
-      constexpr int
+      int
       compare(size_type __pos1, size_type __n1,
 	      basic_string_view __str, size_type __pos2, size_type __n2) const
       {
 	return this->substr(__pos1, __n1).compare(__str.substr(__pos2, __n2));
       }
 
-      constexpr int
+      int
       compare(const _CharT* __str) const noexcept
       { return this->compare(basic_string_view{__str}); }
 
@@ -278,7 +284,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       compare(size_type __pos1, size_type __n1, const _CharT* __str) const
       { return this->substr(__pos1, __n1).compare(basic_string_view{__str}); }
 
-      constexpr int
+      int
       compare(size_type __pos1, size_type __n1,
 	      const _CharT* __str, size_type __n2) const noexcept(false)
       {
@@ -290,10 +296,10 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       find(basic_string_view __str, size_type __pos = 0) const noexcept
       { return this->find(__str._M_str, __pos, __str._M_len); }
 
-      constexpr size_type
+      size_type
       find(_CharT __c, size_type __pos = 0) const noexcept;
 
-      constexpr size_type
+      size_type
       find(const _CharT* __str, size_type __pos, size_type __n) const noexcept;
 
       constexpr size_type
@@ -304,10 +310,10 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       rfind(basic_string_view __str, size_type __pos = npos) const noexcept
       { return this->rfind(__str._M_str, __pos, __str._M_len); }
 
-      constexpr size_type
+      size_type
       rfind(_CharT __c, size_type __pos = npos) const noexcept;
 
-      constexpr size_type
+      size_type
       rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept;
 
       constexpr size_type
@@ -322,7 +328,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       find_first_of(_CharT __c, size_type __pos = 0) const noexcept
       { return this->find(__c, __pos); }
 
-      constexpr size_type
+      size_type
       find_first_of(const _CharT* __str, size_type __pos, size_type __n) const noexcept;
 
       constexpr size_type
@@ -338,7 +344,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       find_last_of(_CharT __c, size_type __pos=npos) const noexcept
       { return this->rfind(__c, __pos); }
 
-      constexpr size_type
+      size_type
       find_last_of(const _CharT* __str, size_type __pos,
 		   size_type __n) const noexcept;
 
@@ -351,10 +357,10 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 			size_type __pos = 0) const noexcept
       { return this->find_first_not_of(__str._M_str, __pos, __str._M_len); }
 
-      constexpr size_type
+      size_type
       find_first_not_of(_CharT __c, size_type __pos = 0) const noexcept;
 
-      constexpr size_type
+      size_type
       find_first_not_of(const _CharT* __str,
 			size_type __pos, size_type __n) const noexcept;
 
@@ -370,10 +376,10 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		       size_type __pos = npos) const noexcept
       { return this->find_last_not_of(__str._M_str, __pos, __str._M_len); }
 
-      constexpr size_type
+      size_type
       find_last_not_of(_CharT __c, size_type __pos = npos) const noexcept;
 
-      constexpr size_type
+      size_type
       find_last_not_of(const _CharT* __str,
 		       size_type __pos, size_type __n) const noexcept;
 
@@ -385,13 +391,13 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 				      traits_type::length(__str));
       }
 
-      constexpr size_type
+      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());
+	  error (_("%s: __pos (which is %zu) > "
+		   "this->size() (which is %zu)"),
+		   __s, __pos, this->size());
 	return __pos;
       }
 
@@ -405,7 +411,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       
     private:
 
-      static constexpr int
+      static int
       _S_compare(size_type __n1, size_type __n2) noexcept
       {
 	const difference_type __diff = __n1 - __n2;
@@ -428,11 +434,11 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     // argument participates in template argument deduction and the other
     // argument gets implicitly converted to the deduced type. See n3766.html.
     template<typename _Tp>
-      using __idt = common_type_t<_Tp>;
+      using __idt = typename std::common_type<_Tp>::type;
   }
 
   template<typename _CharT, typename _Traits>
-    constexpr bool
+    bool
     operator==(basic_string_view<_CharT, _Traits> __x,
                basic_string_view<_CharT, _Traits> __y) noexcept
     { return __x.size() == __y.size() && __x.compare(__y) == 0; }
@@ -541,8 +547,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   // [string.view.io], Inserters and extractors
   template<typename _CharT, typename _Traits>
-    inline basic_ostream<_CharT, _Traits>&
-    operator<<(basic_ostream<_CharT, _Traits>& __os,
+    inline std::basic_ostream<_CharT, _Traits>&
+    operator<<(std::basic_ostream<_CharT, _Traits>& __os,
 	       basic_string_view<_CharT,_Traits> __str)
     { return __ostream_insert(__os, __str.data(), __str.size()); }
 
@@ -550,13 +556,6 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // basic_string_view typedef names
 
   using string_view = basic_string_view<char>;
-#ifdef _GLIBCXX_USE_WCHAR_T
-  using wstring_view = basic_string_view<wchar_t>;
-#endif
-#ifdef _GLIBCXX_USE_C99_STDINT_TR1
-  using u16string_view = basic_string_view<char16_t>;
-  using u32string_view = basic_string_view<char32_t>;
-#endif
 
   // [string.view.hash], hash support:
 
@@ -565,97 +564,32 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template<>
     struct hash<string_view>
-    : public __hash_base<size_t, string_view>
+    : public std::__hash_base<size_t, string_view>
     {
       size_t
       operator()(const string_view& __str) const noexcept
       { return std::_Hash_impl::hash(__str.data(), __str.length()); }
     };
+} /* namespace gdb */
 
-  template<>
-    struct __is_fast_hash<hash<string_view>> : std::false_type
-    { };
-
-#ifdef _GLIBCXX_USE_WCHAR_T
-  template<>
-    struct hash<wstring_view>
-    : public __hash_base<size_t, wstring>
-    {
-      size_t
-      operator()(const wstring_view& __s) const noexcept
-      { return std::_Hash_impl::hash(__s.data(),
-                                     __s.length() * sizeof(wchar_t)); }
-    };
-
-  template<>
-    struct __is_fast_hash<hash<wstring_view>> : std::false_type
-    { };
-#endif
-
-#ifdef _GLIBCXX_USE_C99_STDINT_TR1
-  template<>
-    struct hash<u16string_view>
-    : public __hash_base<size_t, u16string_view>
-    {
-      size_t
-      operator()(const u16string_view& __s) const noexcept
-      { return std::_Hash_impl::hash(__s.data(),
-                                     __s.length() * sizeof(char16_t)); }
-    };
-
-  template<>
-    struct __is_fast_hash<hash<u16string_view>> : std::false_type
-    { };
-
-  template<>
-    struct hash<u32string_view>
-    : public __hash_base<size_t, u32string_view>
-    {
-      size_t
-      operator()(const u32string_view& __s) const noexcept
-      { return std::_Hash_impl::hash(__s.data(),
-                                     __s.length() * sizeof(char32_t)); }
-    };
-
-  template<>
-    struct __is_fast_hash<hash<u32string_view>> : std::false_type
-    { };
-#endif
+#include "string_view.tcc"
 
+namespace gdb {
   inline namespace literals
   {
   inline namespace string_view_literals
   {
+#pragma GCC system_header
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wliteral-suffix"
     inline constexpr basic_string_view<char>
-    operator""sv(const char* __str, size_t __len) noexcept
+    operator"" sv(const char* __str, size_t __len) noexcept
     { return basic_string_view<char>{__str, __len}; }
-
-#ifdef _GLIBCXX_USE_WCHAR_T
-    inline constexpr basic_string_view<wchar_t>
-    operator""sv(const wchar_t* __str, size_t __len) noexcept
-    { return basic_string_view<wchar_t>{__str, __len}; }
-#endif
-
-#ifdef _GLIBCXX_USE_C99_STDINT_TR1
-    inline constexpr basic_string_view<char16_t>
-    operator""sv(const char16_t* __str, size_t __len) noexcept
-    { return basic_string_view<char16_t>{__str, __len}; }
-
-    inline constexpr basic_string_view<char32_t>
-    operator""sv(const char32_t* __str, size_t __len) noexcept
-    { return basic_string_view<char32_t>{__str, __len}; }
-#endif
 #pragma GCC diagnostic pop
   } // namespace string_literals
   } // namespace literals
-
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace std
-
-#include <bits/string_view.tcc>
+} // namespace gdb
 
 #endif // __cplusplus <= 201402L
 
-#endif // _GLIBCXX_EXPERIMENTAL_STRING_VIEW
+#endif /* STRING_VIEW_H */
diff --git a/gdb/common/string_view.tcc b/gdb/common/string_view.tcc
index 07ccc849dd70..c47806ba8e6e 100644
--- a/gdb/common/string_view.tcc
+++ b/gdb/common/string_view.tcc
@@ -1,5 +1,8 @@ 
 // Components for manipulating non-owning sequences of characters -*- C++ -*-
 
+// Note: This file has been stolen from the gcc repo
+// (libstdc++-v3/include/bits/string_view.tcc) and has local modifications.
+
 // Copyright (C) 2013-2018 Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
@@ -31,19 +34,13 @@ 
 // N3762 basic_string_view library
 //
 
-#ifndef _GLIBCXX_STRING_VIEW_TCC
-#define _GLIBCXX_STRING_VIEW_TCC 1
-
-#pragma GCC system_header
-
-#if __cplusplus >= 201703L
+#ifndef STRING_VIEW_TCC
+#define STRING_VIEW_TCC 1
 
-namespace std _GLIBCXX_VISIBILITY(default)
+namespace gdb
 {
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
   template<typename _CharT, typename _Traits>
-    constexpr typename basic_string_view<_CharT, _Traits>::size_type
+    typename basic_string_view<_CharT, _Traits>::size_type
     basic_string_view<_CharT, _Traits>::
     find(const _CharT* __str, size_type __pos, size_type __n) const noexcept
     {
@@ -64,7 +61,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
   template<typename _CharT, typename _Traits>
-    constexpr typename basic_string_view<_CharT, _Traits>::size_type
+    typename basic_string_view<_CharT, _Traits>::size_type
     basic_string_view<_CharT, _Traits>::
     find(_CharT __c, size_type __pos) const noexcept
     {
@@ -80,7 +77,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
   template<typename _CharT, typename _Traits>
-    constexpr typename basic_string_view<_CharT, _Traits>::size_type
+    typename basic_string_view<_CharT, _Traits>::size_type
     basic_string_view<_CharT, _Traits>::
     rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept
     {
@@ -100,7 +97,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
   template<typename _CharT, typename _Traits>
-    constexpr typename basic_string_view<_CharT, _Traits>::size_type
+    typename basic_string_view<_CharT, _Traits>::size_type
     basic_string_view<_CharT, _Traits>::
     rfind(_CharT __c, size_type __pos) const noexcept
     {
@@ -117,7 +114,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
   template<typename _CharT, typename _Traits>
-    constexpr typename basic_string_view<_CharT, _Traits>::size_type
+    typename basic_string_view<_CharT, _Traits>::size_type
     basic_string_view<_CharT, _Traits>::
     find_first_of(const _CharT* __str, size_type __pos,
 		  size_type __n) const noexcept
@@ -134,7 +131,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
   template<typename _CharT, typename _Traits>
-    constexpr typename basic_string_view<_CharT, _Traits>::size_type
+    typename basic_string_view<_CharT, _Traits>::size_type
     basic_string_view<_CharT, _Traits>::
     find_last_of(const _CharT* __str, size_type __pos,
 		 size_type __n) const noexcept
@@ -156,7 +153,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
   template<typename _CharT, typename _Traits>
-    constexpr typename basic_string_view<_CharT, _Traits>::size_type
+    typename basic_string_view<_CharT, _Traits>::size_type
     basic_string_view<_CharT, _Traits>::
     find_first_not_of(const _CharT* __str, size_type __pos,
 		      size_type __n) const noexcept
@@ -169,7 +166,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
   template<typename _CharT, typename _Traits>
-    constexpr typename basic_string_view<_CharT, _Traits>::size_type
+    typename basic_string_view<_CharT, _Traits>::size_type
     basic_string_view<_CharT, _Traits>::
     find_first_not_of(_CharT __c, size_type __pos) const noexcept
     {
@@ -180,7 +177,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
   template<typename _CharT, typename _Traits>
-    constexpr typename basic_string_view<_CharT, _Traits>::size_type
+    typename basic_string_view<_CharT, _Traits>::size_type
     basic_string_view<_CharT, _Traits>::
     find_last_not_of(const _CharT* __str, size_type __pos,
 		     size_type __n) const noexcept
@@ -202,7 +199,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
   template<typename _CharT, typename _Traits>
-    constexpr typename basic_string_view<_CharT, _Traits>::size_type
+    typename basic_string_view<_CharT, _Traits>::size_type
     basic_string_view<_CharT, _Traits>::
     find_last_not_of(_CharT __c, size_type __pos) const noexcept
     {
@@ -220,10 +217,6 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	}
       return npos;
     }
+} // namespace gdb
 
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace std
-
-#endif // __cplusplus <= 201402L
-
-#endif // _GLIBCXX_STRING_VIEW_TCC
+#endif // STRING_VIEW_TCC