From b82f988e8d21c709426d691329cf025e978d94ed Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Tue, 13 May 2014 18:22:08 +0100 Subject: [PATCH] re PR libstdc++/60497 (unique_ptr tries to complete its type T even though it's not required to be a complete type) 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 | 15 ++++++ libstdc++-v3/include/debug/array | 2 +- libstdc++-v3/include/profile/array | 2 +- libstdc++-v3/include/std/array | 2 +- libstdc++-v3/include/std/functional | 14 +++--- libstdc++-v3/include/std/mutex | 57 ++++++++-------------- libstdc++-v3/testsuite/20_util/bind/60497.cc | 40 +++++++++++++++ .../23_containers/array/element_access/60497.cc | 38 +++++++++++++++ .../testsuite/30_threads/call_once/60497.cc | 41 ++++++++++++++++ .../testsuite/30_threads/unique_lock/cons/60497.cc | 49 +++++++++++++++++++ 10 files changed, 213 insertions(+), 47 deletions(-) create mode 100644 libstdc++-v3/testsuite/20_util/bind/60497.cc create mode 100644 libstdc++-v3/testsuite/23_containers/array/element_access/60497.cc create mode 100644 libstdc++-v3/testsuite/30_threads/call_once/60497.cc create mode 100644 libstdc++-v3/testsuite/30_threads/unique_lock/cons/60497.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 9a776d1..680791f 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -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 * config/abi/pre/gnu.ver (GLIBCXX_3.4.20): Correct regex_error export. diff --git a/libstdc++-v3/include/debug/array b/libstdc++-v3/include/debug/array index ef01c98..2266a53 100644 --- a/libstdc++-v3/include/debug/array +++ b/libstdc++-v3/include/debug/array @@ -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 diff --git a/libstdc++-v3/include/profile/array b/libstdc++-v3/include/profile/array index 1c38b05..1a43a48 100644 --- a/libstdc++-v3/include/profile/array +++ b/libstdc++-v3/include/profile/array @@ -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 diff --git a/libstdc++-v3/include/std/array b/libstdc++-v3/include/std/array index 67680d6..22947ce 100644 --- a/libstdc++-v3/include/std/array +++ b/libstdc++-v3/include/std/array @@ -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 diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional index 295022d..2bc3d8d 100644 --- a/libstdc++-v3/include/std/functional +++ b/libstdc++-v3/include/std/functional @@ -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 diff --git a/libstdc++-v3/include/std/mutex b/libstdc++-v3/include/std/mutex index 0b481d6..3d70754 100644 --- a/libstdc++-v3/include/std/mutex +++ b/libstdc++-v3/include/std/mutex @@ -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 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 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 inline void swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) noexcept { __x.swap(__y); } - template - struct __unlock_impl - { - template - 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 - static void - __do_unlock(tuple<_Lock&...>&) - { } - }; - template - 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 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 + template 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; #else unique_lock __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 index 0000000..759c9d8 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/bind/60497.cc @@ -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 +// . + +// libstdc++/60497 + +#include +#include + +struct A; +template struct B { T t; }; + +using UP = std::unique_ptr>; + +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 index 0000000..14932a1b --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/array/element_access/60497.cc @@ -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 +// . + +// libstdc++/60497 + +#include +#include +#include +#include + +struct A; +template struct B { T t; }; + +std::array*, 1> a; +auto b = std::get<0>(std::move(a)); + +std::__debug::array*, 1> c; +auto d = std::__debug::get<0>(std::move(c)); + +std::__profile::array*, 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 index 0000000..76cc710 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/call_once/60497.cc @@ -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 +// . + +// libstdc++/60497 + +#include +#include + +struct A; +template struct B { T t; }; + +using UP = std::unique_ptr>; + +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 index 0000000..19be845 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/unique_lock/cons/60497.cc @@ -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 +// . + +// libstdc++/60497 + +#include +#include + +struct A; +template struct B { T t; }; + +template +struct Lockable +{ + void lock(); + void unlock(); + bool try_lock(); +}; + +using test_type = Lockable>>; + +void test01() +{ + test_type l; + std::unique_lock ul(l); +} + +void test02() +{ + test_type l1, l2, l3; + std::lock(l1, l2, l3); +} -- 2.7.4