public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Fwd: [PATCH][GSoC] Extend shared_ptr to support arrays
       [not found] <CALvpekGQvTp2zRz65cnP+Ex7TKHQygdrYkqo5nUKGJ3bLQj8ww@mail.gmail.com>
@ 2015-06-11 15:36 ` Fan You
  2015-06-11 15:44 ` Jonathan Wakely
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 9+ messages in thread
From: Fan You @ 2015-06-11 15:36 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 548 bytes --]

Hi,

This is my first patch for GSoC project: extend shared_ptr to support arrays.

Changes are made in these files:

* libstdc++-v3/include/bits/shared_ptr_base.h : Renamed
_Sp_counted_deleter to _Sp_counted_array, changed _shared_count
construct from _Sp_counted_ptr to _Sp_counted_array. Added
specialization for __shared_ptr and __weak_ptr to support array.

* libstdc++-v3/include/experimental/memory : add shared_ptr into fundamentals_v1

Is it too long for reviewing? Should I detach them into different
patches? Any comments?

Thanks,

Fan

[-- Attachment #2: a.patch --]
[-- Type: application/octet-stream, Size: 37999 bytes --]

Index: include/bits/shared_ptr_base.h
===================================================================
--- include/bits/shared_ptr_base.h	(revision 224363)
+++ include/bits/shared_ptr_base.h	(working copy)
@@ -353,6 +353,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     class enable_shared_from_this;
 
+  namespace experimental{
+  inline namespace fundamentals_v1 {
+    template<typename _Tp>
+      class enable_shared_from_this;
+  }
+  }
+
   template<_Lock_policy _Lp = __default_lock_policy>
     class __weak_count;
 
@@ -428,60 +435,61 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       _Tp _M_tp;
     };
 
-  // Support for custom deleter and/or allocator
+  // rename _Sp_counted_deleter to _Sp_counted_array
   template<typename _Ptr, typename _Deleter, typename _Alloc, _Lock_policy _Lp>
-    class _Sp_counted_deleter final : public _Sp_counted_base<_Lp>
+    class _Sp_counted_array : public _Sp_counted_base<_Lp> 
     {
       class _Impl : _Sp_ebo_helper<0, _Deleter>, _Sp_ebo_helper<1, _Alloc>
       {
 	typedef _Sp_ebo_helper<0, _Deleter>	_Del_base;
-	typedef _Sp_ebo_helper<1, _Alloc>	_Alloc_base;
-
+        typedef _Sp_ebo_helper<1, _Alloc>	_Alloc_base;
+          
       public:
 	_Impl(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept
-	: _M_ptr(__p), _Del_base(__d), _Alloc_base(__a)
-	{ }
-
-	_Deleter& _M_del() noexcept { return _Del_base::_S_get(*this); }
-	_Alloc& _M_alloc() noexcept { return _Alloc_base::_S_get(*this); }
-
-	_Ptr _M_ptr;
+      	: _M_ptr(__p), _Del_base(__d), _Alloc_base(__a)
+      	{ }
+        
+        _Deleter& _M_del() noexcept { return _Del_base::_S_get(*this); }
+        _Alloc& _M_alloc() noexcept { return _Alloc_base::_S_get(*this); }
+        
+        _Ptr _M_ptr;
       };
 
     public:
-      using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_deleter>;
+      using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_array>;
 
+      _Sp_counted_array(_Ptr __p) noexcept
+      : _M_impl(__p, _Deleter(), _Alloc()) { }
+      
       // __d(__p) must not throw.
-      _Sp_counted_deleter(_Ptr __p, _Deleter __d) noexcept
+      _Sp_counted_array(_Ptr __p, _Deleter __d) noexcept
       : _M_impl(__p, __d, _Alloc()) { }
-
+      
       // __d(__p) must not throw.
-      _Sp_counted_deleter(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept
+      _Sp_counted_array(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept
       : _M_impl(__p, __d, __a) { }
-
-      ~_Sp_counted_deleter() noexcept { }
-
+      
+      ~_Sp_counted_array() noexcept { }
+      
       virtual void
       _M_dispose() noexcept
       { _M_impl._M_del()(_M_impl._M_ptr); }
-
+      
       virtual void
       _M_destroy() noexcept
       {
-	__allocator_type __a(_M_impl._M_alloc());
-	__allocated_ptr<__allocator_type> __guard_ptr{ __a, this };
-	this->~_Sp_counted_deleter();
+	typedef typename allocator_traits<_Alloc>::template
+      	rebind_traits<_Sp_counted_array> _Alloc_traits;
+      	typename _Alloc_traits::allocator_type __a(_M_impl._M_alloc());
+      	_Alloc_traits::destroy(__a, this);
+      	_Alloc_traits::deallocate(__a, this, 1);
       }
-
+      
       virtual void*
       _M_get_deleter(const std::type_info& __ti) noexcept
       {
-#if __cpp_rtti
-	// _GLIBCXX_RESOLVE_LIB_DEFECTS
-	// 2400. shared_ptr's get_deleter() should use addressof()
-        return __ti == typeid(_Deleter)
-	  ? std::__addressof(_M_impl._M_del())
-	  : nullptr;
+#ifdef __GXX_RTTI
+	return __ti == typeid(_Deleter) ? &_M_impl._M_del() : nullptr;
 #else
         return nullptr;
 #endif
@@ -565,20 +573,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       constexpr __shared_count() noexcept : _M_pi(0)
       { }
 
+      // replace _Sp_counted_ptr here
       template<typename _Ptr>
-        explicit
-	__shared_count(_Ptr __p) : _M_pi(0)
-	{
-	  __try
-	    {
-	      _M_pi = new _Sp_counted_ptr<_Ptr, _Lp>(__p);
-	    }
-	  __catch(...)
-	    {
-	      delete __p;
-	      __throw_exception_again;
-	    }
-	}
+	explicit
+	__shared_count(_Ptr __p)
+	: __shared_count(__p, [](_Ptr __p){delete __p;}, allocator<void>())
+	{ }
 
       template<typename _Ptr, typename _Deleter>
 	__shared_count(_Ptr __p, _Deleter __d)
@@ -588,7 +588,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       template<typename _Ptr, typename _Deleter, typename _Alloc>
 	__shared_count(_Ptr __p, _Deleter __d, _Alloc __a) : _M_pi(0)
 	{
-	  typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type;
+	  typedef _Sp_counted_array<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type;
 	  __try
 	    {
 	      typename _Sp_cd_type::__allocator_type __a2(__a);
@@ -642,7 +642,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	      reference_wrapper<typename remove_reference<_Del>::type>,
 	      _Del>::type;
 	  using _Sp_cd_type
-	    = _Sp_counted_deleter<_Ptr, _Del2, allocator<void>, _Lp>;
+	    = _Sp_counted_array<_Ptr, _Del2, allocator<void>, _Lp>;
 	  using _Alloc = allocator<_Sp_cd_type>;
 	  using _Alloc_traits = allocator_traits<_Alloc>;
 	  _Alloc __a;
@@ -868,6 +868,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { }
 
 
+  // extend shared_ptr to support array tag
+  template <typename _Tp>
+    struct __libfund_v1 { using type = _Tp; };
+
   template<typename _Tp, _Lock_policy _Lp>
     class __shared_ptr
     {
@@ -1181,6 +1185,592 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __shared_count<_Lp>  _M_refcount;    // Reference counter.
     };
 
+  // alias for original __shared_ptr
+  template <typename _Tp, _Lock_policy _Lp>
+    class __shared_ptr<__libfund_v1<_Tp>, _Lp> : public __shared_ptr<_Tp, _Lp>
+    { 
+    public:
+      template<typename _Ptr>
+	using _Convertible
+	  = typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
+
+      using element_type = _Tp;
+      using __base_type = __shared_ptr<_Tp, _Lp>;
+
+      constexpr __shared_ptr() noexcept
+      : __base_type()
+      { }
+
+      template<typename _Tp1>
+	explicit __shared_ptr(_Tp1* __p)
+	: __base_type(__p)
+	{ }
+
+      template<typename _Tp1, typename _Deleter>
+	__shared_ptr(_Tp1* __p, _Deleter __d)
+	: __base_type(__p, __d)
+	{ }
+
+      template<typename _Tp1, typename _Deleter, typename _Alloc>
+	__shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
+	: __base_type(__p, __d, __a)
+	{ }
+
+      template<typename _Deleter>
+	__shared_ptr(nullptr_t __p, _Deleter __d)
+	: __base_type(__p, __d)
+	{ }
+
+      template<typename _Deleter, typename _Alloc>
+	__shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
+	: __base_type(__p, __d, __a)
+	{ }
+
+      template<typename _Tp1>
+	__shared_ptr(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __r, _Tp* __p) noexcept
+	: __base_type(__r, __p)
+	{ }
+
+      __shared_ptr(const __shared_ptr&) noexcept = default;
+      __shared_ptr& operator=(const __shared_ptr&) noexcept = default;
+      ~__shared_ptr() = default;
+
+      template<typename _Tp1, typename = _Convertible<_Tp1*>>
+	__shared_ptr(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
+	: __base_type(__r)
+	{ }
+
+      template<typename _Tp1, typename = _Convertible<_Tp1*>>
+	__shared_ptr(__shared_ptr<__libfund_v1<_Tp1>, _Lp>&& __r) noexcept
+	: __base_type(__r)
+	{ }
+
+      template<typename _Tp1>
+	explicit __shared_ptr(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __r)
+	: __base_type(__r)
+	{ }
+
+      // If an exception is thrown this constructor has no effect.
+      template<typename _Tp1, typename _Del, typename
+               = _Convertible<typename unique_ptr<_Tp1, _Del>::pointer>>
+        __shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
+	 : __base_type(__r)
+	 { }
+
+#if _GLIBCXX_USE_DEPRECATED
+      // Postcondition: use_count() == 1 and __r.get() == 0
+      template<typename _Tp1>
+        __shared_ptr(std::auto_ptr<_Tp1>&& __r);
+#endif
+
+      constexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { }
+    };
+
+  // array support
+  template<typename _Tp, _Lock_policy _Lp, unsigned N>
+    class __shared_ptr<__libfund_v1<_Tp[N]>, _Lp>
+    {
+      template<typename _Ptr>
+	using _Convertible
+	  = typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
+
+    public:
+      using element_type = _Tp[N];
+
+      constexpr __shared_ptr() noexcept
+      : _M_ptr(0), _M_refcount()
+      { }
+      
+      template<typename _Tp1>
+	explicit __shared_ptr(_Tp1* __p)
+      	: _M_ptr(__p), _M_refcount(__p, _Array_Deleter()) // default deleter
+      	{
+	  __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
+      	  static_assert( !is_void<_Tp1>::value, "incomplete type" );
+      	  static_assert( sizeof(_Tp1) > 0, "incomplete type" );
+      	  __enable_shared_from_this_helper(_M_refcount, __p, __p);
+      	}
+      
+      template<typename _Tp1, typename _Deleter>
+	__shared_ptr(_Tp1* __p, _Deleter __d)
+      	: _M_ptr(__p), _M_refcount(__p, __d) // custom deleter // nullptr
+      	{
+      	  __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
+      	  __enable_shared_from_this_helper(_M_refcount, __p, __p);
+      	}
+      
+      template<typename _Tp1, typename _Deleter, typename _Alloc>
+	__shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
+      	: _M_ptr(__p), _M_refcount(__p, __d, std::move(__a))
+      	{
+      	  __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
+      	  __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, _Alloc __a)
+	: _M_ptr(0), _M_refcount(__p, __d, std::move(__a))
+	{ }
+
+      template<typename _Tp1>
+	__shared_ptr(const __shared_ptr<__libfund_v1<_Tp1[N]>, _Lp>&
+		     __r, _Tp* __p) noexcept
+	: _M_ptr(__p), _M_refcount(__r._M_refcount)
+	{ }
+
+      __shared_ptr(const __shared_ptr&) noexcept = default;
+      __shared_ptr& operator=(const __shared_ptr&) noexcept = default;
+      ~__shared_ptr() = default;
+
+      template<typename _Tp1, typename = _Convertible<_Tp1*>>
+	__shared_ptr(const __shared_ptr<__libfund_v1<_Tp1[N]>, _Lp>& __r) noexcept
+	: _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
+	{ }
+
+      template<typename _Tp1, typename = _Convertible<_Tp1*>>
+	__shared_ptr(__shared_ptr<__libfund_v1<_Tp1[N]>, _Lp>&& __r) noexcept
+	: _M_ptr(__r._M_ptr), _M_refcount()
+	{
+	  _M_refcount._M_swap(__r._M_refcount);
+	  __r._M_ptr = 0;
+	}
+
+      template<typename _Tp1>
+	explicit __shared_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
+	: _M_refcount(__r._M_refcount) // may throw
+	{
+	  __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
+	  _M_ptr = __r._M_ptr;
+	}
+
+      template<typename _Tp1, typename _Del, typename
+	      = _Convertible<typename unique_ptr<_Tp1, _Del>::pointer>>
+	  __shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
+	  : _M_ptr(__r.get()), _M_refcount()
+	  {
+	    __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
+	    auto __raw = _S_raw_ptr(__r.get());
+	    _M_refcount = __shared_count<_Lp>(std::move(__r));
+	    __enable_shared_from_this_helper(_M_refcount, __raw, __raw);
+	  }
+
+      // Array did not support construct from auto_ptr
+
+      constexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { }
+
+      template<typename _Tp1>
+	__shared_ptr&
+	operator=(const __shared_ptr<__libfund_v1<_Tp1[N]>, _Lp>& __r) noexcept
+	{
+	  _M_ptr = __r._M_ptr;
+	  _M_refcount = __r._M_refcount;
+	  return *this;
+	}
+
+      template<class _Tp1>
+	__shared_ptr&
+	operator=(__shared_ptr<__libfund_v1<_Tp1[N]>, _Lp>&& __r) noexcept
+	{
+	  __shared_ptr(std::move(__r)).swap(*this);
+	  return *this;
+	}
+
+      template<typename _Tp1, typename _Del>
+	__shared_ptr&
+	operator=(std::unique_ptr<_Tp1, _Del>&& __r)
+	{
+	  __shared_ptr(std::move(__r)).swap(*this);
+	  return *this;
+	}
+
+      // reset
+      void
+      reset() noexcept
+      { __shared_ptr(nullptr, _Array_Deleter()).swap(*this); }
+
+      template<typename _Tp1>
+	void
+	reset(_Tp1* __p)
+	{
+	  _GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != _M_ptr);
+	  __shared_ptr(__p, _Array_Deleter()).swap(*this);
+	}
+
+      template<typename _Tp1, typename _Deleter>
+	void
+	reset(_Tp1* __p, _Deleter __d)
+	{ __shared_ptr(__p, __d).swap(*this); }
+
+      template<typename _Tp1, typename _Deleter, typename _Alloc>
+	void
+	reset(_Tp1* __p, _Deleter __d, _Alloc __a)
+	{ __shared_ptr(__p, __d, std::move(__a)).swap(*this); }
+
+      //observers
+      typename std::add_lvalue_reference<_Tp>::type
+	operator*() const noexcept
+	{
+	  _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
+	  return *_M_ptr;
+	}
+
+      _Tp*
+      operator->() const noexcept
+      {
+        _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
+        return _M_ptr;
+      }
+
+      _Tp&
+      operator[](ptrdiff_t i) const noexcept
+      {
+        _GLIBCXX_DEBUG_ASSERT(get() !=0 && i>=0);
+        return _M_ptr[i];
+      }
+      
+      _Tp*
+      get() const noexcept
+      {	return _M_ptr; }
+
+      explicit operator bool() const
+      { return _M_ptr == 0 ? false : true; }
+      
+      bool
+      unique() const noexcept
+      { return _M_refcount._M_unique(); }
+
+      long
+      use_count() const noexcept
+      { return _M_refcount._M_get_use_count(); }
+
+      void
+      swap(__shared_ptr<__libfund_v1<_Tp[N]>, _Lp>& __other) noexcept
+      {
+        std::swap(_M_ptr, __other._M_ptr);
+        _M_refcount._M_swap(__other._M_refcount);
+      }
+
+      template<typename _Tp1>
+	bool
+	owner_before(__shared_ptr<__libfund_v1<_Tp1[N]>, _Lp> const& __rhs) const
+	{ return _M_refcount._M_less(__rhs._M_refcount); }
+
+      template<typename _Tp1>
+	bool
+	owner_before(__weak_ptr<__libfund_v1<_Tp1[N]>, _Lp> const& __rhs) const
+	{ return _M_refcount._M_less(__rhs._M_refcount); }
+      
+    protected:
+        
+      // forward args for shared_count
+      template<typename _Alloc, typename... _Args>
+	__shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
+      	             _Args&&... __args)
+      	: _M_ptr(), _M_refcount(__tag, (_Tp*)0, __a,
+      	                        std::forward<_Args>(__args)...)
+      	{
+      	  void* __p = _M_refcount._M_get_deleter(typeid(__tag));
+      	  _M_ptr = static_cast<_Tp*>(__p);
+      	  __enable_shared_from_this_helper(_M_refcount, _M_ptr, _M_ptr);
+      	}
+      
+      struct _Array_Deleter
+      {
+        void
+        operator()(_Tp const *__p) const
+        {
+          delete [] __p;
+        }
+      };
+      
+      // __weak_ptr::lock()
+      __shared_ptr(const __weak_ptr<_Tp[N], _Lp>& __r, std::nothrow_t)
+      : _M_refcount(__r._M_refcount, std::nothrow)
+      {
+        _M_ptr = _M_refcount._M_get_use_count() ?  __r._M_ptr : nullptr;
+      }
+      
+    private:
+      void*
+      _M_get_deleter(const std::type_info& __ti) const noexcept
+      { return _M_refcount._M_get_deleter(__ti); }
+
+      template<typename _Tp1>
+	static _Tp1*
+	_S_raw_ptr(_Tp1* __ptr)
+	{ return __ptr; }
+
+      template<typename _Tp1>
+	static auto
+	_S_raw_ptr(_Tp1 __ptr) -> decltype(std::__addressof(*__ptr))
+	{ return std::__addressof(*__ptr); }
+      
+      template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
+      template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
+      
+      template<typename _Del, typename _Tp1, _Lock_policy _Lp1>
+	friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept;
+      
+      _Tp*		  _M_ptr;	//ptr
+      __shared_count<_Lp> _M_refcount;	//ref counter
+    };
+
+  template<typename _Tp, _Lock_policy _Lp>
+    class __shared_ptr<__libfund_v1<_Tp[]>, _Lp>
+    {
+      template<typename _Ptr>
+	using _Convertible
+	  = typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
+
+    public:
+      using element_type = _Tp;
+
+      constexpr __shared_ptr() noexcept
+      : _M_ptr(0), _M_refcount()
+      { }
+      
+      template<typename _Tp1>
+	explicit __shared_ptr(_Tp1* __p)
+      	: _M_ptr(__p), _M_refcount(__p, _Array_Deleter()) // default deleter
+      	{
+	  __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
+      	  static_assert( !is_void<_Tp1>::value, "incomplete type" );
+      	  static_assert( sizeof(_Tp1) > 0, "incomplete type" );
+      	  __enable_shared_from_this_helper(_M_refcount, __p, __p);
+      	}
+      
+      template<typename _Tp1, typename _Deleter>
+	__shared_ptr(_Tp1* __p, _Deleter __d)
+      	: _M_ptr(__p), _M_refcount(__p, __d) // custom deleter // nullptr
+      	{
+      	  __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
+      	  __enable_shared_from_this_helper(_M_refcount, __p, __p);
+      	}
+      
+      template<typename _Tp1, typename _Deleter, typename _Alloc>
+	__shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
+      	: _M_ptr(__p), _M_refcount(__p, __d, std::move(__a))
+      	{
+      	  __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
+      	  __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, _Alloc __a)
+	: _M_ptr(0), _M_refcount(__p, __d, std::move(__a))
+	{ }
+
+      template<typename _Tp1>
+	__shared_ptr(const __shared_ptr<__libfund_v1<_Tp1[]>, _Lp>&
+		     __r, _Tp* __p) noexcept
+	: _M_ptr(__p), _M_refcount(__r._M_refcount)
+	{ }
+
+      __shared_ptr(const __shared_ptr&) noexcept = default;
+      __shared_ptr& operator=(const __shared_ptr&) noexcept = default;
+      ~__shared_ptr() = default;
+
+      template<typename _Tp1, typename = _Convertible<_Tp1*>>
+	__shared_ptr(const __shared_ptr<__libfund_v1<_Tp1[]>, _Lp>& __r) noexcept
+	: _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
+	{ }
+
+      template<typename _Tp1, typename = _Convertible<_Tp1*>>
+	__shared_ptr(__shared_ptr<__libfund_v1<_Tp1[]>, _Lp>&& __r) noexcept
+	: _M_ptr(__r._M_ptr), _M_refcount()
+	{
+	  _M_refcount._M_swap(__r._M_refcount);
+	  __r._M_ptr = 0;
+	}
+
+      template<typename _Tp1>
+	explicit __shared_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
+	: _M_refcount(__r._M_refcount) // may throw
+	{
+	  __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
+	  _M_ptr = __r._M_ptr;
+	}
+
+      template<typename _Tp1, typename _Del, typename
+	      = _Convertible<typename unique_ptr<_Tp1, _Del>::pointer>>
+	  __shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
+	  : _M_ptr(__r.get()), _M_refcount()
+	  {
+	    __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
+	    auto __raw = _S_raw_ptr(__r.get());
+	    _M_refcount = __shared_count<_Lp>(std::move(__r));
+	    __enable_shared_from_this_helper(_M_refcount, __raw, __raw);
+	  }
+
+      // shared_ptr Array did not support construct from auto_ptr
+
+      constexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { }
+
+      template<typename _Tp1>
+	__shared_ptr&
+	operator=(const __shared_ptr<__libfund_v1<_Tp1[]>, _Lp>& __r) noexcept
+	{
+	  _M_ptr = __r._M_ptr;
+	  _M_refcount = __r._M_refcount;
+	  return *this;
+	}
+
+      template<class _Tp1>
+	__shared_ptr&
+	operator=(__shared_ptr<__libfund_v1<_Tp1[]>, _Lp>&& __r) noexcept
+	{
+	  __shared_ptr(std::move(__r)).swap(*this);
+	  return *this;
+	}
+
+      template<typename _Tp1, typename _Del>
+	__shared_ptr&
+	operator=(std::unique_ptr<_Tp1, _Del>&& __r)
+	{
+	  __shared_ptr(std::move(__r)).swap(*this);
+	  return *this;
+	}
+
+      // reset
+      void
+      reset() noexcept
+      { __shared_ptr(nullptr, _Array_Deleter()).swap(*this); }
+
+      template<typename _Tp1>
+	void
+	reset(_Tp1* __p)
+	{
+	  _GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != _M_ptr);
+	  __shared_ptr(__p, _Array_Deleter()).swap(*this);
+	}
+
+      template<typename _Tp1, typename _Deleter>
+	void
+	reset(_Tp1* __p, _Deleter __d)
+	{ __shared_ptr(__p, __d).swap(*this); }
+
+      template<typename _Tp1, typename _Deleter, typename _Alloc>
+	void
+	reset(_Tp1* __p, _Deleter __d, _Alloc __a)
+	{ __shared_ptr(__p, __d, std::move(__a)).swap(*this); }
+
+      //observers
+      typename std::add_lvalue_reference<_Tp>::type
+	operator*() const noexcept
+	{
+	  _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
+	  return *_M_ptr;
+	}
+
+      _Tp*
+      operator->() const noexcept
+      {
+        _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
+        return _M_ptr;
+      }
+
+      _Tp&
+      operator[](ptrdiff_t i) const noexcept
+      {
+        return _M_ptr[i];
+      }
+      
+      _Tp*
+      get() const noexcept
+      {	return _M_ptr; }
+
+      explicit operator bool() const
+      { return _M_ptr == 0 ? false : true; }
+      
+      bool
+      unique() const noexcept
+      { return _M_refcount._M_unique(); }
+
+      long
+      use_count() const noexcept
+      { return _M_refcount._M_get_use_count(); }
+
+      void
+      swap(__shared_ptr<__libfund_v1<_Tp[]>, _Lp>& __other) noexcept
+      {
+        std::swap(_M_ptr, __other._M_ptr);
+        _M_refcount._M_swap(__other._M_refcount);
+      }
+
+      template<typename _Tp1>
+	bool
+	owner_before(__shared_ptr<__libfund_v1<_Tp1[]>, _Lp> const& __rhs) const
+	{ return _M_refcount._M_less(__rhs._M_refcount); }
+
+      template<typename _Tp1>
+	bool
+	owner_before(__weak_ptr<__libfund_v1<_Tp1[]>, _Lp> const& __rhs) const
+	{ return _M_refcount._M_less(__rhs._M_refcount); }
+      
+    protected:
+        
+      // forward args for shared_count
+      template<typename _Alloc, typename... _Args>
+	__shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
+      	             _Args&&... __args)
+      	: _M_ptr(), _M_refcount(__tag, (_Tp*)0, __a,
+      	                        std::forward<_Args>(__args)...)
+      	{
+      	  void* __p = _M_refcount._M_get_deleter(typeid(__tag));
+      	  _M_ptr = static_cast<_Tp*>(__p);
+      	  __enable_shared_from_this_helper(_M_refcount, _M_ptr, _M_ptr);
+      	}
+      
+      struct _Array_Deleter
+      {
+        void
+        operator()(_Tp const *__p) const
+        {
+          delete [] __p;
+        }
+      };
+      
+      // __weak_ptr::lock()
+      __shared_ptr(const __weak_ptr<_Tp[], _Lp>& __r, std::nothrow_t)
+      : _M_refcount(__r._M_refcount, std::nothrow)
+      {
+        _M_ptr = _M_refcount._M_get_use_count() ?  __r._M_ptr : nullptr;
+      }
+      
+    private:
+      void*
+      _M_get_deleter(const std::type_info& __ti) const noexcept
+      { return _M_refcount._M_get_deleter(__ti); }
+
+      template<typename _Tp1>
+	static _Tp1*
+	_S_raw_ptr(_Tp1* __ptr)
+	{ return __ptr; }
+
+      template<typename _Tp1>
+	static auto
+	_S_raw_ptr(_Tp1 __ptr) -> decltype(std::__addressof(*__ptr))
+	{ return std::__addressof(*__ptr); }
+      
+      template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
+      template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
+      
+      template<typename _Del, typename _Tp1, _Lock_policy _Lp1>
+	friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept;
+      
+      _Tp*		  _M_ptr;	//ptr
+      __shared_count<_Lp> _M_refcount;	//ref counter
+    };
 
   // 20.7.2.2.7 shared_ptr comparisons
   template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
@@ -1476,6 +2066,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
       template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
+      friend class experimental::enable_shared_from_this<_Tp>;
       friend class __enable_shared_from_this<_Tp, _Lp>;
       friend class enable_shared_from_this<_Tp>;
 
@@ -1483,6 +2074,42 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __weak_count<_Lp>  _M_refcount;    // Reference counter.
     };
 
+  template<typename _Tp, _Lock_policy _Lp>
+    class __weak_ptr<__libfund_v1<_Tp>, _Lp> : public __weak_ptr<_Tp, _Lp>
+    {
+      template<typename _Ptr>
+	using _Convertible
+	  = typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
+
+      using __base_type = __weak_ptr<_Tp, _Lp>;
+
+    public:
+      typedef _Tp element_type;
+
+      constexpr __weak_ptr() noexcept
+      : __base_type()
+      { }
+
+      __weak_ptr(const __weak_ptr&) noexcept = default;
+
+      ~__weak_ptr() = default;
+
+      template<typename _Tp1, typename = _Convertible<_Tp1*>>
+	__weak_ptr(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
+	: __base_type(__r)
+      	{ }
+
+      template<typename _Tp1, typename = _Convertible<_Tp1*>>
+	__weak_ptr(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
+	: __base_type(__r)
+      	{ }
+
+      template<typename _Tp1, typename = _Convertible<_Tp1*>>
+	__weak_ptr(__weak_ptr<__libfund_v1<_Tp1>, _Lp>&& __r) noexcept
+	: __base_type(__r)
+	{ }
+    };
+
   // 20.7.2.3.6 weak_ptr specialized algorithms.
   template<typename _Tp, _Lock_policy _Lp>
     inline void
Index: include/experimental/memory
===================================================================
--- include/experimental/memory	(revision 224363)
+++ include/experimental/memory	(working copy)
@@ -233,6 +233,411 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace fundamentals_v2
+inline namespace fundamentals_v1
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+#define __cpp_lib_experimental_shared_ptr_array 201506
+
+  //  8.2.1
+  template<typename _Tp> class shared_ptr;
+
+  //for non default lock policy
+  template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
+    using __shared_ptr = std::__shared_ptr<_Tp, _Lp>;
+
+  template<typename _Tp>
+    class shared_ptr : public __shared_ptr<__libfund_v1<_Tp>>
+    {
+    public:
+      template<typename _Ptr>
+	using _Convertible 
+	  = typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
+
+      using __base_type = __shared_ptr<__libfund_v1<_Tp>>;
+      using element_type = typename remove_extent<_Tp>::type;
+
+      // 8.2.1.1, shared_ptr constructors
+      constexpr shared_ptr() noexcept = default;
+
+      template<typename _Tp1>
+        explicit shared_ptr(_Tp1* __p) : __base_type(__p) { }
+
+      template<typename _Tp1, typename _Deleter> 
+        shared_ptr(_Tp1* __p, _Deleter __d)
+        : __base_type(__p, __d) { }
+
+      template<typename _Tp1, typename _Deleter, typename _Alloc> 
+        shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
+        : __base_type(__p, __d, __a) { }
+
+      template<typename _Deleter>
+        shared_ptr(nullptr_t __p, _Deleter __d)
+        : __base_type(__p, __d) { }
+
+      template<typename _Deleter, typename _Alloc>
+        shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
+        : __base_type(__p, __d, __a) { }
+
+      template<typename _Tp1>
+        shared_ptr(const shared_ptr<_Tp1>& __r, _Tp* __p) noexcept
+        : __base_type(__r, __p) { }
+
+      shared_ptr(const shared_ptr& __r) noexcept
+	: __base_type(__r) { }
+
+      template<typename _Tp1, typename = typename
+	       std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type> 
+	shared_ptr(const shared_ptr<_Tp1>& __r) noexcept
+	: __base_type(__r) { }
+
+      shared_ptr(const shared_ptr<_Tp>&& __r) noexcept
+      : __base_type(std::move(__r)) { }
+
+      template<typename _Tp1, typename = typename
+	       std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type> 
+	shared_ptr(shared_ptr<_Tp1>&& __r) noexcept
+	: __base_type(std::move(__r)) { }
+
+      template<typename _Tp1>
+        explicit shared_ptr(const weak_ptr<__libfund_v1<_Tp1>>& __r)
+        : __base_type(__r) { }
+
+      // construction from auto_ptr is not supported for shared_ptr<T[]>
+
+#if _GLIBCXX_USE_DEPRECATED
+      template<typename _Tp1>
+	shared_ptr(std::auto_ptr<_Tp1>&& __r)
+	: __base_type() { }
+#endif
+
+      template<typename _Tp1, typename _Del, typename
+	       = _Convertible<typename unique_ptr<_Tp1, _Del>::pointer>>
+	  shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
+	  : __base_type(std::move(__r)) { }
+
+      constexpr shared_ptr(nullptr_t __p)
+      : __base_type(__p) { }
+
+      // C++14 §20.8.2.2
+      ~shared_ptr() = default;
+
+      // C++14 §20.8.2.3
+      shared_ptr& operator=(const shared_ptr&) noexcept = default;
+
+      template <typename _Tp1>
+	shared_ptr& 
+      	operator=(const shared_ptr<_Tp1>& __r) noexcept
+	{
+	  this->__base_type::operator=(__r);
+	  return *this;
+	}
+
+      shared_ptr& 
+      operator=(shared_ptr&& __r) noexcept
+      {
+        this->__base_type::operator=(std::move(__r));
+        return *this;
+      }
+
+      template <typename _Tp1>
+	shared_ptr& 
+      	operator=(shared_ptr<_Tp1>&& __r) noexcept
+	{
+	  this->__base_type::operator=(std::move(__r));
+	  return *this;
+	}
+      
+      // no auto ptr
+
+      template <typename _Tp1, typename _Del> 
+	shared_ptr& 
+	operator=(unique_ptr<_Tp1, _Del>&& __r)
+	{
+	  this->__base_type::operator=(std::move(__r));
+	  return *this;
+	}
+
+      // C++14 §20.8.2.2.4
+      // swap & reset
+      // 8.2.1.2 shared_ptr observers 
+      // in __shared_ptr_base.h
+
+    private:
+      template<typename _Alloc, typename... _Args>
+      shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
+        	 _Args&&... __args)
+      : __base_type(__tag, __a, std::forward<_Args>(__args)...)
+      { }
+
+      template<typename _Tp1, typename _Alloc, typename... _Args>
+	friend shared_ptr<_Tp1>
+	allocate_shared(const _Alloc& __a, _Args&&...  __args);
+
+      shared_ptr(const weak_ptr<__libfund_v1<_Tp>>& __r, std::nothrow_t)
+      : __base_type(__r, std::nothrow) { }
+
+      friend class weak_ptr<__libfund_v1<_Tp>>;
+    };
+
+  // C++14 §20.8.2.2.7 //DOING
+   template<typename _Tp1, typename _Tp2>
+     bool operator==(const shared_ptr<_Tp1>& __a, 
+		     const shared_ptr<_Tp2>& __b) noexcept
+     { return __a.get() == __b.get(); }
+
+   template<typename _Tp>
+     inline bool
+     operator==(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
+     { return !__a; }
+
+   template<typename _Tp>
+     inline bool
+     operator==(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
+     { return !__a; }
+
+   template<typename _Tp1, typename _Tp2>
+     inline bool
+     operator!=(const shared_ptr<_Tp1>& __a,
+		const shared_ptr<_Tp2>& __b) noexcept
+     { return __a.get() != __b.get(); }
+
+   template<typename _Tp>
+     inline bool
+     operator!=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
+     { return (bool)__a; }
+
+   template<typename _Tp>
+     inline bool
+     operator!=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
+     { return (bool)__a; }
+
+   template<typename _Tp1, typename _Tp2>
+     inline bool
+     operator<(const shared_ptr<_Tp1>& __a,
+	       const shared_ptr<_Tp2>& __b) noexcept
+     {
+       using _Tp1_RE = typename remove_extent<_Tp1>::type;
+       using _Tp2_RE = typename remove_extent<_Tp2>::type;
+       using _CT = typename std::common_type<_Tp1_RE*, _Tp2_RE*>::type;
+       return std::less<_CT>()(__a.get(), __b.get());
+     }
+
+   template<typename _Tp>
+     inline bool
+     operator<(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
+     { 
+       using _Tp_RE = typename remove_extent<_Tp>::type;
+       return std::less<_Tp_RE>()(__a.get(), nullptr); 
+     }
+
+   template<typename _Tp>
+     inline bool
+     operator<(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
+     { 
+       using _Tp_RE = typename remove_extent<_Tp>::type;
+       return std::less<_Tp_RE*>()(nullptr, __a.get()); 
+     }
+
+   template<typename _Tp1, typename _Tp2>
+     inline bool
+     operator<=(const shared_ptr<_Tp1>& __a,
+		const shared_ptr<_Tp2>& __b) noexcept
+     { return !(__b < __a); }
+
+   template<typename _Tp>
+     inline bool
+     operator<=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
+     { return !(nullptr < __a); }
+
+   template<typename _Tp>
+     inline bool
+     operator<=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
+     { return !(__a < nullptr); }
+
+   template<typename _Tp1, typename _Tp2>
+     inline bool
+     operator>(const shared_ptr<_Tp1>& __a,
+	       const shared_ptr<_Tp2>& __b) noexcept
+     { return (__b < __a); }
+
+   template<typename _Tp>
+     inline bool
+     operator>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
+     { 
+       using _Tp_RE = typename remove_extent<_Tp>::type;
+       return std::less<_Tp_RE*>()(nullptr, __a.get()); 
+     }
+
+   template<typename _Tp>
+     inline bool
+     operator>(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
+     { 
+       using _Tp_RE = typename remove_extent<_Tp>::type;
+       return std::less<_Tp_RE*>()(__a.get(), nullptr); 
+     }
+
+   template<typename _Tp1, typename _Tp2>
+     inline bool
+     operator>=(const shared_ptr<_Tp1>& __a,
+		const shared_ptr<_Tp2>& __b) noexcept
+     { return !(__a < __b); }
+
+   template<typename _Tp>
+     inline bool
+     operator>=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
+     { return !(__a < nullptr); }
+
+   template<typename _Tp>
+     inline bool
+     operator>=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
+     { return !(nullptr < __a); }
+
+   // C++14 §20.8.2.2.8
+   template<typename _Tp>
+     inline void
+     swap(shared_ptr<_Tp>& __a, shared_ptr<_Tp>& __b) noexcept
+     { __a.swap(__b); }
+
+   // 8.2.1.3, shared_ptr casts
+   template<typename _Tp, typename _Tp1>
+     inline shared_ptr<_Tp>
+     static_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
+     { return shared_ptr<_Tp>(__r, static_cast<_Tp*>(__r.get())); }
+
+   template<typename _Tp, typename _Tp1>
+     inline shared_ptr<_Tp>
+     dynamic_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
+     {
+       if (_Tp* __p = dynamic_cast<_Tp*>(__r.get()))
+         return shared_ptr<_Tp>(__r, __p);
+       return shared_ptr<_Tp>();
+     }
+
+   template<typename _Tp, typename _Tp1>
+     inline shared_ptr<_Tp>
+     const_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
+     { return shared_ptr<_Tp>(__r, const_cast<_Tp*>(__r.get())); }
+
+   template<typename _Tp, typename _Tp1>
+     inline shared_ptr<_Tp>
+     reinterpret_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
+     { return shared_ptr<_Tp>(__r, reinterpret_cast<_Tp*>(__r.get())); }
+
+   // C++14 §20.8.2.6
+   template<typename _Tp>
+     inline bool
+     atomic_is_lock_free(const shared_ptr<_Tp>* __p)
+     { return std::atomic_is_lock_free<_Tp, __default_lock_policy>(__p); }
+
+   template<typename _Tp>
+     shared_ptr<_Tp> atomic_load(const shared_ptr<_Tp>* __p)
+     { return std::atomic_load<_Tp>(__p); }
+
+   template<typename _Tp>
+     shared_ptr<_Tp>
+     atomic_load_explicit(const shared_ptr<_Tp>* __p, memory_order __mo)
+     { return std::atomic_load_explicit<_Tp>(__p, __mo); }
+
+   template<typename _Tp>
+     void atomic_store(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r)
+     { return std::atomic_store<_Tp>(__p, __r); }
+
+   template<typename _Tp>
+     shared_ptr<_Tp>
+     atomic_store_explicit(const shared_ptr<_Tp>* __p,
+			    shared_ptr<_Tp> __r,
+			    memory_order __mo)
+     { return std::atomic_store_explicit<_Tp>(__p, __r, __mo); }
+
+   template<typename _Tp>
+     void atomic_exchange(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r)
+     { return std::atomic_exchange<_Tp>(__p, __r); }
+
+   template<typename _Tp>
+     shared_ptr<_Tp>
+     atomic_exchange_explicit(const shared_ptr<_Tp>* __p,
+			       shared_ptr<_Tp> __r,
+			       memory_order __mo)
+     { return std::atomic_exchange_explicit<_Tp>(__p, __r, __mo); }
+
+   template<typename _Tp>
+     bool atomic_compare_exchange_weak(shared_ptr<_Tp>* __p,
+				        shared_ptr<_Tp>* __v,
+				        shared_ptr<_Tp> __w) 
+     { return std::atomic_compare_exchange_weak<_Tp>(__p, __v, __w); }
+
+   template<typename _Tp>
+     bool atomic_compare_exchange_strong(shared_ptr<_Tp>* __p,
+					  shared_ptr<_Tp>* __v,
+					  shared_ptr<_Tp> __w) 
+     { return std::atomic_compare_exchange_strong<_Tp>(__p, __v, __w); }
+
+   template<typename _Tp>
+     bool atomic_compare_exchange_weak_explicit(shared_ptr<_Tp>* __p,
+						 shared_ptr<_Tp>* __v,
+						 shared_ptr<_Tp> __w,
+						 memory_order __success, 
+						 memory_order __failure) 
+     { return std::atomic_compare_exchange_weak_explicit<_Tp>(__p, __v, __w,
+							       __success,
+							       __failure); }
+
+   template<typename _Tp>
+     bool atomic_compare_exchange_strong_explicit(shared_ptr<_Tp>* __p,
+						   shared_ptr<_Tp>* __v,
+						   shared_ptr<_Tp> __w,
+						   memory_order __success, 
+						   memory_order __failure) 
+     { return std::atomic_compare_exchange_strong_explicit<_Tp>(__p, __v, __w,
+								 __success,
+								 __failure); }
+
+  //enable_shared_from_this
+  template<typename _Tp>
+    class enable_shared_from_this
+    {
+    protected:
+      constexpr enable_shared_from_this() noexcept { }
+
+      enable_shared_from_this(const enable_shared_from_this&) noexcept { }
+
+      enable_shared_from_this&
+      operator=(const enable_shared_from_this&) noexcept
+      { return *this; }
+
+      ~enable_shared_from_this() { }
+
+    public:
+      shared_ptr<_Tp>
+      shared_from_this()
+      { return shared_ptr<_Tp>(this->_M_weak_this); }
+
+      shared_ptr<const _Tp>
+      shared_from_this() const
+      { return shared_ptr<const _Tp>(this->_M_weak_this); }
+
+    private:
+      template<typename _Tp1>
+	void
+	_M_weak_assign(_Tp1* __p, const __shared_count<>& __n) const noexcept
+	{ _M_weak_this._M_assign(__p, __n); }
+
+      template<typename _Tp1>
+	friend void 
+	__enable_shared_from_this_helper(const __shared_count<>& __pn,
+					 const enable_shared_from_this* __pe,
+					 const _Tp1* __px) noexcept
+	{ 
+	  if(__pe != 0)
+	    __pe->_M_weak_assign(const_cast<_Tp1*>(__px), __pn);
+	}
+
+      mutable weak_ptr<__libfund_v1<_Tp>>  _M_weak_this;
+    };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace fundamentals_v1
 } // namespace experimental
 
 template <typename _Tp>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH][GSoC] Extend shared_ptr to support arrays
       [not found] <CALvpekGQvTp2zRz65cnP+Ex7TKHQygdrYkqo5nUKGJ3bLQj8ww@mail.gmail.com>
  2015-06-11 15:36 ` Fwd: [PATCH][GSoC] Extend shared_ptr to support arrays Fan You
@ 2015-06-11 15:44 ` Jonathan Wakely
  2015-06-11 16:21 ` Jonathan Wakely
  2015-06-12  6:45 ` Tim Shen
  3 siblings, 0 replies; 9+ messages in thread
From: Jonathan Wakely @ 2015-06-11 15:44 UTC (permalink / raw)
  To: Fan You; +Cc: Tim Shen, gcc-patches

On 11/06/15 23:32 +0800, Fan You wrote:
>Any comments?

I haven't looked at the patch yet, but please CC all libstdc++ patches
to the libstdc++ list as well as gcc-patches, thanks.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH][GSoC] Extend shared_ptr to support arrays
       [not found] <CALvpekGQvTp2zRz65cnP+Ex7TKHQygdrYkqo5nUKGJ3bLQj8ww@mail.gmail.com>
  2015-06-11 15:36 ` Fwd: [PATCH][GSoC] Extend shared_ptr to support arrays Fan You
  2015-06-11 15:44 ` Jonathan Wakely
@ 2015-06-11 16:21 ` Jonathan Wakely
  2015-06-12  6:45 ` Tim Shen
  3 siblings, 0 replies; 9+ messages in thread
From: Jonathan Wakely @ 2015-06-11 16:21 UTC (permalink / raw)
  To: Fan You; +Cc: Tim Shen, gcc-patches, libstdc++

On 11/06/15 23:32 +0800, Fan You wrote:
>Hi,
>
>This is my first patch for GSoC project: extend shared_ptr to support
>arrays.
>
>Changes are made in these files:
>
>* libstdc++-v3/include/bits/shared_ptr_base.h : Renamed _Sp_counted_deleter
>to _Sp_counted_array, changed _shared_count construct from _Sp_counted_ptr
>to _Sp_counted_array.

Why?

As far as I can see it has nothing to do with arrays.

>* libstdc++-v3/include/experimental/memory : add shared_ptr into
>fundamentals_v1
>
>Is it too long for reviewing? Should I detach them into different patches?
>Any comments?

General comments:

Please fix the lines that consist of nothing but whitespace, they
should just be empty lines.

You're going to need tests!


Comments on changes to include/bits/shared_ptr_base.h:

This type should not be declared when including <memory>:

+  namespace experimental{
+  inline namespace fundamentals_v1 {
+    template<typename _Tp>
+      class enable_shared_from_this;
+  }
+  }
+

You will need to find another way to make
experimental::enable_shared_from_this work, without declaring it in
<bits/shared_ptr.h> (e.g. add a new type with a reserved name and make
experimental::enable_shared_from_this use that, and only declare
experimental::enable_shared_from_this in <experimental/memory>).


Please review the patch to ensure you are not reverting my recent
changes on trunk e.g.

-#if __cpp_rtti
-       // _GLIBCXX_RESOLVE_LIB_DEFECTS
-       // 2400. shared_ptr's get_deleter() should use addressof()
-        return __ti == typeid(_Deleter)
-         ? std::__addressof(_M_impl._M_del())
-         : nullptr;
+#ifdef __GXX_RTTI
+       return __ti == typeid(_Deleter) ? &_M_impl._M_del() : nullptr;
 #else
         return nullptr;
 #endif

This should definitely not be in the patch, it's a regression.

You've also reverted changes to _Sp_counted_deleter::_M_destroy().

Maybe I'm wrong, but I don't tink it's necessary to provide three
partial specializations:

+  // alias for original __shared_ptr
+  template <typename _Tp, _Lock_policy _Lp>
+    class __shared_ptr<__libfund_v1<_Tp>, _Lp> : public __shared_ptr<_Tp, _Lp>
+    {
...
+  // array support
+  template<typename _Tp, _Lock_policy _Lp, unsigned N>
+    class __shared_ptr<__libfund_v1<_Tp[N]>, _Lp>
+    {
...
+  template<typename _Tp, _Lock_policy _Lp>
+    class __shared_ptr<__libfund_v1<_Tp[]>, _Lp>

Isn't it possible to provide just one, which handles all three cases?

  // Implementation of std::experimental::shared_ptr
  template <typename _Tp, _Lock_policy _Lp>
    class __shared_ptr<__libfund_v1<_Tp>, _Lp>
    {
      using _Deleter_type = typename conditional<is_array<_Tp>::value,
        _Normal_deleter, _Array_deleter>::type;

    public:
      using element_type = typename remove_extent<_Tp>::type;

      template<typename _Tp1>
        __shared_ptr(_Tp1* __p)
        : _M_ptr(__p), _M_refcount(__p, Deleter_type{})


Alternatively, have one partial specialization for non-arrays (which
derives from __shared_ptr<_Tp>, as you have now) and another for
arrays. That could be done like so:

  template<typename _Tp, bool = is_array<_Tp>::value>
    struct __libfund_v1 { };

  // Implementation of std::experimental::shared_ptr for non-arrays
  template <typename _Tp, _Lock_policy _Lp>
    class __shared_ptr<__libfund_v1<_Tp, false>, _Lp>
    : public __shared_ptr<_Tp>
    {
      // ...
    }

  // Implementation of std::experimental::shared_ptr for arrays
  template <typename _Tp, _Lock_policy _Lp>
    class __shared_ptr<__libfund_v1<_Tp, true>, _Lp>
    : public __shared_ptr<_Tp>
    {
      // ...
    }

It should be possible for the same partial specialization to work for
shared_ptr<T[]> and shared_ptr<T[N]>.


Even if that isn't possible, this is wrong:

+      using element_type = _Tp[N];

And in your new _weak_ptr<__libfund_v1<_Tp>, _Lp> specialization this
is wrong:

+      using element_type = _Tp;



It looks to me as though calling experimental::__weak_ptr<T>::lock()
will return the wrong type of __shared_ptr. That might not be
important.


Comments on changes to include/experimental/memory:

I don't see a definition of experimental::weak_ptr.


The way you've defined experimental::__shared_ptr means it doesn't
support arrays (apologies if you've done what I suggested ... it
obviously wasn't right).

I think it should be something like this:

+  //for non default lock policy
+  template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
+    using __shared_ptr = std::__shared_ptr<__libfund_v1<_Tp>, _Lp>;

i.e. experimental::__shared_ptr<T[]> should use the partial
specialization for arrays.

Then experimental::shared_ptr can just use that:

+  template<typename _Tp>
+    class shared_ptr : public __shared_ptr<_Tp>
+    {



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH][GSoC] Extend shared_ptr to support arrays
       [not found] <CALvpekGQvTp2zRz65cnP+Ex7TKHQygdrYkqo5nUKGJ3bLQj8ww@mail.gmail.com>
                   ` (2 preceding siblings ...)
  2015-06-11 16:21 ` Jonathan Wakely
@ 2015-06-12  6:45 ` Tim Shen
  2015-06-12  9:07   ` Jonathan Wakely
  3 siblings, 1 reply; 9+ messages in thread
From: Tim Shen @ 2015-06-12  6:45 UTC (permalink / raw)
  To: Fan You; +Cc: Jonathan Wakely, gcc-patches, libstdc++

On Thu, Jun 11, 2015 at 8:32 AM, Fan You <youfan.noey@gmail.com> wrote:
> Hi,
>
> This is my first patch for GSoC project: extend shared_ptr to support
> arrays.

+      using element_type = _Tp[N];

using element_type = typename std::remove_extent_t<_Tp>; ?

> using _Deleter_type = typename conditional<is_array<_Tp>::value,
>       _Normal_deleter, _Array_deleter>::type;

Sadly std::default_delete doesn't support _Tp[N]. It will also works
to create a std::default_delete-ish helper trait, with _Tp[N]
specialized to `delete []` as well.


-- 
Regards,
Tim Shen

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH][GSoC] Extend shared_ptr to support arrays
  2015-06-12  6:45 ` Tim Shen
@ 2015-06-12  9:07   ` Jonathan Wakely
       [not found]     ` <CALvpekG4+YxSVz+jm_quo20=2bWYXnkBFrjDyBu6eYXW4YarHQ@mail.gmail.com>
  0 siblings, 1 reply; 9+ messages in thread
From: Jonathan Wakely @ 2015-06-12  9:07 UTC (permalink / raw)
  To: Tim Shen; +Cc: Fan You, gcc-patches, libstdc++

On 11/06/15 23:43 -0700, Tim Shen wrote:
>+      using element_type = _Tp[N];
>
>using element_type = typename std::remove_extent_t<_Tp>; ?

Well at that point in the file we're inside the
__shared_ptr<__libfund_v1<_Tp[N]> specialization, so it could be
simply:

+      using element_type = _Tp;

However, if we combine some or all of the partial specializations into
one, as I suggested, then it would become simply:

  using element_type = std::remove_extent_t<_Tp>;

(Without the 'typename', although for this to work the new partial
specializations need to be surrounded in #if __cplusplus >= 201402L,
otherwise the remove_extent_t alias is no available.)

This is a good example of why I think we should combine the very
similar specializations, and then use helper traits to define the
parts that vary depending on _Tp, instead of duplicating the entire
class template.

>> using _Deleter_type = typename conditional<is_array<_Tp>::value,
>>       _Normal_deleter, _Array_deleter>::type;
>
>Sadly std::default_delete doesn't support _Tp[N]. It will also works
>to create a std::default_delete-ish helper trait, with _Tp[N]
>specialized to `delete []` as well.

Yes.

Another point I missed in my review is that 'N' is not a reserved
identifier, it needs to be changed to _Nm or something else in the
implementation namespace, so that it still works even if users do:

#define N  "Boom!" :-P
#include <experimental/memory>


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH][GSoC] Extend shared_ptr to support arrays
       [not found]     ` <CALvpekG4+YxSVz+jm_quo20=2bWYXnkBFrjDyBu6eYXW4YarHQ@mail.gmail.com>
@ 2015-06-15  9:44       ` Jonathan Wakely
       [not found]         ` <CALvpekE2a8qi8qRjdzsDOi2OCRJw_ccYd1CrL6z68rLFW0fK0g@mail.gmail.com>
  0 siblings, 1 reply; 9+ messages in thread
From: Jonathan Wakely @ 2015-06-15  9:44 UTC (permalink / raw)
  To: Fan You; +Cc: Tim Shen, gcc-patches, libstdc++

On 14/06/15 23:45 +0800, Fan You wrote:
>This is the revised patch.
>
>Bootstrapped and Tested on Darwin 10.9.4. with testsuite 20_util/*

Great, it's *very* important that you can run the tests, so we know
your changes haven't broken the existing code.

You will also need to write new tests (under testsuite/experimental/)
to check that your new code works as intended.

>Tim also advice to do this:
>
>__shared_ptr<libfund<_Tp>> : private __shared_ptr<std::remove_extent<_Tp>>
>
>to prevent changing everything once __shared_ptr<_Tp> has changed.

Yes, that probably makes sense.

This patch is looking much better now.

I noticed this macro is wrong:

+#define __cpp_lib_experimental_shared_ptr_array 201506

The correct name and value are given in
https://rawgit.com/cplusplus/fundamentals-ts/v1/fundamentals-ts.html#general.feature.test


I wonder if all the new code really needs to be in <bits/shared_ptr.h>
or if it can just be in <experimental/memory> instead. There should be
no need to declare most of it (except maybe the enable_shared_from_this
parts?) when users include <memory>.



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH][GSoC] Extend shared_ptr to support arrays
       [not found]         ` <CALvpekE2a8qi8qRjdzsDOi2OCRJw_ccYd1CrL6z68rLFW0fK0g@mail.gmail.com>
@ 2015-06-16 13:30           ` Jonathan Wakely
       [not found]             ` <CALvpekFiRrz2UHTvGh+aqnkQPdL-Y=O-vRUXhxwVs-Wz+5v-RA@mail.gmail.com>
  0 siblings, 1 reply; 9+ messages in thread
From: Jonathan Wakely @ 2015-06-16 13:30 UTC (permalink / raw)
  To: Fan You; +Cc: Tim Shen, gcc-patches, libstdc++

On 16/06/15 21:15 +0800, Fan You wrote:
>> You will also need to write new tests (under testsuite/experimental/)
>> to check that your new code works as intended.
>
>
>Is there any pattern or rules I should follow when writing testcase, or I
>can just refer to 20_util/* and add some array specified tests?

Follow the style of the 20_util tests, but put the new ones under
testsuite/experimental. Tim can help you with any questions about the
testsuite, it doesn't need to be discussed on the gcc-patches list
(since there's nothing ready to be committed yet anyway).

>> I wonder if all the new code really needs to be in <bits/shared_ptr.h>
>>
>
>why it need to be in <bits/shared_ptr.h>?

It doesn't, that's what I mean.

All the new code is only usable after including <experimental/memory>,
but you have added lots of code to <bits/shared_ptr.h>.

>> or if it can just be in <experimental/memory> instead. There should be
>> no need to declare most of it (except maybe the enable_shared_from_this
>> parts?) when users include <memory>.
>>
>>
>>
>>
>So, what else should I do before its ready to be committed?

Tests, tests and more tests.

Currently you haven't got a single test, so I have no way of knowing
if the code even does what it's supposed to do.

Once you have written tests and they all pass then we can review the
code again fully and get it ready to commit. We are not there yet.

It might be a good idea to publish your changes somewhere visible, so
that people who want to try your code can clone it and test it without
having to apply patches. Are you using Git locally?  If you have a
github account you could fork https://github.com/gcc-mirror/gcc and
then push your changes to a new branch in your fork.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH][GSoC] Extend shared_ptr to support arrays
       [not found]                 ` <CAG4ZjN=ahVX37AEMsjYEcL_N=quqLA9P1keiDC2NCKhkaCbmqQ@mail.gmail.com>
@ 2015-06-24 18:19                   ` Fan You
  2015-06-25  4:01                     ` Tim Shen
  0 siblings, 1 reply; 9+ messages in thread
From: Fan You @ 2015-06-24 18:19 UTC (permalink / raw)
  To: Tim Shen, gcc-patches; +Cc: Jonathan Wakely, libstdc++

[-- Attachment #1: Type: text/plain, Size: 2646 bytes --]

Hi,

Here is the revised patch including all the test case.

This can also be seen at <https://github.com/Noeyfan/gcc-1> on branch
<shared_arrays>

Any comments?

2015-06-23 12:19 GMT+08:00 Tim Shen <timshen@google.com>:
> On Sun, Jun 21, 2015 at 3:50 AM, Tim Shen <timshen@google.com> wrote:
>> Quickly looked at __shared_ptr<__libfund_v1<_Tp>, _Lp>; will look at
>> the rest parts later.
>
> All suggestions apply for all occursions, not just for the quoted code.
>
> +  // helpers for std::experimental::enable_shared_from_this
> +
> +  template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
> +    struct __helper_for_experimental_enable_shared
> +    {
> +      void _Call_M_assign(__weak_ptr<__libfund_v1<_Tp>, _Lp>& __wp,
> +                         _Tp* __ptr,
> +                         const __shared_count<_Lp>& __refcount)
> +       { __wp._M_assign(__ptr, __refcount); }
> +    };
> Make the function it static; Suggested class name: __weak_ptr_friend,
> function name _S_assign.
>
> +      // Used by __enable_shared_from_this.
> +      void
> +      _M_assign(_Tp* __ptr, const __shared_count<_Lp>& __refcount) noexcept
> +      {
> +       _M_ptr = __ptr;
> +       _M_refcount = __refcount;
> +      }
> element_type* __ptr?
>
> Also need a _Compatible; possible implementation:
>
> template<typename _From_type, typename _To_type>
>   struct __sp_compatible_helper
>   {  static constexpr bool value = std::is_convertible<_From_type*,
> _To_type*>::value;  };
>
> template<size_t _Nm, typename _Tp>
>   struct __sp_compatible_helper<_Tp[_Nm], _Tp[]>
>   { static constexpr bool value = true; };
>
> ...
>
> template<typename _Tp1>
>   using _Compatible = typename std::enable_if<__sp_compatible<_Tp1,
> _Tp>::value>::type;
>
> +   template<typename _Tp1, typename _Tp2>
> +     inline bool
> +     operator<(const shared_ptr<_Tp1>& __a,
> +              const shared_ptr<_Tp2>& __b) noexcept
> +     {
> +       using _Tp1_RE = typename remove_extent<_Tp1>::type;
> +       using _Tp2_RE = typename remove_extent<_Tp2>::type;
> +       using _CT = typename std::common_type<_Tp1_RE*, _Tp2_RE*>::type;
> +       return std::less<_CT>()(__a.get(), __b.get());
> +     }
> using _Tp1_RE = typename shared_ptr<_Tp1>::element_type;
>
> +   // 8.2.1.3, shared_ptr casts
> +   template<typename _Tp, typename _Tp1>
> +     inline shared_ptr<_Tp>
> +     static_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
> +     { shared_ptr<_Tp>(__r, static_cast<typename
> shared_ptr<_Tp>::element_type*>(__r.get())); }
> +
> Missing "return". You can turn on -Wsystem-headers to check for warnings.
>
>
> --
> Regards,
> Tim Shen

[-- Attachment #2: a --]
[-- Type: application/octet-stream, Size: 76196 bytes --]

Index: libstdc++-v3/include/bits/shared_ptr_base.h
===================================================================
--- libstdc++-v3/include/bits/shared_ptr_base.h	(revision 224707)
+++ libstdc++-v3/include/bits/shared_ptr_base.h	(working copy)
@@ -865,6 +865,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     __enable_shared_from_this_helper(const __shared_count<_Lp>&, ...) noexcept
     { }
 
+  // extend shared_ptr to support array tag
+  template <typename _Tp>
+    struct __libfund_v1 { using type = _Tp; };
+
+  // helper for _Compatible
+  template<typename _From_type, typename _To_type>
+    struct __sp_compatible_helper
+    {
+      static constexpr bool
+      value = is_convertible<_From_type*, _To_type*>::value;
+    };
+
+  template<size_t _Nm, typename _Tp>
+    struct __sp_compatible_helper<_Tp[_Nm], _Tp[]>
+    {
+      static constexpr bool value = true;
+    };
 
   template<typename _Tp, _Lock_policy _Lp>
     class __shared_ptr
@@ -1179,6 +1196,227 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __shared_count<_Lp>  _M_refcount;    // Reference counter.
     };
 
+  // Extend shared_ptr to support arrays
+  template<typename _Tp, _Lock_policy _Lp>
+    class __shared_ptr<__libfund_v1<_Tp>, _Lp>
+    : __shared_ptr<typename remove_extent<_Tp>::type, _Lp>
+    {
+      using element_type = typename remove_extent<_Tp>::type;
+
+      struct _Array_Deleter
+      {
+        void
+        operator()(element_type const *__p) const
+        { delete [] __p; }
+      };
+
+      struct _Normal_Deleter
+      {
+        void
+        operator()(element_type const *__p) const
+        { delete __p; }
+      };
+
+      using _Deleter_type
+	= typename conditional<is_array<_Tp>
+                               ::value, _Array_Deleter, _Normal_Deleter>::type;
+
+      template<typename _Tp1>
+	using _Compatible
+	  = typename enable_if<__sp_compatible_helper<_Tp1, _Tp>::value>::type;
+
+      using __Base_type = __shared_ptr<element_type>;
+
+    public:
+
+      constexpr __shared_ptr() noexcept
+      : __Base_type()
+      { }
+
+      template<typename _Tp1>
+	explicit __shared_ptr(_Tp1* __p)
+      	: __Base_type(__p, _Deleter_type())
+        { }
+
+      template<typename _Tp1, typename _Deleter>
+	__shared_ptr(_Tp1* __p, _Deleter __d)
+      	: __Base_type(__p, __d)
+        { }
+
+      template<typename _Tp1, typename _Deleter, typename _Alloc>
+	__shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
+      	: __Base_type(__p, __d, __a)
+        { }
+
+      template<typename _Deleter>
+	__shared_ptr(nullptr_t __p, _Deleter __d)
+        : __Base_type(__p, __d)
+        { }
+
+      template<typename _Deleter, typename _Alloc>
+	__shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
+        : __Base_type(__p, __d, __a)
+        { }
+
+      template<typename _Tp1>
+	__shared_ptr(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>&
+		     __r, element_type* __p) noexcept
+        : __Base_type(static_cast<const typename __shared_ptr
+                      <__libfund_v1<_Tp1>>::__Base_type&>(__r), __p)
+        { }
+
+      __shared_ptr(const __shared_ptr&) noexcept = default;
+      __shared_ptr& operator=(const __shared_ptr&) noexcept = default;
+      ~__shared_ptr() = default;
+
+      template<typename _Tp1, typename = _Compatible<_Tp1>>
+        __shared_ptr(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
+        : __Base_type(static_cast<const typename __shared_ptr
+                      <__libfund_v1<_Tp1>>::__Base_type&>(__r))
+        { }
+
+      template<typename _Tp1, typename = _Compatible<_Tp1>>
+	__shared_ptr(__shared_ptr<__libfund_v1<_Tp1>, _Lp>&& __r) noexcept
+        : __Base_type(static_cast<typename __shared_ptr
+                      <__libfund_v1<_Tp1>>::__Base_type&&>(std::move(__r)))
+        { }
+
+      template<typename _Tp1>
+	explicit __shared_ptr(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __r)
+        : __Base_type(static_cast<const typename __weak_ptr
+                      <__libfund_v1<_Tp1>>::__Base_type&>(__r))
+        { }
+
+      template<typename _Tp1, typename _Del, typename
+	      = _Compatible<typename remove_pointer<typename unique_ptr<_Tp1, _Del>
+                                                    ::pointer>::type>>
+	  __shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
+          : __Base_type(std::move(__r))
+          { }
+
+      // Array did not support construct from auto_ptr
+
+      constexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { }
+
+      // reset
+      void
+      reset() noexcept
+      { __shared_ptr(nullptr).swap(*this); }
+
+      template<typename _Tp1>
+	void
+	reset(_Tp1* __p)
+	{
+	  _GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != get());
+	  __shared_ptr(__p, _Deleter_type()).swap(*this);
+	}
+
+      template<typename _Tp1, typename _Deleter>
+	void
+	reset(_Tp1* __p, _Deleter __d)
+	{ __shared_ptr(__p, __d).swap(*this); }
+
+      template<typename _Tp1, typename _Deleter, typename _Alloc>
+	void
+	reset(_Tp1* __p, _Deleter __d, _Alloc __a)
+	{ __shared_ptr(__p, __d, std::move(__a)).swap(*this); }
+
+      element_type&
+      operator[](ptrdiff_t i) const noexcept
+      {
+        _GLIBCXX_DEBUG_ASSERT(get() != 0 && i >= 0);
+        return get()[i];
+      }
+
+      template<typename _Tp1>
+	__shared_ptr&
+	operator=(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
+	{
+          this->__Base_type::operator=(__r);
+          return *this;
+	}
+
+      __shared_ptr&
+      operator=(__shared_ptr&& __r) noexcept
+      {
+        this->__Base_type::operator=(std::move(__r));
+        return *this;
+      }
+
+      template<class _Tp1>
+	__shared_ptr&
+	operator=(__shared_ptr<_Tp1, _Lp>&& __r) noexcept
+	{
+          this->__Base_type::operator=(std::move(__r));
+          return *this;
+	}
+
+      void
+      swap(__shared_ptr& __other) noexcept
+      { this->__Base_type::swap(__other); }
+
+      template<typename _Tp1>
+        bool
+        owner_before(__shared_ptr<__libfund_v1<_Tp1>, _Lp> const& __rhs) const
+        { return __Base_type::owner_before(static_cast<const typename
+                                           __shared_ptr<__libfund_v1<_Tp1>>
+                                           ::__Base_type&>(__rhs)); }
+
+      template<typename _Tp1>
+        bool
+        owner_before(__weak_ptr<__libfund_v1<_Tp1>, _Lp> const& __rhs) const
+        { return __Base_type::owner_before(static_cast<const typename
+                                           __weak_ptr<__libfund_v1<_Tp1>>
+                                           ::__Base_type&>(__rhs)); }
+
+      using __Base_type::operator*;
+      using __Base_type::operator->;
+      using __Base_type::operator bool;
+      using __Base_type::get;
+      using __Base_type::unique;
+      using __Base_type::use_count;
+
+    protected:
+
+      // make_shared not yet support for shared_ptr_arrays
+      //template<typename _Alloc, typename... _Args>
+      //  __shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
+      //	             _Args&&... __args)
+      //	: _M_ptr(), _M_refcount(__tag, (_Tp*)0, __a,
+      //	                        std::forward<_Args>(__args)...)
+      //	{
+      //	  void* __p = _M_refcount._M_get_deleter(typeid(__tag));
+      //	  _M_ptr = static_cast<_Tp*>(__p);
+      //	  __enable_shared_from_this_helper(_M_refcount, _M_ptr, _M_ptr);
+      //	}
+
+      // __weak_ptr::lock()
+      __shared_ptr(const __weak_ptr<__libfund_v1<_Tp>, _Lp>& __r,
+                   std::nothrow_t)
+      : __Base_type(static_cast<const typename __weak_ptr
+                    <__libfund_v1<_Tp>>::__Base_type&>(__r),
+                    std::nothrow)
+      { }
+
+    private:
+      using __Base_type::_M_get_deleter;
+
+      template<typename _Tp1>
+	static _Tp1*
+	_S_raw_ptr(_Tp1* __ptr)
+	{ return __ptr; }
+
+      template<typename _Tp1>
+	static auto
+	_S_raw_ptr(_Tp1 __ptr) -> decltype(std::__addressof(*__ptr))
+	{ return std::__addressof(*__ptr); }
+
+      template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
+      template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
+
+      template<typename _Del, typename _Tp1, _Lock_policy _Lp1>
+	friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept;
+    };
 
   // 20.7.2.2.7 shared_ptr comparisons
   template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
@@ -1481,6 +1719,138 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __weak_count<_Lp>  _M_refcount;    // Reference counter.
     };
 
+  // helpers for std::experimental::enable_shared_from_this
+
+  template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
+    struct __weak_ptr_friend
+    {
+      static void
+      _S_assign(__weak_ptr<__libfund_v1<_Tp>, _Lp>& __wp,
+                _Tp* __ptr,
+                const __shared_count<_Lp>& __refcount)
+      { __wp._M_assign(__ptr, __refcount); }
+    };
+
+  // weak_ptr specialization for __shared_ptr array
+  template<typename _Tp, _Lock_policy _Lp>
+    class __weak_ptr<__libfund_v1<_Tp>, _Lp>
+    : __weak_ptr<typename remove_extent<_Tp>::type, _Lp>
+    {
+      using element_type = typename remove_extent<_Tp>::type;
+
+      template<typename _Tp1>
+	using _Compatible
+	  = typename enable_if<__sp_compatible_helper<_Tp1, _Tp>::value>::type;
+
+      using __Base_type = __weak_ptr<element_type>;
+
+    public:
+
+      constexpr __weak_ptr() noexcept
+      : __Base_type()
+      { }
+
+      __weak_ptr(const __weak_ptr&) noexcept = default;
+
+      ~__weak_ptr() = default;
+
+      template<typename _Tp1, typename = _Compatible<_Tp1>>
+	__weak_ptr(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
+	: __Base_type(static_cast<const typename __weak_ptr
+                      <__libfund_v1<_Tp>>::__Base_type&>(__r))
+        { }
+
+      template<typename _Tp1, typename = _Compatible<_Tp1>>
+	__weak_ptr(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
+        : __Base_type(static_cast<const typename __shared_ptr
+                      <__libfund_v1<_Tp1>>::__Base_type&>(__r))
+	{ }
+
+      __weak_ptr(__weak_ptr&& __r) noexcept
+      : __Base_type(std::move(__r))
+      { }
+
+      template<typename _Tp1, typename = _Compatible<_Tp1>>
+	__weak_ptr(__weak_ptr<__libfund_v1<_Tp1>, _Lp>&& __r) noexcept
+        : __Base_type(static_cast<typename __weak_ptr
+                      <__libfund_v1<_Tp1>>::__Base_type&&>(std::move(__r)))
+        { }
+
+      __weak_ptr&
+      operator=(const __weak_ptr& __r) noexcept = default;
+
+      template<typename _Tp1>
+	__weak_ptr&
+	operator=(const __weak_ptr<_Tp1, _Lp>& __r) noexcept
+	{
+          this->__Base_type::operator=(__r);
+          return *this;
+	}
+
+      template<typename _Tp1>
+	__weak_ptr&
+	operator=(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
+	{
+          this->__Base_type::operator=(__r);
+          return *this;
+	}
+
+      __weak_ptr&
+      operator=(__weak_ptr&& __r) noexcept
+      {
+        this->__Base_type::operator=(std::move(__r));
+        return *this;
+      }
+
+      template<typename _Tp1>
+	__weak_ptr&
+	operator=(__weak_ptr<_Tp1, _Lp>&& __r) noexcept
+	{
+          this->__Base_type::operator=(std::move(__r));
+          return *this;
+	}
+
+      void
+      swap(__weak_ptr& __other) noexcept
+      { this->__Base_type::swap(__other); }
+
+      template<typename _Tp1>
+        bool
+        owner_before(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __rhs) const
+        { return __Base_type::owner_before(static_cast<const typename
+                                           __shared_ptr<__libfund_v1<_Tp1>>
+                                           ::__Base_type&>(__rhs)); }
+
+      template<typename _Tp1>
+        bool
+        owner_before(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __rhs) const
+        { return __Base_type::owner_before(static_cast<const typename
+                                           __weak_ptr<__libfund_v1<_Tp1>>
+                                           ::__Base_type&>(__rhs)); }
+
+      __shared_ptr<__libfund_v1<_Tp>, _Lp>
+      lock() const noexcept  // should not be element_type
+      { return __shared_ptr<__libfund_v1<_Tp>, _Lp>(*this, std::nothrow); }
+
+      using __Base_type::use_count;
+      using __Base_type::expired;
+      using __Base_type::reset;
+
+    private:
+      // Used by __enable_shared_from_this.
+      void
+      _M_assign(element_type* __ptr, const __shared_count<_Lp>& __refcount) noexcept
+      {
+        this->__Base_type::_M_assign(__ptr, __refcount);
+      }
+
+      template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
+      template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
+      friend class __enable_shared_from_this<_Tp, _Lp>;
+      friend class __weak_ptr_friend<_Tp, _Lp>;
+      friend class enable_shared_from_this<_Tp>;
+    };
+
   // 20.7.2.3.6 weak_ptr specialized algorithms.
   template<typename _Tp, _Lock_policy _Lp>
     inline void
Index: libstdc++-v3/include/experimental/memory
===================================================================
--- libstdc++-v3/include/experimental/memory	(revision 224707)
+++ libstdc++-v3/include/experimental/memory	(working copy)
@@ -233,6 +233,499 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace fundamentals_v2
+inline namespace fundamentals_v1
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+#define __cpp_lib_experimental_shared_ptr_arrays 201406
+
+  // 8.2.1
+
+  template<typename _Tp> class shared_ptr;
+  template<typename _Tp> class weak_ptr;
+
+  template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
+    using __shared_ptr = std::__shared_ptr<__libfund_v1<_Tp>, _Lp>;
+
+  template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
+    using __weak_ptr = std::__weak_ptr<__libfund_v1<_Tp>, _Lp>;
+
+  template<typename _Tp>
+    class shared_ptr : public __shared_ptr<_Tp>
+    {
+    public:
+      using element_type = typename remove_extent<_Tp>::type;
+
+      template<typename _Tp1>
+	using _Compatible
+	  = typename enable_if<__sp_compatible_helper<_Tp1, _Tp>::value>::type;
+
+      using __Base_type = __shared_ptr<_Tp>;
+
+      // 8.2.1.1, shared_ptr constructors
+      constexpr shared_ptr() noexcept = default;
+
+      template<typename _Tp1>
+        explicit shared_ptr(_Tp1* __p) : __Base_type(__p) { }
+
+      template<typename _Tp1, typename _Deleter>
+        shared_ptr(_Tp1* __p, _Deleter __d)
+        : __Base_type(__p, __d) { }
+
+      template<typename _Tp1, typename _Deleter, typename _Alloc>
+        shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
+        : __Base_type(__p, __d, __a) { }
+
+      template<typename _Deleter>
+        shared_ptr(nullptr_t __p, _Deleter __d)
+        : __Base_type(__p, __d) { }
+
+      template<typename _Deleter, typename _Alloc>
+        shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
+        : __Base_type(__p, __d, __a) { }
+
+      template<typename _Tp1>
+        shared_ptr(const shared_ptr<_Tp1>& __r, element_type* __p) noexcept
+        : __Base_type(__r, __p) { }
+
+      shared_ptr(const shared_ptr& __r) noexcept
+	: __Base_type(__r) { }
+
+      template<typename _Tp1, typename = _Compatible<_Tp1>>
+	shared_ptr(const shared_ptr<_Tp1>& __r) noexcept
+	: __Base_type(__r) { }
+
+      shared_ptr(const shared_ptr<_Tp>&& __r) noexcept
+      : __Base_type(std::move(__r)) { }
+
+      template<typename _Tp1, typename = _Compatible<_Tp1>>
+	shared_ptr(shared_ptr<_Tp1>&& __r) noexcept
+	: __Base_type(std::move(__r)) { }
+
+      template<typename _Tp1>
+        explicit shared_ptr(const weak_ptr<_Tp1>& __r)
+        : __Base_type(__r) { }
+
+#if _GLIBCXX_USE_DEPRECATED
+      template<typename _Tp1>
+	shared_ptr(std::auto_ptr<_Tp1>&& __r)
+	: __Base_type() { }
+#endif
+
+      template<typename _Tp1, typename _Del, typename
+                 = _Compatible<typename remove_pointer<typename unique_ptr<_Tp1, _Del>
+                                                       ::pointer>::type>>
+	  shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
+	  : __Base_type(std::move(__r)) { }
+
+      constexpr shared_ptr(nullptr_t __p)
+      : __Base_type(__p) { }
+
+      // C++14 §20.8.2.2
+      ~shared_ptr() = default;
+
+      // C++14 §20.8.2.3
+      shared_ptr& operator=(const shared_ptr&) noexcept = default;
+
+      template <typename _Tp1>
+	shared_ptr&
+      	operator=(const shared_ptr<_Tp1>& __r) noexcept
+	{
+	  this->__Base_type::operator=(__r);
+	  return *this;
+	}
+
+      shared_ptr&
+      operator=(shared_ptr&& __r) noexcept
+      {
+        this->__Base_type::operator=(std::move(__r));
+        return *this;
+      }
+
+      template <typename _Tp1>
+	shared_ptr&
+      	operator=(shared_ptr<_Tp1>&& __r) noexcept
+	{
+	  this->__Base_type::operator=(std::move(__r));
+	  return *this;
+	}
+
+#if _GLIBCXX_USE_DEPRECATED
+      template<typename _Tp1>
+	shared_ptr&
+	operator=(std::auto_ptr<_Tp1>&& __r)
+	{
+	  this->__shared_ptr<_Tp>::operator=(std::move(__r));
+	  return *this;
+	}
+#endif
+
+      template <typename _Tp1, typename _Del>
+	shared_ptr&
+	operator=(unique_ptr<_Tp1, _Del>&& __r)
+	{
+	  this->__Base_type::operator=(std::move(__r));
+	  return *this;
+	}
+
+      // C++14 §20.8.2.2.4
+      // swap & reset
+      // 8.2.1.2 shared_ptr observers
+      // in __shared_ptr_base.h
+
+    private:
+      template<typename _Alloc, typename... _Args>
+      shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
+        	 _Args&&... __args)
+      : __Base_type(__tag, __a, std::forward<_Args>(__args)...)
+      { }
+
+      template<typename _Tp1, typename _Alloc, typename... _Args>
+	friend shared_ptr<_Tp1>
+	allocate_shared(const _Alloc& __a, _Args&&...  __args);
+
+      shared_ptr(const weak_ptr<_Tp>& __r, std::nothrow_t)
+      : __Base_type(__r, std::nothrow) { }
+
+      friend class weak_ptr<_Tp>;
+    };
+
+  // C++14 §20.8.2.2.7 //DOING
+   template<typename _Tp1, typename _Tp2>
+     bool operator==(const shared_ptr<_Tp1>& __a,
+		     const shared_ptr<_Tp2>& __b) noexcept
+     { return __a.get() == __b.get(); }
+
+   template<typename _Tp>
+     inline bool
+     operator==(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
+     { return !__a; }
+
+   template<typename _Tp>
+     inline bool
+     operator==(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
+     { return !__a; }
+
+   template<typename _Tp1, typename _Tp2>
+     inline bool
+     operator!=(const shared_ptr<_Tp1>& __a,
+		const shared_ptr<_Tp2>& __b) noexcept
+     { return __a.get() != __b.get(); }
+
+   template<typename _Tp>
+     inline bool
+     operator!=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
+     { return (bool)__a; }
+
+   template<typename _Tp>
+     inline bool
+     operator!=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
+     { return (bool)__a; }
+
+   template<typename _Tp1, typename _Tp2>
+     inline bool
+     operator<(const shared_ptr<_Tp1>& __a,
+	       const shared_ptr<_Tp2>& __b) noexcept
+     {
+       using _Tp1_RE = typename remove_extent<_Tp1>::type;
+       using _Tp2_RE = typename remove_extent<_Tp2>::type;
+       using _CT = typename std::common_type<_Tp1_RE*, _Tp2_RE*>::type;
+       return std::less<_CT>()(__a.get(), __b.get());
+     }
+
+   template<typename _Tp>
+     inline bool
+     operator<(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
+     {
+       using _Tp_RE = typename remove_extent<_Tp>::type;
+       return std::less<_Tp_RE>()(__a.get(), nullptr);
+     }
+
+   template<typename _Tp>
+     inline bool
+     operator<(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
+     {
+       using _Tp_RE = typename remove_extent<_Tp>::type;
+       return std::less<_Tp_RE*>()(nullptr, __a.get());
+     }
+
+   template<typename _Tp1, typename _Tp2>
+     inline bool
+     operator<=(const shared_ptr<_Tp1>& __a,
+		const shared_ptr<_Tp2>& __b) noexcept
+     { return !(__b < __a); }
+
+   template<typename _Tp>
+     inline bool
+     operator<=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
+     { return !(nullptr < __a); }
+
+   template<typename _Tp>
+     inline bool
+     operator<=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
+     { return !(__a < nullptr); }
+
+   template<typename _Tp1, typename _Tp2>
+     inline bool
+     operator>(const shared_ptr<_Tp1>& __a,
+	       const shared_ptr<_Tp2>& __b) noexcept
+     { return (__b < __a); }
+
+   template<typename _Tp>
+     inline bool
+     operator>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
+     {
+       using _Tp_RE = typename remove_extent<_Tp>::type;
+       return std::less<_Tp_RE*>()(nullptr, __a.get());
+     }
+
+   template<typename _Tp>
+     inline bool
+     operator>(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
+     {
+       using _Tp_RE = typename remove_extent<_Tp>::type;
+       return std::less<_Tp_RE*>()(__a.get(), nullptr);
+     }
+
+   template<typename _Tp1, typename _Tp2>
+     inline bool
+     operator>=(const shared_ptr<_Tp1>& __a,
+		const shared_ptr<_Tp2>& __b) noexcept
+     { return !(__a < __b); }
+
+   template<typename _Tp>
+     inline bool
+     operator>=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
+     { return !(__a < nullptr); }
+
+   template<typename _Tp>
+     inline bool
+     operator>=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
+     { return !(nullptr < __a); }
+
+   // C++14 §20.8.2.2.8
+   template<typename _Tp>
+     inline void
+     swap(shared_ptr<_Tp>& __a, shared_ptr<_Tp>& __b) noexcept
+     { __a.swap(__b); }
+
+   // 8.2.1.3, shared_ptr casts
+   template<typename _Tp, typename _Tp1>
+     inline shared_ptr<_Tp>
+     static_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
+     { return shared_ptr<_Tp>(__r,
+                              static_cast<typename shared_ptr<_Tp>
+                              ::element_type*>(__r.get())); }
+
+   template<typename _Tp, typename _Tp1>
+     inline shared_ptr<_Tp>
+     dynamic_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
+     {
+       if (_Tp* __p = dynamic_cast<typename shared_ptr<_Tp>::element_type*>(__r.get()))
+         return shared_ptr<_Tp>(__r, __p);
+       return shared_ptr<_Tp>();
+     }
+
+   template<typename _Tp, typename _Tp1>
+     inline shared_ptr<_Tp>
+     const_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
+     { return shared_ptr<_Tp>(__r,
+                              const_cast<typename shared_ptr<_Tp>::element_type*>(__r.get())); }
+
+   template<typename _Tp, typename _Tp1>
+     inline shared_ptr<_Tp>
+     reinterpret_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
+     { return shared_ptr<_Tp>(__r,
+                              reinterpret_cast<typename shared_ptr<_Tp>::element_type*>(__r.get())); }
+
+   // C++14 §20.8.2.3
+   template<typename _Tp>
+     class weak_ptr : public __weak_ptr<_Tp>
+     {
+      template<typename _Tp1>
+	using _Compatible
+	  = typename enable_if<__sp_compatible_helper<_Tp1, _Tp>::value>::type;
+
+      using __Base_type = __weak_ptr<_Tp>;
+
+   public:
+       constexpr weak_ptr() noexcept = default;
+
+       template<typename _Tp1, typename = _Compatible<_Tp1>>
+	 weak_ptr(const shared_ptr<_Tp1>& __r) noexcept
+	 : __Base_type(__r) { }
+
+       weak_ptr(const weak_ptr&) noexcept = default;
+
+       template<typename _Tp1, typename = _Compatible<_Tp1>>
+	 weak_ptr(const weak_ptr<_Tp1>& __r) noexcept
+	 : __Base_type(__r) { }
+
+       weak_ptr(weak_ptr&&) noexcept = default;
+
+       template<typename _Tp1, typename = _Compatible<_Tp1>>
+	 weak_ptr(weak_ptr<_Tp1>&& __r) noexcept
+	 : __Base_type(std::move(__r)) { }
+
+       weak_ptr&
+       operator=(const weak_ptr& __r) noexcept = default;
+
+       template<typename _Tp1>
+	 weak_ptr&
+	 operator=(const weak_ptr<_Tp1>& __r) noexcept
+	 {
+	   this->__Base_type::operator=(__r);
+	   return *this;
+	 }
+
+       template<typename _Tp1>
+	 weak_ptr&
+	 operator=(const shared_ptr<_Tp1>& __r) noexcept
+	 {
+	   this->__Base_type::operator=(__r);
+	   return *this;
+	 }
+
+       weak_ptr&
+       operator=(weak_ptr&& __r) noexcept = default;
+
+       template<typename _Tp1>
+	 weak_ptr&
+	 operator=(weak_ptr<_Tp1>&& __r) noexcept
+	 {
+	   this->__Base_type::operator=(std::move(__r));
+	   return *this;
+	 }
+
+       shared_ptr<_Tp>
+       lock() const noexcept
+       { return shared_ptr<_Tp>(*this, std::nothrow); }
+     };
+
+
+   // C++14 §20.8.2.3.6
+   template<typename _Tp>
+     inline void
+     swap(weak_ptr<_Tp>& __a, weak_ptr<_Tp>& __b) noexcept
+     { __a.swap(__b); }
+
+   // C++14 §20.8.2.4
+   template<typename _Tp> class owner_less;
+
+   // C++14 §20.8.2.6
+   template<typename _Tp>
+     inline bool
+     atomic_is_lock_free(const shared_ptr<_Tp>* __p)
+     { return std::atomic_is_lock_free<_Tp, __default_lock_policy>(__p); }
+
+   template<typename _Tp>
+     shared_ptr<_Tp> atomic_load(const shared_ptr<_Tp>* __p)
+     { return std::atomic_load<_Tp>(__p); }
+
+   template<typename _Tp>
+     shared_ptr<_Tp>
+     atomic_load_explicit(const shared_ptr<_Tp>* __p, memory_order __mo)
+     { return std::atomic_load_explicit<_Tp>(__p, __mo); }
+
+   template<typename _Tp>
+     void atomic_store(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r)
+     { return std::atomic_store<_Tp>(__p, __r); }
+
+   template<typename _Tp>
+     shared_ptr<_Tp>
+     atomic_store_explicit(const shared_ptr<_Tp>* __p,
+			   shared_ptr<_Tp> __r,
+			   memory_order __mo)
+     { return std::atomic_store_explicit<_Tp>(__p, __r, __mo); }
+
+   template<typename _Tp>
+     void atomic_exchange(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r)
+     { return std::atomic_exchange<_Tp>(__p, __r); }
+
+   template<typename _Tp>
+     shared_ptr<_Tp>
+     atomic_exchange_explicit(const shared_ptr<_Tp>* __p,
+			      shared_ptr<_Tp> __r,
+			      memory_order __mo)
+     { return std::atomic_exchange_explicit<_Tp>(__p, __r, __mo); }
+
+   template<typename _Tp>
+     bool atomic_compare_exchange_weak(shared_ptr<_Tp>* __p,
+				       shared_ptr<_Tp>* __v,
+				       shared_ptr<_Tp> __w)
+     { return std::atomic_compare_exchange_weak<_Tp>(__p, __v, __w); }
+
+   template<typename _Tp>
+     bool atomic_compare_exchange_strong(shared_ptr<_Tp>* __p,
+					 shared_ptr<_Tp>* __v,
+					 shared_ptr<_Tp> __w)
+     { return std::atomic_compare_exchange_strong<_Tp>(__p, __v, __w); }
+
+   template<typename _Tp>
+     bool atomic_compare_exchange_weak_explicit(shared_ptr<_Tp>* __p,
+						shared_ptr<_Tp>* __v,
+						shared_ptr<_Tp> __w,
+						memory_order __success,
+						memory_order __failure)
+     { return std::atomic_compare_exchange_weak_explicit<_Tp>(__p, __v, __w,
+							      __success,
+							      __failure); }
+
+   template<typename _Tp>
+     bool atomic_compare_exchange_strong_explicit(shared_ptr<_Tp>* __p,
+						  shared_ptr<_Tp>* __v,
+						  shared_ptr<_Tp> __w,
+						  memory_order __success,
+						  memory_order __failure)
+     { return std::atomic_compare_exchange_strong_explicit<_Tp>(__p, __v, __w,
+								__success,
+								__failure); }
+
+  //enable_shared_from_this
+  template<typename _Tp>
+    class enable_shared_from_this
+    {
+    protected:
+      constexpr enable_shared_from_this() noexcept { }
+
+      enable_shared_from_this(const enable_shared_from_this&) noexcept { }
+
+      enable_shared_from_this&
+      operator=(const enable_shared_from_this&) noexcept
+      { return *this; }
+
+      ~enable_shared_from_this() { }
+
+    public:
+      shared_ptr<_Tp>
+      shared_from_this()
+      { return shared_ptr<_Tp>(this->_M_weak_this); }
+
+      shared_ptr<const _Tp>
+      shared_from_this() const
+      { return shared_ptr<const _Tp>(this->_M_weak_this); }
+
+    private:
+      template<typename _Tp1>
+	void
+	_M_weak_assign(_Tp1* __p, const __shared_count<>& __n) const noexcept
+	{ __weak_ptr_friend<_Tp>::_S_assign(_M_weak_this, __p,__n); }
+
+      template<typename _Tp1>
+	friend void
+	__enable_shared_from_this_helper(const __shared_count<>& __pn,
+					 const enable_shared_from_this* __pe,
+					 const _Tp1* __px) noexcept
+	{
+	  if(__pe != 0)
+	    __pe->_M_weak_assign(const_cast<_Tp1*>(__px), __pn);
+	}
+
+      mutable weak_ptr<_Tp>  _M_weak_this;
+    };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace fundamentals_v1
 } // namespace experimental
 
 template <typename _Tp>
Index: libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/assign/assign.cc
===================================================================
--- libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/assign/assign.cc	(revision 0)
+++ libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/assign/assign.cc	(working copy)
@@ -0,0 +1,104 @@
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2015 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/>.
+
+// 8.2.1 Class template shared_ptr [memory.smartptr.shared]
+
+
+#include <experimental/memory>
+#include <testsuite_hooks.h>
+
+
+struct A
+{
+  A() { ++ctor_count; }
+  virtual ~A() { ++dtor_count; }
+  static long ctor_count;
+  static long dtor_count;
+};
+long A::ctor_count = 0;
+long A::dtor_count = 0;
+
+struct B : A
+{
+  B() { ++ctor_count; }
+  virtual ~B() { ++dtor_count; }
+  static long ctor_count;
+  static long dtor_count;
+};
+long B::ctor_count = 0;
+long B::dtor_count = 0;
+
+struct reset_count_struct
+{
+  ~reset_count_struct()
+  {
+    A::ctor_count = 0;
+    A::dtor_count = 0;
+    B::ctor_count = 0;
+    B::dtor_count = 0;
+  }
+};
+
+// C++14 §20.8.2.2.3 shared_ptr assignment
+
+void
+test01()
+{
+  reset_count_struct __attribute__((unused)) reset;
+  bool test __attribute__((unused)) = true;
+
+  std::experimental::shared_ptr<A[5]> a;
+  std::experimental::shared_ptr<A[]> a1;
+  std::experimental::shared_ptr<B[5]> a2;
+
+  a = std::experimental::shared_ptr<A[5]> ();
+  VERIFY( a.get() == 0 );
+  VERIFY( A::ctor_count == 0 );
+  VERIFY( A::dtor_count == 0 );
+  VERIFY( B::ctor_count == 0 );
+  VERIFY( B::dtor_count == 0 );
+
+  a = std::experimental::shared_ptr<A[5]> (new A[5]);
+  VERIFY( a.get() != 0 );
+  VERIFY( A::ctor_count == 5 );
+  VERIFY( A::dtor_count == 0 );
+  VERIFY( B::ctor_count == 0 );
+  VERIFY( B::dtor_count == 0 );
+
+  a1 = std::experimental::shared_ptr<A[5]> (new A[5]);
+  VERIFY( a1.get() != 0 );
+  VERIFY( A::ctor_count == 10 );
+  VERIFY( A::dtor_count == 0 );
+  VERIFY( B::ctor_count == 0 );
+  VERIFY( B::dtor_count == 0 );
+
+  a2 = std::experimental::shared_ptr<B[5]> (new B[5]);
+  VERIFY( a2.get() != 0 );
+  VERIFY( A::ctor_count == 15 );
+  VERIFY( A::dtor_count == 0 );
+  VERIFY( B::ctor_count == 5 );
+  VERIFY( B::dtor_count == 0 );
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}
Index: libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cast/cast.cc
===================================================================
--- libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cast/cast.cc	(revision 0)
+++ libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cast/cast.cc	(working copy)
@@ -0,0 +1,44 @@
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2015 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/>.
+
+// 8.2.1.3 shared_ptr casts [memory.smartptr.shared.cast]
+
+#include <experimental/memory>
+#include <testsuite_tr1.h>
+
+// { dg-do compile }
+
+struct A { };
+
+int
+main()
+{
+  using __gnu_test::check_ret_type;
+  using std::experimental::shared_ptr;
+  using std::experimental::static_pointer_cast;
+  using std::experimental::const_pointer_cast;
+  using std::experimental::dynamic_pointer_cast;
+
+  shared_ptr<A[5]> spa;
+  shared_ptr<const A[5]> spa1;
+
+  check_ret_type<shared_ptr<A[]> >(static_pointer_cast<A[]>(spa));
+  check_ret_type<shared_ptr<A[]> >(const_pointer_cast<A[]>(spa1));
+  return 0;
+}
Index: libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/comparison/comparison.cc
===================================================================
--- libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/comparison/comparison.cc	(revision 0)
+++ libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/comparison/comparison.cc	(working copy)
@@ -0,0 +1,84 @@
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2015 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/>.
+
+// 8.2.1 Class template shared_ptr [memory.smartptr.shared]
+
+#include <experimental/memory>
+#include <testsuite_hooks.h>
+
+struct A
+{
+    virtual ~A() { }
+};
+
+struct B : A
+{
+};
+
+// 20.8.2.2.7 shared_ptr comparison
+
+int
+test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  // test empty shared_ptrs compare equivalent
+  std::experimental::shared_ptr<A[5]> p1;
+  std::experimental::shared_ptr<B[5]> p2;
+  VERIFY( p1 == p2 );
+  VERIFY( !(p1 != p2) );
+  VERIFY( !(p1 < p2) && !(p2 < p1) );
+  return 0;
+}
+
+int
+test02()
+{
+  bool test __attribute__((unused)) = true;
+
+  std::experimental::shared_ptr<A[5]> A_default;
+
+  std::experimental::shared_ptr<A[5]> A_from_A(new A[5]);
+  VERIFY( A_default != A_from_A );
+  VERIFY( !(A_default == A_from_A) );
+  VERIFY( (A_default < A_from_A) || (A_from_A < A_default) );
+
+  std::experimental::shared_ptr<B[5]> B_from_B(new B[5]);
+  VERIFY( B_from_B != A_from_A );
+  VERIFY( !(B_from_B == A_from_A) );
+  VERIFY( (B_from_B < A_from_A) || (A_from_A < B_from_B) );
+
+  A_from_A.reset();
+  VERIFY( A_default == A_from_A );
+  VERIFY( !(A_default != A_from_A) );
+  VERIFY( !(A_default < A_from_A) && !(A_from_A < A_default));
+
+  B_from_B.reset();
+  VERIFY( B_from_B == A_from_A );
+  VERIFY( !(B_from_B != A_from_A) );
+  VERIFY( !(B_from_B < A_from_A) && !(A_from_A < B_from_B) );
+
+  return 0;
+}
+
+int
+main()
+{
+  return 0;
+}
Index: libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cons/alias_ctor.cc
===================================================================
--- libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cons/alias_ctor.cc	(revision 0)
+++ libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cons/alias_ctor.cc	(working copy)
@@ -0,0 +1,106 @@
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2015 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/>.
+
+// 8.2.1 Class template shared_ptr [memory.smartptr.shared]
+
+#include <experimental/memory>
+#include <testsuite_hooks.h>
+
+struct A
+{
+  A() : i() { }
+  virtual ~A() { }
+  int i;
+};
+
+struct B : A
+{
+  B() : A(), a() { }
+  virtual ~B() { }
+  A a;
+};
+
+// 8.2.1.1 shared_ptr constructors [memory.smartptr.shared.const]
+
+// Aliasing constructors
+
+int
+test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  std::experimental::shared_ptr<A[5]> a;
+  std::experimental::shared_ptr<bool> b1(a, &test);
+  VERIFY( b1.use_count() == 0 );
+  VERIFY( a.get() == 0 );
+  VERIFY( b1.get() == &test );
+
+  std::experimental::shared_ptr<bool> b2(b1);
+  VERIFY( b2.use_count() == 0 );
+  VERIFY( b1.get() == b2.get() );
+
+  return 0;
+}
+
+int
+test02()
+{
+  bool test __attribute__((unused)) = true;
+
+  std::experimental::shared_ptr<A[5]> a(new A[5]);
+  std::experimental::shared_ptr<int> i1(a, &a->i);
+  VERIFY( i1.use_count() == 2 );
+
+  std::experimental::shared_ptr<int> i2(i1);
+  VERIFY( i2.use_count() == 3 );
+  VERIFY( i2.get() == &a->i );
+
+  return 0;
+}
+
+int
+test03()
+{
+  bool test __attribute__((unused)) = true;
+
+  std::experimental::shared_ptr<B> b(new B);
+  std::experimental::shared_ptr<A> a1(b, b.get());
+  std::experimental::shared_ptr<A> a2(b, &b->a);
+  VERIFY( a2.use_count() == 3 );
+  VERIFY( a1 == b );
+  VERIFY( a2 != b );
+  VERIFY( a1.get() != a2.get() );
+
+  std::experimental::shared_ptr<A> a3(a1);
+  VERIFY( a3 == b );
+
+  a3 = a2;
+  VERIFY( a3.get() == &b->a );
+
+  return 0;
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  test03();
+  return 0;
+}
Index: libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cons/alloc_ctor.cc
===================================================================
--- libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cons/alloc_ctor.cc	(revision 0)
+++ libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cons/alloc_ctor.cc	(working copy)
@@ -0,0 +1,73 @@
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2015 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/>.
+
+// 8.2.1 Class template shared_ptr [memory.smartptr.shared]
+
+#include <experimental/memory>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::tracker_allocator_counter;
+using __gnu_test::tracker_allocator;
+
+struct A { };
+void deletefunc(A* p) { delete [] p; }
+struct D
+{
+    void operator()(A* p) { delete [] p; ++delete_count; }
+    static long delete_count;
+};
+long D::delete_count = 0;
+
+// 8.2.1.1 shared_ptr constructors [memory.smartptr.shared.const]
+
+// Construction with allocator
+
+int
+test01()
+{
+  bool test __attribute__((unused)) = true;
+  tracker_allocator_counter::reset();
+
+  std::experimental::shared_ptr<A[5]> p1(new A[5], deletefunc, tracker_allocator<A[5]>());
+  std::size_t const sz = tracker_allocator_counter::get_allocation_count();
+  VERIFY( sz > 0 );
+  {
+    std::experimental::shared_ptr<A[5]> p2(p1);
+    VERIFY( p2.use_count() == 2 );
+    VERIFY( tracker_allocator_counter::get_allocation_count() == sz );
+    VERIFY( tracker_allocator_counter::get_deallocation_count() == 0 );
+  }
+  VERIFY( p1.use_count() == 1 );
+  VERIFY( tracker_allocator_counter::get_allocation_count() == sz);
+  VERIFY( tracker_allocator_counter::get_deallocation_count() == 0 );
+  p1.reset();
+  VERIFY( p1.use_count() == 0 );
+  VERIFY( tracker_allocator_counter::get_allocation_count() == sz );
+  VERIFY( tracker_allocator_counter::get_deallocation_count() == sz );
+
+  return 0;
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}
Index: libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cons/copy_ctor.cc
===================================================================
--- libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cons/copy_ctor.cc	(revision 0)
+++ libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cons/copy_ctor.cc	(working copy)
@@ -0,0 +1,158 @@
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2015 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/>.
+
+// 8.2.1 Class template shared_ptr [memory.smartptr.shared]
+
+#include <experimental/memory>
+#include <testsuite_hooks.h>
+
+struct A
+{
+  A() { ++ctor_count; }
+  virtual ~A() { ++dtor_count; }
+  static long ctor_count;
+  static long dtor_count;
+};
+long A::ctor_count = 0;
+long A::dtor_count = 0;
+
+struct B : A
+{
+  B() { ++ctor_count; }
+  virtual ~B() { ++dtor_count; }
+  static long ctor_count;
+  static long dtor_count;
+};
+long B::ctor_count = 0;
+long B::dtor_count = 0;
+
+void deleter(A* p) { delete [] p; }
+
+struct reset_count_struct
+{
+  ~reset_count_struct()
+    {
+      A::ctor_count = 0;
+      A::dtor_count = 0;
+      B::ctor_count = 0;
+      B::dtor_count = 0;
+    }
+};
+
+// 8.2.1.1 shared_ptr constructors [memory.smartptr.shared.const]
+
+// Copy construction
+
+int
+test01()
+{
+  reset_count_struct __attribute__((unused)) reset;
+  bool test __attribute__((unused)) = true;
+
+  std::experimental::shared_ptr<A[5]> a1;
+  std::experimental::shared_ptr<A[5]> a2(a1);
+  VERIFY( a2.use_count() == 0 );
+  VERIFY( A::ctor_count == 0 );
+  VERIFY( A::dtor_count == 0 );
+  VERIFY( B::ctor_count == 0 );
+  VERIFY( B::dtor_count == 0 );
+
+  return 0;
+}
+
+int
+test02()
+{
+  reset_count_struct __attribute__((unused)) reset;
+  bool test __attribute__((unused)) = true;
+
+  std::experimental::shared_ptr<A[5]> a1(new A[5]);
+  std::experimental::shared_ptr<A[5]> a2(a1);
+  VERIFY( a2.use_count() == 2 );
+  VERIFY( A::ctor_count == 5 );
+  VERIFY( A::dtor_count == 0 );
+  VERIFY( B::ctor_count == 0 );
+  VERIFY( B::dtor_count == 0 );
+
+  return 0;
+}
+
+int
+test03()
+{
+  reset_count_struct __attribute__((unused)) reset;
+  bool test __attribute__((unused)) = true;
+
+  std::experimental::shared_ptr<A[5]> a1(new A[5], &deleter);
+  std::experimental::shared_ptr<A[5]> a2(a1);
+  VERIFY( a2.use_count() == 2 );
+  VERIFY( A::ctor_count == 5 );
+  VERIFY( A::dtor_count == 0 );
+  VERIFY( B::ctor_count == 0 );
+  VERIFY( B::dtor_count == 0 );
+
+  return 0;
+}
+
+int
+test04()
+{
+  reset_count_struct __attribute__((unused)) reset;
+  bool test __attribute__((unused)) = true;
+
+  std::experimental::shared_ptr<A[5]> a1(std::experimental::shared_ptr<A[5]>
+                                          (new A[5]));
+  VERIFY( a1.use_count() == 1 );
+  VERIFY( A::ctor_count == 5 );
+  VERIFY( A::dtor_count == 0 );
+  VERIFY( B::ctor_count == 0 );
+  VERIFY( B::dtor_count == 0 );
+
+  return 0;
+}
+
+int
+test05()
+{
+  reset_count_struct __attribute__((unused)) reset;
+  bool test __attribute__((unused)) = true;
+
+  std::experimental::shared_ptr<A[5]> a1(new A[5]);
+  std::experimental::shared_ptr<A[]> a2(a1);
+
+  VERIFY( a2.use_count() == 2 );
+  VERIFY( a2.get() == a1.get() );
+  VERIFY( A::ctor_count == 5 );
+  VERIFY( A::dtor_count == 0 );
+  VERIFY( B::ctor_count == 0 );
+  VERIFY( B::dtor_count == 0 );
+
+  return 0;
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+  test05();
+  return 0;
+}
Index: libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cons/copy_ctor_neg.cc
===================================================================
--- libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cons/copy_ctor_neg.cc	(revision 0)
+++ libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cons/copy_ctor_neg.cc	(working copy)
@@ -0,0 +1,59 @@
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2015 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/>.
+
+// 8.2.1 Class template shared_ptr [memory.smartptr.shared]
+
+
+#include <experimental/memory>
+#include <testsuite_hooks.h>
+
+
+struct A { virtual ~A() { } };
+struct B : A { };
+
+
+// 8.2.1.1 shared_ptr constructors [memory.smartptr.shared.const]
+
+// Copy construction
+
+void
+test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  std::experimental::shared_ptr<A[3]> a;
+  a = std::experimental::shared_ptr<B[3]> (new B[3]); // { dg-excess-errors "no matching" }
+}
+
+void
+test02()
+{
+  bool test __attribute__((unused)) = true;
+
+  std::experimental::shared_ptr<A[]> a(new A[3]);
+  std::experimental::shared_ptr<A[2]> spa(a); // { dg-excess-errors "no matching" }
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  return 0;
+}
Index: libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cons/default_ctor.cc
===================================================================
--- libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cons/default_ctor.cc	(revision 0)
+++ libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cons/default_ctor.cc	(working copy)
@@ -0,0 +1,46 @@
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2015 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/>.
+
+// 8.2.1 Class template shared_ptr [memory.smartptr.shared]
+
+#include <experimental/memory>
+#include <testsuite_hooks.h>
+
+struct A { };
+
+// 8.2.1.1 shared_ptr constructors [memory.smartptr.shared.const]
+
+// Default construction
+int
+test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  std::experimental::shared_ptr<A[5]> a;
+  VERIFY( a.get() == 0 );
+
+  return 0;
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}
Index: libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cons/move_ctor.cc
===================================================================
--- libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cons/move_ctor.cc	(revision 0)
+++ libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cons/move_ctor.cc	(working copy)
@@ -0,0 +1,146 @@
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2015 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/>.
+
+// 8.2.1 Class template shared_ptr [memory.smartptr.shared]
+
+#include <experimental/memory>
+#include <testsuite_hooks.h>
+
+struct A
+{
+  A() { ++ctor_count; }
+  virtual ~A() { ++dtor_count; }
+  static long ctor_count;
+  static long dtor_count;
+};
+long A::ctor_count = 0;
+long A::dtor_count = 0;
+
+struct D
+{
+  void operator()(A* p) const { delete [] p; ++delete_count; }
+  static long delete_count;
+};
+long D::delete_count = 0;
+
+struct reset_count_struct
+{
+  ~reset_count_struct()
+    {
+      A::ctor_count = 0;
+      A::dtor_count = 0;
+      D::delete_count = 0;
+    }
+};
+
+// 8.2.1.1 shared_ptr constructors [memory.smartptr.shared.const]
+
+// Rvalue construction
+int test01()
+{
+  reset_count_struct __attribute__((unused)) reset;
+  bool test __attribute__((unused)) = true;
+
+  std::experimental::shared_ptr<A[5]> a1;
+  std::experimental::shared_ptr<A[5]> a2(std::move(a1));
+  VERIFY( a1.use_count() == 0 );
+  VERIFY( a2.use_count() == 0 );
+  VERIFY( A::ctor_count == 0 );
+  VERIFY( A::dtor_count == 0 );
+
+  return 0;
+}
+
+int
+test02()
+{
+  reset_count_struct __attribute__((unused)) reset;
+  bool test __attribute__((unused)) = true;
+
+  std::experimental::shared_ptr<A[5]> a1(new A[5]);
+  std::experimental::shared_ptr<A[5]> a2(std::move(a1));
+  VERIFY( a2.use_count() == 1 );
+  VERIFY( A::ctor_count == 5 );
+  VERIFY( A::dtor_count == 0 );
+
+  return 0;
+}
+
+int
+test03()
+{
+  reset_count_struct __attribute__((unused)) reset;
+  bool test __attribute__((unused)) = true;
+
+  std::experimental::shared_ptr<A[5]> b(new A[5], D());
+  std::experimental::shared_ptr<A[5]> b1(std::move(b));
+  VERIFY( b.use_count() == 0 );
+  VERIFY( b1.use_count() == 1 );
+  VERIFY( A::ctor_count == 5 );
+  VERIFY( A::dtor_count == 0 );
+
+  b1 = std::move(std::experimental::shared_ptr<A[5]> ());
+
+  VERIFY( A::ctor_count == 5 );
+  VERIFY( A::dtor_count == 5 );
+  VERIFY( D::delete_count == 1 );
+
+  return 0;
+}
+
+void
+test04()
+{
+  reset_count_struct __attribute__((unused)) reset;
+  bool test __attribute__((unused)) = true;
+
+  std::experimental::shared_ptr<A[5]> a(std::move(std::experimental
+                                        ::shared_ptr<A[5]>
+                                        (new A[5])));
+
+  VERIFY( a.use_count() == 1 );
+  VERIFY( A::ctor_count == 5 );
+  VERIFY( A::dtor_count == 0 );
+}
+
+void
+test05()
+{
+  reset_count_struct __attribute__((unused)) reset;
+  bool test __attribute__((unused)) = true;
+
+  std::experimental::shared_ptr<A[]> a(std::move(std::experimental
+                                        ::shared_ptr<A[5]>
+                                        (new A[5])));
+
+  VERIFY( a.use_count() == 1 );
+  VERIFY( A::ctor_count == 5 );
+  VERIFY( A::dtor_count == 0 );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+  test05();
+  return 0;
+}
Index: libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cons/pointer_ctor.cc
===================================================================
--- libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cons/pointer_ctor.cc	(revision 0)
+++ libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cons/pointer_ctor.cc	(working copy)
@@ -0,0 +1,75 @@
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2015 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/>.
+
+// 8.2.1 Class template shared_ptr [memory.smartptr.shared]
+
+#include <experimental/memory>
+#include <testsuite_hooks.h>
+
+struct A { };
+struct B : A { };
+
+// 8.2.1.1 shared_ptr constructors [memory.smartptr.shared.const]
+
+// Construction from pointer
+int
+test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  A * const a = 0;
+  std::experimental::shared_ptr<A> p(a);
+  VERIFY( p.get() == 0 );
+  VERIFY( p.use_count() == 1 );
+  return 0;
+}
+
+int
+test02()
+{
+  bool test __attribute__((unused)) = true;
+
+  A * const a = new A[5];
+  std::experimental::shared_ptr<A[5]> p(a);
+  VERIFY( p.get() == a );
+  VERIFY( p.use_count() == 1 );
+  return 0;
+}
+
+int
+test03()
+{
+  bool test __attribute__((unused)) = true;
+
+  B * const b = new B[5];
+  std::experimental::shared_ptr<A[5]> p(b);
+  VERIFY( p.get() == b );
+  VERIFY( p.use_count() == 1 );
+
+  return 0;
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  test03();
+  return 0;
+}
Index: libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cons/unique_ptr_ctor.cc
===================================================================
--- libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cons/unique_ptr_ctor.cc	(revision 0)
+++ libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cons/unique_ptr_ctor.cc	(working copy)
@@ -0,0 +1,60 @@
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2015 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/>.
+
+// 8.2.1 Class template shared_ptr [memory.smartptr.shared]
+
+#include <experimental/memory>
+#include <testsuite_hooks.h>
+
+int destroyed = 0;
+
+struct A : std::experimental::enable_shared_from_this<A>
+{
+    ~A() { ++destroyed; }
+};
+
+// 8.2.1.1 shared_ptr constructors [memory.smartptr.shared.const]
+
+// Construction from unique_ptr<A[]>
+
+int
+test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  std::unique_ptr<A[]> up(new A[5]);
+  std::experimental::shared_ptr<A> sp(std::move(up));
+  VERIFY( up.get() == 0 );
+  VERIFY( sp.get() != 0 );
+  VERIFY( sp.use_count() == 1 );
+
+  VERIFY( sp->shared_from_this() != nullptr );
+
+  sp.reset();
+  VERIFY( destroyed == 5 );
+
+  return 0;
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}
Index: libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cons/weak_ptr_ctor.cc
===================================================================
--- libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cons/weak_ptr_ctor.cc	(revision 0)
+++ libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/cons/weak_ptr_ctor.cc	(working copy)
@@ -0,0 +1,54 @@
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2015 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/>.
+
+// 8.2.1 Class template shared_ptr [memory.smartptr.shared]
+
+#include <experimental/memory>
+#include <testsuite_hooks.h>
+
+struct A { };
+
+// 8.2.1.1 shared_ptr constructors [memory.smartptr.shared.const]
+
+// Construction from weak_ptr
+int
+test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  A * a = new A[5];
+  std::experimental::shared_ptr<A[5]> a1(a);
+  std::experimental::weak_ptr<A[5]> wa(a1);
+  std::experimental::shared_ptr<A[5]> a2(wa);
+  std::experimental::shared_ptr<A[5]> a3 = wa.lock();
+  VERIFY( a2.get() == a );
+  VERIFY( a3.get() == a );
+  VERIFY( a2.use_count() == wa.use_count() );
+  VERIFY( a3.use_count() == wa.use_count() );
+
+  return 0;
+}
+
+
+int
+main()
+{
+  test01();
+  return 0;
+}
Index: libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/dest/dest.cc
===================================================================
--- libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/dest/dest.cc	(revision 0)
+++ libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/dest/dest.cc	(working copy)
@@ -0,0 +1,129 @@
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2015 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/>.
+
+// 8.2.1 Class template shared_ptr [memory.smartptr.shared]
+
+#include <experimental/memory>
+#include <testsuite_hooks.h>
+
+struct A
+{
+  A() { ++ctor_count; }
+  ~A() { ++dtor_count; }
+  static long ctor_count;
+  static long dtor_count;
+};
+long A::ctor_count = 0;
+long A::dtor_count = 0;
+
+struct B : A
+{
+  B() { ++ctor_count; }
+  ~B() { ++dtor_count; }
+  static long ctor_count;
+  static long dtor_count;
+};
+long B::ctor_count = 0;
+long B::dtor_count = 0;
+
+struct D
+{
+  void operator()(const B* p) { delete [] p; ++delete_count; }
+  static long delete_count;
+};
+long D::delete_count = 0;
+
+struct reset_count_struct
+{
+  ~reset_count_struct()
+    {
+      A::ctor_count = 0;
+      A::dtor_count = 0;
+      B::ctor_count = 0;
+      B::dtor_count = 0;
+      D::delete_count = 0;
+    }
+};
+
+// 20.8.2.2.2 shared_ptr destructor
+
+int
+test01()
+{
+  reset_count_struct __attribute__((unused)) reset;
+  bool test __attribute__((unused)) = true;
+
+  {
+    std::experimental::shared_ptr<A[5]> a;
+  }
+  VERIFY( A::ctor_count == 0 );
+  VERIFY( A::dtor_count == 0 );
+  VERIFY( B::ctor_count == 0 );
+  VERIFY( B::dtor_count == 0 );
+  VERIFY( D::delete_count == 0 );
+
+  return 0;
+}
+
+int
+test02()
+{
+  reset_count_struct __attribute__((unused)) reset;
+  bool test __attribute__((unused)) = true;
+
+  {
+    std::experimental::shared_ptr<B[5]> a;
+    a = std::experimental::shared_ptr<B[5]>(new B[5], D());
+  }
+  VERIFY( A::ctor_count == 5 );
+  VERIFY( A::dtor_count == 5 );
+  VERIFY( B::ctor_count == 5 );
+  VERIFY( B::dtor_count == 5 );
+  VERIFY( D::delete_count == 1 );
+
+  return 0;
+}
+
+int
+test03()
+{
+  reset_count_struct __attribute__((unused)) reset;
+  bool test __attribute__((unused)) = true;
+
+  {
+    std::experimental::shared_ptr<B[]> a;
+    a = std::experimental::shared_ptr<B[5]>(new B[5], D());
+  }
+  VERIFY( A::ctor_count == 5 );
+  VERIFY( A::dtor_count == 5 );
+  VERIFY( B::ctor_count == 5 );
+  VERIFY( B::dtor_count == 5 );
+  VERIFY( D::delete_count == 1 );
+
+  return 0;
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  test03();
+  return 0;
+}
Index: libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/modifiers/reset.cc
===================================================================
--- libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/modifiers/reset.cc	(revision 0)
+++ libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/modifiers/reset.cc	(working copy)
@@ -0,0 +1,89 @@
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2015 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/>.
+
+// 8.2.1 Class template shared_ptr [memory.smartptr.shared]
+
+#include <experimental/memory>
+#include <testsuite_hooks.h>
+
+struct A { };
+struct B : A { };
+struct D
+{
+  void operator()(B* p) { delete [] p; ++delete_count; }
+  static long delete_count;
+};
+long D::delete_count = 0;
+
+// C++14 §20.8.2.2.4
+
+// reset
+int
+test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  A * const a = new A[5];
+  std::experimental::shared_ptr<A[5]> p1(a);
+  std::experimental::shared_ptr<A[5]> p2(p1);
+  p1.reset();
+  VERIFY( p1.get() == 0 );
+  VERIFY( p2.get() == a );
+
+  return 0;
+}
+
+int
+test02()
+{
+  bool test __attribute__((unused)) = true;
+
+  A * const a = new A[5];
+  B * const b = new B[5];
+  std::experimental::shared_ptr<A[5]> p1(a);
+  std::experimental::shared_ptr<A[5]> p2(p1);
+  p1.reset(b);
+  VERIFY( p1.get() == b );
+  VERIFY( p2.get() == a );
+
+  return 0;
+}
+
+int
+test03()
+{
+  bool test __attribute__((unused)) = true;
+
+  {
+    std::experimental::shared_ptr<A[5]> p1;
+    p1.reset(new B[5], D());
+  }
+  VERIFY( D::delete_count == 1 );
+
+  return 0;
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  test03();
+  return 0;
+}
Index: libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/modifiers/swap.cc
===================================================================
--- libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/modifiers/swap.cc	(revision 0)
+++ libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/modifiers/swap.cc	(working copy)
@@ -0,0 +1,53 @@
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2015 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/>.
+
+// 8.2.1 Class template shared_ptr [memory.smartptr.shared]
+
+#include <experimental/memory>
+#include <testsuite_hooks.h>
+
+struct A { };
+
+// C++14 §20.8.2.2.4
+
+// swap
+int
+test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  A * const a1 = new A[5];
+  A * const a2 = new A[5];
+  std::experimental::shared_ptr<A[5]> p1(a1);
+  std::experimental::shared_ptr<A[5]> p2(a2);
+  p1.swap(p2);
+  VERIFY( p1.get() == a2 );
+  VERIFY( p2.get() == a1 );
+
+  return 0;
+}
+
+
+
+int
+main()
+{
+  test01();
+  return 0;
+}
Index: libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/observers/bool_conv.cc
===================================================================
--- libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/observers/bool_conv.cc	(revision 0)
+++ libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/observers/bool_conv.cc	(working copy)
@@ -0,0 +1,74 @@
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2015 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/>.
+
+// 8.2.1 Class template shared_ptr [memory.smartptr.shared]
+
+#include <experimental/memory>
+#include <testsuite_hooks.h>
+
+struct A { };
+
+// 8.2.1.2 shared_ptr observers [memory.smartptr.shared.obs]
+
+// Conversion to bool
+void
+test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  const std::experimental::shared_ptr<A[5]> p1;
+  VERIFY( static_cast<bool>(p1) == false );
+  const std::experimental::shared_ptr<A[5]> p2(p1);
+  VERIFY( static_cast<bool>(p2) == false );
+}
+
+void
+test02()
+{
+  bool test __attribute__((unused)) = true;
+
+  std::experimental::shared_ptr<A[5]> p1(new A[5]);
+  VERIFY( static_cast<bool>(p1) );
+  std::experimental::shared_ptr<A[5]> p2(p1);
+  VERIFY( static_cast<bool>(p2) );
+  p1.reset();
+  VERIFY( !static_cast<bool>(p1) );
+  VERIFY( static_cast<bool>(p2) );
+}
+
+void
+test03()
+{
+  bool test __attribute__((unused)) = true;
+
+  std::experimental::shared_ptr<A[5]> p1(new A[5]);
+  std::experimental::shared_ptr<A[5]> p2(p1);
+  p2.reset(new A[5]);
+  VERIFY( static_cast<bool>(p1) );
+  VERIFY( static_cast<bool>(p2) );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  test03();
+  return 0;
+}
Index: libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/observers/operators.cc
===================================================================
--- libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/observers/operators.cc	(revision 0)
+++ libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/observers/operators.cc	(working copy)
@@ -0,0 +1,93 @@
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2015 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/>.
+
+// 8.2.1 Class template shared_ptr [memory.smartptr.shared]
+
+#include <experimental/memory>
+#include <testsuite_hooks.h>
+
+struct A
+{
+  A() : i() {}
+  int i;
+};
+
+// 8.2.1.2 shared_ptr observers [memory.smartptr.shared.obs]
+
+// get
+void
+test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  A * const a = new A[5];
+  const std::experimental::shared_ptr<A[5]> p(a);
+  VERIFY( p.get() == a );
+}
+
+// operator []
+int
+test02()
+{
+  A * p = new A[5];
+  std::experimental::shared_ptr<A[5]> a(p);
+
+  for(int j = 0; j < 5; j++)
+  { a[j].i = j; }
+
+  VERIFY(a.get() == p);
+  VERIFY(a.use_count() == 1);
+
+  for(int j = 0; j < 5; j++)
+  { VERIFY(a[j].i == j); }
+
+  return 0;
+}
+
+// operator*
+void
+test03()
+{
+  bool test __attribute__((unused)) = true;
+
+  A * const a = new A[5];
+  const std::experimental::shared_ptr<A[5]> p(a);
+  VERIFY( &*p == a );
+}
+
+// operator->
+void
+test04()
+{
+  bool test __attribute__((unused)) = true;
+
+  A * const a = new A[5];
+  const std::experimental::shared_ptr<A[5]> p(a);
+  VERIFY( &p->i == &a->i );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+  return 0;
+}
Index: libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/observers/owner_before.cc
===================================================================
--- libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/observers/owner_before.cc	(revision 0)
+++ libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/observers/owner_before.cc	(working copy)
@@ -0,0 +1,86 @@
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2015 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/>.
+
+// 8.2.1 Class template shared_ptr [memory.smartptr.shared]
+
+#include <experimental/memory>
+#include <testsuite_hooks.h>
+
+struct A
+{
+  int i;
+  virtual ~A() { }
+};
+
+struct B : A { };
+
+// 8.2.1.2 shared_ptr observers [memory.smartptr.shared.obs]
+
+// owner_before
+void
+test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  // test empty shared_ptrs compare equivalent
+  std::experimental::shared_ptr<A[5]> p1;
+  std::experimental::shared_ptr<B[5]> p2;
+  VERIFY( !p1.owner_before(p2) && !p2.owner_before(p1) );
+}
+
+void
+test02()
+{
+  bool test __attribute__((unused)) = true;
+
+  std::experimental::shared_ptr<A[5]> a0;
+
+  std::experimental::shared_ptr<A[5]> a1(new A[5]);
+  VERIFY( a1.owner_before(a0) || a0.owner_before(a1) );
+  VERIFY( !(a1.owner_before(a0) && a0.owner_before(a1)) );
+
+  std::experimental::shared_ptr<B[5]> b1(new B[5]);
+  VERIFY( a1.owner_before(b1) || b1.owner_before(a1) );
+  VERIFY( !(a1.owner_before(b1) && b1.owner_before(a1)) );
+
+  std::experimental::shared_ptr<A[5]> a2(a1);
+  VERIFY( !a1.owner_before(a2) && !a2.owner_before(a1) );
+
+  std::experimental::weak_ptr<A[5]> w1(a1);
+  VERIFY( !a1.owner_before(w1) && !w1.owner_before(a1) );
+}
+
+void
+test03()
+{
+  bool test __attribute__((unused)) = true;
+
+  std::experimental::shared_ptr<A[5]> p1(new A[5]);
+  std::experimental::shared_ptr<int> p2(p1, &p1->i);
+  VERIFY( !p1.owner_before(p2) && !p2.owner_before(p1) );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  test03();
+  return 0;
+}
Index: libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/observers/use_count.cc
===================================================================
--- libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/observers/use_count.cc	(revision 0)
+++ libstdc++-v3/testsuite/experimental/memory/shared_ptr_arrays/observers/use_count.cc	(working copy)
@@ -0,0 +1,73 @@
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2015 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/>.
+
+// 8.2.1 Class template shared_ptr [memory.smartptr.shared]
+
+#include <experimental/memory>
+#include <testsuite_hooks.h>
+
+struct A { };
+struct B : A { };
+
+// 8.2.1.2 shared_ptr observers [memory.smartptr.shared.obs]
+
+// use_count
+void
+test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  const std::experimental::shared_ptr<A[5]> p1;
+  VERIFY( p1.use_count() == 0 );
+  const std::experimental::shared_ptr<A[5]> p2(p1);
+  VERIFY( p1.use_count() == 0 );
+}
+
+void
+test02()
+{
+  bool test __attribute__((unused)) = true;
+
+  std::experimental::shared_ptr<A[5]> p1(new A[5]);
+  std::experimental::shared_ptr<A[5]> p2(p1);
+  p1.reset();
+  VERIFY( p1.use_count() == 0 );
+  VERIFY( p2.use_count() == 1 );
+}
+
+void
+test03()
+{
+  bool test __attribute__((unused)) = true;
+
+  std::experimental::shared_ptr<A[5]> p1(new A[5]);
+  std::experimental::shared_ptr<A[5]> p2(p1);
+  p2.reset(new B[5]);
+  VERIFY( p1.use_count() == 1 );
+  VERIFY( p2.use_count() == 1 );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  test03();
+  return 0;
+}

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH][GSoC] Extend shared_ptr to support arrays
  2015-06-24 18:19                   ` Fan You
@ 2015-06-25  4:01                     ` Tim Shen
  0 siblings, 0 replies; 9+ messages in thread
From: Tim Shen @ 2015-06-25  4:01 UTC (permalink / raw)
  To: Fan You; +Cc: gcc-patches, Jonathan Wakely, libstdc++

On Wed, Jun 24, 2015 at 10:33 AM, Fan You <youfan.noey@gmail.com> wrote:
> Hi,
>
> Here is the revised patch including all the test case.
>
> This can also be seen at <https://github.com/Noeyfan/gcc-1> on branch
> <shared_arrays>
>
> Any comments?

I ran `git diff c7248656569bb0b4549f5c1ed347f7e028a15664
90aff5632fd9f3044d53ce190ae99fb69c41ce49`.

To systematically detect consecutive spaces (to convert them to tabs),
I'll just simply do:
`egrep "^\t* {8}" shared_ptr*`

-       = typename conditional<is_array<_Tp>::value, _Array_Deleter,
_Normal_Deleter>::type;
+       = typename conditional<is_array<_Tp>
+                               ::value, _Array_Deleter, _Normal_Deleter>::type;
Tabs. Also, I personally prefer to put '::value' to the same line as
is_array<_Tp>.

-      using __base_type = __shared_ptr<element_type>;
+      using __Base_type = __shared_ptr<element_type>;
_Base_type, not __Base_type. Also, the mostly used is _Base:

...src/gcc/libstdc++-v3 % grep -r '_Base[a-zA-Z_0-9]*' . -o | grep
':.*$' -o|sort|uniq -c
   2350 :_Base
      1 :_Base_biteset
     62 :_Base_bitset
    120 :_Base_const_iterator
     20 :_Base_const_local_iterator
      4 :_Based
    177 :_Base_iterator
      1 :_Base_Iterator
      8 :_Base_local_iterator
     21 :_Base_manager
    133 :_Base_ptr
      9 :_Base_ref
      2 :_BaseSequence
    173 :_Base_type
      3 :_BaseType

-       : __base_type(__p, _Deleter_type())
+       : __Base_type(__p, _Deleter_type())
Please be aware of tabs.

-      template<typename _Tp1, typename = _Convertible<_Tp1*>>
+      template<typename _Tp1, typename = _Compatible<_Tp1>>
        __shared_ptr(__shared_ptr<__libfund_v1<_Tp1>, _Lp>&& __r) noexcept
-        : __base_type(std::move(__r))
+        : __Base_type(static_cast<typename __shared_ptr
+                      <__libfund_v1<_Tp1>>::__Base_type&&>(std::move(__r)))
static_cast<typename __shared_ptr<__libfund_v1<_Tp1>>::__Base_type&&>(__r)
is enough, since std::move is actually a static_cast to rvalue reference.

Alternatively, you may define a template alias for the static_cast, if
you find it too long.

-       operator=(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
+       operator=(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
Why?

    template<typename _Tp>
      inline bool
      operator<(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
-     {
+     {
        using _Tp_RE = typename remove_extent<_Tp>::type;
-       return std::less<_Tp_RE>()(__a.get(), nullptr);
+       return std::less<_Tp_RE>()(__a.get(), nullptr);
      }
using _Tp_RE = typename shared_ptr<_Tp>::element_type;



-- 
Regards,
Tim Shen

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2015-06-25  3:53 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CALvpekGQvTp2zRz65cnP+Ex7TKHQygdrYkqo5nUKGJ3bLQj8ww@mail.gmail.com>
2015-06-11 15:36 ` Fwd: [PATCH][GSoC] Extend shared_ptr to support arrays Fan You
2015-06-11 15:44 ` Jonathan Wakely
2015-06-11 16:21 ` Jonathan Wakely
2015-06-12  6:45 ` Tim Shen
2015-06-12  9:07   ` Jonathan Wakely
     [not found]     ` <CALvpekG4+YxSVz+jm_quo20=2bWYXnkBFrjDyBu6eYXW4YarHQ@mail.gmail.com>
2015-06-15  9:44       ` Jonathan Wakely
     [not found]         ` <CALvpekE2a8qi8qRjdzsDOi2OCRJw_ccYd1CrL6z68rLFW0fK0g@mail.gmail.com>
2015-06-16 13:30           ` Jonathan Wakely
     [not found]             ` <CALvpekFiRrz2UHTvGh+aqnkQPdL-Y=O-vRUXhxwVs-Wz+5v-RA@mail.gmail.com>
     [not found]               ` <CAG4ZjNnyp7Tax3CU0BAnbR0DSo6Xc+z8S7+3BSkYSyPpUpyu6g@mail.gmail.com>
     [not found]                 ` <CAG4ZjN=ahVX37AEMsjYEcL_N=quqLA9P1keiDC2NCKhkaCbmqQ@mail.gmail.com>
2015-06-24 18:19                   ` Fan You
2015-06-25  4:01                     ` Tim Shen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).