From fb8b3e2993f4f1bb646369feab59b3bd80d1d0e1 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 24 Apr 2019 16:17:53 +0100 Subject: [PATCH] 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): 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. From-SVN: r270548 --- libstdc++-v3/ChangeLog | 42 +++++ libstdc++-v3/include/bits/basic_string.h | 42 ++--- libstdc++-v3/include/experimental/string_view | 4 +- libstdc++-v3/include/std/string_view | 143 +++++++++--------- .../modifiers/remove_prefix/char/1.cc | 4 +- .../modifiers/remove_prefix/wchar_t/1.cc | 4 +- .../modifiers/remove_suffix/char/1.cc | 4 +- .../modifiers/remove_suffix/wchar_t/1.cc | 4 +- .../requirements/traits_neg.cc | 37 +++++ .../requirements/typedefs.cc | 9 ++ .../modifiers/remove_prefix/char/1.cc | 2 +- .../modifiers/remove_prefix/wchar_t/1.cc | 2 +- .../modifiers/remove_suffix/char/1.cc | 2 +- .../modifiers/remove_suffix/wchar_t/1.cc | 2 +- .../string_view/requirements/typedefs.cc | 13 ++ 15 files changed, 213 insertions(+), 101 deletions(-) create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string_view/requirements/traits_neg.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 2ab686ba3bb..5e8a09a6636 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,47 @@ 2019-04-24 Jonathan Wakely + * 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): 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 922536965e3..40ef8758a51 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -1336,8 +1336,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 { __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 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 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 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 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 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 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 @@ _GLIBCXX_END_NAMESPACE_CXX11 { __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 @@ _GLIBCXX_END_NAMESPACE_CXX11 { __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 @@ _GLIBCXX_END_NAMESPACE_CXX11 { __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 @@ _GLIBCXX_END_NAMESPACE_CXX11 { __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 ce2c14cfe36..9e810dec844 100644 --- a/libstdc++-v3/include/experimental/string_view +++ b/libstdc++-v3/include/experimental/string_view @@ -78,9 +78,9 @@ inline namespace fundamentals_v1 // 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 844cfb148ad..42822cc41ab 100644 --- a/libstdc++-v3/include/std/string_view +++ b/libstdc++-v3/include/std/string_view @@ -49,6 +49,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #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 * @brief A non-owning reference to a string. @@ -70,24 +89,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template> 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; - 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 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION 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 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // [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 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *(this->_M_str + __pos); } - constexpr const _CharT& + constexpr const_reference at(size_type __pos) const { if (__pos >= _M_len) @@ -185,7 +208,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION 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 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION 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 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION 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 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION 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 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION 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 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION .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 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION 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 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #ifdef _GLIBCXX_USE_WCHAR_T template<> struct hash - : public __hash_base + : public __hash_base { 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 eedc6b99f70..944260652bf 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 @@ test01() 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 @@ test02() 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 e0177511f4f..c8ad5528b31 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 @@ test01() 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 @@ test02() 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 67a8a589c5f..d4d5d7dd06d 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 @@ test01() 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 @@ test02() 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 81ccb91b504..deccc252840 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 @@ test01() 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 @@ test02() 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 00000000000..93ea80854f4 --- /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 +// . + +// { dg-options "-std=gnu++17" } +// { dg-do compile { target c++17 } } + +#include + +// 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> s1; // { dg-error "here" } +std::basic_string_view> 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 41b8f566a90..b11ef572800 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::basic_types t2b; __gnu_test::reversible_types t2r; typedef typename std::wstring_view::traits_type traits_type2; #endif + +static_assert(std::is_same(), + "pointer should be value_type*"); +static_assert(std::is_same(), + "const_pointer should be const value_type*"); +static_assert(std::is_same(), + "reference should be value_type&"); +static_assert(std::is_same(), + "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 12a407889a4..8a7b6b87679 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 @@ test01() 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 e92d6d9c70a..153349f2a9f 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 @@ test01() 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 ab990cb296d..612a62c045b 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 @@ test01() 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 7c7c63ee851..b1114d1799b 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 @@ test01() 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 269633bdf7e..38e20e1625c 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::basic_types t2b; __gnu_test::reversible_types t2r; typedef typename std::experimental::wstring_view::traits_type traits_type2; #endif + +static_assert( + std::is_same(), + "pointer should be value_type*"); +static_assert( + std::is_same(), + "const_pointer should be const value_type*"); +static_assert( + std::is_same(), + "reference should be value_type&"); +static_assert( + std::is_same(), + "const_reference should be const value_type&"); -- 2.30.2