Following:
https://gcc.gnu.org/pipermail/libstdc++/2021-March/052158.html
Here is the patch to complete __gnu_debug::basic_string support.
Contrarily to what I thought code in std::basic_string to generate a
basic_string_view works just fine for __gnu_debug::basic_string.
libstdc++: [_GLIBCXX_DEBUG] Add __gnu_debug
u8string/u16string/u32string
Complete __gnu_debug::basic_string support so that it can be used as a
transparent replacement of std::basic_string.
libstdc++-v3/ChangeLog:
* include/debug/string
(basic_string(const _CharT*, const _Allocator&)): Remove
assign call.
(basic_string<>::insert(const_iterator, _InputIte,
_InputIte)): Try to
remove iterator debug layer even if !_GLIBCXX_USE_CXX11_ABI.
[_GLIBCXX_USE_CHAR8_T] (__gnu_debug::u8string): New.
(__gnu_debug::u16string, __gnu_debug::u32string): New.
[!_GLIBCXX_COMPATIBILITY_CXX0X](std::hash<__gnu_debug::string>): New.
[!_GLIBCXX_COMPATIBILITY_CXX0X][_GLIBCXX_USE_WCHAR_T](std::hash<__gnu_debug::wstring>):
New.
[_GLIBCXX_USE_CHAR8_T](std::hash<__gnu_debug::u8string>): New.
(std::hash<__gnu_debug::u16string>): New.
(std::hash<__gnu_debug::u32string>): New.
* testsuite/21_strings/basic_string/hash/hash_char8_t.cc:
Adapt for
__gnu_debug basic_string.
Tested under Linux x86_64.
Ok to commit ?
François
diff --git a/libstdc++-v3/include/debug/string b/libstdc++-v3/include/debug/string
index d6eb5280ade..dec23f6277b 100644
--- a/libstdc++-v3/include/debug/string
+++ b/libstdc++-v3/include/debug/string
@@ -41,6 +41,14 @@
__gnu_debug::_Error_formatter::_S_at(_File, _Line, _Func) \
._M_message(#_Cond)._M_error()
+#if _GLIBCXX_USE_CXX11_ABI && __cplusplus >= 201103
+# define _GLIBCXX_CPP11_AND_CXX11_ABI 1
+# define _GLIBCXX_CPP11_AND_CXX11_ABI_ONLY(Statement) Statement
+#else
+# define _GLIBCXX_CPP11_AND_CXX11_ABI 0
+# define _GLIBCXX_CPP11_AND_CXX11_ABI_ONLY(Statement)
+#endif
+
namespace __gnu_debug
{
/** Checks that __s is non-NULL or __n == 0, and then returns __s. */
@@ -180,7 +188,7 @@ namespace __gnu_debug
basic_string(const _CharT* __s, const _Allocator& __a = _Allocator())
: _Base(__glibcxx_check_string_constructor(__s), __a)
- { this->assign(__s); }
+ { }
basic_string(size_type __n, _CharT __c,
const _Allocator& __a = _Allocator())
@@ -637,15 +645,22 @@ namespace __gnu_debug
__glibcxx_check_insert_range(__p, __first, __last, __dist);
typename _Base::iterator __res;
-#if _GLIBCXX_USE_CXX11_ABI && __cplusplus >= 201103
+#if ! _GLIBCXX_CPP11_AND_CXX11_ABI
+ const size_type __offset = __p.base() - _Base::begin();
+#endif
if (__dist.second >= __dp_sign)
- __res = _Base::insert(__p.base(), __gnu_debug::__unsafe(__first),
- __gnu_debug::__unsafe(__last));
+ {
+ _GLIBCXX_CPP11_AND_CXX11_ABI_ONLY(__res =)
+ _Base::insert(__p.base(), __gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ }
else
- __res = _Base::insert(__p.base(), __first, __last);
-#else
- const size_type __offset = __p.base() - _Base::begin();
- _Base::insert(__p.base(), __first, __last);
+ {
+ _GLIBCXX_CPP11_AND_CXX11_ABI_ONLY(__res =)
+ _Base::insert(__p.base(), __first, __last);
+ }
+
+#if ! _GLIBCXX_CPP11_AND_CXX11_ABI
__res = _Base::begin() + __offset;
#endif
this->_M_invalidate_all();
@@ -1287,6 +1302,19 @@ namespace __gnu_debug
typedef basic_string<wchar_t> wstring;
#endif
+#ifdef _GLIBCXX_USE_CHAR8_T
+ /// A string of @c char8_t
+ typedef basic_string<char8_t> u8string;
+#endif
+
+#if __cplusplus >= 201103L
+ /// A string of @c char16_t
+ typedef basic_string<char16_t> u16string;
+
+ /// A string of @c char32_t
+ typedef basic_string<char32_t> u32string;
+#endif
+
template<typename _CharT, typename _Traits, typename _Allocator>
struct _Insert_range_from_self_is_safe<
__gnu_debug::basic_string<_CharT, _Traits, _Allocator> >
@@ -1294,4 +1322,96 @@ namespace __gnu_debug
} // namespace __gnu_debug
+#if __cplusplus >= 201103L
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ // DR 1182.
+
+#ifndef _GLIBCXX_COMPATIBILITY_CXX0X
+ /// std::hash specialization for string.
+ template<>
+ struct hash<__gnu_debug::string>
+ : public __hash_base<size_t, __gnu_debug::string>
+ {
+ size_t
+ operator()(const __gnu_debug::string& __s) const noexcept
+ { return std::hash<std::string>()(__s); }
+ };
+
+ template<>
+ struct __is_fast_hash<hash<__gnu_debug::string>> : std::false_type
+ { };
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+ /// std::hash specialization for wstring.
+ template<>
+ struct hash<__gnu_debug::wstring>
+ : public __hash_base<size_t, __gnu_debug::wstring>
+ {
+ size_t
+ operator()(const __gnu_debug::wstring& __s) const noexcept
+ { return std::hash<__gnu_debug::wstring>()(__s); }
+ };
+
+ template<>
+ struct __is_fast_hash<hash<__gnu_debug::wstring>> : std::false_type
+ { };
+#endif
+#endif /* _GLIBCXX_COMPATIBILITY_CXX0X */
+
+#ifdef _GLIBCXX_USE_CHAR8_T
+ /// std::hash specialization for u8string.
+ template<>
+ struct hash<__gnu_debug::u8string>
+ : public __hash_base<size_t, __gnu_debug::u8string>
+ {
+ size_t
+ operator()(const __gnu_debug::u8string& __s) const noexcept
+ { return std::hash<std::u8string>()(__s); }
+ };
+
+ template<>
+ struct __is_fast_hash<hash<__gnu_debug::u8string>> : std::false_type
+ { };
+#endif
+
+ /// std::hash specialization for u16string.
+ template<>
+ struct hash<__gnu_debug::u16string>
+ : public __hash_base<size_t, __gnu_debug::u16string>
+ {
+ size_t
+ operator()(const __gnu_debug::u16string& __s) const noexcept
+ { return std::hash<std::u16string>()(__s); }
+ };
+
+ template<>
+ struct __is_fast_hash<hash<__gnu_debug::u16string>> : std::false_type
+ { };
+
+ /// std::hash specialization for u32string.
+ template<>
+ struct hash<__gnu_debug::u32string>
+ : public __hash_base<size_t, __gnu_debug::u32string>
+ {
+ size_t
+ operator()(const __gnu_debug::u32string& __s) const noexcept
+ { return std::hash<std::u32string>()(__s); }
+ };
+
+ template<>
+ struct __is_fast_hash<hash<__gnu_debug::u32string>> : std::false_type
+ { };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+ } // namespace std
+
+#endif /* C++11 */
+
+#undef _GLIBCXX_CPP11_AND_CXX11_ABI
+#undef _GLIBCXX_CPP11_AND_CXX11_ABI_ONLY
+
#endif
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/hash/hash_char8_t.cc b/libstdc++-v3/testsuite/21_strings/basic_string/hash/hash_char8_t.cc
index c0e8975ce4a..7f8792bbd76 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/hash/hash_char8_t.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/hash/hash_char8_t.cc
@@ -18,10 +18,19 @@
// { dg-options "-std=gnu++2a" }
// { dg-do run { target c++2a } }
-#include <string>
#include <memory_resource>
#include <testsuite_hooks.h>
+#ifdef _GLIBCXX_DEBUG
+# include <debug/string>
+
+using namespace __gnu_debug;
+#else
+# include <string>
+
+using namespace std;
+#endif
+
// C++2a N4810 21.3.5 [basic.string.hash]
// If S is one of these string types, SV is the corresponding string view type,
// and s is an object of type S, then hash<S>()(s) == hash<SV>()(SV(s)).
@@ -38,8 +47,8 @@ template<typename S>
void
test01()
{
- VERIFY( test(std::string("a narrow string")) );
- VERIFY( test(std::u8string(u8"a utf-8 string")) );
+ VERIFY( test(string("a narrow string")) );
+ VERIFY( test(u8string(u8"a utf-8 string")) );
#if _GLIBCXX_USE_CXX11_ABI
VERIFY( test(std::pmr::string("a narrow string, but with PMR!")) );
VERIFY( test(std::pmr::u8string(u8"a utf-8 string, but with PMR!")) );
@@ -50,9 +59,9 @@ void
test02()
{
using std::hash;
- std::string native("a string, a string, my stringdom for a string");
- std::u8string utf8(u8"a string, a string, my stringdom for a string");
- VERIFY( hash<std::string>()(native) == hash<std::u8string>()(utf8) );
+ string native("a string, a string, my stringdom for a string");
+ u8string utf8(u8"a string, a string, my stringdom for a string");
+ VERIFY( hash<string>()(native) == hash<u8string>()(utf8) );
}
int