* 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.
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>
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>
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>
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))...);
}
};
__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
__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
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
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
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
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
{ }
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
}
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()
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
__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();
}
__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;
* 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();
#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());
--- /dev/null
+// { 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;
+}
--- /dev/null
+// { 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));
--- /dev/null
+// { 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));
+}
--- /dev/null
+// { 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);
+}