summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorredi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>2018-07-04 11:44:45 +0000
committerredi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>2018-07-04 11:44:45 +0000
commit261bd5e266dfaed9b1b06f4ba12f0c23d4bcd16e (patch)
tree4d3ea065dde75f7ed86c33b04623f17e08a1599d
parent0ab6ef3b0bbc17a1ca502d16bf25ef7e72136871 (diff)
PR libstdc++/86292 fix exception safety of std::vector<InputIterator> constructor
Backport from mainline 2018-06-25 Jonathan Wakely <jwakely@redhat.com> PR libstdc++/86292 * include/bits/stl_vector.h (vector::_M_range_initialize<InputIter>): Add try-catch block. * testsuite/23_containers/vector/cons/86292.cc: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-8-branch@262386 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--libstdc++-v3/ChangeLog8
-rw-r--r--libstdc++-v3/include/bits/stl_vector.h19
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/cons/86292.cc64
3 files changed, 84 insertions, 7 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 410e66c1a54f..13999301333f 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,6 +1,14 @@
2018-07-04 Jonathan Wakely <jwakely@redhat.com>
Backport from mainline
+ 2018-06-25 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/86292
+ * include/bits/stl_vector.h (vector::_M_range_initialize<InputIter>):
+ Add try-catch block.
+ * testsuite/23_containers/vector/cons/86292.cc: New.
+
+ Backport from mainline
2018-06-27 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/86138
diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h
index acec501bc1be..129d45cd34b1 100644
--- a/libstdc++-v3/include/bits/stl_vector.h
+++ b/libstdc++-v3/include/bits/stl_vector.h
@@ -1440,22 +1440,27 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// Called by the second initialize_dispatch above
template<typename _InputIterator>
void
- _M_range_initialize(_InputIterator __first,
- _InputIterator __last, std::input_iterator_tag)
+ _M_range_initialize(_InputIterator __first, _InputIterator __last,
+ std::input_iterator_tag)
{
- for (; __first != __last; ++__first)
+ __try {
+ for (; __first != __last; ++__first)
#if __cplusplus >= 201103L
- emplace_back(*__first);
+ emplace_back(*__first);
#else
- push_back(*__first);
+ push_back(*__first);
#endif
+ } __catch(...) {
+ clear();
+ __throw_exception_again;
+ }
}
// Called by the second initialize_dispatch above
template<typename _ForwardIterator>
void
- _M_range_initialize(_ForwardIterator __first,
- _ForwardIterator __last, std::forward_iterator_tag)
+ _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last,
+ std::forward_iterator_tag)
{
const size_type __n = std::distance(__first, __last);
this->_M_impl._M_start = this->_M_allocate(__n);
diff --git a/libstdc++-v3/testsuite/23_containers/vector/cons/86292.cc b/libstdc++-v3/testsuite/23_containers/vector/cons/86292.cc
new file mode 100644
index 000000000000..7103efb82ff9
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/cons/86292.cc
@@ -0,0 +1,64 @@
+// 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 }
+
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+struct X
+{
+ X() { ++count; }
+ X(const X&) { if (++copies >= max_copies) throw 1; ++count; }
+ ~X() { --count; }
+
+ static int count;
+ static int copies;
+ static int max_copies;
+};
+
+int X::count = 0;
+int X::copies = 0;
+int X::max_copies = 0;
+
+void
+test01()
+{
+ X x[3];
+ const int count = X::count;
+ X::max_copies = 2;
+ __gnu_test::test_container<const X, __gnu_test::input_iterator_wrapper>
+ x_input(x, x+3);
+ bool caught = false;
+ try
+ {
+ std::vector<X> v(x_input.begin(), x_input.end());
+ }
+ catch(int)
+ {
+ caught = true;
+ }
+ VERIFY( caught );
+ VERIFY( X::count == count );
+}
+
+int
+main()
+{
+ test01();
+}