]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR libstdc++/60497 (unique_ptr<T> tries to complete its type T even though it...
authorJonathan Wakely <jwakely@redhat.com>
Tue, 13 May 2014 17:22:08 +0000 (18:22 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Tue, 13 May 2014 17:22:08 +0000 (18:22 +0100)
PR libstdc++/60497
* include/debug/array (get): Qualify call to other get overload.
* include/profile/array (get): Likewise.
* include/std/array (get): Likewise.
* include/std/functional (_Mu, _Bind, _Bind_result): Qualify std::get.
* include/std/mutex (unique_lock, call_once): Use __addressof.
(__unlock_impl): Remove unused template.
(__try_to_lock): Declare inline.
(__try_lock_impl::__do_try_lock): Qualify function calls.
(lock): Avoid narrowing conversion.
* testsuite/20_util/bind/60497.cc: New.
* testsuite/23_containers/array/element_access/60497.cc: New.
* testsuite/30_threads/call_once/60497.cc: New.
* testsuite/30_threads/unique_lock/cons/60497.cc: New.

From-SVN: r210388

libstdc++-v3/ChangeLog
libstdc++-v3/include/debug/array
libstdc++-v3/include/profile/array
libstdc++-v3/include/std/array
libstdc++-v3/include/std/functional
libstdc++-v3/include/std/mutex
libstdc++-v3/testsuite/20_util/bind/60497.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/array/element_access/60497.cc [new file with mode: 0644]
libstdc++-v3/testsuite/30_threads/call_once/60497.cc [new file with mode: 0644]
libstdc++-v3/testsuite/30_threads/unique_lock/cons/60497.cc [new file with mode: 0644]

index 9a776d1af62619a428947c9e67efd86a3754d3df..680791ff5bf93a15336cd9af379fd34e28ac319a 100644 (file)
@@ -6,6 +6,21 @@
        * testsuite/20_util/tuple/60497.cc: Test accessing rvalues.
        * testsuite/20_util/tuple/comparison_operators/overloaded.cc: New.
 
+       PR libstdc++/60497
+       * include/debug/array (get): Qualify call to other get overload.
+       * include/profile/array (get): Likewise.
+       * include/std/array (get): Likewise.
+       * include/std/functional (_Mu, _Bind, _Bind_result): Qualify std::get.
+       * include/std/mutex (unique_lock, call_once): Use __addressof.
+       (__unlock_impl): Remove unused template.
+       (__try_to_lock): Declare inline.
+       (__try_lock_impl::__do_try_lock): Qualify function calls.
+       (lock): Avoid narrowing conversion.
+       * testsuite/20_util/bind/60497.cc: New.
+       * testsuite/23_containers/array/element_access/60497.cc: New.
+       * testsuite/30_threads/call_once/60497.cc: New.
+       * testsuite/30_threads/unique_lock/cons/60497.cc: New.
+
 2014-05-09  Jonathan Wakely  <jwakely@redhat.com>
 
        * config/abi/pre/gnu.ver (GLIBCXX_3.4.20): Correct regex_error export.
index ef01c981bd425057f217c5b0fcd6d6bf38fda5c1..2266a53e41aa81fa2482f23ed0303adb676ef116 100644 (file)
@@ -278,7 +278,7 @@ namespace __debug
     get(array<_Tp, _Nm>&& __arr) noexcept
     {
       static_assert(_Int < _Nm, "index is out of bounds");
-      return std::move(get<_Int>(__arr));
+      return std::move(__debug::get<_Int>(__arr));
     }
 
   template<std::size_t _Int, typename _Tp, std::size_t _Nm>
index 1c38b05c56c07a46331ca58345ddcb025a6aa06f..1a43a4888d733707133ce75d970072ef1d172514 100644 (file)
@@ -240,7 +240,7 @@ namespace __profile
     get(array<_Tp, _Nm>&& __arr) noexcept
     {
       static_assert(_Int < _Nm, "index is out of bounds");
-      return std::move(get<_Int>(__arr));
+      return std::move(__profile::get<_Int>(__arr));
     }
 
   template<std::size_t _Int, typename _Tp, std::size_t _Nm>
index 67680d61e583ae2db610e37b32c400da905cbe4e..22947ceb300637d2ea4bbe7a2433ddaffc0c9ad6 100644 (file)
@@ -281,7 +281,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     get(array<_Tp, _Nm>&& __arr) noexcept
     {
       static_assert(_Int < _Nm, "index is out of bounds");
-      return std::move(get<_Int>(__arr));
+      return std::move(_GLIBCXX_STD_C::get<_Int>(__arr));
     }
 
   template<std::size_t _Int, typename _Tp, std::size_t _Nm>
index 295022de8ee3f4f58c2d7486e99b10b15ca6deb7..2bc3d8da8a41b51b4c9447ea994c5d28276883d4 100644 (file)
@@ -1120,7 +1120,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
               const _Index_tuple<_Indexes...>&) const volatile
        -> decltype(__arg(declval<_Args>()...))
        {
-         return __arg(std::forward<_Args>(get<_Indexes>(__tuple))...);
+         return __arg(std::forward<_Args>(std::get<_Indexes>(__tuple))...);
        }
     };
 
@@ -1261,7 +1261,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
        __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>)
        {
          return _M_f(_Mu<_Bound_args>()
-                     (get<_Indexes>(_M_bound_args), __args)...);
+                     (std::get<_Indexes>(_M_bound_args), __args)...);
        }
 
       // Call as const
@@ -1270,7 +1270,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
        __call_c(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const
        {
          return _M_f(_Mu<_Bound_args>()
-                     (get<_Indexes>(_M_bound_args), __args)...);
+                     (std::get<_Indexes>(_M_bound_args), __args)...);
        }
 
       // Call as volatile
@@ -1393,7 +1393,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
            typename __disable_if_void<_Res>::type = 0)
        {
          return _M_f(_Mu<_Bound_args>()
-                     (get<_Indexes>(_M_bound_args), __args)...);
+                     (std::get<_Indexes>(_M_bound_args), __args)...);
        }
 
       // Call unqualified, return void
@@ -1403,7 +1403,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
            typename __enable_if_void<_Res>::type = 0)
        {
          _M_f(_Mu<_Bound_args>()
-              (get<_Indexes>(_M_bound_args), __args)...);
+              (std::get<_Indexes>(_M_bound_args), __args)...);
        }
 
       // Call as const
@@ -1413,7 +1413,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
            typename __disable_if_void<_Res>::type = 0) const
        {
          return _M_f(_Mu<_Bound_args>()
-                     (get<_Indexes>(_M_bound_args), __args)...);
+                     (std::get<_Indexes>(_M_bound_args), __args)...);
        }
 
       // Call as const, return void
@@ -1423,7 +1423,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
            typename __enable_if_void<_Res>::type = 0) const
        {
          _M_f(_Mu<_Bound_args>()
-              (get<_Indexes>(_M_bound_args),  __args)...);
+              (std::get<_Indexes>(_M_bound_args),  __args)...);
        }
 
       // Call as volatile
index 0b481d609feab2097deb1a2bceb0fd167a46586e..3d70754d94bef49b1f8144d9f16ce85d33222d85 100644 (file)
@@ -400,22 +400,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       { }
 
       explicit unique_lock(mutex_type& __m)
-      : _M_device(&__m), _M_owns(false)
+      : _M_device(std::__addressof(__m)), _M_owns(false)
       {
        lock();
        _M_owns = true;
       }
 
       unique_lock(mutex_type& __m, defer_lock_t) noexcept
-      : _M_device(&__m), _M_owns(false)
+      : _M_device(std::__addressof(__m)), _M_owns(false)
       { }
 
       unique_lock(mutex_type& __m, try_to_lock_t)
-      : _M_device(&__m), _M_owns(_M_device->try_lock())
+      : _M_device(std::__addressof(__m)), _M_owns(_M_device->try_lock())
       { }
 
       unique_lock(mutex_type& __m, adopt_lock_t)
-      : _M_device(&__m), _M_owns(true)
+      : _M_device(std::__addressof(__m)), _M_owns(true)
       {
        // XXX calling thread owns mutex
       }
@@ -423,13 +423,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       template<typename _Clock, typename _Duration>
        unique_lock(mutex_type& __m,
                    const chrono::time_point<_Clock, _Duration>& __atime)
-       : _M_device(&__m), _M_owns(_M_device->try_lock_until(__atime))
+       : _M_device(std::__addressof(__m)),
+         _M_owns(_M_device->try_lock_until(__atime))
        { }
 
       template<typename _Rep, typename _Period>
        unique_lock(mutex_type& __m,
                    const chrono::duration<_Rep, _Period>& __rtime)
-       : _M_device(&__m), _M_owns(_M_device->try_lock_for(__rtime))
+       : _M_device(std::__addressof(__m)),
+         _M_owns(_M_device->try_lock_for(__rtime))
        { }
 
       ~unique_lock()
@@ -563,37 +565,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       bool             _M_owns; // XXX use atomic_bool
     };
 
-  /// Partial specialization for unique_lock objects.
+  /// Swap overload for unique_lock objects.
   template<typename _Mutex>
     inline void
     swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) noexcept
     { __x.swap(__y); }
 
-  template<int _Idx>
-    struct __unlock_impl
-    {
-      template<typename... _Lock>
-       static void
-       __do_unlock(tuple<_Lock&...>& __locks)
-       {
-         std::get<_Idx>(__locks).unlock();
-         __unlock_impl<_Idx - 1>::__do_unlock(__locks);
-       }
-    };
-
-  template<>
-    struct __unlock_impl<-1>
-    {
-      template<typename... _Lock>
-       static void
-       __do_unlock(tuple<_Lock&...>&)
-       { }
-    };
-
   template<typename _Lock>
-    unique_lock<_Lock>
+    inline unique_lock<_Lock>
     __try_to_lock(_Lock& __l)
-    { return unique_lock<_Lock>(__l, try_to_lock); }
+    { return unique_lock<_Lock>{__l, try_to_lock}; }
 
   template<int _Idx, bool _Continue = true>
     struct __try_lock_impl
@@ -603,11 +584,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
        {
           __idx = _Idx;
-          auto __lock = __try_to_lock(std::get<_Idx>(__locks));
+          auto __lock = std::__try_to_lock(std::get<_Idx>(__locks));
           if (__lock.owns_lock())
             {
-              __try_lock_impl<_Idx + 1, _Idx + 2 < sizeof...(_Lock)>::
-                __do_try_lock(__locks, __idx);
+             constexpr bool __cont = _Idx + 2 < sizeof...(_Lock);
+             using __try_locker = __try_lock_impl<_Idx + 1, __cont>;
+             __try_locker::__do_try_lock(__locks, __idx);
               if (__idx == -1)
                 __lock.release();
             }
@@ -622,7 +604,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
        {
           __idx = _Idx;
-          auto __lock = __try_to_lock(std::get<_Idx>(__locks));
+          auto __lock = std::__try_to_lock(std::get<_Idx>(__locks));
           if (__lock.owns_lock())
             {
               __idx = -1;
@@ -665,16 +647,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *  and unlock().  If the call exits via an exception any locks that were
    *  obtained will be released.
    */
-  template<typename _L1, typename _L2, typename ..._L3>
+  template<typename _L1, typename _L2, typename... _L3>
     void
     lock(_L1& __l1, _L2& __l2, _L3&... __l3)
     {
       while (true)
         {
+          using __try_locker = __try_lock_impl<0, sizeof...(_L3) != 0>;
           unique_lock<_L1> __first(__l1);
           int __idx;
           auto __locks = std::tie(__l2, __l3...);
-          __try_lock_impl<0, sizeof...(_L3)>::__do_try_lock(__locks, __idx);
+          __try_locker::__do_try_lock(__locks, __idx);
           if (__idx == -1)
             {
               __first.release();
@@ -735,7 +718,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #ifdef _GLIBCXX_HAVE_TLS
       auto __bound_functor = std::__bind_simple(std::forward<_Callable>(__f),
           std::forward<_Args>(__args)...);
-      __once_callable = &__bound_functor;
+      __once_callable = std::__addressof(__bound_functor);
       __once_call = &__once_call_impl<decltype(__bound_functor)>;
 #else
       unique_lock<mutex> __functor_lock(__get_once_mutex());
diff --git a/libstdc++-v3/testsuite/20_util/bind/60497.cc b/libstdc++-v3/testsuite/20_util/bind/60497.cc
new file mode 100644 (file)
index 0000000..759c9d8
--- /dev/null
@@ -0,0 +1,40 @@
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+// Copyright (C) 2014 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/>.
+
+// libstdc++/60497
+
+#include <functional>
+#include <memory>
+
+struct A;
+template<typename T> struct B { T t; };
+
+using UP = std::unique_ptr<B<A>>;
+
+bool f(UP&, UP&) { return true; }
+
+bool g(UP& p)
+{
+  auto binder = std::bind(f, std::ref(p), std::placeholders::_1);
+  bool b1 = binder(std::ref(p));
+  auto binderbinder = std::bind(binder, std::placeholders::_1);
+  bool b2 = binderbinder(std::ref(p));
+  return b1 && b2;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/array/element_access/60497.cc b/libstdc++-v3/testsuite/23_containers/array/element_access/60497.cc
new file mode 100644 (file)
index 0000000..14932a1
--- /dev/null
@@ -0,0 +1,38 @@
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+//
+// Copyright (C) 2014 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/>.
+
+// libstdc++/60497
+
+#include <array>
+#include <debug/array>
+#include <profile/array>
+#include <memory>
+
+struct A;
+template<typename T> struct B { T t; };
+
+std::array<B<A>*, 1> a;
+auto b = std::get<0>(std::move(a));
+
+std::__debug::array<B<A>*, 1> c;
+auto d = std::__debug::get<0>(std::move(c));
+
+std::__profile::array<B<A>*, 1> e;
+auto f = std::__profile::get<0>(std::move(e));
diff --git a/libstdc++-v3/testsuite/30_threads/call_once/60497.cc b/libstdc++-v3/testsuite/30_threads/call_once/60497.cc
new file mode 100644 (file)
index 0000000..76cc710
--- /dev/null
@@ -0,0 +1,41 @@
+// { dg-do compile }
+// { dg-options " -std=gnu++11 -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++11 -pthreads" { target *-*-solaris* } }
+// { dg-options " -std=gnu++11 " { target *-*-cygwin *-*-darwin* } }
+// { dg-require-cstdint "" }
+// { dg-require-gthreads "" }
+
+// Copyright (C) 2014 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/>.
+
+// libstdc++/60497
+
+#include <mutex>
+#include <memory>
+
+struct A;
+template<typename T> struct B { T t; };
+
+using UP = std::unique_ptr<B<A>>;
+
+void f(UP&) { }
+
+void g(UP& p)
+{
+  std::once_flag o;
+  std::call_once(o, f, std::ref(p));
+}
diff --git a/libstdc++-v3/testsuite/30_threads/unique_lock/cons/60497.cc b/libstdc++-v3/testsuite/30_threads/unique_lock/cons/60497.cc
new file mode 100644 (file)
index 0000000..19be845
--- /dev/null
@@ -0,0 +1,49 @@
+// { dg-do compile }
+// { dg-options " -std=gnu++11 " }
+
+// Copyright (C) 2014 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/>.
+
+// libstdc++/60497
+
+#include <mutex>
+#include <memory>
+
+struct A;
+template<typename  T> struct B { T t; };
+
+template<typename Dummy>
+struct Lockable
+{
+  void lock();
+  void unlock();
+  bool try_lock();
+};
+
+using test_type = Lockable<std::unique_ptr<B<A>>>;
+
+void test01()
+{
+  test_type l;
+  std::unique_lock<test_type> ul(l);
+}
+
+void test02()
+{
+  test_type l1, l2, l3;
+  std::lock(l1, l2, l3);
+}