re PR libstdc++/57779 (vector insert fails to diagnose iterators pointing into *this...
authorFrançois Dumont <fdumont@gcc.gnu.org>
Thu, 1 Aug 2013 19:54:46 +0000 (19:54 +0000)
committerFrançois Dumont <fdumont@gcc.gnu.org>
Thu, 1 Aug 2013 19:54:46 +0000 (19:54 +0000)
2013-08-01  François Dumont  <fdumont@gcc.gnu.org>

PR libstdc++/57779
* include/debug/formatter.h (_Debug_msg_id): Add
__msg_insert_itself_range entry.
* include/debug/functions.h (_Insert_range_from_self_is_safe<>):
New, indicate container types supporting self range insertion in
GNU implementation.
(__foreign_iterator): New, check if an iterator points to a given
sequence.
* include/debug/macros.h (__glibcxx_check_insert_range): Add check
using __foreign_iterator.
(__gibcxx_check_insert_range_after): Likewise.
* include/debug/string (_Insert_range_from_self_is_safe<>):
Partially specialized to mark __gnu_debug::basic_string<> as
supporting self range insert.
* include/debug/list (_Insert_range_from_self_is_safe<>):
Partially specialized to mark std::list as supporting self range
insert if _GLIBCXX_DEBUG_PEDANTIC is not defined.
* include/debug/forward_list (_Insert_range_from_self_is_safe<>):
Likewise.
* src/c++11/debug.cc (_S_debug_messages): Add
__msg_insert_itself_range_entry message.
(_Error_formatter::_Parameter::_M_print_description): Display
iterator sequence address rather than sequence address when the
parameter type is an iterator.
(_Error_formatter::_M_print_word): Enhance behavior when
displaying a word with an appended '\n'.
* testsuite/util/debug/checks.h (check_insert4<>): New.
* testsuite/23_containers/deque/debug/insert5_neg.cc: New.
* testsuite/23_containers/vector/debug/insert5_neg.cc: Likewise.
* testsuite/23_containers/vector/debug/insert6_neg.cc: Likewise.
* testsuite/23_containers/vector/debug/57779_neg.cc: Likewise.
* testsuite/23_containers/list/debug/insert5_neg.cc: Likewise.
* testsuite/23_containers/forward_list/debug/insert_after4_neg.cc:
Likewise.

From-SVN: r201416

15 files changed:
libstdc++-v3/ChangeLog
libstdc++-v3/include/debug/formatter.h
libstdc++-v3/include/debug/forward_list
libstdc++-v3/include/debug/functions.h
libstdc++-v3/include/debug/list
libstdc++-v3/include/debug/macros.h
libstdc++-v3/include/debug/string
libstdc++-v3/src/c++11/debug.cc
libstdc++-v3/testsuite/23_containers/deque/debug/insert5_neg.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/forward_list/debug/insert_after4_neg.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/list/debug/insert5_neg.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/vector/debug/57779_neg.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/vector/debug/insert5_neg.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/vector/debug/insert6_neg.cc [new file with mode: 0644]
libstdc++-v3/testsuite/util/debug/checks.h

index 4eea924f028c087f4808667c7e75da1ad10f7e95..651f8b6a9747b8babad51de0812cd53aea64916c 100644 (file)
@@ -1,3 +1,40 @@
+2013-08-01  François Dumont  <fdumont@gcc.gnu.org>
+
+       PR libstdc++/57779
+       * include/debug/formatter.h (_Debug_msg_id): Add
+       __msg_insert_itself_range entry.
+       * include/debug/functions.h (_Insert_range_from_self_is_safe<>):
+       New, indicate container types supporting self range insertion in
+       GNU implementation.
+       (__foreign_iterator): New, check if an iterator points to a given
+       sequence.
+       * include/debug/macros.h (__glibcxx_check_insert_range): Add check
+       using __foreign_iterator.
+       (__gibcxx_check_insert_range_after): Likewise.
+       * include/debug/string (_Insert_range_from_self_is_safe<>):
+       Partially specialized to mark __gnu_debug::basic_string<> as
+       supporting self range insert.
+       * include/debug/list (_Insert_range_from_self_is_safe<>):
+       Partially specialized to mark std::list as supporting self range
+       insert if _GLIBCXX_DEBUG_PEDANTIC is not defined.
+       * include/debug/forward_list (_Insert_range_from_self_is_safe<>):
+       Likewise.
+       * src/c++11/debug.cc (_S_debug_messages): Add
+       __msg_insert_itself_range_entry message.
+       (_Error_formatter::_Parameter::_M_print_description): Display
+       iterator sequence address rather than sequence address when the
+       parameter type is an iterator.
+       (_Error_formatter::_M_print_word): Enhance behavior when
+       displaying a word with an appended '\n'.
+       * testsuite/util/debug/checks.h (check_insert4<>): New.
+       * testsuite/23_containers/deque/debug/insert5_neg.cc: New.
+       * testsuite/23_containers/vector/debug/insert5_neg.cc: Likewise.
+       * testsuite/23_containers/vector/debug/insert6_neg.cc: Likewise.
+       * testsuite/23_containers/vector/debug/57779_neg.cc: Likewise.
+       * testsuite/23_containers/list/debug/insert5_neg.cc: Likewise.
+       * testsuite/23_containers/forward_list/debug/insert_after4_neg.cc:
+       Likewise.
+
 2013-08-01  Fabien Chêne  <fabien@gcc.gnu.org>
 
        PR c++/54537
index 4c65e1ac4da3f889b5a3a9209a95cb9243e8b5d4..15dd8d7379714fa9f5e6a661c3b9aed201c0114c 100644 (file)
@@ -114,7 +114,9 @@ namespace __gnu_debug
     // unordered container buckets
     __msg_bucket_index_oob,
     __msg_valid_load_factor,
-    __msg_equal_allocs
+    // others
+    __msg_equal_allocs,
+    __msg_insert_range_from_self
   };
 
   class _Error_formatter
index 90a2e9c3e657a5b76d12013e9eb37e9215e2ca49..4c8ac371c9410c894c5f40b2e622fbef74849196 100644 (file)
@@ -796,6 +796,13 @@ namespace __gnu_debug
       _S_Is_Beginnest(_BaseIt __it, const _Sequence* __seq)
       { return _S_Is(__it, __seq); }
     };
+
+#ifndef _GLIBCXX_DEBUG_PEDANTIC
+  template<class _Tp, class _Alloc>
+    struct _Insert_range_from_self_is_safe<
+      std::__debug::forward_list<_Tp, _Alloc> >
+      { enum { __value = 1 }; };
+#endif
 }
 
 #endif
index 3f16098185c169eded5cbf29fd373c1c85267899..87478c6fbc15b2b8c954be04ec0f895b1e3706c7 100644 (file)
 #include <bits/c++config.h>
 #include <bits/stl_iterator_base_types.h> // for iterator_traits, categories and
                                          // _Iter_base
-#include <bits/cpp_type_traits.h>         // for __is_integer
+#include <bits/cpp_type_traits.h>        // for __is_integer
+#if __cplusplus >= 201103L
+# include <bits/stl_function.h>                  // for less and greater_equal
+# include <type_traits>                          // for common_type
+#endif
 #include <debug/formatter.h>
 
 namespace __gnu_debug
@@ -40,6 +44,10 @@ namespace __gnu_debug
   template<typename _Iterator, typename _Sequence>
     class _Safe_iterator;
 
+  template<typename _Sequence>
+    struct _Insert_range_from_self_is_safe
+    { enum { __value = 0 }; };
+
   // An arbitrary iterator pointer is not singular.
   inline bool
   __check_singular_aux(const void*) { return false; }
@@ -162,6 +170,123 @@ namespace __gnu_debug
       return __first;
     }
 
+#if __cplusplus >= 201103L
+  template<typename _Iterator, typename _Sequence,
+          typename _InputIterator,
+          typename _PointerType1,
+          typename _PointerType2>
+    inline bool
+    __foreign_iterator_aux4(const _Safe_iterator<_Iterator, _Sequence>& __it,
+                           _InputIterator __other,
+                           _PointerType1, _PointerType2)
+    {
+      typedef typename std::common_type<_PointerType1,
+                                       _PointerType2>::type _PointerType;
+      std::less<_PointerType> __l;
+      std::greater_equal<_PointerType> __ge;
+
+      return
+       __l(std::addressof(*__other),
+           std::addressof(*(__it._M_get_sequence()->_M_base().begin())))
+       || __ge(std::addressof(*__other),
+               std::addressof(*(__it._M_get_sequence()->_M_base().end() - 1)) + 1);
+      
+    }
+                         
+  template<typename _Iterator, typename _Sequence, typename _InputIterator>
+    inline bool
+    __foreign_iterator_aux3(const _Safe_iterator<_Iterator, _Sequence>& __it,
+                           _InputIterator __other,
+                           std::true_type)
+    {
+      // Only containers with all elements in contiguous memory can have their
+      // elements passed through pointers.
+      // Arithmetics is here just to make sure we are not dereferencing
+      // past-the-end iterator.
+      if (__it._M_get_sequence()->_M_base().begin()
+         != __it._M_get_sequence()->_M_base().end())
+       if (std::__addressof(*(__it._M_get_sequence()->_M_base().end() - 1))
+           - std::__addressof(*(__it._M_get_sequence()->_M_base().begin()))
+           == __it._M_get_sequence()->size() - 1)
+         return __foreign_iterator_aux4(__it, __other,
+                       std::addressof(*(__it._M_get_sequence()->_M_base().begin())),
+                       std::addressof(*__other));
+      return true;
+    }
+                          
+  /* Fallback overload for which we can't say, assume it is valid. */
+  template<typename _Iterator, typename _Sequence, typename _InputIterator>
+    inline bool
+    __foreign_iterator_aux3(const _Safe_iterator<_Iterator, _Sequence>& __it,
+                           _InputIterator __other,
+                           std::false_type)
+    { return true; }
+#endif
+                          
+  /** Checks that iterators do not belong to the same sequence. */
+  template<typename _Iterator, typename _Sequence, typename _OtherIterator>
+    inline bool
+    __foreign_iterator_aux2(const _Safe_iterator<_Iterator, _Sequence>& __it,
+               const _Safe_iterator<_OtherIterator, _Sequence>& __other,
+               std::input_iterator_tag)
+    { return __it._M_get_sequence() != __other._M_get_sequence(); }
+                          
+#if __cplusplus >= 201103L
+  /* This overload detects when passing pointers to the contained elements rather
+     than using iterators.
+   */
+  template<typename _Iterator, typename _Sequence, typename _InputIterator>
+    inline bool
+    __foreign_iterator_aux2(const _Safe_iterator<_Iterator, _Sequence>& __it,
+                           _InputIterator __other,
+                           std::random_access_iterator_tag)
+    {
+      typedef typename _Sequence::const_iterator _ItType;
+      typedef typename std::iterator_traits<_ItType>::reference _Ref;
+      return __foreign_iterator_aux3(__it, __other,
+                                    std::is_lvalue_reference<_Ref>());
+    }
+#endif
+                          
+  /* Fallback overload for which we can't say, assume it is valid. */
+  template<typename _Iterator, typename _Sequence, typename _InputIterator>
+    inline bool
+    __foreign_iterator_aux2(const _Safe_iterator<_Iterator, _Sequence>&,
+                          _InputIterator,
+                          std::input_iterator_tag)
+    { return true; }
+                          
+  template<typename _Iterator, typename _Sequence,
+          typename _Integral>
+    inline bool
+    __foreign_iterator_aux(const _Safe_iterator<_Iterator, _Sequence>& __it,
+                          _Integral __other,
+                          std::__true_type)
+    { return true; }
+
+  template<typename _Iterator, typename _Sequence,
+          typename _InputIterator>
+    inline bool
+    __foreign_iterator_aux(const _Safe_iterator<_Iterator, _Sequence>& __it,
+                          _InputIterator __other,
+                          std::__false_type)
+    {
+      return
+       _Insert_range_from_self_is_safe<_Sequence>::__value
+       || __foreign_iterator_aux2(__it, __other,
+                                  std::__iterator_category(__it));
+    }
+
+  template<typename _Iterator, typename _Sequence,
+          typename _InputIterator>
+    inline bool
+    __foreign_iterator(const _Safe_iterator<_Iterator, _Sequence>& __it,
+                      _InputIterator __other)
+    {
+      typedef typename std::__is_integer<_InputIterator>::__type _Integral;
+      return __foreign_iterator_aux(__it, __other, _Integral());
+    }
+
   /** Checks that __s is non-NULL or __n == 0, and then returns __s. */
   template<typename _CharT, typename _Integer>
     inline const _CharT*
index 1ae8507ca864e73ab6e8687883c388c25fc2f726..fd00b0148a9dd3bf1c3027af3ae37ed74a36cbed 100644 (file)
@@ -791,4 +791,13 @@ namespace __debug
 } // namespace __debug
 } // namespace std
 
+#ifndef _GLIBCXX_DEBUG_PEDANTIC
+namespace __gnu_debug
+{
+  template<class _Tp, class _Alloc>
+    struct _Insert_range_from_self_is_safe<std::__debug::list<_Tp, _Alloc> >
+    { enum { __value = 1 }; };
+}
+#endif
+
 #endif
index 26732c9e3e2267c32d0442a4b50787d324d09c49..521e8c0fa4761f1266087f7d180f010356d1a999 100644 (file)
@@ -72,11 +72,11 @@ _GLIBCXX_DEBUG_VERIFY(_First != _Last,                                      \
 */
 #define __glibcxx_check_insert(_Position)                              \
 _GLIBCXX_DEBUG_VERIFY(!_Position._M_singular(),                                \
-                     _M_message(__gnu_debug::__msg_insert_singular) \
+                     _M_message(__gnu_debug::__msg_insert_singular)    \
                      ._M_sequence(*this, "this")                       \
                      ._M_iterator(_Position, #_Position));             \
 _GLIBCXX_DEBUG_VERIFY(_Position._M_attached_to(this),                  \
-                     _M_message(__gnu_debug::__msg_insert_different) \
+                     _M_message(__gnu_debug::__msg_insert_different)   \
                      ._M_sequence(*this, "this")                       \
                      ._M_iterator(_Position, #_Position))
 
@@ -101,15 +101,16 @@ _GLIBCXX_DEBUG_VERIFY(!_Position._M_is_end(),                             \
  *  that it reference the sequence we are inserting into, and that the
  *  iterator range [_First, Last) is a valid (possibly empty)
  *  range. Note that this macro is only valid when the container is a
- *  _Safe_sequence and the iterator is a _Safe_iterator.
- *
- *  @todo We would like to be able to check for noninterference of
- *  _Position and the range [_First, _Last), but that can't (in
- *  general) be done.
+ *  _Safe_sequence and the _Position iterator is a _Safe_iterator.
 */
 #define __glibcxx_check_insert_range(_Position,_First,_Last)           \
 __glibcxx_check_valid_range(_First,_Last);                             \
-__glibcxx_check_insert(_Position)
+__glibcxx_check_insert(_Position);                                     \
+_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__foreign_iterator(_Position,_First),\
+                     _M_message(__gnu_debug::__msg_insert_range_from_self)\
+                     ._M_iterator(_First, #_First)                     \
+                     ._M_iterator(_Last, #_Last)                       \
+                     ._M_sequence(*this, "this"))
 
 /** Verify that we can insert the values in the iterator range
  *  [_First, _Last) into *this after the iterator _Position.  Insertion
@@ -126,7 +127,12 @@ __glibcxx_check_insert(_Position)
 */
 #define __glibcxx_check_insert_range_after(_Position,_First,_Last)     \
 __glibcxx_check_valid_range(_First,_Last);                             \
-__glibcxx_check_insert_after(_Position)
+__glibcxx_check_insert_after(_Position);                                       \
+_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__foreign_iterator(_Position,_First),\
+                     _M_message(__gnu_debug::__msg_insert_range_from_self)\
+                     ._M_iterator(_First, #_First)                     \
+                     ._M_iterator(_Last, #_Last)                       \
+                     ._M_sequence(*this, "this"))
 
 /** Verify that we can erase the element referenced by the iterator
  * _Position. We can erase the element if the _Position iterator is
@@ -332,7 +338,7 @@ _GLIBCXX_DEBUG_VERIFY(_F > 0.0f,                                    \
                      _M_message(__gnu_debug::__msg_valid_load_factor)  \
                       ._M_sequence(*this, "this"))
 
-#define __glibcxx_check_equal_allocs(_Other)                   \
+#define __glibcxx_check_equal_allocs(_Other)                           \
 _GLIBCXX_DEBUG_VERIFY(this->get_allocator() == _Other.get_allocator(), \
                      _M_message(__gnu_debug::__msg_equal_allocs)       \
                      ._M_sequence(*this, "this"))
index 8a5bf9b0367f27eae2604b4d369ad389b87cd367..9e856c1ee8c54cc5f528b59534d944946254b999 100644 (file)
@@ -1156,6 +1156,11 @@ namespace __gnu_debug
   typedef basic_string<wchar_t> wstring;
 #endif
 
+  template<typename _CharT, typename _Traits, typename _Allocator>
+    struct _Insert_range_from_self_is_safe<
+      __gnu_debug::basic_string<_CharT, _Traits, _Allocator> >
+      { enum { __value = 1 }; };
+
 } // namespace __gnu_debug
 
 #endif
index 3655f392f7a4963229df9577c4f6e61f47a57de1..260009c1172dec3f589d50ce8a85addfd0ce4299 100644 (file)
@@ -181,7 +181,8 @@ namespace __gnu_debug
     "attempt to access container with out-of-bounds bucket index %2;,"
     " container only holds %3; buckets",
     "load factor shall be positive",
-    "allocators must be equal"
+    "allocators must be equal",
+    "attempt to insert with an iterator range [%1.name;, %2.name;) from this container"
   };
 
   void
@@ -695,7 +696,7 @@ namespace __gnu_debug
              }
            
            __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p\n", 
-                                       _M_variant._M_sequence._M_address);
+                                       _M_variant._M_iterator._M_sequence);
            __formatter->_M_print_word(__buf);
          }
        __formatter->_M_print_word("}\n");
@@ -808,8 +809,11 @@ namespace __gnu_debug
     if (__length == 0)
       return;
     
-    if ((_M_column + __length < _M_max_length)
-       || (__length >= _M_max_length && _M_column == 1)) 
+    size_t __visual_length
+      = __word[__length - 1] == '\n' ? __length - 1 : __length;
+    if (__visual_length == 0
+       || (_M_column + __visual_length < _M_max_length)
+       || (__visual_length >= _M_max_length && _M_column == 1)) 
       {
        // If this isn't the first line, indent
        if (_M_column == 1 && !_M_first_line)
@@ -823,17 +827,17 @@ namespace __gnu_debug
          }
        
        fprintf(stderr, "%s", __word);
-       _M_column += __length;
        
        if (__word[__length - 1] == '\n') 
          {
            _M_first_line = false;
            _M_column = 1;
          }
+       else
+         _M_column += __length;
       }
     else
       {
-       _M_column = 1;
        _M_print_word("\n");
        _M_print_word(__word);
       }
diff --git a/libstdc++-v3/testsuite/23_containers/deque/debug/insert5_neg.cc b/libstdc++-v3/testsuite/23_containers/deque/debug/insert5_neg.cc
new file mode 100644 (file)
index 0000000..51d9fd3
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright (C) 2013 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-require-debug-mode "" }
+// { dg-do run { xfail *-*-* } }
+
+#include <deque>
+#include <debug/checks.h>
+
+void test01()
+{
+  __gnu_test::check_insert4<std::deque<int> >();
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/debug/insert_after4_neg.cc b/libstdc++-v3/testsuite/23_containers/forward_list/debug/insert_after4_neg.cc
new file mode 100644 (file)
index 0000000..f2e7847
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright (C) 2013 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-require-debug-mode "" }
+// { dg-options "-std=gnu++11 -D_GLIBCXX_DEBUG_PEDANTIC" }
+// { dg-do run { xfail *-*-* } }
+
+#include <forward_list>
+#include <iterator>
+
+void test01()
+{
+  std::forward_list<int> fl{ 1, 2, 3 };
+  fl.insert_after(fl.before_begin(), fl.begin(), std::next(fl.begin(), 2));
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/list/debug/insert5_neg.cc b/libstdc++-v3/testsuite/23_containers/list/debug/insert5_neg.cc
new file mode 100644 (file)
index 0000000..7f748bb
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright (C) 2013 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-require-debug-mode "" }
+// { dg-options "-D_GLIBCXX_DEBUG_PEDANTIC" }
+// { dg-do run { xfail *-*-* } }
+
+#include <list>
+#include <debug/checks.h>
+
+void test01()
+{
+  __gnu_test::check_insert4<std::list<int> >();
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/vector/debug/57779_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/debug/57779_neg.cc
new file mode 100644 (file)
index 0000000..10ee766
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright (C) 2013 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-options "-std=gnu++11" }
+// { dg-require-debug-mode "" }
+// { dg-do run { xfail *-*-* } }
+
+#include <vector>
+#include <debug/checks.h>
+
+void test01()
+{
+  std::vector<int> v;
+  for (int i = 0; i != 10; ++i)
+    v.push_back(i);
+
+  v.insert(v.begin(), v.data() + 1, v.data() + 5); // Expected failure
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/vector/debug/insert5_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/debug/insert5_neg.cc
new file mode 100644 (file)
index 0000000..ccdafad
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright (C) 2013 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-require-debug-mode "" }
+// { dg-do run { xfail *-*-* } }
+
+#include <vector>
+#include <debug/checks.h>
+
+void test01()
+{
+  __gnu_test::check_insert4<std::vector<int> >();
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/vector/debug/insert6_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/debug/insert6_neg.cc
new file mode 100644 (file)
index 0000000..679df5b
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright (C) 2013 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 { xfail *-*-* } }
+
+#include <vector>
+#include <debug/vector>
+#include <debug/checks.h>
+
+void test01()
+{
+  std::vector<bool> v;
+  __gnu_debug::vector<bool> dv;
+  for (int i = 0; i != 10; ++i)
+    {
+      v.push_back((i % 2) != 0);
+      dv.push_back((i % 2) == 0);
+    }
+
+  dv.insert(dv.begin(), v.begin(), v.begin() + 5);
+  VERIFY( dv.size() == 15 );
+}
+
+void test02()
+{
+  __gnu_test::check_insert4<__gnu_debug::vector<bool> >();
+}
+
+int main()
+{
+  test01();
+  test02();
+  return 0;
+}
index 6ad39aded34defb2d84e78be902ad2f35265fed0..01c5beb5cd4be1a831d4094068fdba9b9e0201c0 100644 (file)
@@ -129,7 +129,7 @@ namespace __gnu_test
       c2.assign(last, first); // Expected failure
     }
 
-  // Check that invalid range of debug !random debug iterators is detected
+  // Check that invalid range of debug not random iterators is detected
   template<typename _Tp>
     void
     check_assign3()
@@ -376,6 +376,34 @@ namespace __gnu_test
       InsertRangeHelper<cont_type>::Insert(c2, last, first); // Expected failure
     }
 
+  template<typename _Tp>
+    void
+    check_insert4()
+    {
+      bool test __attribute__((unused)) = true;
+
+      typedef _Tp cont_type;
+      typedef typename cont_type::value_type cont_val_type;
+      typedef typename CopyableValueType<cont_val_type>::value_type val_type;
+      typedef std::list<val_type> list_type;
+
+      generate_unique<val_type> gu;
+
+      list_type l;
+      for (int i = 0; i != 5; ++i)
+        l.push_back(gu.build());
+      VERIFY(l.size() == 5);
+
+      typename list_type::iterator first = l.begin(); ++first;
+      typename list_type::iterator last = first; ++last; ++last;
+
+      cont_type c1;
+      InsertRangeHelper<cont_type>::Insert(c1, l.begin(), l.end());
+      VERIFY(c1.size() == 5);
+
+      c1.insert(c1.begin(), c1.begin(), c1.end()); // Expected failure.
+    }
+
   template<typename _Tp>
     void use_invalid_iterator()
     {