aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libstdc++-v3/include/bits/basic_string.h3
-rw-r--r--libstdc++-v3/include/bits/cow_string.h3
-rw-r--r--libstdc++-v3/testsuite/21_strings/basic_string/cons/char/103919.cc43
3 files changed, 47 insertions, 2 deletions
diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index 463cef2..a91ba51 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -766,7 +766,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
* @param __n The number of characters to copy from __t.
* @param __a Allocator to use.
*/
- template<typename _Tp, typename = _If_sv<_Tp, void>>
+ template<typename _Tp,
+ typename = enable_if_t<is_convertible_v<const _Tp&, __sv_type>>>
_GLIBCXX20_CONSTEXPR
basic_string(const _Tp& __t, size_type __pos, size_type __n,
const _Alloc& __a = _Alloc())
diff --git a/libstdc++-v3/include/bits/cow_string.h b/libstdc++-v3/include/bits/cow_string.h
index 8d0b772..84aab2f 100644
--- a/libstdc++-v3/include/bits/cow_string.h
+++ b/libstdc++-v3/include/bits/cow_string.h
@@ -690,7 +690,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @param __n The number of characters to copy from __t.
* @param __a Allocator to use.
*/
- template<typename _Tp, typename = _If_sv<_Tp, void>>
+ template<typename _Tp,
+ typename = enable_if_t<is_convertible_v<const _Tp&, __sv_type>>>
basic_string(const _Tp& __t, size_type __pos, size_type __n,
const _Alloc& __a = _Alloc())
: basic_string(_S_to_string_view(__t).substr(__pos, __n), __a) { }
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/103919.cc b/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/103919.cc
new file mode 100644
index 0000000..94400e3
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/103919.cc
@@ -0,0 +1,43 @@
+// { dg-do run { target c++17 } }
+
+#include <string>
+#include <new>
+#include <cstdlib>
+#include <cstring>
+#include <testsuite_hooks.h>
+
+std::size_t counter = 0;
+
+void* operator new(std::size_t n)
+{
+ counter += n;
+ return std::malloc(n);
+}
+
+void operator delete(void* p)
+{
+ std::free(p);
+}
+
+void operator delete(void* p, std::size_t)
+{
+ std::free(p);
+}
+
+int main()
+{
+ const char* str = "A string that is considerably longer than the SSO buffer";
+
+ // PR libstdc++/103919
+ // basic_string(const T&, size_t, size_t) constructor is overconstrained
+ counter = 0;
+ std::string s(str, 2, 6);
+ VERIFY( s == "string" );
+#if _GLIBCXX_USE_CXX11_ABI
+ // The string fits in the SSO buffer, so nothing is allocated.
+ VERIFY( counter == 0 );
+#else
+ // The COW string allocates a string rep and 7 chars.
+ VERIFY( counter < std::strlen(str) );
+#endif
+}