mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-31 03:00:25 +08:00
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 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. (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. * 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<>>): New partial specialization. * testsuite/21_strings/basic_string/hash/debug.cc: New test. * testsuite/21_strings/basic_string/requirements/citerators.cc: Add test on __gnu_debug::string. * 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.
This commit is contained in:
parent
990a123ef7
commit
50bb46e4d2
@ -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 (__dist.second >= __dp_sign)
|
||||
__res = _Base::insert(__p.base(), __gnu_debug::__unsafe(__first),
|
||||
__gnu_debug::__unsafe(__last));
|
||||
else
|
||||
__res = _Base::insert(__p.base(), __first, __last);
|
||||
#else
|
||||
#if ! _GLIBCXX_INSERT_RETURNS_ITERATOR
|
||||
const size_type __offset = __p.base() - _Base::begin();
|
||||
_Base::insert(__p.base(), __first, __last);
|
||||
#endif
|
||||
if (__dist.second >= __dp_sign)
|
||||
{
|
||||
_GLIBCXX_INSERT_RETURNS_ITERATOR_ONLY(__res =)
|
||||
_Base::insert(__p.base(), __gnu_debug::__unsafe(__first),
|
||||
__gnu_debug::__unsafe(__last));
|
||||
}
|
||||
else
|
||||
{
|
||||
_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
|
||||
|
69
libstdc++-v3/testsuite/21_strings/basic_string/hash/debug.cc
Normal file
69
libstdc++-v3/testsuite/21_strings/basic_string/hash/debug.cc
Normal file
@ -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
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>;
|
||||
|
@ -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>;
|
||||
|
@ -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>;
|
||||
|
@ -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>;
|
||||
|
@ -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>;
|
||||
|
@ -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
|
||||
|
@ -275,6 +275,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) { }
|
||||
@ -701,6 +715,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
|
||||
|
@ -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>>
|
||||
|
Loading…
x
Reference in New Issue
Block a user