commit 23d36bb4513f6917f55729080e03f3d69f558acf Author: Jonathan Wakely Date: Tue Aug 16 13:50:55 2016 +0100 PR 77264 constrain new std::basic_string overloads PR libstdc++/77264 * include/bits/basic_string.h (operator=(__sv_type) (append(__sv_type), assign(__sv_type), insert(size_type, __sv_type)) (replace(size_type, size_type, __sv_type)) (replace(const_iterator, const_iterator, __sv_type)) (find(__sv_type, size_type), rfind(__sv_type, size_type)) (compare(size_type, size_type, __sv_type)): Reformat. (_If_sv): Define helper for SFINAE constaints. (append(const _Tp&, size_type, size_type)) (assign(const _Tp&, size_type, size_type)) (insert(size_type, const _Tp&, size_type, size_type)) (replace(size_type, size_type, const _Tp&, size_type, size_type)): Use _If_sv. * testsuite/21_strings/basic_string/modifiers/append/char/4.cc: Test SFINAE constraints. * testsuite/21_strings/basic_string/modifiers/append/wchar_t/4.cc: Likewise. * testsuite/21_strings/basic_string/modifiers/replace/char/7.cc: Likewise. * testsuite/21_strings/basic_string/modifiers/replace/wchar_t/7.cc: Likewise. * testsuite/21_strings/basic_string/modifiers/assign/char/4.cc: Likewise. * testsuite/21_strings/basic_string/modifiers/assign/wchar_t/4.cc: Likewise. * testsuite/21_strings/basic_string/modifiers/insert/char/3.cc: Likewise. * testsuite/21_strings/basic_string/modifiers/insert/wchar_t/3.cc: Likewise. * testsuite/21_strings/basic_string/modifiers/replace/char/7.cc: Likewise. * testsuite/21_strings/basic_string/operations/compare/char/2.cc: Likewise. * testsuite/21_strings/basic_string/operations/compare/wchar_t/2.cc: Likewise. diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index 89e2100..68cfc99 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -709,7 +709,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @brief Set value to string constructed from a string_view. * @param __sv A string_view. */ - basic_string& operator=(__sv_type __sv) + basic_string& + operator=(__sv_type __sv) { return this->assign(__sv); } /** @@ -1217,9 +1218,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __sv The string_view to be appended. * @return Reference to this string. */ - basic_string& append(__sv_type __sv) + basic_string& + append(__sv_type __sv) { return this->append(__sv.data(), __sv.size()); } + template + using _If_sv = enable_if_t< + __and_, + __not_>>::value, + _Res>; + /** * @brief Append a range of characters from a string_view. * @param __sv The string_view to be appended from. @@ -1227,17 +1235,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __n The number of characters to append from the string_view. * @return Reference to this string. */ - template , - bool> = true> - basic_string& append(const _Tp& __svt, - size_type __pos, size_type __n = npos) - { - __sv_type __sv = __svt; - return _M_append(__sv.data() - + __sv._M_check(__pos, "basic_string::append"), - __sv._M_limit(__pos, __n)); - } + template + _If_sv<_Tp, basic_string&> + append(const _Tp& __svt, size_type __pos, size_type __n = npos) + { + __sv_type __sv = __svt; + return _M_append(__sv.data() + + __sv._M_check(__pos, "basic_string::append"), + __sv._M_limit(__pos, __n)); + } #endif // C++17 /** @@ -1386,7 +1392,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __sv The source string_view. * @return Reference to this string. */ - basic_string& assign(__sv_type __sv) + basic_string& + assign(__sv_type __sv) { return this->assign(__sv.data(), __sv.size()); } /** @@ -1396,18 +1403,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __n The number of characters to assign. * @return Reference to this string. */ - template , - bool> = true> - basic_string& - 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)); - } + template + _If_sv<_Tp, basic_string&> + 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)); + } #endif // C++17 #if __cplusplus >= 201103L @@ -1647,8 +1651,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __sv The string_view to insert. * @return Reference to this string. */ - basic_string& insert(size_type __pos, - __sv_type __sv) + basic_string& + insert(size_type __pos, __sv_type __sv) { return this->insert(__pos, __sv.data(), __sv.size()); } /** @@ -1660,17 +1664,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __n The number of characters to insert. * @return Reference to this string. */ - template , - bool> = true> - basic_string& insert(size_type __pos1, const _Tp& __svt, - 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)); - } + template + _If_sv<_Tp, basic_string&> + insert(size_type __pos1, const _Tp& __svt, + 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)); + } #endif // C++17 /** @@ -2070,8 +2073,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __sv The string_view to insert. * @return Reference to this string. */ - basic_string& replace(size_type __pos, size_type __n, - __sv_type __sv) + basic_string& + replace(size_type __pos, size_type __n, __sv_type __sv) { return this->replace(__pos, __n, __sv.data(), __sv.size()); } /** @@ -2083,18 +2086,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __n2 The number of characters to insert. * @return Reference to this string. */ - template , - bool> = true> - basic_string& replace(size_type __pos1, size_type __n1, - const _Tp& __svt, - 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)); - } + template + _If_sv<_Tp, basic_string&> + replace(size_type __pos1, size_type __n1, const _Tp& __svt, + 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)); + } /** * @brief Replace range of characters with string_view. @@ -2105,8 +2106,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __sv The string_view to insert from. * @return Reference to this string. */ - basic_string& replace(const_iterator __i1, const_iterator __i2, - __sv_type __sv) + basic_string& + replace(const_iterator __i1, const_iterator __i2, __sv_type __sv) { return this->replace(__i1 - begin(), __i2 - __i1, __sv); } #endif // C++17 @@ -2241,8 +2242,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Index of start of first occurrence. */ size_type - find(__sv_type __sv, - size_type __pos = 0) const noexcept + find(__sv_type __sv, size_type __pos = 0) const noexcept { return this->find(__sv.data(), __pos, __sv.size()); } #endif // C++17 @@ -2299,8 +2299,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Index of start of last occurrence. */ size_type - rfind (__sv_type __sv, - size_type __pos = npos) const noexcept + rfind(__sv_type __sv, size_type __pos = npos) const noexcept { return this->rfind(__sv.data(), __pos, __sv.size()); } #endif // C++17 @@ -2721,11 +2720,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Integer < 0, 0, or > 0. */ int - compare(size_type __pos, size_type __n, - __sv_type __sv) const - { - return __sv_type(*this).substr(__pos, __n).compare(__sv); - } + compare(size_type __pos, size_type __n, __sv_type __sv) const + { return __sv_type(*this).substr(__pos, __n).compare(__sv); } /** * @brief Compare to a string_view. @@ -2736,17 +2732,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __n2 The number of characters to compare. * @return Integer < 0, 0, or > 0. */ - template , - bool> = true> - int compare(size_type __pos1, size_type __n1, - const _Tp& __svt, - size_type __pos2, size_type __n2 = npos) const - { - __sv_type __sv = __svt; - return __sv_type(*this) - .substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2)); - } + template + _If_sv<_Tp, int> + compare(size_type __pos1, size_type __n1, const _Tp& __svt, + size_type __pos2, size_type __n2 = npos) const + { + __sv_type __sv = __svt; + return __sv_type(*this) + .substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2)); + } #endif // C++17 /** diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/char/4.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/char/4.cc index 2a94452..0df4a6d 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/char/4.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/char/4.cc @@ -38,8 +38,38 @@ test03() VERIFY (str4 == "oo"); } +// PR libstdc++/77264 +void +test04() +{ + bool test __attribute__((unused)) = true; + + std::string str("a"); + char c = 'b'; + str.append(&c, 1); + VERIFY (str[1] == c); + + char arr[] = "c"; + str.append(arr, 1); + VERIFY (str[2] == arr[0]); + + const char carr[] = "d"; + str.append(carr, 1); + VERIFY (str[3] == carr[0]); + + struct S { + operator char*() { return &c; } + operator std::string_view() { return "!"; } + char c = 'e'; + }; + + str.append(S{}, 1); + VERIFY (str[4] == S{}.c); +} + int main() { test03(); + test04(); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/wchar_t/4.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/wchar_t/4.cc index 5512f06..dc1bd64 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/wchar_t/4.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/wchar_t/4.cc @@ -38,8 +38,39 @@ test03() VERIFY (str4 == L"oo"); } +// PR libstdc++/77264 +void +test04() +{ + bool test __attribute__((unused)) = true; + + std::wstring str(L"a"); + + wchar_t c = L'b'; + str.append(&c, 1); + VERIFY (str[1] == c); + + wchar_t arr[] = L"c"; + str.append(arr, 1); + VERIFY (str[2] == arr[0]); + + const wchar_t carr[] = L"d"; + str.append(carr, 1); + VERIFY (str[3] == carr[0]); + + struct S { + operator wchar_t*() { return &c; } + operator std::wstring_view() { return L"!"; } + wchar_t c = L'e'; + }; + + str.append(S{}, 1); + VERIFY (str[4] == S{}.c); +} + int main() { test03(); + test04(); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/char/4.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/char/4.cc index b8955b5..201dee0 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/char/4.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/char/4.cc @@ -35,8 +35,38 @@ test03() VERIFY (str4 == "oo"); } +// PR libstdc++/77264 +void +test04() +{ + bool test __attribute__((unused)) = true; + + std::string str("a"); + char c = 'b'; + str.assign(&c, 1); + VERIFY (str[0] == c); + + char arr[] = "c"; + str.assign(arr, 1); + VERIFY (str[0] == arr[0]); + + const char carr[] = "d"; + str.assign(carr, 1); + VERIFY (str[0] == carr[0]); + + struct S { + operator char*() { return &c; } + operator std::string_view() { return "!"; } + char c = 'e'; + }; + + str.assign(S{}, 1); + VERIFY (str[0] == S{}.c); +} + int main() { test03(); + test04(); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/wchar_t/4.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/wchar_t/4.cc index bde158f..5fb7a64 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/wchar_t/4.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/wchar_t/4.cc @@ -35,8 +35,39 @@ test03() VERIFY (str4 == L"oo"); } +// PR libstdc++/77264 +void +test04() +{ + bool test __attribute__((unused)) = true; + + std::wstring str(L"a"); + + wchar_t c = L'b'; + str.assign(&c, 1); + VERIFY (str[0] == c); + + wchar_t arr[] = L"c"; + str.assign(arr, 1); + VERIFY (str[0] == arr[0]); + + const wchar_t carr[] = L"d"; + str.assign(carr, 1); + VERIFY (str[0] == carr[0]); + + struct S { + operator wchar_t*() { return &c; } + operator std::wstring_view() { return L"!"; } + wchar_t c = L'e'; + }; + + str.assign(S{}, 1); + VERIFY (str[0] == S{}.c); +} + int main() { test03(); + test04(); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/char/3.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/char/3.cc index 71e5165..7ebbb33 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/char/3.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/char/3.cc @@ -39,8 +39,38 @@ test03() VERIFY (str4 == "foooooo"); } +// PR libstdc++/77264 +void +test04() +{ + bool test __attribute__((unused)) = true; + + std::string str("a"); + char c = 'b'; + str.insert(0, &c, 1); + VERIFY (str[0] == c); + + char arr[] = "c"; + str.insert(0, arr, 1); + VERIFY (str[0] == arr[0]); + + const char carr[] = "d"; + str.insert(0, carr, 1); + VERIFY (str[0] == carr[0]); + + struct S { + operator char*() { return &c; } + operator std::string_view() { return "!"; } + char c = 'e'; + }; + + str.insert(0, S{}, 1); + VERIFY (str[0] == S{}.c); +} + int main() { test03(); + test04(); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/wchar_t/3.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/wchar_t/3.cc index 6cddcbe..5d2587c 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/wchar_t/3.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/wchar_t/3.cc @@ -39,8 +39,39 @@ test03() VERIFY (str4 == L"foooooo"); } +// PR libstdc++/77264 +void +test04() +{ + bool test __attribute__((unused)) = true; + + std::wstring str(L"a"); + + wchar_t c = L'b'; + str.insert(0, &c, 1); + VERIFY (str[0] == c); + + wchar_t arr[] = L"c"; + str.insert(0, arr, 1); + VERIFY (str[0] == arr[0]); + + const wchar_t carr[] = L"d"; + str.insert(0, carr, 1); + VERIFY (str[0] == carr[0]); + + struct S { + operator wchar_t*() { return &c; } + operator std::wstring_view() { return L"!"; } + wchar_t c = L'e'; + }; + + str.insert(0, S{}, 1); + VERIFY (str[0] == S{}.c); +} + int main() { test03(); + test04(); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/char/7.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/char/7.cc index 004b235..afefa84 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/char/7.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/char/7.cc @@ -47,8 +47,38 @@ test03() VERIFY (str2 == "foofoo"); } +// PR libstdc++/77264 +void +test04() +{ + bool test __attribute__((unused)) = true; + + std::string str("a"); + char c = 'b'; + str.replace(0, 1, &c, 1); + VERIFY (str[0] == c); + + char arr[] = "c"; + str.replace(0, 1, arr, 1); + VERIFY (str[0] == arr[0]); + + const char carr[] = "d"; + str.replace(0, 1, carr, 1); + VERIFY (str[0] == carr[0]); + + struct S { + operator char*() { return &c; } + operator std::string_view() { return "!"; } + char c = 'e'; + }; + + str.replace(0, 1, S{}, 1); + VERIFY (str[0] == S{}.c); +} + int main() { test03(); + test04(); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/wchar_t/7.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/wchar_t/7.cc index 88d2666..692c52d 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/wchar_t/7.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/wchar_t/7.cc @@ -47,8 +47,39 @@ test03() VERIFY (str2 == L"foofoo"); } +// PR libstdc++/77264 +void +test04() +{ + bool test __attribute__((unused)) = true; + + std::wstring str(L"a"); + + wchar_t c = L'b'; + str.replace(0, 1, &c, 1); + VERIFY (str[0] == c); + + wchar_t arr[] = L"c"; + str.replace(0, 1, arr, 1); + VERIFY (str[0] == arr[0]); + + const wchar_t carr[] = L"d"; + str.replace(0, 1, carr, 1); + VERIFY (str[0] == carr[0]); + + struct S { + operator wchar_t*() { return &c; } + operator std::wstring_view() { return L"!"; } + wchar_t c = L'e'; + }; + + str.replace(0, 1, S{}, 1); + VERIFY (str[0] == S{}.c); +} + int main() { test03(); + test04(); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/compare/char/2.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/compare/char/2.cc index 65474d0..08b3f0c 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/operations/compare/char/2.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/compare/char/2.cc @@ -49,8 +49,38 @@ test03() VERIFY (x == 0); } +// PR libstdc++/77264 +void +test04() +{ + bool test __attribute__((unused)) = true; + + const std::string str("a"); + char c = 'a'; + int res = str.compare(0, 1, &c, 1); + VERIFY ( !res ); + + char arr[] = "a"; + res = str.compare(0, 1, arr, 1); + VERIFY ( !res ); + + const char carr[] = "a"; + res = str.compare(0, 1, carr, 1); + VERIFY ( !res ); + + struct S { + operator char*() { return &c; } + operator std::string_view() { return "!"; } + char c = 'a'; + }; + + res = str.compare(0, 1, S{}, 1); + VERIFY ( !res ); +} + int main() { test03(); + test04(); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/compare/wchar_t/2.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/compare/wchar_t/2.cc index f7a9760..d79dcd5 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/operations/compare/wchar_t/2.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/compare/wchar_t/2.cc @@ -49,8 +49,39 @@ test03() VERIFY (x == 0); } +// PR libstdc++/77264 +void +test04() +{ + bool test __attribute__((unused)) = true; + + const std::wstring str(L"a"); + + wchar_t c = L'a'; + int res = str.compare(0, 1, &c, 1); + VERIFY ( !res ); + + wchar_t arr[] = L"a"; + res = str.compare(0, 1, arr, 1); + VERIFY ( !res ); + + const wchar_t carr[] = L"a"; + res = str.compare(0, 1, carr, 1); + VERIFY ( !res ); + + struct S { + operator wchar_t*() { return &c; } + operator std::wstring_view() { return L"!"; } + wchar_t c = L'a'; + }; + + res = str.compare(0, 1, S{}, 1); + VERIFY ( !res ); +} + int main() { test03(); + test04(); return 0; }