2017-04-28 Jonathan Wakely <jwakely@redhat.com>
+ PR libstdc++/80553
+ * include/bits/stl_construct.h (_Destroy, _Destroy_n): Add static
+ assertions to ensure type is destructible.
+ (destroy_at, destroy, destroy_n): Move from stl_uninitialized.h.
+ * include/bits/stl_uninitialized.h (destroy_at, destroy, destroy_n):
+ Move to stl_construct.h.
+ * testsuite/20_util/specialized_algorithms/memory_management_tools/
+ destroy_neg.cc: New test.
+ * testsuite/23_containers/vector/cons/destructible_neg.cc: New test.
+
* testsuite/17_intro/headers/c++1998/stdc++_assert_neg.cc: Remove
superfluous "" in dg-error.
{
typedef typename iterator_traits<_ForwardIterator>::value_type
_Value_type;
+#if __cplusplus >= 201103L
+ // A deleted destructor is trivial, this ensures we reject such types:
+ static_assert(is_destructible<_Value_type>::value,
+ "value type is destructible");
+#endif
std::_Destroy_aux<__has_trivial_destructor(_Value_type)>::
__destroy(__first, __last);
}
template<typename _ForwardIterator, typename _Size>
static _ForwardIterator
__destroy_n(_ForwardIterator __first, _Size __count)
- {
- std::advance(__first, __count);
- return __first;
- }
+ {
+ std::advance(__first, __count);
+ return __first;
+ }
};
/**
{
typedef typename iterator_traits<_ForwardIterator>::value_type
_Value_type;
+#if __cplusplus >= 201103L
+ // A deleted destructor is trivial, this ensures we reject such types:
+ static_assert(is_destructible<_Value_type>::value,
+ "value type is destructible");
+#endif
return std::_Destroy_n_aux<__has_trivial_destructor(_Value_type)>::
__destroy_n(__first, __count);
}
_Destroy(__first, __last);
}
+#if __cplusplus > 201402L
+ template <typename _Tp>
+ inline void
+ destroy_at(_Tp* __location)
+ {
+ std::_Destroy(__location);
+ }
+
+ template <typename _ForwardIterator>
+ inline void
+ destroy(_ForwardIterator __first, _ForwardIterator __last)
+ {
+ std::_Destroy(__first, __last);
+ }
+
+ template <typename _ForwardIterator, typename _Size>
+ inline _ForwardIterator
+ destroy_n(_ForwardIterator __first, _Size __count)
+ {
+ return std::_Destroy_n(__first, __count);
+ }
+#endif
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
inline void
uninitialized_default_construct(_ForwardIterator __first,
_ForwardIterator __last)
- {
- __uninitialized_default_novalue(__first, __last);
- }
+ {
+ __uninitialized_default_novalue(__first, __last);
+ }
template <typename _ForwardIterator, typename _Size>
inline _ForwardIterator
uninitialized_default_construct_n(_ForwardIterator __first, _Size __count)
- {
- return __uninitialized_default_novalue_n(__first, __count);
- }
+ {
+ return __uninitialized_default_novalue_n(__first, __count);
+ }
template <typename _ForwardIterator>
inline void
uninitialized_value_construct(_ForwardIterator __first,
_ForwardIterator __last)
- {
- return __uninitialized_default(__first, __last);
- }
+ {
+ return __uninitialized_default(__first, __last);
+ }
template <typename _ForwardIterator, typename _Size>
inline _ForwardIterator
uninitialized_value_construct_n(_ForwardIterator __first, _Size __count)
- {
- return __uninitialized_default_n(__first, __count);
- }
+ {
+ return __uninitialized_default_n(__first, __count);
+ }
template <typename _InputIterator, typename _ForwardIterator>
inline _ForwardIterator
uninitialized_move(_InputIterator __first, _InputIterator __last,
_ForwardIterator __result)
- {
- return std::uninitialized_copy
- (_GLIBCXX_MAKE_MOVE_ITERATOR(__first),
- _GLIBCXX_MAKE_MOVE_ITERATOR(__last), __result);
- }
+ {
+ return std::uninitialized_copy
+ (_GLIBCXX_MAKE_MOVE_ITERATOR(__first),
+ _GLIBCXX_MAKE_MOVE_ITERATOR(__last), __result);
+ }
template <typename _InputIterator, typename _Size, typename _ForwardIterator>
inline pair<_InputIterator, _ForwardIterator>
uninitialized_move_n(_InputIterator __first, _Size __count,
_ForwardIterator __result)
- {
- auto __res = std::__uninitialized_copy_n_pair
- (_GLIBCXX_MAKE_MOVE_ITERATOR(__first),
- __count, __result);
- return {__res.first.base(), __res.second};
- }
-
- template <typename _Tp>
- inline void
- destroy_at(_Tp* __location)
- {
- std::_Destroy(__location);
- }
-
- template <typename _ForwardIterator>
- inline void
- destroy(_ForwardIterator __first, _ForwardIterator __last)
- {
- std::_Destroy(__first, __last);
- }
-
- template <typename _ForwardIterator, typename _Size>
- inline _ForwardIterator
- destroy_n(_ForwardIterator __first, _Size __count)
- {
- return std::_Destroy_n(__first, __count);
- }
-
+ {
+ auto __res = std::__uninitialized_copy_n_pair
+ (_GLIBCXX_MAKE_MOVE_ITERATOR(__first),
+ __count, __result);
+ return {__res.first.base(), __res.second};
+ }
#endif
-
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
--- /dev/null
+// Copyright (C) 2017 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++17" }
+// { dg-do compile { target c++1z } }
+
+#include <memory>
+
+// This has a trivial destructor, but should not be destructible!
+struct DeletedDtor {
+ ~DeletedDtor() = delete;
+};
+
+void
+test01()
+{
+ alignas(DeletedDtor) unsigned char buf[sizeof(DeletedDtor)];
+ auto p = ::new (buf) DeletedDtor();
+ std::destroy(p, p + 1); // { dg-error "here" }
+ std::destroy_n(p, 1); // { dg-error "here" }
+}
+
+class PrivateDtor {
+ ~PrivateDtor() { }
+};
+
+void
+test02()
+{
+ alignas(PrivateDtor) unsigned char buf[sizeof(PrivateDtor)];
+ auto p = ::new (buf) PrivateDtor();
+ std::destroy(p, p + 1); // { dg-error "here" }
+ std::destroy_n(p, 1); // { dg-error "here" }
+}
+
+// { dg-error "value type is destructible" "" { target *-*-* } 0 }
--- /dev/null
+// Copyright (C) 2017 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 compile { target c++11 } }
+
+#include <vector>
+
+// PR libstdc++/80553
+
+struct DeletedDtor {
+ ~DeletedDtor() = delete;
+};
+
+class PrivateDtor {
+ ~PrivateDtor() { }
+};
+
+void
+test01()
+{
+ std::vector<DeletedDtor> v; // { dg-error "here" }
+}
+
+void
+test02()
+{
+ std::vector<PrivateDtor> v; // { dg-error "here" }
+}
+
+// { dg-error "value type is destructible" "" { target *-*-* } 0 }