LWG2788 basic_string spurious use of a default constructible allocator
authorNina Dinka Ranns <dinka.ranns@gmail.com>
Thu, 30 May 2019 19:48:48 +0000 (19:48 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Thu, 30 May 2019 19:48:48 +0000 (20:48 +0100)
This only change the cxx11 basic_string, because COW strings don't
correctly propagate allocators anyway.

2019-05-30  Nina Dinka Ranns  <dinka.ranns@gmail.com>

LWG2788 basic_string spurious use of a default constructible allocator
* include/bits/basic_string.tcc [_GLIBCXX_USE_CXX11_ABI]
(basic_string::_M_replace_dispatch): Construct temporary string with
the current allocator.
* testsuite/21_strings/basic_string/allocator/char/lwg2788.cc: New.
* testsuite/21_strings/basic_string/allocator/wchar_t/lwg2788.cc: New.

From-SVN: r271789

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/basic_string.tcc
libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/lwg2788.cc [new file with mode: 0644]
libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/lwg2788.cc [new file with mode: 0644]

index 15a388c62d3243669bf19b84550c31eac8f29e25..cd535fe0887d46cc23487cf055f9af9101198a4d 100644 (file)
@@ -1,3 +1,12 @@
+2019-05-30  Nina Dinka Ranns  <dinka.ranns@gmail.com>
+
+       LWG2788 basic_string spurious use of a default constructible allocator
+       * include/bits/basic_string.tcc [_GLIBCXX_USE_CXX11_ABI]
+       (basic_string::_M_replace_dispatch): Construct temporary string with
+       the current allocator.
+       * testsuite/21_strings/basic_string/allocator/char/lwg2788.cc: New.
+       * testsuite/21_strings/basic_string/allocator/wchar_t/lwg2788.cc: New.
+
 2019-05-30  Jonathan Wakely  <jwakely@redhat.com>
 
        * doc/xml/manual/diagnostics.xml: Update list of headers that define
index e2315cb14678209b5a499b9bf5a22ff51bbf6c38..ab986a6c82711b357d116fd54e681072a8d3fb4b 100644 (file)
@@ -381,7 +381,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                          _InputIterator __k1, _InputIterator __k2,
                          std::__false_type)
       {
-       const basic_string __s(__k1, __k2);
+       // _GLIBCXX_RESOLVE_LIB_DEFECTS
+       // 2788. unintentionally require a default constructible allocator
+       const basic_string __s(__k1, __k2, this->get_allocator());
        const size_type __n1 = __i2 - __i1;
        return _M_replace(__i1 - begin(), __n1, __s._M_data(),
                          __s.size());
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/lwg2788.cc b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/lwg2788.cc
new file mode 100644 (file)
index 0000000..36dd414
--- /dev/null
@@ -0,0 +1,85 @@
+// { dg-do run { target c++11 } }
+// { dg-require-effective-target cxx11-abi }
+
+// 2019-05-27  Nina Dinka Ranns  <dinka.ranns@gmail.com>
+//
+// Copyright (C) 2015-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
+// <http://www.gnu.org/licenses/>.
+
+#include <string>
+#include <testsuite_hooks.h>
+
+using C = char;
+using traits = std::char_traits<C>;
+int constructCount = 0;
+
+static void resetCounter()
+{
+ constructCount = 0;
+}
+
+template <class Tp>
+struct TestAllocator
+{
+  typedef Tp value_type;
+  using size_type = unsigned;
+
+  TestAllocator() noexcept { constructCount++; }
+
+  template <class T>
+  TestAllocator(const TestAllocator<T>&) {}
+
+  Tp *allocate(std::size_t n)
+  { return std::allocator<Tp>().allocate(n); }
+
+  void deallocate(Tp *p, std::size_t n)
+  { std::allocator<Tp>().deallocate(p, n); }
+
+};
+
+template <class T, class U>
+bool operator==(const TestAllocator<T>&, const TestAllocator<U>&)
+{ return true; }
+template <class T, class U>
+bool operator!=(const TestAllocator<T>&, const TestAllocator<U>&)
+{ return false; }
+
+void test01()
+{
+  typedef TestAllocator<C> alloc_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+  test_type v1{alloc_type()};
+  std::string v2{"some_content"};
+
+  resetCounter();
+  v1.assign(v2.begin(),v2.end());
+  VERIFY( constructCount == 0);
+
+  v1.append(v2.begin(),v2.end());
+  VERIFY( constructCount == 0);
+
+  v1.insert(v1.begin(),v1.begin(),v1.end());
+  VERIFY( constructCount == 0);
+
+  v1.replace(v1.begin(),v1.end(),v1.begin(),v1.end());
+  VERIFY( constructCount == 0);
+}
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/lwg2788.cc b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/lwg2788.cc
new file mode 100644 (file)
index 0000000..8e26dd7
--- /dev/null
@@ -0,0 +1,85 @@
+// { dg-do run { target c++11 } }
+// { dg-require-effective-target cxx11-abi }
+
+// 2019-05-27  Nina Dinka Ranns  <dinka.ranns@gmail.com>
+//
+// Copyright (C) 2015-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
+// <http://www.gnu.org/licenses/>.
+
+#include <string>
+#include <testsuite_hooks.h>
+
+using C = wchar_t;
+using traits = std::char_traits<C>;
+int constructCount = 0;
+
+static void resetCounter()
+{
+ constructCount = 0;
+}
+
+template <class Tp>
+struct TestAllocator
+{
+  typedef Tp value_type;
+  using size_type = unsigned;
+
+  TestAllocator() noexcept { constructCount++; }
+
+  template <class T>
+  TestAllocator(const TestAllocator<T>&) {}
+
+  Tp *allocate(std::size_t n)
+  { return std::allocator<Tp>().allocate(n); }
+
+  void deallocate(Tp *p, std::size_t n)
+  { std::allocator<Tp>().deallocate(p, n); }
+
+};
+
+template <class T, class U>
+bool operator==(const TestAllocator<T>&, const TestAllocator<U>&)
+{ return true; }
+template <class T, class U>
+bool operator!=(const TestAllocator<T>&, const TestAllocator<U>&)
+{ return false; }
+
+void test01()
+{
+  typedef TestAllocator<C> alloc_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+  test_type v1{alloc_type()};
+  std::wstring v2{L"some_content"};
+
+  resetCounter();
+  v1.assign(v2.begin(),v2.end());
+  VERIFY( constructCount == 0);
+
+  v1.append(v2.begin(),v2.end());
+  VERIFY( constructCount == 0);
+
+  v1.insert(v1.begin(),v1.begin(),v1.end());
+  VERIFY( constructCount == 0);
+
+  v1.replace(v1.begin(),v1.end(),v1.begin(),v1.end());
+  VERIFY( constructCount == 0);
+}
+int main()
+{
+  test01();
+  return 0;
+}