diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2018-09-18 17:05:36 +0100 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2018-09-18 17:05:36 +0100 |
commit | a12c16de529755cdf4dbc594dd48742107ad349e (patch) | |
tree | 972c09ab072dd40014d9173255ca43195237a020 | |
parent | f96c8666f57e89182c3b0661f2e5e19f8b70aa8a (diff) | |
download | gcc-a12c16de529755cdf4dbc594dd48742107ad349e.zip gcc-a12c16de529755cdf4dbc594dd48742107ad349e.tar.gz gcc-a12c16de529755cdf4dbc594dd48742107ad349e.tar.bz2 |
Fix location of invocable check for unique_ptr deleter
The deleter only needs to be invocable when the unique_ptr destructor
and reset member function are instantiated. In other contexts it might
not be possible to pass unique_ptr<T, D>::pointer to the deleter, if
that requires a derived-to-base conversion from T* and T is incomplete.
* include/bits/unique_ptr.h (__uniq_ptr_impl): Remove static assertion
checking invocable condition.
(unique_ptr::~unique_ptr, unique_ptr::reset): Restore static assertion
here, where types must be complete. Pass pointer to deleter as an
rvalue.
* testsuite/20_util/unique_ptr/requirements/incomplete.cc: New test.
From-SVN: r264399
-rw-r--r-- | libstdc++-v3/ChangeLog | 9 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/unique_ptr.h | 10 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/unique_ptr/requirements/incomplete.cc | 33 |
3 files changed, 48 insertions, 4 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 6e4fffc..0ed4baf 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,12 @@ +2018-09-18 Jonathan Wakely <jwakely@redhat.com> + + * include/bits/unique_ptr.h (__uniq_ptr_impl): Remove static assertion + checking invocable condition. + (unique_ptr::~unique_ptr, unique_ptr::reset): Restore static assertion + here, where types must be complete. Pass pointer to deleter as an + rvalue. + * testsuite/20_util/unique_ptr/requirements/incomplete.cc: New test. + 2018-09-13 Jonathan Wakely <jwakely@redhat.com> * include/std/variant (variant) [__clang__]: Limit workaround to diff --git a/libstdc++-v3/include/bits/unique_ptr.h b/libstdc++-v3/include/bits/unique_ptr.h index ddc6ae0..0717c1e 100644 --- a/libstdc++-v3/include/bits/unique_ptr.h +++ b/libstdc++-v3/include/bits/unique_ptr.h @@ -142,8 +142,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static_assert( !is_rvalue_reference<_Dp>::value, "unique_ptr's deleter type must be a function object type" " or an lvalue reference type" ); - static_assert( __is_invocable<_Dp&, pointer&>::value, - "unique_ptr's deleter must be invocable with a pointer" ); __uniq_ptr_impl() = default; __uniq_ptr_impl(pointer __p) : _M_t() { _M_ptr() = __p; } @@ -282,9 +280,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Destructor, invokes the deleter if the stored pointer is not null. ~unique_ptr() noexcept { + static_assert(__is_invocable<deleter_type&, pointer>::value, + "unique_ptr's deleter must be invocable with a pointer"); auto& __ptr = _M_t._M_ptr(); if (__ptr != nullptr) - get_deleter()(__ptr); + get_deleter()(std::move(__ptr)); __ptr = pointer(); } @@ -389,10 +389,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void reset(pointer __p = pointer()) noexcept { + static_assert(__is_invocable<deleter_type&, pointer>::value, + "unique_ptr's deleter must be invocable with a pointer"); using std::swap; swap(_M_t._M_ptr(), __p); if (__p != pointer()) - get_deleter()(__p); + get_deleter()(std::move(__p)); } /// Exchange the pointer and deleter with another object. diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/requirements/incomplete.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/requirements/incomplete.cc new file mode 100644 index 0000000..96e02e4 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/unique_ptr/requirements/incomplete.cc @@ -0,0 +1,33 @@ +// 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 compile { target c++11 } } + +#include <memory> + +struct Base; // incomplete + +struct BaseDeleter { + void operator()(Base*) const; +}; + +struct Derived; // incomplete + +struct X { + std::unique_ptr<Derived, BaseDeleter> p; + ~X(); // defined elsewhere, where Derived is complete +}; |