PR libstdc++/87194 fix range insertion into maps and sets
authorJonathan Wakely <jwakely@redhat.com>
Mon, 3 Sep 2018 14:25:25 +0000 (15:25 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Mon, 3 Sep 2018 14:25:25 +0000 (15:25 +0100)
Since C++11 range insertion and construction of maps and sets from a
pair of iterators only requires that the iterator's value_type is
convertible to the container's value_type (previously it had to be the
same).

This fixes the implementation to meet that relaxed requirement, by
defining a pair of overloads that either insert or emplace, depending on
the iterator's value_type. Instead of adding yet another overload of
_M_insert_unique and _M_insert_equal, the overloads taking iterators are
renamed to _M_insert_range_unique and _M_insert_range_equal.

PR libstdc++/87194
* include/bits/stl_map.h
(map::map(initializer_list<value_type>, const Compare&, const Alloc&))
(map::map(initializer_list<value_type>, const Alloc&))
(map::map(InputIterator, InputIterator, const Alloc&))
(map::map(InputIterator, InputIterator))
(map::map(InputIterator, InputIterator, const Compare&, const Alloc&))
(map::insert(InputIterator, InputIterator)):
Call _M_insert_range_unique instead of _M_insert_unique.
* include/bits/stl_multimap.h
(multimap::multimap(initializer_list<value_type>, const C&, const A&))
(multimap::multimap(initializer_list<value_type>, const A&))
(multimap::multimap(InputIterator, InputIterator, const A&))
(multimap::multimap(InputIterator, InputIterator))
(multimap::multimap(InputIterator, InputIterator, const C&, const A&))
(multimap::insert(InputIterator, InputIterator)): Call
_M_insert_range_equal instead of _M_insert_equal.
* include/bits/stl_multiset.h
(multiset::multiset(InputIterator, InputIterator))
(multiset::multiset(InputIterator, InputIterator, const C&, const A&))
(multiset::multiset(initializer_list<value_type>, const C&, const A&))
(multiset::multiset(initializer_list<value_type>, const A&))
(multiset::multiset(InputIterator, InputIterator, const A&))
(multiset::insert(InputIterator, InputIterator)): Call
_M_insert_range_equal instead of _M_insert_equal.
* include/bits/stl_set.h
(set::set(InputIterator, InputIterator))
(set::set(InputIterator, InputIterator, const Compare&, const Alloc&))
(set::set(initializer_list<value_type>, const Compare&, const Alloc&))
(set::set(initializer_list<value_type>, const Alloc&))
(set::set(InputIterator, InputIterator, const Alloc&))
(set::insert(InputIterator, InputIterator)):
Call _M_insert_range_unique instead of _M_insert_unique.
* include/bits/stl_tree.h
[__cplusplus >= 201103L] (_Rb_tree::__same_value_type): New alias
template for SFINAE constraints.
[__cplusplus >= 201103L] (_Rb_tree::_M_insert_range_unique): Pair of
constrained overloads that either insert or emplace, depending on
iterator's value_type.
[__cplusplus >= 201103L] (_Rb_tree::_M_insert_range_equal): Likewise.
[__cplusplus < 201103L] (_Rb_tree::_M_insert_range_unique)
(_Rb_tree::_M_insert_range_equal): New functions replacing range
versions of _M_insert_unique and _M_insert_equal.
(_Rb_tree::_M_insert_unique(_InputIterator, _InputIterator))
(_Rb_tree::_M_insert_equal(_InputIterator, _InputIterator)): Remove.
* testsuite/23_containers/map/modifiers/insert/87194.cc: New test.
* testsuite/23_containers/multimap/modifiers/insert/87194.cc: New test.
* testsuite/23_containers/multiset/modifiers/insert/87194.cc: New test.
* testsuite/23_containers/set/modifiers/insert/87194.cc: New test.

From-SVN: r264060

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/stl_map.h
libstdc++-v3/include/bits/stl_multimap.h
libstdc++-v3/include/bits/stl_multiset.h
libstdc++-v3/include/bits/stl_set.h
libstdc++-v3/include/bits/stl_tree.h
libstdc++-v3/testsuite/23_containers/map/modifiers/insert/87194.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/multimap/modifiers/insert/87194.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/multiset/modifiers/insert/87194.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/set/modifiers/insert/87194.cc [new file with mode: 0644]

index 763da9ea7782bd911ecc94e14a20ddbd90bb07f7..6a576baeed5135ce9f8184681049e4b9944e9ef3 100644 (file)
@@ -1,5 +1,55 @@
 2018-09-03  Jonathan Wakely  <jwakely@redhat.com>
 
+       PR libstdc++/87194
+       * include/bits/stl_map.h
+       (map::map(initializer_list<value_type>, const Compare&, const Alloc&))
+       (map::map(initializer_list<value_type>, const Alloc&))
+       (map::map(InputIterator, InputIterator, const Alloc&))
+       (map::map(InputIterator, InputIterator))
+       (map::map(InputIterator, InputIterator, const Compare&, const Alloc&))
+       (map::insert(InputIterator, InputIterator)):
+       Call _M_insert_range_unique instead of _M_insert_unique.
+       * include/bits/stl_multimap.h
+       (multimap::multimap(initializer_list<value_type>, const C&, const A&))
+       (multimap::multimap(initializer_list<value_type>, const A&))
+       (multimap::multimap(InputIterator, InputIterator, const A&))
+       (multimap::multimap(InputIterator, InputIterator))
+       (multimap::multimap(InputIterator, InputIterator, const C&, const A&))
+       (multimap::insert(InputIterator, InputIterator)): Call
+       _M_insert_range_equal instead of _M_insert_equal.
+       * include/bits/stl_multiset.h
+       (multiset::multiset(InputIterator, InputIterator))
+       (multiset::multiset(InputIterator, InputIterator, const C&, const A&))
+       (multiset::multiset(initializer_list<value_type>, const C&, const A&))
+       (multiset::multiset(initializer_list<value_type>, const A&))
+       (multiset::multiset(InputIterator, InputIterator, const A&))
+       (multiset::insert(InputIterator, InputIterator)): Call
+       _M_insert_range_equal instead of _M_insert_equal.
+       * include/bits/stl_set.h
+       (set::set(InputIterator, InputIterator))
+       (set::set(InputIterator, InputIterator, const Compare&, const Alloc&))
+       (set::set(initializer_list<value_type>, const Compare&, const Alloc&))
+       (set::set(initializer_list<value_type>, const Alloc&))
+       (set::set(InputIterator, InputIterator, const Alloc&))
+       (set::insert(InputIterator, InputIterator)):
+       Call _M_insert_range_unique instead of _M_insert_unique.
+       * include/bits/stl_tree.h
+       [__cplusplus >= 201103L] (_Rb_tree::__same_value_type): New alias
+       template for SFINAE constraints.
+       [__cplusplus >= 201103L] (_Rb_tree::_M_insert_range_unique): Pair of
+       constrained overloads that either insert or emplace, depending on
+       iterator's value_type.
+       [__cplusplus >= 201103L] (_Rb_tree::_M_insert_range_equal): Likewise.
+       [__cplusplus < 201103L] (_Rb_tree::_M_insert_range_unique)
+       (_Rb_tree::_M_insert_range_equal): New functions replacing range
+       versions of _M_insert_unique and _M_insert_equal.
+       (_Rb_tree::_M_insert_unique(_InputIterator, _InputIterator))
+       (_Rb_tree::_M_insert_equal(_InputIterator, _InputIterator)): Remove.
+       * testsuite/23_containers/map/modifiers/insert/87194.cc: New test.
+       * testsuite/23_containers/multimap/modifiers/insert/87194.cc: New test.
+       * testsuite/23_containers/multiset/modifiers/insert/87194.cc: New test.
+       * testsuite/23_containers/set/modifiers/insert/87194.cc: New test.
+
        PR libstdc++/78595
        * include/bits/stl_map.h (map::insert(_Pair&&))
        (map::insert(const_iterator, _Pair&&)): Do emplace instead of insert.
index 6ce9c3e1f601139bdb40252ab25e19388b898deb..0a4946ccb9617cbed80f7e917b105260f99623df 100644 (file)
@@ -227,7 +227,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
          const _Compare& __comp = _Compare(),
          const allocator_type& __a = allocator_type())
       : _M_t(__comp, _Pair_alloc_type(__a))
-      { _M_t._M_insert_unique(__l.begin(), __l.end()); }
+      { _M_t._M_insert_range_unique(__l.begin(), __l.end()); }
 
       /// Allocator-extended default constructor.
       explicit
@@ -247,14 +247,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       /// Allocator-extended initialier-list constructor.
       map(initializer_list<value_type> __l, const allocator_type& __a)
       : _M_t(_Pair_alloc_type(__a))
-      { _M_t._M_insert_unique(__l.begin(), __l.end()); }
+      { _M_t._M_insert_range_unique(__l.begin(), __l.end()); }
 
       /// Allocator-extended range constructor.
       template<typename _InputIterator>
        map(_InputIterator __first, _InputIterator __last,
            const allocator_type& __a)
        : _M_t(_Pair_alloc_type(__a))
-       { _M_t._M_insert_unique(__first, __last); }
+       { _M_t._M_insert_range_unique(__first, __last); }
 #endif
 
       /**
@@ -270,7 +270,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       template<typename _InputIterator>
        map(_InputIterator __first, _InputIterator __last)
        : _M_t()
-       { _M_t._M_insert_unique(__first, __last); }
+       { _M_t._M_insert_range_unique(__first, __last); }
 
       /**
        *  @brief  Builds a %map from a range.
@@ -289,7 +289,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
            const _Compare& __comp,
            const allocator_type& __a = allocator_type())
        : _M_t(__comp, _Pair_alloc_type(__a))
-       { _M_t._M_insert_unique(__first, __last); }
+       { _M_t._M_insert_range_unique(__first, __last); }
 
 #if __cplusplus >= 201103L
       /**
@@ -889,7 +889,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       template<typename _InputIterator>
        void
        insert(_InputIterator __first, _InputIterator __last)
-       { _M_t._M_insert_unique(__first, __last); }
+       { _M_t._M_insert_range_unique(__first, __last); }
 
 #if __cplusplus > 201402L
 #define __cpp_lib_map_insertion 201411
index d49738707630d4b97a7003eb773c5df031b75fa7..6d5c264e67fa6fde5247b8bca1a79385e9878136 100644 (file)
@@ -224,7 +224,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
               const _Compare& __comp = _Compare(),
               const allocator_type& __a = allocator_type())
       : _M_t(__comp, _Pair_alloc_type(__a))
-      { _M_t._M_insert_equal(__l.begin(), __l.end()); }
+      { _M_t._M_insert_range_equal(__l.begin(), __l.end()); }
 
       /// Allocator-extended default constructor.
       explicit
@@ -244,14 +244,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       /// Allocator-extended initialier-list constructor.
       multimap(initializer_list<value_type> __l, const allocator_type& __a)
       : _M_t(_Pair_alloc_type(__a))
-      { _M_t._M_insert_equal(__l.begin(), __l.end()); }
+      { _M_t._M_insert_range_equal(__l.begin(), __l.end()); }
 
       /// Allocator-extended range constructor.
       template<typename _InputIterator>
        multimap(_InputIterator __first, _InputIterator __last,
                 const allocator_type& __a)
        : _M_t(_Pair_alloc_type(__a))
-       { _M_t._M_insert_equal(__first, __last); }
+       { _M_t._M_insert_range_equal(__first, __last); }
 #endif
 
       /**
@@ -266,7 +266,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       template<typename _InputIterator>
        multimap(_InputIterator __first, _InputIterator __last)
        : _M_t()
-       { _M_t._M_insert_equal(__first, __last); }
+       { _M_t._M_insert_range_equal(__first, __last); }
 
       /**
        *  @brief  Builds a %multimap from a range.
@@ -284,7 +284,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
                 const _Compare& __comp,
                 const allocator_type& __a = allocator_type())
        : _M_t(__comp, _Pair_alloc_type(__a))
-       { _M_t._M_insert_equal(__first, __last); }
+       { _M_t._M_insert_range_equal(__first, __last); }
 
 #if __cplusplus >= 201103L
       /**
@@ -609,7 +609,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       template<typename _InputIterator>
        void
        insert(_InputIterator __first, _InputIterator __last)
-       { _M_t._M_insert_equal(__first, __last); }
+       { _M_t._M_insert_range_equal(__first, __last); }
 
 #if __cplusplus >= 201103L
       /**
index ebac76731edda06426f8e500d57f47f681acd2a2..f150471d07a2a26db4cf5f25b6b9c3ba84245f14 100644 (file)
@@ -186,7 +186,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       template<typename _InputIterator>
        multiset(_InputIterator __first, _InputIterator __last)
        : _M_t()
-       { _M_t._M_insert_equal(__first, __last); }
+       { _M_t._M_insert_range_equal(__first, __last); }
 
       /**
        *  @brief  Builds a %multiset from a range.
@@ -204,7 +204,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
                 const _Compare& __comp,
                 const allocator_type& __a = allocator_type())
        : _M_t(__comp, _Key_alloc_type(__a))
-       { _M_t._M_insert_equal(__first, __last); }
+       { _M_t._M_insert_range_equal(__first, __last); }
 
       /**
        *  @brief  %Multiset copy constructor.
@@ -240,7 +240,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
               const _Compare& __comp = _Compare(),
               const allocator_type& __a = allocator_type())
       : _M_t(__comp, _Key_alloc_type(__a))
-      { _M_t._M_insert_equal(__l.begin(), __l.end()); }
+      { _M_t._M_insert_range_equal(__l.begin(), __l.end()); }
 
       /// Allocator-extended default constructor.
       explicit
@@ -260,14 +260,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       /// Allocator-extended initialier-list constructor.
       multiset(initializer_list<value_type> __l, const allocator_type& __a)
       : _M_t(_Key_alloc_type(__a))
-      { _M_t._M_insert_equal(__l.begin(), __l.end()); }
+      { _M_t._M_insert_range_equal(__l.begin(), __l.end()); }
 
       /// Allocator-extended range constructor.
       template<typename _InputIterator>
        multiset(_InputIterator __first, _InputIterator __last,
                 const allocator_type& __a)
        : _M_t(_Key_alloc_type(__a))
-       { _M_t._M_insert_equal(__first, __last); }
+       { _M_t._M_insert_range_equal(__first, __last); }
 
       /**
        *  The dtor only erases the elements, and note that if the elements
@@ -549,7 +549,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       template<typename _InputIterator>
        void
        insert(_InputIterator __first, _InputIterator __last)
-       { _M_t._M_insert_equal(__first, __last); }
+       { _M_t._M_insert_range_equal(__first, __last); }
 
 #if __cplusplus >= 201103L
       /**
index ee959d5fc1e93e21084547e9f13df8837ce94701..a8d10d5a7884037465330761ab6948272adea394 100644 (file)
@@ -190,7 +190,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       template<typename _InputIterator>
        set(_InputIterator __first, _InputIterator __last)
        : _M_t()
-       { _M_t._M_insert_unique(__first, __last); }
+       { _M_t._M_insert_range_unique(__first, __last); }
 
       /**
        *  @brief  Builds a %set from a range.
@@ -209,7 +209,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
            const _Compare& __comp,
            const allocator_type& __a = allocator_type())
        : _M_t(__comp, _Key_alloc_type(__a))
-       { _M_t._M_insert_unique(__first, __last); }
+       { _M_t._M_insert_range_unique(__first, __last); }
 
       /**
        *  @brief  %Set copy constructor.
@@ -244,7 +244,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
          const _Compare& __comp = _Compare(),
          const allocator_type& __a = allocator_type())
       : _M_t(__comp, _Key_alloc_type(__a))
-      { _M_t._M_insert_unique(__l.begin(), __l.end()); }
+      { _M_t._M_insert_range_unique(__l.begin(), __l.end()); }
 
       /// Allocator-extended default constructor.
       explicit
@@ -264,14 +264,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       /// Allocator-extended initialier-list constructor.
       set(initializer_list<value_type> __l, const allocator_type& __a)
       : _M_t(_Key_alloc_type(__a))
-      { _M_t._M_insert_unique(__l.begin(), __l.end()); }
+      { _M_t._M_insert_range_unique(__l.begin(), __l.end()); }
 
       /// Allocator-extended range constructor.
       template<typename _InputIterator>
        set(_InputIterator __first, _InputIterator __last,
            const allocator_type& __a)
        : _M_t(_Key_alloc_type(__a))
-       { _M_t._M_insert_unique(__first, __last); }
+       { _M_t._M_insert_range_unique(__first, __last); }
 
       /**
        *  The dtor only erases the elements, and note that if the elements
@@ -564,7 +564,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       template<typename _InputIterator>
        void
        insert(_InputIterator __first, _InputIterator __last)
-       { _M_t._M_insert_unique(__first, __last); }
+       { _M_t._M_insert_range_unique(__first, __last); }
 
 #if __cplusplus >= 201103L
       /**
index 09e8d758873ab5d0b700a196e6d6fe3879f133b4..70d7483c7b17c4077e2ca212afb672c85cc0209d 100644 (file)
@@ -1104,6 +1104,45 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       template<typename... _Args>
        iterator
        _M_emplace_hint_equal(const_iterator __pos, _Args&&... __args);
+
+      template<typename _Iter>
+       using __same_value_type
+         = is_same<value_type, typename iterator_traits<_Iter>::value_type>;
+
+      template<typename _InputIterator>
+       __enable_if_t<__same_value_type<_InputIterator>::value>
+       _M_insert_range_unique(_InputIterator __first, _InputIterator __last)
+       {
+         _Alloc_node __an(*this);
+         for (; __first != __last; ++__first)
+           _M_insert_unique_(end(), *__first, __an);
+       }
+
+      template<typename _InputIterator>
+       __enable_if_t<!__same_value_type<_InputIterator>::value>
+       _M_insert_range_unique(_InputIterator __first, _InputIterator __last)
+       {
+         for (; __first != __last; ++__first)
+           _M_emplace_unique(*__first);
+       }
+
+      template<typename _InputIterator>
+       __enable_if_t<__same_value_type<_InputIterator>::value>
+       _M_insert_range_equal(_InputIterator __first, _InputIterator __last)
+       {
+         _Alloc_node __an(*this);
+         for (; __first != __last; ++__first)
+           _M_insert_equal_(end(), *__first, __an);
+       }
+
+      template<typename _InputIterator>
+       __enable_if_t<!__same_value_type<_InputIterator>::value>
+       _M_insert_range_equal(_InputIterator __first, _InputIterator __last)
+       {
+         _Alloc_node __an(*this);
+         for (; __first != __last; ++__first)
+           _M_emplace_equal(*__first);
+       }
 #else
       pair<iterator, bool>
       _M_insert_unique(const value_type& __x);
@@ -1133,15 +1172,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        _Alloc_node __an(*this);
        return _M_insert_equal_(__pos, __x, __an);
       }
-#endif
 
       template<typename _InputIterator>
        void
-       _M_insert_unique(_InputIterator __first, _InputIterator __last);
+       _M_insert_range_unique(_InputIterator __first, _InputIterator __last)
+       {
+         _Alloc_node __an(*this);
+         for (; __first != __last; ++__first)
+           _M_insert_unique_(end(), *__first, __an);
+       }
 
       template<typename _InputIterator>
        void
-       _M_insert_equal(_InputIterator __first, _InputIterator __last);
+       _M_insert_range_equal(_InputIterator __first, _InputIterator __last)
+       {
+         _Alloc_node __an(*this);
+         for (; __first != __last; ++__first)
+           _M_insert_equal_(end(), *__first, __an);
+       }
+#endif
 
     private:
       void
@@ -2471,29 +2520,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       }
 #endif
 
-  template<typename _Key, typename _Val, typename _KoV,
-          typename _Cmp, typename _Alloc>
-    template<class _II>
-      void
-      _Rb_tree<_Key, _Val, _KoV, _Cmp, _Alloc>::
-      _M_insert_unique(_II __first, _II __last)
-      {
-       _Alloc_node __an(*this);
-       for (; __first != __last; ++__first)
-         _M_insert_unique_(end(), *__first, __an);
-      }
-
-  template<typename _Key, typename _Val, typename _KoV,
-          typename _Cmp, typename _Alloc>
-    template<class _II>
-      void
-      _Rb_tree<_Key, _Val, _KoV, _Cmp, _Alloc>::
-      _M_insert_equal(_II __first, _II __last)
-      {
-       _Alloc_node __an(*this);
-       for (; __first != __last; ++__first)
-         _M_insert_equal_(end(), *__first, __an);
-      }
 
   template<typename _Key, typename _Val, typename _KeyOfValue,
           typename _Compare, typename _Alloc>
diff --git a/libstdc++-v3/testsuite/23_containers/map/modifiers/insert/87194.cc b/libstdc++-v3/testsuite/23_containers/map/modifiers/insert/87194.cc
new file mode 100644 (file)
index 0000000..4daba40
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright (C) 2018 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++11 } }
+
+#include <map>
+#include <iterator>
+#include <testsuite_hooks.h>
+
+struct S
+{
+  operator std::pair<const int, int>() &&
+  { int i = val; val = 0; return {i, 0}; }
+
+  int val;
+};
+
+void
+test01()
+{
+  S a[3] = { {1}, {2}, {3} };
+  std::map<int, int> s;
+  s.insert(std::make_move_iterator(a), std::make_move_iterator(a+3));
+  VERIFY( s.size() == 3 );
+  VERIFY( s.find(0) == s.end() );
+}
+
+int
+main()
+{
+  test01();
+}
diff --git a/libstdc++-v3/testsuite/23_containers/multimap/modifiers/insert/87194.cc b/libstdc++-v3/testsuite/23_containers/multimap/modifiers/insert/87194.cc
new file mode 100644 (file)
index 0000000..8a47101
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright (C) 2018 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++11 } }
+
+#include <map>
+#include <iterator>
+#include <testsuite_hooks.h>
+
+struct S
+{
+  operator std::pair<const int, int>() &&
+  { int i = val; val = 0; return {i, 0}; }
+
+  int val;
+};
+
+void
+test01()
+{
+  S a[3] = { {1}, {2}, {3} };
+  std::multimap<int, int> s;
+  s.insert(std::make_move_iterator(a), std::make_move_iterator(a+3));
+  VERIFY( s.size() == 3 );
+  VERIFY( s.find(0) == s.end() );
+}
+
+int
+main()
+{
+  test01();
+}
diff --git a/libstdc++-v3/testsuite/23_containers/multiset/modifiers/insert/87194.cc b/libstdc++-v3/testsuite/23_containers/multiset/modifiers/insert/87194.cc
new file mode 100644 (file)
index 0000000..c2a21d3
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright (C) 2018 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++11 } }
+
+#include <set>
+#include <iterator>
+#include <testsuite_hooks.h>
+
+struct S {
+  S(int v) : val(v) {}
+  operator int() && { int i = val; val = 0; return i; }
+  int val;
+};
+
+void
+test01()
+{
+  S a[3] = { {1}, {2}, {3} };
+  std::multiset<int> s;
+  s.insert(std::make_move_iterator(a), std::make_move_iterator(a+3));
+  VERIFY( s.size() == 3 );
+  VERIFY( s.find(0) == s.end() );
+}
+
+int
+main()
+{
+  test01();
+}
diff --git a/libstdc++-v3/testsuite/23_containers/set/modifiers/insert/87194.cc b/libstdc++-v3/testsuite/23_containers/set/modifiers/insert/87194.cc
new file mode 100644 (file)
index 0000000..14bf54e
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright (C) 2018 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++11 } }
+
+#include <set>
+#include <iterator>
+#include <testsuite_hooks.h>
+
+struct S {
+  S(int v) : val(v) {}
+  operator int() && { int i = val; val = 0; return i; }
+  int val;
+};
+
+void
+test01()
+{
+  S a[3] = { {1}, {2}, {3} };
+  std::set<int> s;
+  s.insert(std::make_move_iterator(a), std::make_move_iterator(a+3));
+  VERIFY( s.size() == 3 );
+  VERIFY( s.find(0) == s.end() );
+}
+
+int
+main()
+{
+  test01();
+}