On 14/12/17 17:29 +0000, Jonathan Wakely wrote:
Richard Smith pointed out that our "weak result type" implementation
(used by std::reference_wrapper and std::bind) doesn't work for
noexcept functions.
The simple fix is to adjust every partial specialization to include
noexcept deduction (which I'll do for gcc-7-branch), [...]
Here's the patch for the branch, which keeps all the partial
specializations for member functions, adding the deduction to them.
This doesn't remove the unused partial specializations, but also
doesn't "fix" them to detect noexcept.
Tested x86_64-linux, committed to trunk.
commit d12e6a7a3c605b95ee526bb6d11dbc286663492f
Author: Jonathan Wakely <jwak...@redhat.com>
Date: Thu Dec 14 16:47:47 2017 +0000
PR libstdc++/83427 detect weak result type from noexcept functions
PR libstdc++/83427
* include/bits/refwrap.h (_Weak_result_type_impl)
(_Reference_wrapper_base): Deduce noexcept for function types.
* testsuite/20_util/bind/83427.cc: New test.
* testsuite/20_util/reference_wrapper/83427.cc: New test.
diff --git a/libstdc++-v3/include/bits/refwrap.h b/libstdc++-v3/include/bits/refwrap.h
index 124ee97bd2a..86260dac993 100644
--- a/libstdc++-v3/include/bits/refwrap.h
+++ b/libstdc++-v3/include/bits/refwrap.h
@@ -64,12 +64,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ };
/// Retrieve the result type for a function type.
- template<typename _Res, typename... _ArgTypes>
- struct _Weak_result_type_impl<_Res(_ArgTypes...)>
+ template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+ struct _Weak_result_type_impl<_Res(_ArgTypes...) _GLIBCXX_NOEXCEPT_QUAL>
{ typedef _Res result_type; };
- template<typename _Res, typename... _ArgTypes>
- struct _Weak_result_type_impl<_Res(_ArgTypes......)>
+ template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+ struct _Weak_result_type_impl<_Res(_ArgTypes......) _GLIBCXX_NOEXCEPT_QUAL>
{ typedef _Res result_type; };
template<typename _Res, typename... _ArgTypes>
@@ -106,50 +106,65 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ typedef _Res result_type; };
/// Retrieve the result type for a function pointer.
- template<typename _Res, typename... _ArgTypes>
- struct _Weak_result_type_impl<_Res(*)(_ArgTypes...)>
+ template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+ struct _Weak_result_type_impl<_Res(*)(_ArgTypes...) _GLIBCXX_NOEXCEPT_QUAL>
{ typedef _Res result_type; };
- template<typename _Res, typename... _ArgTypes>
- struct _Weak_result_type_impl<_Res(*)(_ArgTypes......)>
+ template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+ struct _Weak_result_type_impl<_Res(*)(_ArgTypes......)
+ _GLIBCXX_NOEXCEPT_QUAL>
{ typedef _Res result_type; };
/// Retrieve result type for a member function pointer.
- template<typename _Res, typename _Class, typename... _ArgTypes>
- struct _Weak_result_type_impl<_Res (_Class::*)(_ArgTypes...)>
+ template<typename _Res, typename _Class, typename... _ArgTypes
+ _GLIBCXX_NOEXCEPT_PARM>
+ struct _Weak_result_type_impl<_Res (_Class::*)(_ArgTypes...)
+ _GLIBCXX_NOEXCEPT_QUAL>
{ typedef _Res result_type; };
- template<typename _Res, typename _Class, typename... _ArgTypes>
- struct _Weak_result_type_impl<_Res (_Class::*)(_ArgTypes......)>
+ template<typename _Res, typename _Class, typename... _ArgTypes
+ _GLIBCXX_NOEXCEPT_PARM>
+ struct _Weak_result_type_impl<_Res (_Class::*)(_ArgTypes......)
+ _GLIBCXX_NOEXCEPT_QUAL>
{ typedef _Res result_type; };
/// Retrieve result type for a const member function pointer.
- template<typename _Res, typename _Class, typename... _ArgTypes>
- struct _Weak_result_type_impl<_Res (_Class::*)(_ArgTypes...) const>
+ template<typename _Res, typename _Class, typename... _ArgTypes
+ _GLIBCXX_NOEXCEPT_PARM>
+ struct _Weak_result_type_impl<_Res (_Class::*)(_ArgTypes...) const
+ _GLIBCXX_NOEXCEPT_QUAL>
{ typedef _Res result_type; };
- template<typename _Res, typename _Class, typename... _ArgTypes>
- struct _Weak_result_type_impl<_Res (_Class::*)(_ArgTypes......) const>
+ template<typename _Res, typename _Class, typename... _ArgTypes
+ _GLIBCXX_NOEXCEPT_PARM>
+ struct _Weak_result_type_impl<_Res (_Class::*)(_ArgTypes......) const
+ _GLIBCXX_NOEXCEPT_QUAL>
{ typedef _Res result_type; };
/// Retrieve result type for a volatile member function pointer.
- template<typename _Res, typename _Class, typename... _ArgTypes>
- struct _Weak_result_type_impl<_Res (_Class::*)(_ArgTypes...) volatile>
+ template<typename _Res, typename _Class, typename... _ArgTypes
+ _GLIBCXX_NOEXCEPT_PARM>
+ struct _Weak_result_type_impl<_Res (_Class::*)(_ArgTypes...) volatile
+ _GLIBCXX_NOEXCEPT_QUAL>
{ typedef _Res result_type; };
- template<typename _Res, typename _Class, typename... _ArgTypes>
- struct _Weak_result_type_impl<_Res (_Class::*)(_ArgTypes......) volatile>
+ template<typename _Res, typename _Class, typename... _ArgTypes
+ _GLIBCXX_NOEXCEPT_PARM>
+ struct _Weak_result_type_impl<_Res (_Class::*)(_ArgTypes......) volatile
+ _GLIBCXX_NOEXCEPT_QUAL>
{ typedef _Res result_type; };
/// Retrieve result type for a const volatile member function pointer.
- template<typename _Res, typename _Class, typename... _ArgTypes>
+ template<typename _Res, typename _Class, typename... _ArgTypes
+ _GLIBCXX_NOEXCEPT_PARM>
struct _Weak_result_type_impl<_Res (_Class::*)(_ArgTypes...)
- const volatile>
+ const volatile _GLIBCXX_NOEXCEPT_QUAL>
{ typedef _Res result_type; };
- template<typename _Res, typename _Class, typename... _ArgTypes>
+ template<typename _Res, typename _Class, typename... _ArgTypes
+ _GLIBCXX_NOEXCEPT_PARM>
struct _Weak_result_type_impl<_Res (_Class::*)(_ArgTypes......)
- const volatile>
+ const volatile _GLIBCXX_NOEXCEPT_QUAL>
{ typedef _Res result_type; };
/**
@@ -201,8 +216,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ };
// - a function type (unary)
- template<typename _Res, typename _T1>
- struct _Reference_wrapper_base<_Res(_T1)>
+ template<typename _Res, typename _T1 _GLIBCXX_NOEXCEPT_PARM>
+ struct _Reference_wrapper_base<_Res(_T1) _GLIBCXX_NOEXCEPT_QUAL>
: unary_function<_T1, _Res>
{ };
@@ -222,8 +237,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ };
// - a function type (binary)
- template<typename _Res, typename _T1, typename _T2>
- struct _Reference_wrapper_base<_Res(_T1, _T2)>
+ template<typename _Res, typename _T1, typename _T2 _GLIBCXX_NOEXCEPT_PARM>
+ struct _Reference_wrapper_base<_Res(_T1, _T2) _GLIBCXX_NOEXCEPT_QUAL>
: binary_function<_T1, _T2, _Res>
{ };
@@ -243,62 +258,62 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ };
// - a function pointer type (unary)
- template<typename _Res, typename _T1>
- struct _Reference_wrapper_base<_Res(*)(_T1)>
+ template<typename _Res, typename _T1 _GLIBCXX_NOEXCEPT_PARM>
+ struct _Reference_wrapper_base<_Res(*)(_T1) _GLIBCXX_NOEXCEPT_QUAL>
: unary_function<_T1, _Res>
{ };
// - a function pointer type (binary)
- template<typename _Res, typename _T1, typename _T2>
- struct _Reference_wrapper_base<_Res(*)(_T1, _T2)>
+ template<typename _Res, typename _T1, typename _T2 _GLIBCXX_NOEXCEPT_PARM>
+ struct _Reference_wrapper_base<_Res(*)(_T1, _T2) _GLIBCXX_NOEXCEPT_QUAL>
: binary_function<_T1, _T2, _Res>
{ };
// - a pointer to member function type (unary, no qualifiers)
- template<typename _Res, typename _T1>
- struct _Reference_wrapper_base<_Res (_T1::*)()>
+ template<typename _Res, typename _T1 _GLIBCXX_NOEXCEPT_PARM>
+ struct _Reference_wrapper_base<_Res (_T1::*)() _GLIBCXX_NOEXCEPT_QUAL>
: unary_function<_T1*, _Res>
{ };
// - a pointer to member function type (binary, no qualifiers)
- template<typename _Res, typename _T1, typename _T2>
- struct _Reference_wrapper_base<_Res (_T1::*)(_T2)>
+ template<typename _Res, typename _T1, typename _T2 _GLIBCXX_NOEXCEPT_PARM>
+ struct _Reference_wrapper_base<_Res (_T1::*)(_T2) _GLIBCXX_NOEXCEPT_QUAL>
: binary_function<_T1*, _T2, _Res>
{ };
// - a pointer to member function type (unary, const)
- template<typename _Res, typename _T1>
- struct _Reference_wrapper_base<_Res (_T1::*)() const>
+ template<typename _Res, typename _T1 _GLIBCXX_NOEXCEPT_PARM>
+ struct _Reference_wrapper_base<_Res (_T1::*)() const _GLIBCXX_NOEXCEPT_QUAL>
: unary_function<const _T1*, _Res>
{ };
// - a pointer to member function type (binary, const)
- template<typename _Res, typename _T1, typename _T2>
- struct _Reference_wrapper_base<_Res (_T1::*)(_T2) const>
+ template<typename _Res, typename _T1, typename _T2 _GLIBCXX_NOEXCEPT_PARM>
+ struct _Reference_wrapper_base<_Res (_T1::*)(_T2) const _GLIBCXX_NOEXCEPT_QUAL>
: binary_function<const _T1*, _T2, _Res>
{ };
// - a pointer to member function type (unary, volatile)
- template<typename _Res, typename _T1>
- struct _Reference_wrapper_base<_Res (_T1::*)() volatile>
+ template<typename _Res, typename _T1 _GLIBCXX_NOEXCEPT_PARM>
+ struct _Reference_wrapper_base<_Res (_T1::*)() volatile _GLIBCXX_NOEXCEPT_QUAL>
: unary_function<volatile _T1*, _Res>
{ };
// - a pointer to member function type (binary, volatile)
- template<typename _Res, typename _T1, typename _T2>
- struct _Reference_wrapper_base<_Res (_T1::*)(_T2) volatile>
+ template<typename _Res, typename _T1, typename _T2 _GLIBCXX_NOEXCEPT_PARM>
+ struct _Reference_wrapper_base<_Res (_T1::*)(_T2) volatile _GLIBCXX_NOEXCEPT_QUAL>
: binary_function<volatile _T1*, _T2, _Res>
{ };
// - a pointer to member function type (unary, const volatile)
- template<typename _Res, typename _T1>
- struct _Reference_wrapper_base<_Res (_T1::*)() const volatile>
+ template<typename _Res, typename _T1 _GLIBCXX_NOEXCEPT_PARM>
+ struct _Reference_wrapper_base<_Res (_T1::*)() const volatile _GLIBCXX_NOEXCEPT_QUAL>
: unary_function<const volatile _T1*, _Res>
{ };
// - a pointer to member function type (binary, const volatile)
- template<typename _Res, typename _T1, typename _T2>
- struct _Reference_wrapper_base<_Res (_T1::*)(_T2) const volatile>
+ template<typename _Res, typename _T1, typename _T2 _GLIBCXX_NOEXCEPT_PARM>
+ struct _Reference_wrapper_base<_Res (_T1::*)(_T2) const volatile _GLIBCXX_NOEXCEPT_QUAL>
: binary_function<const volatile _T1*, _T2, _Res>
{ };
diff --git a/libstdc++-v3/testsuite/20_util/bind/83427.cc b/libstdc++-v3/testsuite/20_util/bind/83427.cc
new file mode 100644
index 00000000000..3b8a6506966
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/bind/83427.cc
@@ -0,0 +1,31 @@
+// Copyright (C) 2017 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/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++1z } }
+
+#include <functional>
+
+// PR libstdc++/83427
+
+int f() noexcept { return 0; }
+auto b = std::bind(f);
+static_assert(std::is_same_v<decltype(b)::result_type, int>);
+
+struct X { long f() const noexcept { return 0L; } };
+auto b2 = std::bind(&X::f, X{});
+static_assert(std::is_same_v<decltype(b2)::result_type, long>);
diff --git a/libstdc++-v3/testsuite/20_util/reference_wrapper/83427.cc b/libstdc++-v3/testsuite/20_util/reference_wrapper/83427.cc
new file mode 100644
index 00000000000..170caf92045
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/reference_wrapper/83427.cc
@@ -0,0 +1,39 @@
+// Copyright (C) 2017 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/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++1z } }
+
+#include <functional>
+
+// PR libstdc++/83427
+
+int f(short) noexcept { return 0; }
+std::reference_wrapper<decltype(f)> r(f);
+static_assert(std::is_same_v<decltype(r)::result_type, int>);
+static_assert(std::is_same_v<decltype(r)::argument_type, short>);
+
+auto* p = &f;
+std::reference_wrapper<decltype(&f)> r2(p);
+static_assert(std::is_same_v<decltype(r2)::result_type, int>);
+static_assert(std::is_same_v<decltype(r2)::argument_type, short>);
+
+struct X { long f() const noexcept { return 0L; } };
+auto m = &X::f;
+std::reference_wrapper<decltype(m)> r3(m);
+static_assert(std::is_same_v<decltype(r3)::result_type, long>);
+static_assert(std::is_same_v<decltype(r3)::argument_type, const X*>);