Eric Fiselier 4e7d53664d Add support for "fancy" pointers to shared_ptr. Fixes PR20616
Summary:
This patch add support for "fancy pointers/allocators" as well as fixing support for shared_pointer and "minimal" allocators.

Fancy pointers are class types that meet the NullablePointer requirements. In our case they are created by fancy allocators. `support/min_allocator.h` is an archetype for these types.

There are three types of changes made in this patch:
1. `_Alloc::template rebind<T>::other` -> `__allocator_traits_rebind<_Alloc, T>::type`. This change was made because allocators don't need a rebind template. `__allocator_traits_rebind` is used instead of `allocator_traits::rebind` because use of `allocator_traits::rebind` requires a workaround for when template aliases are unavailable.
2. `a.deallocate(this, 1)` -> `a.deallocate(pointer_traits<self>::pointer_to(*this), 1)`. This change change is made because fancy pointers aren't always constructible from raw pointers. 
3. `p.get()` -> `addressof(*p.get())`. Fancy pointers aren't actually a pointer. When we need a "real" pointer we take the address of dereferencing the fancy pointer. This should give us the actual raw pointer.

Test Plan: Tests were added using `support/min_allocator.h` to each affected shared_ptr overload and creation function. These tests can only be executed in C++11 or greater since min_allocator is only available then. A extra test was added for the non-variadic versions of allocate_shared. 

Reviewers: danalbert, mclow.lists

Reviewed By: mclow.lists

Subscribers: cfe-commits

Differential Revision: http://reviews.llvm.org/D4859

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@220469 91177308-0d34-0410-b5e6-96231b3b80d8
2014-10-23 04:12:28 +00:00

79 lines
1.8 KiB
C++

//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// <memory>
// shared_ptr
// template<class T, class A, class... Args>
// shared_ptr<T> allocate_shared(const A& a, Args&&... args);
#include <memory>
#include <new>
#include <cstdlib>
#include <cassert>
#include "test_allocator.h"
#include "min_allocator.h"
int new_count = 0;
struct A
{
static int count;
A(int i, char c) : int_(i), char_(c) {++count;}
A(const A& a)
: int_(a.int_), char_(a.char_)
{++count;}
~A() {--count;}
int get_int() const {return int_;}
char get_char() const {return char_;}
private:
int int_;
char char_;
};
int A::count = 0;
int main()
{
{
int i = 67;
char c = 'e';
std::shared_ptr<A> p = std::allocate_shared<A>(test_allocator<A>(54), i, c);
assert(test_allocator<A>::alloc_count == 1);
assert(A::count == 1);
assert(p->get_int() == 67);
assert(p->get_char() == 'e');
}
assert(A::count == 0);
assert(test_allocator<A>::alloc_count == 0);
#if __cplusplus >= 201103L
{
int i = 67;
char c = 'e';
std::shared_ptr<A> p = std::allocate_shared<A>(min_allocator<void>(), i, c);
assert(A::count == 1);
assert(p->get_int() == 67);
assert(p->get_char() == 'e');
}
assert(A::count == 0);
{
int i = 68;
char c = 'f';
std::shared_ptr<A> p = std::allocate_shared<A>(bare_allocator<void>(), i, c);
assert(A::count == 1);
assert(p->get_int() == 68);
assert(p->get_char() == 'f');
}
assert(A::count == 0);
#endif
}