diff options
11 files changed, 316 insertions, 33 deletions
diff --git a/libstdc++-v3/include/bits/shared_ptr.h b/libstdc++-v3/include/bits/shared_ptr.h index 5e19600..f01630e 100644 --- a/libstdc++-v3/include/bits/shared_ptr.h +++ b/libstdc++-v3/include/bits/shared_ptr.h @@ -123,6 +123,23 @@ _GLIBCXX_BEGIN_NAMESPACE(std) shared_ptr(_Tp1* __p, _Deleter __d) : __shared_ptr<_Tp>(__p, __d) { } /** + * @brief Construct a %shared_ptr that owns a null pointer + * and the deleter @a __d. + * @param __p A null pointer constant. + * @param __d A deleter. + * @post use_count() == 1 && get() == __p + * @throw std::bad_alloc, in which case @a __d(__p) is called. + * + * Requirements: _Deleter's copy constructor and destructor must + * not throw + * + * The last owner will call __d(__p) + */ + template<typename _Deleter> + shared_ptr(nullptr_t __p, _Deleter __d) + : __shared_ptr<_Tp>(__p, __d) { } + + /** * @brief Construct a %shared_ptr that owns the pointer @a __p * and the deleter @a __d. * @param __p A pointer. @@ -141,6 +158,25 @@ _GLIBCXX_BEGIN_NAMESPACE(std) shared_ptr(_Tp1* __p, _Deleter __d, const _Alloc& __a) : __shared_ptr<_Tp>(__p, __d, __a) { } + /** + * @brief Construct a %shared_ptr that owns a null pointer + * and the deleter @a __d. + * @param __p A null pointer constant. + * @param __d A deleter. + * @param __a An allocator. + * @post use_count() == 1 && get() == __p + * @throw std::bad_alloc, in which case @a __d(__p) is called. + * + * Requirements: _Deleter's copy constructor and destructor must + * not throw _Alloc's copy constructor and destructor must not + * throw. + * + * The last owner will call __d(__p) + */ + template<typename _Deleter, typename _Alloc> + shared_ptr(nullptr_t __p, _Deleter __d, const _Alloc& __a) + : __shared_ptr<_Tp>(__p, __d, __a) { } + // Aliasing constructor /** @@ -212,6 +248,13 @@ _GLIBCXX_BEGIN_NAMESPACE(std) shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r) : __shared_ptr<_Tp>(std::move(__r)) { } + /** + * @brief Construct an empty %shared_ptr. + * @param __p A null pointer constant. + * @post use_count() == 0 && get() == nullptr + */ + shared_ptr(nullptr_t __p) : __shared_ptr<_Tp>(__p) { } + template<typename _Tp1> shared_ptr& operator=(const shared_ptr<_Tp1>& __r) // never throws diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h index 0c366b8..cac1a70 100644 --- a/libstdc++-v3/include/bits/shared_ptr_base.h +++ b/libstdc++-v3/include/bits/shared_ptr_base.h @@ -85,6 +85,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) class _Sp_counted_ptr : public _Sp_counted_base<_Lp> { public: + explicit _Sp_counted_ptr(_Ptr __p) : _M_ptr(__p) { } @@ -107,6 +108,18 @@ _GLIBCXX_BEGIN_NAMESPACE(std) _Ptr _M_ptr; // copy constructor must not throw }; + template<> + void + _Sp_counted_ptr<nullptr_t, _S_single>::_M_dispose() { } + + template<> + void + _Sp_counted_ptr<nullptr_t, _S_mutex>::_M_dispose() { } + + template<> + void + _Sp_counted_ptr<nullptr_t, _S_atomic>::_M_dispose() { } + // Support for custom deleter and/or allocator template<typename _Ptr, typename _Deleter, typename _Alloc, _Lock_policy _Lp> class _Sp_counted_deleter : public _Sp_counted_ptr<_Ptr, _Lp> @@ -181,6 +194,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) _Base_type; public: + explicit _Sp_counted_ptr_inplace(_Alloc __a) : _Base_type(static_cast<_Tp*>(0), _Sp_destroy_inplace<_Tp>(), __a) , _M_storage() @@ -237,6 +251,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) { } template<typename _Ptr> + explicit __shared_count(_Ptr __p) : _M_pi(0) { __try @@ -316,6 +331,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) #if _GLIBCXX_DEPRECATED // Special case for auto_ptr<_Tp> to provide the strong guarantee. template<typename _Tp> + explicit __shared_count(std::auto_ptr<_Tp>&& __r) : _M_pi(new _Sp_counted_ptr<_Tp*, _Lp>(__r.get())) { __r.release(); } @@ -323,6 +339,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) // Special case for unique_ptr<_Tp,_Del> to provide the strong guarantee. template<typename _Tp, typename _Del> + explicit __shared_count(std::unique_ptr<_Tp, _Del>&& __r) : _M_pi(_S_create_from_up(std::move(__r))) { __r.release(); } @@ -567,6 +584,16 @@ _GLIBCXX_BEGIN_NAMESPACE(std) __enable_shared_from_this_helper(_M_refcount, __p, __p); } + template<typename _Deleter> + __shared_ptr(nullptr_t __p, _Deleter __d) + : _M_ptr(0), _M_refcount(__p, __d) + { } + + template<typename _Deleter, typename _Alloc> + __shared_ptr(nullptr_t __p, _Deleter __d, const _Alloc& __a) + : _M_ptr(0), _M_refcount(__p, __d, __a) + { } + template<typename _Tp1> __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, _Tp* __p) : _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws @@ -631,6 +658,10 @@ _GLIBCXX_BEGIN_NAMESPACE(std) } #endif + /* TODO: use delegating constructor */ + __shared_ptr(nullptr_t) : _M_ptr(0), _M_refcount() // never throws + { } + template<typename _Tp1> __shared_ptr& operator=(const __shared_ptr<_Tp1, _Lp>& __r) // never throws diff --git a/libstdc++-v3/include/bits/unique_ptr.h b/libstdc++-v3/include/bits/unique_ptr.h index 7b07ca4..77d3f60 100644 --- a/libstdc++-v3/include/bits/unique_ptr.h +++ b/libstdc++-v3/include/bits/unique_ptr.h @@ -81,7 +81,6 @@ _GLIBCXX_BEGIN_NAMESPACE(std) class unique_ptr { typedef std::tuple<_Tp*, _Tp_Deleter> __tuple_type; - typedef _Tp* unique_ptr::* __unspecified_pointer_type; // use SFINAE to determine whether _Del::pointer exists class _Pointer @@ -126,6 +125,10 @@ _GLIBCXX_BEGIN_NAMESPACE(std) { static_assert(!std::is_reference<deleter_type>::value, "rvalue deleter bound to reference"); } + unique_ptr(nullptr_t) + : _M_t(pointer(), deleter_type()) + { } + // Move constructors. unique_ptr(unique_ptr&& __u) : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { } @@ -157,7 +160,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) } unique_ptr& - operator=(__unspecified_pointer_type) + operator=(nullptr_t) { reset(); return *this; @@ -234,7 +237,6 @@ _GLIBCXX_BEGIN_NAMESPACE(std) class unique_ptr<_Tp[], _Tp_Deleter> { typedef std::tuple<_Tp*, _Tp_Deleter> __tuple_type; - typedef _Tp* unique_ptr::* __unspecified_pointer_type; public: typedef _Tp* pointer; @@ -264,6 +266,11 @@ _GLIBCXX_BEGIN_NAMESPACE(std) { static_assert(!std::is_reference<deleter_type>::value, "rvalue deleter bound to reference"); } + /* TODO: use delegating constructor */ + unique_ptr(nullptr_t) + : _M_t(pointer(), deleter_type()) + { } + // Move constructors. unique_ptr(unique_ptr&& __u) : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { } @@ -295,7 +302,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) } unique_ptr& - operator=(__unspecified_pointer_type) + operator=(nullptr_t) { reset(); return *this; @@ -338,7 +345,16 @@ _GLIBCXX_BEGIN_NAMESPACE(std) { using std::swap; swap(std::get<0>(_M_t), __p); - if (__p != pointer()) + if (__p != nullptr) + get_deleter()(__p); + } + + void + reset(nullptr_t) + { + pointer __p = get(); + std::get<0>(_M_t) = pointer(); + if (__p != nullptr) get_deleter()(__p); } diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional index b6cc6d5..752e783 100644 --- a/libstdc++-v3/include/std/functional +++ b/libstdc++-v3/include/std/functional @@ -1384,13 +1384,6 @@ namespace std class bad_function_call : public std::exception { }; /** - * The integral constant expression 0 can be converted into a - * pointer to this type. It is used by the function template to - * accept NULL pointers. - */ - struct _M_clear_type; - - /** * Trait identifying "location-invariant" types, meaning that the * address of the object (or any of its members) will not escape. * Also implies a trivial copy constructor and assignment operator. @@ -1797,10 +1790,10 @@ namespace std function() : _Function_base() { } /** - * @brief Default construct creates an empty function call wrapper. + * @brief Creates an empty function call wrapper. * @post @c !(bool)*this */ - function(_M_clear_type*) : _Function_base() { } + function(nullptr_t) : _Function_base() { } /** * @brief %Function copy constructor. @@ -1893,7 +1886,7 @@ namespace std * The target of @c *this is deallocated, leaving it empty. */ function& - operator=(_M_clear_type*) + operator=(nullptr_t) { if (_M_manager) { @@ -2139,13 +2132,13 @@ namespace std */ template<typename _Res, typename... _Args> inline bool - operator==(const function<_Res(_Args...)>& __f, _M_clear_type*) + operator==(const function<_Res(_Args...)>& __f, nullptr_t) { return !static_cast<bool>(__f); } /// @overload template<typename _Res, typename... _Args> inline bool - operator==(_M_clear_type*, const function<_Res(_Args...)>& __f) + operator==(nullptr_t, const function<_Res(_Args...)>& __f) { return !static_cast<bool>(__f); } /** @@ -2157,13 +2150,13 @@ namespace std */ template<typename _Res, typename... _Args> inline bool - operator!=(const function<_Res(_Args...)>& __f, _M_clear_type*) + operator!=(const function<_Res(_Args...)>& __f, nullptr_t) { return static_cast<bool>(__f); } /// @overload template<typename _Res, typename... _Args> inline bool - operator!=(_M_clear_type*, const function<_Res(_Args...)>& __f) + operator!=(nullptr_t, const function<_Res(_Args...)>& __f) { return static_cast<bool>(__f); } // [20.7.15.2.7] specialized algorithms diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820.cc index 6350079..c9c7584 100644 --- a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820.cc +++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820.cc @@ -32,10 +32,10 @@ void test01() { X* px = 0; std::shared_ptr<X> p1(px); // { dg-error "here" } - // { dg-error "incomplete" "" { target *-*-* } 549 } + // { dg-error "incomplete" "" { target *-*-* } 566 } std::shared_ptr<X> p9(ap()); // { dg-error "here" } - // { dg-error "incomplete" "" { target *-*-* } 630 } + // { dg-error "incomplete" "" { target *-*-* } 657 } } diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/nullptr.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/nullptr.cc new file mode 100644 index 0000000..82acaed --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/nullptr.cc @@ -0,0 +1,93 @@ +// { dg-options "-std=gnu++0x" } + +// Copyright (C) 2010 Free Software Foundation +// +// 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/>. + +// 20.9.11.2 Class template shared_ptr [util.smartptr.shared] + +#include <memory> +#include <cstddef> +#include <testsuite_hooks.h> +#include <testsuite_allocator.h> + +// 20.9.11.2.1 shared_ptr constructors [util.smartptr.shared.const] + +// Construction from nullptr + +struct deleter +{ + int count; + deleter() : count(0) { } + void operator()(std::nullptr_t) { ++count; } + void operator()(int*) const { throw "wrong type passed to deleter"; } +}; + +void +test01() +{ + bool test __attribute__((unused)) = true; + + std::shared_ptr<int> p = nullptr; + VERIFY( p.get() == nullptr ); + VERIFY( p.use_count() == 0 ); + +} + +void +test02() +{ + bool test __attribute__((unused)) = true; + + deleter d; + std::shared_ptr<int> p(nullptr, std::ref(d)); + VERIFY( p.get() == nullptr ); + VERIFY( p.use_count() == 1 ); + + p = nullptr; + VERIFY( p.use_count() == 0 ); + VERIFY( d.count == 1 ); +} + + +void +test03() +{ + bool test __attribute__((unused)) = true; + + deleter d; + __gnu_test::tracker_allocator<int> a; + std::shared_ptr<int> p(nullptr, std::ref(d), a); + VERIFY( p.get() == nullptr ); + VERIFY( p.use_count() == 1 ); + + p = nullptr; + VERIFY( p.use_count() == 0 ); + VERIFY( d.count == 1 ); + + typedef __gnu_test::tracker_allocator_counter c; + VERIFY( c::get_destruct_count() == c::get_construct_count() ); + VERIFY( c::get_deallocation_count() == c::get_allocation_count() ); +} + +int +main() +{ + test01(); + test02(); + test03(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/assign/assign_neg.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/assign/assign_neg.cc index 4aa93b9..40404f6 100644 --- a/libstdc++-v3/testsuite/20_util/unique_ptr/assign/assign_neg.cc +++ b/libstdc++-v3/testsuite/20_util/unique_ptr/assign/assign_neg.cc @@ -49,14 +49,15 @@ test03() std::unique_ptr<int[2]> p2 = p1; } -// { dg-error "deleted function" "" { target *-*-* } 357 } +// { dg-error "deleted function" "" { target *-*-* } 373 } // { dg-error "used here" "" { target *-*-* } 42 } // { dg-error "no matching" "" { target *-*-* } 48 } -// { dg-warning "note" "" { target *-*-* } 130 } -// { dg-warning "note" "" { target *-*-* } 134 } -// { dg-warning "note" "" { target *-*-* } 123 } -// { dg-warning "note" "" { target *-*-* } 118 } -// { dg-warning "note" "" { target *-*-* } 113 } -// { dg-warning "note" "" { target *-*-* } 107 } -// { dg-error "deleted function" "" { target *-*-* } 222 } +// { dg-warning "note" "" { target *-*-* } 137 } +// { dg-warning "note" "" { target *-*-* } 133 } +// { dg-warning "note" "" { target *-*-* } 128 } +// { dg-warning "note" "" { target *-*-* } 122 } +// { dg-warning "note" "" { target *-*-* } 117 } +// { dg-warning "note" "" { target *-*-* } 112 } +// { dg-warning "note" "" { target *-*-* } 106 } +// { dg-error "deleted function" "" { target *-*-* } 225 } // { dg-error "used here" "" { target *-*-* } 49 } diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/assign/nullptr.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/assign/nullptr.cc new file mode 100644 index 0000000..6f067ee --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/unique_ptr/assign/nullptr.cc @@ -0,0 +1,54 @@ +// { dg-options "-std=gnu++0x" } + +// Copyright (C) 2010 Free Software Foundation +// +// 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/>. + +// 20.9.10 Class template unique_ptr [unique.ptr] + +#include <memory> +#include <testsuite_hooks.h> + +struct A { }; + +void +test01() +{ + bool test __attribute__((unused)) = true; + + std::unique_ptr<A> p(new A); + p = nullptr; + + VERIFY( p.get() == nullptr ); +} + +void +test02() +{ + bool test __attribute__((unused)) = true; + + std::unique_ptr<A[]> p(new A[2]); + p = nullptr; + + VERIFY( p.get() == nullptr ); +} + +int main() +{ + test01(); + test02(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/cons/nullptr.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/cons/nullptr.cc new file mode 100644 index 0000000..1f515ea --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/unique_ptr/cons/nullptr.cc @@ -0,0 +1,52 @@ +// { dg-options "-std=gnu++0x" } + +// Copyright (C) 2010 Free Software Foundation +// +// 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/>. + +// 20.9.10 Class template unique_ptr [unique.ptr] + +#include <memory> +#include <testsuite_hooks.h> + +struct A { }; + +void +test01() +{ + bool test __attribute__((unused)) = true; + + std::unique_ptr<A> p = nullptr; + + VERIFY( p.get() == nullptr ); +} + +void +test02() +{ + bool test __attribute__((unused)) = true; + + std::unique_ptr<A[]> p = nullptr; + + VERIFY( p.get() == nullptr ); +} + +int main() +{ + test01(); + test02(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/modifiers/reset_neg.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/modifiers/reset_neg.cc index 3b389b9..27dd879 100644 --- a/libstdc++-v3/testsuite/20_util/unique_ptr/modifiers/reset_neg.cc +++ b/libstdc++-v3/testsuite/20_util/unique_ptr/modifiers/reset_neg.cc @@ -36,4 +36,4 @@ void test01() } // { dg-error "used here" "" { target *-*-* } 35 } -// { dg-error "deleted function" "" { target *-*-* } 347 } +// { dg-error "deleted function" "" { target *-*-* } 363 } diff --git a/libstdc++-v3/testsuite/20_util/weak_ptr/comparison/cmp_neg.cc b/libstdc++-v3/testsuite/20_util/weak_ptr/comparison/cmp_neg.cc index cbe5f9f..b3a45b11 100644 --- a/libstdc++-v3/testsuite/20_util/weak_ptr/comparison/cmp_neg.cc +++ b/libstdc++-v3/testsuite/20_util/weak_ptr/comparison/cmp_neg.cc @@ -41,9 +41,9 @@ main() return 0; } -// { dg-warning "note" "" { target *-*-* } 281 } -// { dg-warning "note" "" { target *-*-* } 407 } -// { dg-warning "note" "" { target *-*-* } 831 } +// { dg-warning "note" "" { target *-*-* } 324 } +// { dg-warning "note" "" { target *-*-* } 423 } +// { dg-warning "note" "" { target *-*-* } 862 } // { dg-warning "note" "" { target *-*-* } 511 } // { dg-warning "note" "" { target *-*-* } 1005 } // { dg-warning "note" "" { target *-*-* } 340 } |