view gcc/testsuite/g++.dg/torture/pr89303.C @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
line wrap: on
line source

// PR middle-end/89303
// { dg-do run }
// { dg-additional-options "-std=c++14" }

namespace my
{
  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 my::remove_reference<_Tp>::type& __t) noexcept
    { return static_cast<_Tp&&>(__t); }

  template<typename _Tp>
    constexpr _Tp&&
    forward(typename my::remove_reference<_Tp>::type&& __t) noexcept
    {
      return static_cast<_Tp&&>(__t);
    }

  template<typename _Tp>
    constexpr typename my::remove_reference<_Tp>::type&&
    move(_Tp&& __t) noexcept
    { return static_cast<typename my::remove_reference<_Tp>::type&&>(__t); }
}
       
inline void* operator new(my::size_t, void* p) { return p; }

extern "C" void* malloc(my::size_t);
extern "C" void free(void*);

namespace my
{
  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 = my::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, my::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(my::__addressof(__a)), _M_ptr(__ptr)
      { }

      template<typename _Ptr,
        typename _Req = _Require<is_same<_Ptr, value_type*>>>
      __allocated_ptr(_Alloc& __a, _Ptr __ptr)
      : _M_alloc(my::__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)
          my::allocator_traits<_Alloc>::deallocate(*_M_alloc, _M_ptr, 1);
      }

      __allocated_ptr&
      operator=(my::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, my::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(),
              my::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 = my::__allocate_guarded(__a2);
        _Sp_cp_type* __mem = __guard.get();
        auto __pi = ::new (__mem)
          _Sp_cp_type(__a._M_a, my::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, my::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(
              my::declval<const __shared_count&>(),
              my::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},
        my::forward<_Args>(__args)...);
    }

  template<typename _Tp, typename... _Args>
    inline shared_ptr<_Tp>
    make_shared(_Args&&... __args)
    {
      typedef typename my::remove_const<_Tp>::type _Tp_nc;
      return my::allocate_shared<_Tp>(my::allocator<_Tp_nc>(),
           my::forward<_Args>(__args)...);
    }
}

class blob final: public my::enable_shared_from_this<blob>
{
  int* data;

public:
  blob() { data = new int; }
  ~blob() { delete data; }
};

static int
bar(my::shared_ptr<blob>)
{
  return 0;
}

int main()
{
  my::shared_ptr<blob> tg = my::make_shared<blob>();
  return tg->shared_from_this().use_count() - 2;
}