[PATCH] PR libstdc++/87194 fix range insertion into maps and sets

Jonathan Wakely jwakely@redhat.com
Mon Sep 3 14:25:00 GMT 2018


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.

Tested x86_64-linux, committed to trunk.


-------------- next part --------------
commit 0e6c034d39cdccbda8ab27ea9dc7d3c02d51bf0d
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Mon Sep 3 14:45:31 2018 +0100

    PR libstdc++/87194 fix range insertion into maps and sets
    
    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.

diff --git a/libstdc++-v3/include/bits/stl_map.h b/libstdc++-v3/include/bits/stl_map.h
index 6ce9c3e1f60..0a4946ccb96 100644
--- a/libstdc++-v3/include/bits/stl_map.h
+++ b/libstdc++-v3/include/bits/stl_map.h
@@ -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
diff --git a/libstdc++-v3/include/bits/stl_multimap.h b/libstdc++-v3/include/bits/stl_multimap.h
index d4973870763..6d5c264e67f 100644
--- a/libstdc++-v3/include/bits/stl_multimap.h
+++ b/libstdc++-v3/include/bits/stl_multimap.h
@@ -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
       /**
diff --git a/libstdc++-v3/include/bits/stl_multiset.h b/libstdc++-v3/include/bits/stl_multiset.h
index ebac76731ed..f150471d07a 100644
--- a/libstdc++-v3/include/bits/stl_multiset.h
+++ b/libstdc++-v3/include/bits/stl_multiset.h
@@ -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
       /**
diff --git a/libstdc++-v3/include/bits/stl_set.h b/libstdc++-v3/include/bits/stl_set.h
index ee959d5fc1e..a8d10d5a788 100644
--- a/libstdc++-v3/include/bits/stl_set.h
+++ b/libstdc++-v3/include/bits/stl_set.h
@@ -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
       /**
diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h
index 09e8d758873..70d7483c7b1 100644
--- a/libstdc++-v3/include/bits/stl_tree.h
+++ b/libstdc++-v3/include/bits/stl_tree.h
@@ -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,16 +1172,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	_Alloc_node __an(*this);
 	return _M_insert_equal_(__pos, __x, __an);
       }
+
+      template<typename _InputIterator>
+	void
+	_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_range_equal(_InputIterator __first, _InputIterator __last)
+	{
+	  _Alloc_node __an(*this);
+	  for (; __first != __last; ++__first)
+	    _M_insert_equal_(end(), *__first, __an);
+	}
 #endif
 
-      template<typename _InputIterator>
-	void
-	_M_insert_unique(_InputIterator __first, _InputIterator __last);
-
-      template<typename _InputIterator>
-	void
-	_M_insert_equal(_InputIterator __first, _InputIterator __last);
-
     private:
       void
       _M_erase_aux(const_iterator __position);
@@ -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
index 00000000000..4daba408ded
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/map/modifiers/insert/87194.cc
@@ -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
index 00000000000..8a471015772
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/multimap/modifiers/insert/87194.cc
@@ -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
index 00000000000..c2a21d333d3
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/multiset/modifiers/insert/87194.cc
@@ -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
index 00000000000..14bf54e1d65
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/set/modifiers/insert/87194.cc
@@ -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();
+}


More information about the Libstdc++ mailing list