On Sat, Feb 09, 2019 at 09:52:52AM +0100, Jakub Jelinek wrote:
> And two further ones now, bootstrapped/regtested on powerpc64{,le}-linux
> and committed.

4 further ones, bootstrapped/regtested on x86_64-linux and i686-linux.

        Jakub
2019-02-14  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2019-02-09  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/89246
        * config/i386/i386.c (ix86_simd_clone_compute_vecsize_and_simdlen):
        If !node->definition and TYPE_ARG_TYPES is non-NULL, use
        TYPE_ARG_TYPES instead of DECL_ARGUMENTS.

        * gcc.dg/gomp/pr89246-1.c: New test.
        * gcc.dg/gomp/pr89246-2.c: New test.

--- gcc/config/i386/i386.c      (revision 268717)
+++ gcc/config/i386/i386.c      (revision 268718)
@@ -50447,28 +50447,34 @@ ix86_simd_clone_compute_vecsize_and_simd
 
   tree t;
   int i;
+  tree type_arg_types = TYPE_ARG_TYPES (TREE_TYPE (node->decl));
+  bool decl_arg_p = (node->definition || type_arg_types == NULL_TREE);
 
-  for (t = DECL_ARGUMENTS (node->decl), i = 0; t; t = DECL_CHAIN (t), i++)
-    switch (TYPE_MODE (TREE_TYPE (t)))
-      {
-      case E_QImode:
-      case E_HImode:
-      case E_SImode:
-      case E_DImode:
-      case E_SFmode:
-      case E_DFmode:
-      /* case E_SCmode: */
-      /* case E_DCmode: */
-       if (!AGGREGATE_TYPE_P (TREE_TYPE (t)))
-         break;
-       /* FALLTHRU */
-      default:
-       if (clonei->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
-         break;
-       warning_at (DECL_SOURCE_LOCATION (node->decl), 0,
-                   "unsupported argument type %qT for simd", TREE_TYPE (t));
-       return 0;
-      }
+  for (t = (decl_arg_p ? DECL_ARGUMENTS (node->decl) : type_arg_types), i = 0;
+       t && t != void_list_node; t = TREE_CHAIN (t), i++)
+    {
+      tree arg_type = decl_arg_p ? TREE_TYPE (t) : TREE_VALUE (t);
+      switch (TYPE_MODE (arg_type))
+       {
+       case E_QImode:
+       case E_HImode:
+       case E_SImode:
+       case E_DImode:
+       case E_SFmode:
+       case E_DFmode:
+       /* case E_SCmode: */
+       /* case E_DCmode: */
+         if (!AGGREGATE_TYPE_P (arg_type))
+           break;
+         /* FALLTHRU */
+       default:
+         if (clonei->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
+           break;
+         warning_at (DECL_SOURCE_LOCATION (node->decl), 0,
+                     "unsupported argument type %qT for simd", arg_type);
+         return 0;
+       }
+    }
 
   if (!TREE_PUBLIC (node->decl))
     {
--- gcc/testsuite/gcc.dg/gomp/pr89246-1.c       (nonexistent)
+++ gcc/testsuite/gcc.dg/gomp/pr89246-1.c       (revision 268718)
@@ -0,0 +1,19 @@
+/* PR middle-end/89246 */
+/* { dg-do link { target { int128 && vect_simd_clones } } } */
+/* { dg-options "-O2 -fopenmp-simd -w" } */
+/* { dg-additional-sources "pr89246-2.c" } */
+
+#pragma omp declare simd
+int foo (__int128 x)
+{
+  return x;
+}
+
+#pragma omp declare simd
+extern int bar (int x);
+
+int
+main ()
+{
+  return foo (0) + bar (0);
+}
--- gcc/testsuite/gcc.dg/gomp/pr89246-2.c       (nonexistent)
+++ gcc/testsuite/gcc.dg/gomp/pr89246-2.c       (revision 268718)
@@ -0,0 +1,13 @@
+/* PR middle-end/89246 */
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O0 -fno-openmp -fno-openmp-simd" } */
+
+#pragma omp declare simd
+extern int foo (__int128 x);
+
+#pragma omp declare simd
+int
+bar (int x)
+{
+  return x + foo (0);
+}
2019-02-14  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2019-02-13  Jakub Jelinek  <ja...@redhat.com>

        PR target/89290
        * config/i386/predicates.md (x86_64_immediate_operand): Allow
        TLS UNSPECs offsetted by signed 32-bit CONST_INT even with
        -mcmodel=large.

        * gcc.target/i386/pr89290.c: New test.

--- gcc/config/i386/predicates.md       (revision 268836)
+++ gcc/config/i386/predicates.md       (revision 268837)
@@ -182,7 +182,7 @@ (define_predicate "x86_64_immediate_oper
          rtx op1 = XEXP (XEXP (op, 0), 0);
          rtx op2 = XEXP (XEXP (op, 0), 1);
 
-         if (ix86_cmodel == CM_LARGE)
+         if (ix86_cmodel == CM_LARGE && GET_CODE (op1) != UNSPEC)
            return false;
          if (!CONST_INT_P (op2))
            return false;
--- gcc/testsuite/gcc.target/i386/pr89290.c     (nonexistent)
+++ gcc/testsuite/gcc.target/i386/pr89290.c     (revision 268837)
@@ -0,0 +1,19 @@
+/* PR target/89290 */
+/* { dg-do compile { target { tls && lp64 } } } */
+/* { dg-options "-O0 -mcmodel=large" } */
+
+struct S { long int a, b; } e;
+__thread struct S s;
+__thread struct S t[2];
+
+void
+foo (void)
+{
+  s = e;
+}
+
+void
+bar (void)
+{
+  t[1] = e;
+}
2019-02-14  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2019-02-13  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/89281
        * optabs.c (prepare_cmp_insn): Use UINTVAL (size) instead of
        INTVAL (size), compare it to GET_MODE_MASK instead of
        1 << GET_MODE_BITSIZE.

--- gcc/optabs.c        (revision 268840)
+++ gcc/optabs.c        (revision 268841)
@@ -3898,7 +3898,7 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx
 
          /* Must make sure the size fits the insn's mode.  */
          if (CONST_INT_P (size)
-             ? INTVAL (size) >= (1 << GET_MODE_BITSIZE (cmp_mode))
+             ? UINTVAL (size) > GET_MODE_MASK (cmp_mode)
              : (GET_MODE_BITSIZE (as_a <scalar_int_mode> (GET_MODE (size)))
                 > GET_MODE_BITSIZE (cmp_mode)))
            continue;
2019-02-14  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2019-02-13  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/89303
        * tree-ssa-structalias.c (set_uids_in_ptset): Or in vi->is_heap_var
        into pt->vars_contains_escaped_heap instead of setting
        pt->vars_contains_escaped_heap to it.

        2019-02-13  Jonathan Wakely  <jwak...@redhat.com>
                    Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/89303
        * g++.dg/torture/pr89303.C: New test.

--- gcc/tree-ssa-structalias.c  (revision 268842)
+++ gcc/tree-ssa-structalias.c  (revision 268843)
@@ -6412,7 +6412,7 @@ set_uids_in_ptset (bitmap into, bitmap f
              && bitmap_bit_p (escaped_vi->solution, i)))
        {
          pt->vars_contains_escaped = true;
-         pt->vars_contains_escaped_heap = vi->is_heap_var;
+         pt->vars_contains_escaped_heap |= vi->is_heap_var;
        }
 
       if (vi->is_restrict_var)
--- gcc/testsuite/g++.dg/torture/pr89303.C      (nonexistent)
+++ gcc/testsuite/g++.dg/torture/pr89303.C      (revision 268843)
@@ -0,0 +1,792 @@
+// PR middle-end/89303
+// { dg-do run }
+// { dg-additional-options "-std=c++14" }
+
+namespace std
+{
+  typedef __SIZE_TYPE__ size_t;
+  typedef decltype(nullptr) nullptr_t;
+
+  template<typename _Tp, _Tp __v>
+    struct integral_constant
+    {
+      static constexpr _Tp value = __v;
+      typedef _Tp value_type;
+      typedef integral_constant<_Tp, __v> type;
+      constexpr operator value_type() const noexcept { return value; }
+      constexpr value_type operator()() const noexcept { return value; }
+    };
+
+  template<typename _Tp, _Tp __v>
+    constexpr _Tp integral_constant<_Tp, __v>::value;
+
+  typedef integral_constant<bool, true> true_type;
+  typedef integral_constant<bool, false> false_type;
+
+  template<bool __v>
+    using __bool_constant = integral_constant<bool, __v>;
+
+  template<bool, typename, typename>
+    struct conditional;
+
+  template<typename...>
+    struct __and_;
+
+  template<>
+    struct __and_<>
+    : public true_type
+    { };
+
+  template<typename _B1>
+    struct __and_<_B1>
+    : public _B1
+    { };
+
+  template<typename _B1, typename _B2>
+    struct __and_<_B1, _B2>
+    : public conditional<_B1::value, _B2, _B1>::type
+    { };
+
+  template<typename _B1, typename _B2, typename _B3, typename... _Bn>
+    struct __and_<_B1, _B2, _B3, _Bn...>
+    : public conditional<_B1::value, __and_<_B2, _B3, _Bn...>, _B1>::type
+    { };
+
+  template<typename>
+    struct remove_cv;
+
+  template<typename>
+    struct __is_void_helper
+    : public false_type { };
+
+  template<>
+    struct __is_void_helper<void>
+    : public true_type { };
+
+  template<typename _Tp>
+    struct is_void
+    : public __is_void_helper<typename remove_cv<_Tp>::type>::type
+    { };
+
+  template<typename _Tp, typename _Up = _Tp&&>
+    _Up
+    __declval(int);
+
+  template<typename _Tp>
+    _Tp
+    __declval(long);
+
+  template<typename _Tp>
+    auto declval() noexcept -> decltype(__declval<_Tp>(0));
+
+  template<typename, typename>
+    struct is_same
+    : public false_type { };
+
+  template<typename _Tp>
+    struct is_same<_Tp, _Tp>
+    : public true_type { };
+
+  template<typename _Tp>
+    struct remove_const
+    { typedef _Tp type; };
+
+  template<typename _Tp>
+    struct remove_const<_Tp const>
+    { typedef _Tp type; };
+
+  template<typename _Tp>
+    struct remove_volatile
+    { typedef _Tp type; };
+
+  template<typename _Tp>
+    struct remove_volatile<_Tp volatile>
+    { typedef _Tp type; };
+
+  template<typename _Tp>
+    struct remove_cv
+    {
+      typedef typename
+      remove_const<typename remove_volatile<_Tp>::type>::type type;
+    };
+
+  template<typename _Tp>
+    struct remove_reference
+    { typedef _Tp type; };
+
+  template<typename _Tp>
+    struct remove_reference<_Tp&>
+    { typedef _Tp type; };
+
+  template<typename _Tp>
+    struct remove_reference<_Tp&&>
+    { typedef _Tp type; };
+
+  template<bool, typename _Tp = void>
+    struct enable_if
+    { };
+
+  template<typename _Tp>
+    struct enable_if<true, _Tp>
+    { typedef _Tp type; };
+
+  template<typename... _Cond>
+    using _Require = typename enable_if<__and_<_Cond...>::value>::type;
+
+  template<bool _Cond, typename _Iftrue, typename _Iffalse>
+    struct conditional
+    { typedef _Iftrue type; };
+
+  template<typename _Iftrue, typename _Iffalse>
+    struct conditional<false, _Iftrue, _Iffalse>
+    { typedef _Iffalse type; };
+
+  template<typename _Tp>
+    struct __declval_protector
+    {
+      static const bool __stop = false;
+    };
+
+  template<typename _Tp>
+    auto declval() noexcept -> decltype(__declval<_Tp>(0))
+    {
+      static_assert(__declval_protector<_Tp>::__stop,
+      "declval() must not be used!");
+      return __declval<_Tp>(0);
+    }
+
+  namespace void_details {
+    template <class... >
+    struct make_void { using type = void; };
+}
+
+template <class... T> using __void_t = typename void_details 
::make_void<T...>::type;
+
+  template<typename _Tp>
+    inline constexpr _Tp*
+    __addressof(_Tp& __r) noexcept
+    {
+      return reinterpret_cast<_Tp*>
+       (&const_cast<char&>(reinterpret_cast<const volatile char&>(__r)));
+    }
+
+  template<typename _Tp>
+    constexpr _Tp&&
+    forward(typename std::remove_reference<_Tp>::type& __t) noexcept
+    { return static_cast<_Tp&&>(__t); }
+
+  template<typename _Tp>
+    constexpr _Tp&&
+    forward(typename std::remove_reference<_Tp>::type&& __t) noexcept
+    {
+      return static_cast<_Tp&&>(__t);
+    }
+
+  template<typename _Tp>
+    constexpr typename std::remove_reference<_Tp>::type&&
+    move(_Tp&& __t) noexcept
+    { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
+}
+       
+inline void* operator new(std::size_t, void* p) { return p; }
+
+extern "C" void* malloc(std::size_t);
+extern "C" void free(void*);
+
+namespace std
+{
+  template<typename T>
+    class allocator
+    {
+    public:
+      using value_type = T;
+
+      allocator() { }
+
+      template<typename U>
+        allocator(const allocator<U>&) { }
+
+      T* allocate(size_t n) { return (T*)malloc(n*sizeof(T)); }
+      void deallocate(T* p, size_t) { free(p); }
+
+      template<typename U, typename... Args>
+        void construct(U* p, Args&&... args)
+        { ::new((void*)p) U(args...); }
+
+      template<typename U>
+        void destroy(U* p)
+        { p->~U(); }
+    };
+
+  class __undefined;
+
+  template<typename _Tp, typename _Up>
+    struct __replace_first_arg
+    { };
+
+  template<template<typename, typename...> class _Template, typename _Up,
+           typename _Tp, typename... _Types>
+    struct __replace_first_arg<_Template<_Tp, _Types...>, _Up>
+    { using type = _Template<_Up, _Types...>; };
+
+  struct __allocator_traits_base
+  {
+    template<typename _Tp, typename _Up, typename = void>
+      struct __rebind : __replace_first_arg<_Tp, _Up> { };
+
+    template<typename _Tp, typename _Up>
+      struct __rebind<_Tp, _Up,
+        __void_t<typename _Tp::template rebind<_Up>::other>>
+      { using type = typename _Tp::template rebind<_Up>::other; };
+  };
+
+  template<typename _Alloc, typename _Up>
+    using __alloc_rebind
+      = typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type;
+
+  template<typename _Alloc>
+    struct allocator_traits;
+
+  template<typename _Tp>
+    struct allocator_traits<allocator<_Tp>>
+    {
+      using allocator_type = allocator<_Tp>;
+      using value_type = _Tp;
+      using pointer = _Tp*;
+      using const_pointer = const _Tp*;
+      using size_type = std::size_t;
+
+      static pointer
+      allocate(allocator_type& __a, size_type __n)
+      { return __a.allocate(__n); }
+
+      static void
+      deallocate(allocator_type& __a, pointer __p, size_type __n)
+      { __a.deallocate(__p, __n); }
+
+      template<typename _Up, typename... _Args>
+        static void
+        construct(allocator_type& __a, _Up* __p, _Args&&... __args)
+        { __a.construct(__p, std::forward<_Args>(__args)...); }
+
+      template<typename _Up>
+        static void
+        destroy(allocator_type& __a, _Up* __p)
+        { __a.destroy(__p); }
+    };
+
+  template<typename _Alloc>
+    struct __allocated_ptr
+    {
+      using pointer = typename allocator_traits<_Alloc>::pointer;
+      using value_type = typename allocator_traits<_Alloc>::value_type;
+
+      __allocated_ptr(_Alloc& __a, pointer __ptr) noexcept
+      : _M_alloc(std::__addressof(__a)), _M_ptr(__ptr)
+      { }
+
+      template<typename _Ptr,
+        typename _Req = _Require<is_same<_Ptr, value_type*>>>
+      __allocated_ptr(_Alloc& __a, _Ptr __ptr)
+      : _M_alloc(std::__addressof(__a)),
+      _M_ptr(__ptr)
+      { }
+
+      __allocated_ptr(__allocated_ptr&& __gd) noexcept
+      : _M_alloc(__gd._M_alloc), _M_ptr(__gd._M_ptr)
+      { __gd._M_ptr = nullptr; }
+
+      ~__allocated_ptr()
+      {
+        if (_M_ptr != nullptr)
+          std::allocator_traits<_Alloc>::deallocate(*_M_alloc, _M_ptr, 1);
+      }
+
+      __allocated_ptr&
+      operator=(std::nullptr_t) noexcept
+      {
+        _M_ptr = nullptr;
+        return *this;
+      }
+
+      value_type* get() { return _M_ptr; }
+
+    private:
+      _Alloc* _M_alloc;
+      pointer _M_ptr;
+    };
+
+  template<typename _Alloc>
+    __allocated_ptr<_Alloc>
+    __allocate_guarded(_Alloc& __a)
+    {
+      return { __a, std::allocator_traits<_Alloc>::allocate(__a, 1) };
+    }
+
+  template<typename _Tp>
+    struct __aligned_buffer
+    {
+      alignas(__alignof__(_Tp)) unsigned char _M_storage[sizeof(_Tp)];
+      __aligned_buffer() = default;
+
+      void*
+      _M_addr() noexcept
+      {
+        return static_cast<void*>(&_M_storage);
+      }
+
+      const void*
+      _M_addr() const noexcept
+      {
+        return static_cast<const void*>(&_M_storage);
+      }
+
+      _Tp*
+      _M_ptr() noexcept
+      { return static_cast<_Tp*>(_M_addr()); }
+
+      const _Tp*
+      _M_ptr() const noexcept
+      { return static_cast<const _Tp*>(_M_addr()); }
+    };
+
+  class bad_weak_ptr { };
+
+  inline void
+  __throw_bad_weak_ptr()
+  { (throw (bad_weak_ptr())); }
+
+    class _Sp_counted_base
+    {
+    public:
+      _Sp_counted_base() noexcept
+      : _M_use_count(1), _M_weak_count(1) { }
+
+      virtual
+      ~_Sp_counted_base() noexcept
+      { }
+
+      virtual void
+      _M_dispose() noexcept = 0;
+
+      virtual void
+      _M_destroy() noexcept
+      { delete this; }
+
+      void
+      _M_add_ref_copy()
+      { ++_M_use_count; }
+
+      void
+      _M_add_ref_lock()
+      {
+        if (_M_use_count == 0)
+          __throw_bad_weak_ptr();
+        ++_M_use_count;
+      }
+
+      void
+      _M_release() noexcept
+      {
+        if (--_M_use_count == 0)
+        {
+          _M_dispose();
+          if (--_M_weak_count == 0)
+            _M_destroy();
+        }
+      }
+
+      void
+      _M_weak_add_ref() noexcept
+      { ++_M_weak_count; }
+
+      void
+      _M_weak_release() noexcept
+      {
+        if (--_M_weak_count == 0)
+          _M_destroy();
+      }
+
+      long
+      _M_get_use_count() const noexcept
+      {
+        return _M_use_count;
+      }
+
+    private:
+      _Sp_counted_base(_Sp_counted_base const&) = delete;
+      _Sp_counted_base& operator=(_Sp_counted_base const&) = delete;
+
+      int _M_use_count;
+      int _M_weak_count;
+    };
+
+  template<typename _Tp>
+    class shared_ptr;
+
+  template<typename _Tp>
+    class weak_ptr;
+
+  template<typename _Tp>
+    class enable_shared_from_this;
+
+  class __weak_count;
+
+  class __shared_count;
+
+  template<typename _Alloc>
+    struct _Sp_alloc_shared_tag
+    {
+      const _Alloc& _M_a;
+    };
+
+  template<typename _Tp, typename _Alloc>
+    class _Sp_counted_ptr_inplace final : public _Sp_counted_base
+    {
+      class _Impl : _Alloc
+      {
+      public:
+        explicit _Impl(_Alloc __a) noexcept : _Alloc(__a) { }
+
+        _Alloc& _M_alloc() noexcept { return *this; }
+
+        __aligned_buffer<_Tp> _M_storage;
+      };
+
+    public:
+      using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_ptr_inplace>;
+
+      template<typename... _Args>
+        _Sp_counted_ptr_inplace(_Alloc __a, _Args&&... __args)
+        : _M_impl(__a)
+        {
+          allocator_traits<_Alloc>::construct(__a, _M_ptr(),
+              std::forward<_Args>(__args)...);
+        }
+
+      ~_Sp_counted_ptr_inplace() noexcept { }
+
+      virtual void
+      _M_dispose() noexcept
+      {
+        allocator_traits<_Alloc>::destroy(_M_impl._M_alloc(), _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_ptr_inplace();
+      }
+
+    private:
+      friend class __shared_count;
+
+      _Tp* _M_ptr() noexcept { return _M_impl._M_storage._M_ptr(); }
+
+      _Impl _M_impl;
+    };
+
+  class __shared_count
+  {
+  public:
+    constexpr __shared_count() noexcept : _M_pi(0)
+    { }
+
+    template<typename _Tp, typename _Alloc, typename... _Args>
+      __shared_count(_Tp*& __p, _Sp_alloc_shared_tag<_Alloc> __a,
+          _Args&&... __args)
+      {
+        typedef _Sp_counted_ptr_inplace<_Tp, _Alloc> _Sp_cp_type;
+        typename _Sp_cp_type::__allocator_type __a2(__a._M_a);
+        auto __guard = std::__allocate_guarded(__a2);
+        _Sp_cp_type* __mem = __guard.get();
+        auto __pi = ::new (__mem)
+          _Sp_cp_type(__a._M_a, std::forward<_Args>(__args)...);
+        __guard = nullptr;
+        _M_pi = __pi;
+        __p = __pi->_M_ptr();
+      }
+
+    ~__shared_count() noexcept
+    {
+      if (_M_pi != nullptr)
+        _M_pi->_M_release();
+    }
+
+    __shared_count(const __shared_count& __r) noexcept
+    : _M_pi(__r._M_pi)
+    {
+      if (_M_pi != 0)
+        _M_pi->_M_add_ref_copy();
+    }
+
+    explicit __shared_count(const __weak_count& __r);
+
+    long
+    _M_get_use_count() const noexcept
+    { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; }
+
+  private:
+    friend class __weak_count;
+
+    _Sp_counted_base* _M_pi;
+  };
+
+  class __weak_count
+  {
+  public:
+    constexpr __weak_count() noexcept : _M_pi(nullptr)
+    { }
+
+    __weak_count(const __shared_count& __r) noexcept
+    : _M_pi(__r._M_pi)
+    {
+      if (_M_pi != nullptr)
+        _M_pi->_M_weak_add_ref();
+    }
+
+    __weak_count(const __weak_count& __r) noexcept
+    : _M_pi(__r._M_pi)
+    {
+      if (_M_pi != nullptr)
+        _M_pi->_M_weak_add_ref();
+    }
+
+    __weak_count(__weak_count&& __r) noexcept
+    : _M_pi(__r._M_pi)
+    { __r._M_pi = nullptr; }
+
+    ~__weak_count() noexcept
+    {
+      if (_M_pi != nullptr)
+      {
+        _M_pi->_M_weak_release();
+      }
+    }
+
+    __weak_count&
+    operator=(const __shared_count& __r) noexcept
+    {
+      _Sp_counted_base* __tmp = __r._M_pi;
+      if (__tmp != nullptr)
+        __tmp->_M_weak_add_ref();
+      if (_M_pi != nullptr)
+        _M_pi->_M_weak_release();
+      _M_pi = __tmp;
+      return *this;
+    }
+
+    long
+    _M_get_use_count() const noexcept
+    { return _M_pi != nullptr ? _M_pi->_M_get_use_count() : 0; }
+
+  private:
+    friend class __shared_count;
+
+    _Sp_counted_base* _M_pi;
+  };
+
+  inline
+  __shared_count::__shared_count(const __weak_count& __r)
+  : _M_pi(__r._M_pi)
+  {
+    if (_M_pi != nullptr)
+      _M_pi->_M_add_ref_lock();
+    else
+      __throw_bad_weak_ptr();
+  }
+
+  template<typename _Tp>
+    class shared_ptr
+    {
+    public:
+      using element_type = _Tp;
+
+      constexpr shared_ptr() noexcept
+        : _M_ptr(0), _M_refcount()
+        { }
+
+      shared_ptr(const shared_ptr&) noexcept = default;
+      shared_ptr& operator=(const shared_ptr&) noexcept = default;
+      ~shared_ptr() = default;
+
+      template<typename _Yp>
+       explicit shared_ptr(const weak_ptr<_Yp>& __r)
+       : _M_refcount(__r._M_refcount) // may throw
+       {
+         // It is now safe to copy __r._M_ptr, as
+         // _M_refcount(__r._M_refcount) did not throw.
+         _M_ptr = __r._M_ptr;
+       }
+
+      long
+      use_count() const noexcept
+      { return _M_refcount._M_get_use_count(); }
+
+      element_type* operator->() const noexcept { return _M_ptr; }
+
+    protected:
+
+      template<typename _Alloc, typename... _Args>
+        shared_ptr(_Sp_alloc_shared_tag<_Alloc> __tag, _Args&&... __args)
+        : _M_ptr(), _M_refcount(_M_ptr, __tag, std::forward<_Args>(__args)...)
+        { _M_enable_shared_from_this_with(_M_ptr); }
+
+      template<typename _Tp1, typename _Alloc,
+        typename... _Args>
+          friend shared_ptr<_Tp1>
+          allocate_shared(const _Alloc& __a, _Args&&... __args);
+
+      friend class weak_ptr<_Tp>;
+
+    private:
+
+      template<typename _Yp>
+        using __esft_base_t = decltype(__enable_shared_from_this_base(
+              std::declval<const __shared_count&>(),
+              std::declval<_Yp*>()));
+
+      template<typename _Yp, typename = void>
+        struct __has_esft_base
+        : false_type { };
+
+      template<typename _Yp>
+        struct __has_esft_base<_Yp, __void_t<__esft_base_t<_Yp>>>
+        : true_type { };
+
+      template<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type>
+        typename enable_if<__has_esft_base<_Yp2>::value>::type
+        _M_enable_shared_from_this_with(_Yp* __p) noexcept
+        {
+          if (auto __base = __enable_shared_from_this_base(_M_refcount, __p))
+            __base->_M_weak_assign(const_cast<_Yp2*>(__p), _M_refcount);
+        }
+
+      template<typename _Tp1> friend class shared_ptr;
+      template<typename _Tp1> friend class weak_ptr;
+
+      element_type* _M_ptr;
+      __shared_count _M_refcount;
+    };
+
+  template<typename _Tp>
+    class weak_ptr
+    {
+    public:
+      using element_type = _Tp;
+
+      constexpr weak_ptr() noexcept
+      : _M_ptr(nullptr), _M_refcount()
+      { }
+
+      weak_ptr(const weak_ptr&) noexcept = default;
+
+      ~weak_ptr() = default;
+
+      weak_ptr&
+      operator=(const weak_ptr& __r) noexcept = default;
+
+      long
+      use_count() const noexcept
+      { return _M_refcount._M_get_use_count(); }
+
+    private:
+
+      void
+      _M_assign(_Tp* __ptr, const __shared_count& __refcount) noexcept
+      {
+        if (use_count() == 0)
+        {
+          _M_ptr = __ptr;
+          _M_refcount = __refcount;
+        }
+      }
+
+      template<typename _Tp1> friend class shared_ptr;
+      template<typename _Tp1> friend class weak_ptr;
+      friend class enable_shared_from_this<_Tp>;
+
+      element_type* _M_ptr;
+      __weak_count _M_refcount;
+    };
+
+  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); }
+
+      friend const enable_shared_from_this*
+      __enable_shared_from_this_base(const __shared_count&,
+         const enable_shared_from_this* __p)
+      { return __p; }
+
+      template<typename>
+        friend class shared_ptr;
+
+      mutable weak_ptr<_Tp> _M_weak_this;
+    };
+
+  template<typename _Tp, typename _Alloc, typename... _Args>
+    inline shared_ptr<_Tp>
+    allocate_shared(const _Alloc& __a, _Args&&... __args)
+    {
+      return shared_ptr<_Tp>(_Sp_alloc_shared_tag<_Alloc>{__a},
+        std::forward<_Args>(__args)...);
+    }
+
+  template<typename _Tp, typename... _Args>
+    inline shared_ptr<_Tp>
+    make_shared(_Args&&... __args)
+    {
+      typedef typename std::remove_const<_Tp>::type _Tp_nc;
+      return std::allocate_shared<_Tp>(std::allocator<_Tp_nc>(),
+           std::forward<_Args>(__args)...);
+    }
+}
+
+class blob final: public std::enable_shared_from_this<blob>
+{
+  int* data;
+
+public:
+  blob() { data = new int; }
+  ~blob() { delete data; }
+};
+
+static int
+bar(std::shared_ptr<blob>)
+{
+  return 0;
+}
+
+int main()
+{
+  std::shared_ptr<blob> tg = std::make_shared<blob>();
+  return tg->shared_from_this().use_count() - 2;
+}

Reply via email to