PR libstdc++/80553 don't allow destroying non-destructible types

Backport from mainline
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.

From-SVN: r250539
This commit is contained in:
Jonathan Wakely 2017-07-25 19:05:13 +01:00 committed by Jonathan Wakely
parent 0182e8bb7b
commit b65b227362
5 changed files with 167 additions and 50 deletions

View File

@ -1,5 +1,18 @@
2017-07-25 Jonathan Wakely <jwakely@redhat.com>
Backport from mainline
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.
Backport from mainline
2017-05-16 Jonathan Wakely <jwakely@redhat.com>

View File

@ -128,6 +128,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
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);
}
@ -151,10 +156,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
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;
}
};
/**
@ -168,6 +173,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
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);
}
@ -196,6 +206,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_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

View File

@ -831,77 +831,54 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
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

View File

@ -0,0 +1,50 @@
// 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 }

View File

@ -0,0 +1,44 @@
// 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 }