Index: test/std/utilities/memory/util.smartptr/util.smartptr.shared/types.pass.cpp =================================================================== --- test/std/utilities/memory/util.smartptr/util.smartptr.shared/types.pass.cpp +++ test/std/utilities/memory/util.smartptr/util.smartptr.shared/types.pass.cpp @@ -20,14 +20,41 @@ #include "test_macros.h" +template> +struct has_less + : std::false_type +{}; + +template +struct has_less() < std::declval())>> + : std::true_type +{}; + struct A; // purposefully incomplete +struct B { int x = 42; }; -int main(int, char**) +template +void test() { - static_assert((std::is_same::element_type, A>::value), ""); + static_assert(std::is_same::element_type, T>::value); #if TEST_STD_VER > 14 - static_assert((std::is_same::weak_type, std::weak_ptr>::value), ""); + static_assert(std::is_same::weak_type, std::weak_ptr>::value); + static_assert(std::is_copy_constructible>::value); + static_assert(std::is_copy_assignable>::value); + static_assert(has_less>::value); +#if _LIBCPP_NEW_SHARED_PTR + static_assert(std::is_same ::element_type, T>::value); + static_assert(std::is_same::element_type, T>::value); +#endif #endif +} + +int main(int, char**) +{ + test(); + test(); + test(); + test(); - return 0; + return 0; } Index: test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/default.pass.cpp =================================================================== --- test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/default.pass.cpp +++ test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/default.pass.cpp @@ -13,11 +13,30 @@ #include #include +struct A { }; + +template +void test() +{ + { + std::shared_ptr p; + assert(p.use_count() == 0); + assert(p.get() == 0); + } + { + std::shared_ptr p {}; + assert(p.use_count() == 0); + assert(p.get() == 0); + } +} + int main(int, char**) { - std::shared_ptr p; - assert(p.use_count() == 0); - assert(p.get() == 0); + test(); + test(); + test(); + test(); + test(); - return 0; + return 0; } Index: test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer.pass.cpp =================================================================== --- test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer.pass.cpp +++ test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer.pass.cpp @@ -27,21 +27,36 @@ int main(int, char**) { { - A* ptr = new A; - std::shared_ptr p(ptr); - assert(A::count == 1); - assert(p.use_count() == 1); - assert(p.get() == ptr); + A* ptr = new A; + std::shared_ptr p(ptr); + assert(A::count == 1); + assert(p.use_count() == 1); + assert(p.get() == ptr); } assert(A::count == 0); + + { + A* ptr = new A; + std::shared_ptr p(ptr); + assert(A::count == 1); + assert(p.use_count() == 1); + assert(p.get() == ptr); + } + assert(A::count == 0); + +// TODO: add fail tests for when `delete[]` or `delete` does not work. +#if _LIBCPP_NEW_SHARED_PTR { - A* ptr = new A; - std::shared_ptr p(ptr); - assert(A::count == 1); - assert(p.use_count() == 1); - assert(p.get() == ptr); + A* ptr[8]; + for (unsigned i = 0; i < 8; ++i) ptr[i] = new A; + + std::shared_ptr p(ptr); + assert(A::count == 8); + assert(p.use_count() == 1); + assert(p.get() == ptr); } assert(A::count == 0); +#endif - return 0; + return 0; } Index: test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter.fail.cpp =================================================================== --- /dev/null +++ test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter.fail.cpp @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// shared_ptr + +// template shared_ptr(Y* p, D d); + +#include + +struct NotDeleter +{ + NotDeleter() = default; + NotDeleter(NotDeleter const&) = default; + NotDeleter(NotDeleter&&) = default; +}; + +template +struct NoMoveDeleter +{ + NoMoveDeleter() = default; + NoMoveDeleter(NoMoveDeleter const&) = default; + NoMoveDeleter(NoMoveDeleter&&) = delete; + + void operator()(T*) { } +}; + +int main(int, char**) +{ + { + int* ptr = new int; + // expected-error@memory:* {{type 'NotDeleter' does not provide a call operator}} + std::shared_ptr bp0(ptr, NotDeleter()); // expected-error@memory:* {{type 'NotDeleter' does not provide a call operator}} + std::shared_ptr bp1(ptr, NoMoveDeleter()); // expected-error@memory:* {{call to deleted constructor of 'NoMoveDeleter'}} + } + + return 0; +} Index: test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter.pass.cpp =================================================================== --- test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter.pass.cpp +++ test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter.pass.cpp @@ -30,20 +30,21 @@ int main(int, char**) { { - A* ptr = new A; - std::shared_ptr p(ptr, test_deleter(3)); - assert(A::count == 1); - assert(p.use_count() == 1); - assert(p.get() == ptr); - test_deleter* d = std::get_deleter >(p); - assert(test_deleter::count == 1); - assert(test_deleter::dealloc_count == 0); - assert(d); - assert(d->state() == 3); + A* ptr = new A; + std::shared_ptr p(ptr, test_deleter(3)); + assert(A::count == 1); + assert(p.use_count() == 1); + assert(p.get() == ptr); + + test_deleter* d = std::get_deleter>(p); + assert(test_deleter::count == 1); + assert(test_deleter::dealloc_count == 0); + assert(d); + assert(d->state() == 3); } assert(A::count == 0); assert(test_deleter::count == 0); assert(test_deleter::dealloc_count == 1); return 0; } Index: test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_allocator.pass.cpp =================================================================== --- test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_allocator.pass.cpp +++ test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_allocator.pass.cpp @@ -27,22 +27,23 @@ int A::count = 0; - int main(int, char**) { + // TODO: add tests for whatever the result of 41930 happens to be. + { - A* ptr = new A; - std::shared_ptr p(ptr, test_deleter(3), test_allocator(5)); - assert(A::count == 1); - assert(p.use_count() == 1); - assert(p.get() == ptr); - test_deleter* d = std::get_deleter >(p); - assert(test_deleter::count == 1); - assert(test_deleter::dealloc_count == 0); - assert(d); - assert(d->state() == 3); - assert(test_allocator::count == 1); - assert(test_allocator::alloc_count == 1); + A* ptr = new A; + std::shared_ptr p(ptr, test_deleter(3), test_allocator(5)); + assert(A::count == 1); + assert(p.use_count() == 1); + assert(p.get() == ptr); + test_deleter* d = std::get_deleter >(p); + assert(test_deleter::count == 1); + assert(test_deleter::dealloc_count == 0); + assert(d); + assert(d->state() == 3); + assert(test_allocator::count == 1); + assert(test_allocator::alloc_count == 1); } assert(A::count == 0); assert(test_deleter::count == 0); @@ -50,41 +51,41 @@ assert(test_allocator::count == 0); assert(test_allocator::alloc_count == 0); test_deleter::dealloc_count = 0; + // Test an allocator with a minimal interface { - A* ptr = new A; - std::shared_ptr p(ptr, test_deleter(3), bare_allocator()); - assert(A::count == 1); - assert(p.use_count() == 1); - assert(p.get() == ptr); - test_deleter* d = std::get_deleter >(p); - assert(test_deleter::count == 1); - assert(test_deleter::dealloc_count == 0); - assert(d); - assert(d->state() == 3); + A* ptr = new A; + std::shared_ptr p(ptr, test_deleter(3), bare_allocator()); + assert(A::count == 1); + assert(p.use_count() == 1); + assert(p.get() == ptr); + test_deleter* d = std::get_deleter >(p); + assert(test_deleter::count == 1); + assert(test_deleter::dealloc_count == 0); + assert(d); + assert(d->state() == 3); } assert(A::count == 0); assert(test_deleter::count == 0); assert(test_deleter::dealloc_count == 1); test_deleter::dealloc_count = 0; -#if TEST_STD_VER >= 11 + // Test an allocator that returns class-type pointers { - A* ptr = new A; - std::shared_ptr p(ptr, test_deleter(3), min_allocator()); - assert(A::count == 1); - assert(p.use_count() == 1); - assert(p.get() == ptr); - test_deleter* d = std::get_deleter >(p); - assert(test_deleter::count == 1); - assert(test_deleter::dealloc_count == 0); - assert(d); - assert(d->state() == 3); + A* ptr = new A; + std::shared_ptr p(ptr, test_deleter(3), min_allocator()); + assert(A::count == 1); + assert(p.use_count() == 1); + assert(p.get() == ptr); + test_deleter* d = std::get_deleter >(p); + assert(test_deleter::count == 1); + assert(test_deleter::dealloc_count == 0); + assert(d); + assert(d->state() == 3); } assert(A::count == 0); assert(test_deleter::count == 0); assert(test_deleter::dealloc_count == 1); -#endif - return 0; + return 0; } Index: test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_Y_rv.pass.cpp =================================================================== --- test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_Y_rv.pass.cpp +++ test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_Y_rv.pass.cpp @@ -59,6 +59,7 @@ static_assert(( std::is_convertible, std::shared_ptr >::value), ""); static_assert((!std::is_convertible, std::shared_ptr >::value), ""); static_assert((!std::is_convertible, std::shared_ptr >::value), ""); + { std::shared_ptr pA(new A); assert(pA.use_count() == 1); @@ -69,27 +70,17 @@ std::shared_ptr pB(std::move(pA)); assert(B::count == 1); assert(A::count == 1); -#if TEST_STD_VER >= 11 assert(pB.use_count() == 1); assert(pA.use_count() == 0); -#else - assert(pB.use_count() == 2); - assert(pA.use_count() == 2); -#endif assert(p == pB.get()); } -#if TEST_STD_VER >= 11 assert(pA.use_count() == 0); assert(B::count == 0); assert(A::count == 0); -#else - assert(pA.use_count() == 1); - assert(B::count == 1); - assert(A::count == 1); -#endif } assert(B::count == 0); assert(A::count == 0); + { std::shared_ptr pA; assert(pA.use_count() == 0); @@ -102,6 +93,7 @@ assert(pB.use_count() == 0); assert(pA.use_count() == 0); assert(pA.get() == pB.get()); + assert(pA.get() == nullptr); } assert(pA.use_count() == 0); assert(B::count == 0); @@ -110,5 +102,5 @@ assert(B::count == 0); assert(A::count == 0); - return 0; + return 0; } Index: test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_copy_move.fail.cpp =================================================================== --- /dev/null +++ test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_copy_move.fail.cpp @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// shared_ptr + +// template shared_ptr(const shared_ptr& r); + +#include +#include + +struct A { int x = 42; }; + +struct ADel : std::default_delete +{ + typedef A* pointer; +}; + +int main(int, char**) +{ + static_assert(!std::is_convertible::value); + + { + std::shared_ptr pA; + std::shared_ptr pi(pA); // expected-error {{no matching constructor for initialization of 'std::shared_ptr'}} + } + { + std::shared_ptr pA; + std::shared_ptr pi(std::move(pA)); // expected-error {{no matching constructor for initialization of 'std::shared_ptr'}} + } + { + std::weak_ptr pA; + std::shared_ptr pi(std::move(pA)); // expected-error {{no matching constructor for initialization of 'std::shared_ptr'}} + } + +#if TEST_STD_VER > 14 + { + std::unique_ptr ui; + std::shared_ptr pi(std::move(ui)); // expected-error {{no matching constructor for initialization of 'std::shared_ptr'}} + } +#endif + + return 0; +} Index: test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_pointer.pass.cpp =================================================================== --- test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_pointer.pass.cpp +++ test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_pointer.pass.cpp @@ -42,6 +42,7 @@ { std::shared_ptr pA(new A); assert(pA.use_count() == 1); + { B b; std::shared_ptr pB(pA, &b); @@ -58,5 +59,38 @@ assert(A::count == 0); assert(B::count == 0); - return 0; + { + std::shared_ptr p1(nullptr); + std::shared_ptr p2(p1, new int); + assert(p2.get() != nullptr); + } + { + std::shared_ptr p1(new int); + std::shared_ptr p2(p1, nullptr); + assert(p2.get() == nullptr); + } + +#if TEST_STD_VER > 14 + { + std::shared_ptr pA(new A); + assert(pA.use_count() == 1); + + { + B b; + std::shared_ptr pB(std::move(pA), &b); + assert(A::count == 1); + assert(B::count == 1); + assert(pA.use_count() == 2); + assert(pB.use_count() == 2); + assert(pB.get() == &b); + } + assert(pA.use_count() == 1); + assert(A::count == 1); + assert(B::count == 0); + } + assert(A::count == 0); + assert(B::count == 0); +#endif + + return 0; } Index: test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/unique_ptr.pass.cpp =================================================================== --- test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/unique_ptr.pass.cpp +++ test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/unique_ptr.pass.cpp @@ -6,49 +6,64 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: sanitizer-new-delete +// UNSUPPORTED: sanitizer-new-delete, c++98, c++03 + // // template explicit shared_ptr(unique_ptr&&r); #include #include #include #include #include "test_macros.h" #include "count_new.hpp" struct B { static int count; B() {++count;} B(const B&) {++count;} virtual ~B() {--count;} }; int B::count = 0; struct A : public B { static int count; A() {++count;} A(const A&) {++count;} ~A() {--count;} }; int A::count = 0; void fn ( const std::shared_ptr &) {} void fn ( const std::shared_ptr &) { assert (false); } template void assert_deleter ( T * ) { assert(false); } +template +struct StatefulDeleter +{ + int state = 0; + + StatefulDeleter(int val = 0) : state(val) {} + StatefulDeleter(StatefulDeleter const&) { assert(false); } + + void operator()(T* ptr) { + assert(state == 42); + delete ptr; + } +}; + int main(int, char**) { { @@ -74,20 +89,31 @@ } catch (...) { -#if TEST_STD_VER >= 11 assert(A::count == 1); assert(B::count == 1); assert(ptr.get() == raw_ptr); -#else - (void) raw_ptr; // silence 'unused variable' warning - assert(A::count == 0); - assert(B::count == 0); - assert(ptr.get() == 0); -#endif } } #endif + +#if TEST_STD_VER > 14 + { + std::unique_ptr ptr; + std::shared_ptr p(std::move(ptr)); + assert(p.use_count() == 0); + assert(p.get() == nullptr); + } +#endif + + { + StatefulDeleter d; + std::unique_ptr&> u(new A, d); + std::shared_ptr p(std::move(u)); + d.state = 42; + assert(A::count == 1); + } assert(A::count == 0); + { // LWG 2399 fn(std::unique_ptr(new int)); } Index: test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/op_bool.pass.cpp =================================================================== --- test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/op_bool.pass.cpp +++ test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/op_bool.pass.cpp @@ -15,16 +15,32 @@ #include #include +struct A +{ + int a; + virtual ~A() {}; +}; +struct B : A { }; + int main(int, char**) { { - const std::shared_ptr p(new int(32)); - assert(p); + const std::shared_ptr p(new int(32)); + assert(p); + } + { + const std::shared_ptr p; + assert(!p); } { - const std::shared_ptr p; - assert(!p); + bool check = false; + std::shared_ptr basePtr = std::make_shared(); + + if (std::shared_ptr sp = std::dynamic_pointer_cast(basePtr)) + { check = true; } + + assert(check); } - return 0; + return 0; }