On 23/03/21 4:42 pm, Jonathan Wakely wrote:
On 20/03/21 22:32 +0100, François Dumont wrote:
Following your feedback here is the simplified version. I grouped it
with the patch I submitted before.
On 19/03/21 8:41 pm, Jonathan Wakely wrote:
I think we could just define on partial specialization that works for
all cases:
Yes, sounds better. But I relied on std::__hash_base which gives
directly the correct definition.
But that is wrong.
The requirements in https://wg21.link/unord.hash say that std::hash<T>
must be disabled for unsupported types. With std::basic_string the
specialization std::hash<basic_string<int>> is disabled, because there
is no specialization for that type, so it uses the primary template of
std::hash, which is empty:
/// Primary class template hash, usable for enum types only.
// Use with non-enum types still SFINAES.
template<typename _Tp>
struct hash : __hash_enum<_Tp>
{ };
With your patch, std::hash<__gnu_debug::basic_string<int>> will not be
empty. It will provide argument_type and result_type and operator()
but calling operator() will fail to compile.
My suggestion doesn't have that problem. With my suggestion,
hash<_gnu_debug::basic_string<C>> is enabled if (and only if)
hash<std::basic_string<C>> is enabled.
Ok, I adopted your approach then.
libstdc++: Fix and complete __gnu_debug::basic_string implementation
Fix and complete __gnu_debug::basic_string 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.
(std::hash<__gnu_debug::basic_string<>>): New partial specialization.
(std::__is_fast_hash<__gnu_debug::basic_string<>>): Likewise.
(basic_string(const basic_string&, const _Alloc&)):
Define even if !_GLIBCXX_USE_CXX11_ABI.
(basic_string(basic_string&&, const _Alloc&)): Likewise
and add noexcept qualification.
(basic_string<>::erase): Adapt to take __const_iterator.
* testsuite/21_strings/basic_string/hash/debug.cc: New test.
*
testsuite/21_strings/basic_string/hash/debug_char8_t.cc: New test.
*
testsuite/21_strings/basic_string/requirements/citerators.cc: Adapt
to test __gnu_debug::string
when _GLIBCXX_DEBUG is defined.
*
testsuite/21_strings/basic_string/requirements/dr438/constructor.cc:
Likewise.
*
testsuite/21_strings/basic_string/requirements/exception/basic.cc:
Likewise.
*
testsuite/21_strings/basic_string/requirements/exception/generation_prohibited.cc:
Likewise.
*
testsuite/21_strings/basic_string/requirements/exception/propagation_consistent.cc:
Likewise.
*
testsuite/21_strings/basic_string/requirements/explicit_instantiation/char/1.cc:
Likewise.
*
testsuite/21_strings/basic_string/requirements/explicit_instantiation/char16_t/1.cc:
Likewise.
*
testsuite/21_strings/basic_string/requirements/explicit_instantiation/char32_t/1.cc:
Likewise.
*
testsuite/21_strings/basic_string/requirements/explicit_instantiation/char8_t/1.cc:
Likewise.
*
testsuite/21_strings/basic_string/requirements/explicit_instantiation/wchar_t/1.cc:
Likewise.
*
testsuite/21_strings/basic_string/requirements/typedefs.cc: Likewise.
* testsuite/util/exception/safety.h
(erase_base<__gnu_debug::basic_string<>>): New partial
specialization.
(insert_base<__gnu_debug::basic_string<>>): Likewise.
* testsuite/util/testsuite_container_traits.h
(traits<__gnu_debug::basic_string<>>): Likewise.
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 172179530aa..f665c759557 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_INSERT_RETURNS_ITERATOR 1
+# define _GLIBCXX_INSERT_RETURNS_ITERATOR_ONLY(expr) expr
+#else
+# define _GLIBCXX_INSERT_RETURNS_ITERATOR 0
+# define _GLIBCXX_INSERT_RETURNS_ITERATOR_ONLY(expr)
+#endif
+
namespace __gnu_debug
{
/** Checks that __s is non-NULL or __n == 0, and then returns __s. */
@@ -123,21 +131,21 @@ namespace __gnu_debug
using _Base::npos;
- basic_string()
-
_GLIBCXX_NOEXCEPT_IF(std::is_nothrow_default_constructible<_Base>::value)
- : _Base() { }
-
// 21.3.1 construct/copy/destroy:
+
explicit
basic_string(const _Allocator& __a) _GLIBCXX_NOEXCEPT
: _Base(__a) { }
#if __cplusplus < 201103L
+ basic_string() : _Base() { }
+
basic_string(const basic_string& __str)
: _Base(__str) { }
~basic_string() { }
#else
+ basic_string() = default;
basic_string(const basic_string&) = default;
basic_string(basic_string&&) = default;
@@ -146,13 +154,15 @@ namespace __gnu_debug
: _Base(__l, __a)
{ }
-#if _GLIBCXX_USE_CXX11_ABI
basic_string(const basic_string& __s, const _Allocator& __a)
: _Base(__s, __a) { }
basic_string(basic_string&& __s, const _Allocator& __a)
- : _Base(std::move(__s), __a) { }
-#endif
+ noexcept( noexcept(
+ _Base(std::declval<_Base>()), std::declval<const _Allocator&>()) )
There is a closing ')' in the wrong place here. This checks whether
_Base is nothrow_move_constructible and whether std::declval is
nothrow.
Well spotted and fixed in this patch.
The only problem left is that it is a copy/paste of __gnu_debug::vector
implementation. I'll submit a patch for this and maybe for other debug
containers that are just missing their noexception qualification.
You could just use
noexcept(is_nothrow_constructible<_Base, _Base, const
_Allocator&>::value)
or:
noexcept(noexcept(_Base(static_cast<_Base&&>(__s), __a)))
It's a bit confusing that we have a noexcept specifier that only
depends on _Base when the _Safe base class can also throw:
+ : _Safe(std::move(__s._M_safe()), __a),
+ _Base(std::move(__s._M_base()), __a)
+ { }
In fact, it is conditionally noexcept with the same condition as the
_Base type, so checking if the _Base construction is non-throwing is
correct. But confusing.
+ /// std::hash specialization for __gnu_debug::basic_string.
+ template<typename _CharT>
+ struct hash<__gnu_debug::basic_string<_CharT>>
+ : public __hash_base<size_t, __gnu_debug::basic_string<_CharT>>
+ {
+ size_t
+ operator()(const __gnu_debug::basic_string<_CharT>& __s) const
noexcept
+ { return std::hash<std::basic_string<_CharT>>()(__s); }
+ };
+
+ template<typename _CharT>
+ struct __is_fast_hash<hash<__gnu_debug::basic_string<_CharT>>>
+ : std::false_type
This says it's always a slow hash, rather than deferring to
__is_fast_hash<hash<std::basic_string<C>>>.
That means __is_fast_hash is false for __gnu_debug::basic_string<int>
but true for std::basic_string<int>. In practice it probably doesn't
matter, but it's inconsistent.
+ { };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+}
+#endif /* C++11 */
+
+#undef _GLIBCXX_INSERT_RETURNS_ITERATOR
+#undef _GLIBCXX_INSERT_RETURNS_ITERATOR_ONLY
+
#endif
diff --git
a/libstdc++-v3/testsuite/21_strings/basic_string/hash/debug.cc
b/libstdc++-v3/testsuite/21_strings/basic_string/hash/debug.cc
new file mode 100644
index 00000000000..84c989590b7
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/hash/debug.cc
@@ -0,0 +1,53 @@
+// Copyright (C) 2021 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 run { target c++17 } }
-std=gnu++17 is the default now, so should not be given explicitly.
You could combine this test and debug/hash_char8_t.cc by adding the
char8_t parts guarded by _GLIBCXX_USE_CHAR8_T. When the test is run
with a -std=gnu++20 it will test the char8_t parts (which is why we
don't want the redundant -std=gnu++17, because it would prevent it
from being run with -std=gnu++20).
diff --git
a/libstdc++-v3/testsuite/21_strings/basic_string/requirements/citerators.cc
b/libstdc++-v3/testsuite/21_strings/basic_string/requirements/citerators.cc
index 99bf5726dcc..69d4a8d0e51 100644
---
a/libstdc++-v3/testsuite/21_strings/basic_string/requirements/citerators.cc
+++
b/libstdc++-v3/testsuite/21_strings/basic_string/requirements/citerators.cc
@@ -18,14 +18,21 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-#include <string>
#include <testsuite_containers.h>
+#ifdef _GLIBCXX_DEBUG
+# include <debug/string>
+using namespace __gnu_debug;
+#else
+# include <string>
+using namespace std;
+#endif
This has the same problem I pointed out previously. With this change,
we don't run this test for std::string in debug mode. When debug
mode is active, we test a different type not std::string.
That means if we introduce a bug to std::string that only affects
debug mode, we might not notice, because we're stopped testing
std::string in debug mode.
If you want to test __gnu_debug::basic_string then those tests should
be added as new tests, not by replacing existing tests that are
already testing something different.
So I added tests on __gnu_debug::basic_string along with the ones on
std::basic_string.
The nice effect of this is that it found a bug in exception safety
testsuite utils, we could be trying to erase the past-the-end iterator.
I still need to find out why, when running test on
__gnu_debug::basic_string after the std::basic_string one, the
generate(sz) call always returns sz.
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 172179530aa..8744a55be64 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_INSERT_RETURNS_ITERATOR 1
+# define _GLIBCXX_INSERT_RETURNS_ITERATOR_ONLY(expr) expr
+#else
+# define _GLIBCXX_INSERT_RETURNS_ITERATOR 0
+# define _GLIBCXX_INSERT_RETURNS_ITERATOR_ONLY(expr)
+#endif
+
namespace __gnu_debug
{
/** Checks that __s is non-NULL or __n == 0, and then returns __s. */
@@ -123,21 +131,21 @@ namespace __gnu_debug
using _Base::npos;
- basic_string()
- _GLIBCXX_NOEXCEPT_IF(std::is_nothrow_default_constructible<_Base>::value)
- : _Base() { }
-
// 21.3.1 construct/copy/destroy:
+
explicit
basic_string(const _Allocator& __a) _GLIBCXX_NOEXCEPT
: _Base(__a) { }
#if __cplusplus < 201103L
+ basic_string() : _Base() { }
+
basic_string(const basic_string& __str)
: _Base(__str) { }
~basic_string() { }
#else
+ basic_string() = default;
basic_string(const basic_string&) = default;
basic_string(basic_string&&) = default;
@@ -146,13 +154,15 @@ namespace __gnu_debug
: _Base(__l, __a)
{ }
-#if _GLIBCXX_USE_CXX11_ABI
basic_string(const basic_string& __s, const _Allocator& __a)
: _Base(__s, __a) { }
basic_string(basic_string&& __s, const _Allocator& __a)
- : _Base(std::move(__s), __a) { }
-#endif
+ noexcept(
+ std::is_nothrow_constructible<_Base, _Base, const _Allocator&>::value )
+ : _Safe(std::move(__s._M_safe()), __a),
+ _Base(std::move(__s._M_base()), __a)
+ { }
~basic_string() = default;
@@ -178,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())
@@ -635,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_INSERT_RETURNS_ITERATOR
+ 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_INSERT_RETURNS_ITERATOR_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_INSERT_RETURNS_ITERATOR_ONLY(__res =)
+ _Base::insert(__p.base(), __first, __last);
+ }
+
+#if ! _GLIBCXX_INSERT_RETURNS_ITERATOR
__res = _Base::begin() + __offset;
#endif
this->_M_invalidate_all();
@@ -676,7 +693,7 @@ namespace __gnu_debug
}
iterator
- erase(iterator __position)
+ erase(__const_iterator __position)
{
__glibcxx_check_erase(__position);
typename _Base::iterator __res = _Base::erase(__position.base());
@@ -685,7 +702,7 @@ namespace __gnu_debug
}
iterator
- erase(iterator __first, iterator __last)
+ erase(__const_iterator __first, __const_iterator __last)
{
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 151. can't currently clear() empty container
@@ -1285,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> >
@@ -1292,4 +1322,27 @@ namespace __gnu_debug
} // namespace __gnu_debug
+#if __cplusplus >= 201103L
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ /// std::hash specialization for __gnu_debug::basic_string.
+ template<typename _CharT>
+ struct hash<__gnu_debug::basic_string<_CharT>>
+ : public hash<std::basic_string<_CharT>>
+ { };
+
+ template<typename _CharT>
+ struct __is_fast_hash<hash<__gnu_debug::basic_string<_CharT>>>
+ : __is_fast_hash<hash<std::basic_string<_CharT>>>
+ { };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+}
+#endif /* C++11 */
+
+#undef _GLIBCXX_INSERT_RETURNS_ITERATOR
+#undef _GLIBCXX_INSERT_RETURNS_ITERATOR_ONLY
+
#endif
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/hash/debug.cc b/libstdc++-v3/testsuite/21_strings/basic_string/hash/debug.cc
new file mode 100644
index 00000000000..596bff9f8c6
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/hash/debug.cc
@@ -0,0 +1,69 @@
+// Copyright (C) 2021 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-do run { target c++17 } }
+
+#include <debug/string>
+#include <memory_resource>
+#include <testsuite_hooks.h>
+
+// C++17 24.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)).
+
+template<typename S>
+ bool
+ test(const S& s)
+ {
+ using std::hash;
+ using SV = std::basic_string_view<typename S::value_type>;
+ return hash<S>()(s) == hash<SV>()(SV(s));
+ }
+
+void
+test01()
+{
+ VERIFY( test(__gnu_debug::string("a narrow string")) );
+#if _GLIBCXX_USE_CHAR8_T
+ VERIFY( test(__gnu_debug::u8string(u8"a narrow string")) );
+#endif
+ VERIFY( test(__gnu_debug::u16string(u"a utf-16 string")) );
+ VERIFY( test(__gnu_debug::u32string(U"a utf-32 string")) );
+#if _GLIBCXX_USE_WCHAR_T
+ VERIFY( test(__gnu_debug::wstring(L"a wide string")) );
+#endif
+}
+
+#if _GLIBCXX_USE_CHAR8_T
+void
+test02()
+{
+ using std::hash;
+ __gnu_debug::string native("a string, a string, my stringdom for a string");
+ __gnu_debug::u8string utf8(u8"a string, a string, my stringdom for a string");
+ VERIFY( hash<__gnu_debug::string>()(native) == hash<__gnu_debug::u8string>()(utf8) );
+}
+#endif
+
+int
+main()
+{
+ test01();
+#if _GLIBCXX_USE_CHAR8_T
+ test02();
+#endif
+}
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/requirements/citerators.cc b/libstdc++-v3/testsuite/21_strings/basic_string/requirements/citerators.cc
index 99bf5726dcc..fca2a8940e9 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/requirements/citerators.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/requirements/citerators.cc
@@ -19,13 +19,17 @@
// <http://www.gnu.org/licenses/>.
#include <string>
+#include <debug/string>
+
#include <testsuite_containers.h>
int main()
{
__gnu_test::citerator<std::string> test1;
+ __gnu_test::citerator<__gnu_debug::string> dtest1;
#ifdef _GLIBCXX_USE_WCHAR_T
__gnu_test::citerator<std::wstring> test2;
+ __gnu_test::citerator<__gnu_debug::wstring> dtest2;
#endif
return 0;
}
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/requirements/dr438/constructor.cc b/libstdc++-v3/testsuite/21_strings/basic_string/requirements/dr438/constructor.cc
index 82d42ebb6a6..059e32aa970 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/requirements/dr438/constructor.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/requirements/dr438/constructor.cc
@@ -20,8 +20,10 @@
// { dg-do compile }
#include <string>
+#include <debug/string>
void f()
{
std::string s(10, 1);
+ __gnu_debug::string ds(10, 1);
}
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/requirements/exception/basic.cc b/libstdc++-v3/testsuite/21_strings/basic_string/requirements/exception/basic.cc
index 2b6e27432e8..2ff020d81d4 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/requirements/exception/basic.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/requirements/exception/basic.cc
@@ -21,6 +21,7 @@
// <http://www.gnu.org/licenses/>.
#include <string>
+#include <debug/string>
#include <exception/safety.h>
void
@@ -31,8 +32,16 @@ value()
typedef char value_type;
typedef __gnu_cxx::throw_allocator_limit<value_type> allocator_type;
typedef std::char_traits<value_type> traits_type;
- typedef std::basic_string<value_type, traits_type, allocator_type> test_type;
- __gnu_test::basic_safety<test_type> test;
+
+ {
+ typedef std::basic_string<value_type, traits_type, allocator_type> test_type;
+ __gnu_test::basic_safety<test_type> test;
+ }
+
+ {
+ typedef __gnu_debug::basic_string<value_type, traits_type, allocator_type> test_type;
+ __gnu_test::basic_safety<test_type> test;
+ }
}
// Container requirement testing, exceptional behavior
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/requirements/exception/generation_prohibited.cc b/libstdc++-v3/testsuite/21_strings/basic_string/requirements/exception/generation_prohibited.cc
index 07d2a2e2074..02d3242db59 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/requirements/exception/generation_prohibited.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/requirements/exception/generation_prohibited.cc
@@ -21,6 +21,7 @@
// <http://www.gnu.org/licenses/>.
#include <string>
+#include <debug/string>
#include <exception/safety.h>
void
@@ -29,8 +30,16 @@ char_allocator()
typedef char value_type;
typedef __gnu_cxx::throw_allocator_random<value_type> allocator_type;
typedef std::char_traits<value_type> traits_type;
- typedef std::basic_string<value_type, traits_type, allocator_type> test_type;
- __gnu_test::generation_prohibited<test_type> test;
+
+ {
+ typedef std::basic_string<value_type, traits_type, allocator_type> test_type;
+ __gnu_test::generation_prohibited<test_type> test;
+ }
+
+ {
+ typedef __gnu_debug::basic_string<value_type, traits_type, allocator_type> test_type;
+ __gnu_test::generation_prohibited<test_type> test;
+ }
}
void
@@ -39,8 +48,16 @@ wchar_allocator()
typedef wchar_t value_type;
typedef __gnu_cxx::throw_allocator_random<value_type> allocator_type;
typedef std::char_traits<value_type> traits_type;
- typedef std::basic_string<value_type, traits_type, allocator_type> test_type;
- __gnu_test::generation_prohibited<test_type> test;
+
+ {
+ typedef std::basic_string<value_type, traits_type, allocator_type> test_type;
+ __gnu_test::generation_prohibited<test_type> test;
+ }
+
+ {
+ typedef __gnu_debug::basic_string<value_type, traits_type, allocator_type> test_type;
+ __gnu_test::generation_prohibited<test_type> test;
+ }
}
// Container requirement testing, exceptional behavior
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/requirements/exception/propagation_consistent.cc b/libstdc++-v3/testsuite/21_strings/basic_string/requirements/exception/propagation_consistent.cc
index ce99dab915e..0526745cb91 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/requirements/exception/propagation_consistent.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/requirements/exception/propagation_consistent.cc
@@ -21,6 +21,7 @@
// <http://www.gnu.org/licenses/>.
#include <string>
+#include <debug/string>
#include <exception/safety.h>
void
@@ -31,8 +32,16 @@ value()
typedef char value_type;
typedef __gnu_cxx::throw_allocator_limit<value_type> allocator_type;
typedef std::char_traits<value_type> traits_type;
- typedef std::basic_string<value_type, traits_type, allocator_type> test_type;
- __gnu_test::propagation_consistent<test_type> test;
+
+ {
+ typedef std::basic_string<value_type, traits_type, allocator_type> test_type;
+ __gnu_test::propagation_consistent<test_type> test;
+ }
+
+ {
+ typedef __gnu_debug::basic_string<value_type, traits_type, allocator_type> test_type;
+ __gnu_test::propagation_consistent<test_type> test;
+ }
}
// Container requirement testing, exceptional behavior
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/requirements/explicit_instantiation/char/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/requirements/explicit_instantiation/char/1.cc
index 275354c1f4c..9d2ca54c5df 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/requirements/explicit_instantiation/char/1.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/requirements/explicit_instantiation/char/1.cc
@@ -18,5 +18,7 @@
// <http://www.gnu.org/licenses/>.
#include <string>
+#include <debug/string>
template class std::basic_string<char>;
+template class __gnu_debug::basic_string<char>;
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/requirements/explicit_instantiation/char16_t/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/requirements/explicit_instantiation/char16_t/1.cc
index 2b5139de533..64030165d2b 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/requirements/explicit_instantiation/char16_t/1.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/requirements/explicit_instantiation/char16_t/1.cc
@@ -18,5 +18,7 @@
// <http://www.gnu.org/licenses/>.
#include <string>
+#include <debug/string>
template class std::basic_string<char16_t>;
+template class __gnu_debug::basic_string<char16_t>;
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/requirements/explicit_instantiation/char32_t/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/requirements/explicit_instantiation/char32_t/1.cc
index 0fa685e9094..6e12fadf8cd 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/requirements/explicit_instantiation/char32_t/1.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/requirements/explicit_instantiation/char32_t/1.cc
@@ -18,5 +18,7 @@
// <http://www.gnu.org/licenses/>.
#include <string>
+#include <debug/string>
template class std::basic_string<char32_t>;
+template class __gnu_debug::basic_string<char32_t>;
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/requirements/explicit_instantiation/char8_t/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/requirements/explicit_instantiation/char8_t/1.cc
index db88b0f47a3..abab7972b8d 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/requirements/explicit_instantiation/char8_t/1.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/requirements/explicit_instantiation/char8_t/1.cc
@@ -19,5 +19,7 @@
// <http://www.gnu.org/licenses/>.
#include <string>
+#include <debug/string>
template class std::basic_string<char8_t>;
+template class __gnu_debug::basic_string<char8_t>;
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/requirements/explicit_instantiation/wchar_t/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/requirements/explicit_instantiation/wchar_t/1.cc
index 7f16ca4cb5b..1a25fa839d4 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/requirements/explicit_instantiation/wchar_t/1.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/requirements/explicit_instantiation/wchar_t/1.cc
@@ -18,5 +18,7 @@
// <http://www.gnu.org/licenses/>.
#include <string>
+#include <debug/string>
template class std::basic_string<wchar_t>;
+template class __gnu_debug::basic_string<wchar_t>;
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/requirements/typedefs.cc b/libstdc++-v3/testsuite/21_strings/basic_string/requirements/typedefs.cc
index 2fc313b9cbf..ff5f98e7805 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/requirements/typedefs.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/requirements/typedefs.cc
@@ -19,9 +19,12 @@
#include <testsuite_containers.h>
#include <string>
+#include <debug/string>
// Check container for required typedefs.
__gnu_test::types<std::string> t1;
+__gnu_test::types<__gnu_debug::string> dt1;
#ifdef _GLIBCXX_USE_WCHAR_T
__gnu_test::types<std::wstring> t2;
+__gnu_test::types<__gnu_debug::wstring> dt2;
#endif
diff --git a/libstdc++-v3/testsuite/util/exception/safety.h b/libstdc++-v3/testsuite/util/exception/safety.h
index 6c91e740e0d..2d6d894f001 100644
--- a/libstdc++-v3/testsuite/util/exception/safety.h
+++ b/libstdc++-v3/testsuite/util/exception/safety.h
@@ -266,6 +266,20 @@ namespace __gnu_test
iterator (container_type::* _F_erase_point)(iterator);
iterator (container_type::* _F_erase_range)(iterator, iterator);
+ erase_base()
+ : _F_erase_point(&container_type::erase),
+ _F_erase_range(&container_type::erase) { }
+ };
+
+ template<typename _Tp1, typename _Tp2, typename _Tp3>
+ struct erase_base<__gnu_debug::basic_string<_Tp1, _Tp2, _Tp3>>
+ {
+ typedef __gnu_debug::basic_string<_Tp1, _Tp2, _Tp3> container_type;
+ typedef typename container_type::iterator iterator;
+
+ iterator (container_type::* _F_erase_point)(iterator);
+ iterator (container_type::* _F_erase_range)(iterator, iterator);
+
erase_base()
: _F_erase_point(&container_type::erase),
_F_erase_range(&container_type::erase) { }
@@ -312,7 +326,7 @@ namespace __gnu_test
// NB: Lowest common denominator: use forward iterator operations.
auto i = __container.begin();
- std::advance(i, generate(sz));
+ std::advance(i, generate(sz - 1));
// Makes it easier to think of this as __container.erase(i)
(__container.*_F_erase_point)(i);
@@ -340,7 +354,7 @@ namespace __gnu_test
// NB: Lowest common denominator: use forward iterator operations.
auto i = __container.before_begin();
- std::advance(i, generate(sz));
+ std::advance(i, generate(sz - 1));
// Makes it easier to think of this as __container.erase(i)
(__container.*_F_erase_point)(i);
@@ -681,6 +695,24 @@ namespace __gnu_test
typedef typename container_type::const_iterator const_iterator;
typedef typename container_type::value_type value_type;
+#if _GLIBCXX_USE_CXX11_ABI == 0 || __cplusplus < 201103L
+ iterator (container_type::* _F_insert_point)(iterator, value_type);
+#else
+ iterator (container_type::* _F_insert_point)(const_iterator,
+ value_type);
+#endif
+
+ insert_base() : _F_insert_point(&container_type::insert) { }
+ };
+
+ template<typename _Tp1, typename _Tp2, typename _Tp3>
+ struct insert_base<__gnu_debug::basic_string<_Tp1, _Tp2, _Tp3>>
+ {
+ typedef __gnu_debug::basic_string<_Tp1, _Tp2, _Tp3> container_type;
+ typedef typename container_type::iterator iterator;
+ typedef typename container_type::const_iterator const_iterator;
+ typedef typename container_type::value_type value_type;
+
#if _GLIBCXX_USE_CXX11_ABI == 0 || __cplusplus < 201103L
iterator (container_type::* _F_insert_point)(iterator, value_type);
#else
diff --git a/libstdc++-v3/testsuite/util/testsuite_container_traits.h b/libstdc++-v3/testsuite/util/testsuite_container_traits.h
index fb1f558011c..0bc7a2aa53a 100644
--- a/libstdc++-v3/testsuite/util/testsuite_container_traits.h
+++ b/libstdc++-v3/testsuite/util/testsuite_container_traits.h
@@ -22,6 +22,7 @@
#include <bits/stdc++.h>
#include <ext/vstring.h>
+#include <debug/string>
namespace __gnu_test
{
@@ -128,6 +129,17 @@ namespace __gnu_test
typedef std::true_type has_insert;
};
+ template<typename _Tp1, typename _Tp2, typename _Tp3>
+ struct traits<__gnu_debug::basic_string<_Tp1, _Tp2, _Tp3>> : public traits_base
+ {
+ typedef std::true_type is_container;
+ typedef std::true_type is_reversible;
+ typedef std::true_type is_allocator_aware;
+
+ typedef std::true_type has_erase;
+ typedef std::true_type has_insert;
+ };
+
template<typename _Tp1, typename _Tp2, typename _Tp3,
template <typename, typename, typename> class _Tp4>
struct traits<__gnu_cxx::__versa_string<_Tp1, _Tp2, _Tp3, _Tp4>>