Commit 00677c48 by Jonathan Wakely Committed by Jonathan Wakely

PR libstdc++/83427 detect weak result type from noexcept functions

	PR libstdc++/83427
	* include/bits/refwrap.h (_Maybe_unary_or_binary_function): Move here
	from <bits/std_function.h>.
	(_Mem_fn_traits_base, _Mem_fn_traits): Move here, from <functional>.
	(_Weak_result_type_impl, _Reference_wrapper_base): Deduce noexcept
	for function types. Remove partial specializations for member
	functions.
	(_Weak_result_type_impl): Remove unused partial specializations for
	non-referenceable function types and for references to functions.
	(_Weak_result_type_memfun, _Reference_wrapper_base_memfun): New
	helpers to handle member functions via _Mem_fn_traits.
	(_Weak_result_type, reference_wrapper): Derive from new helpers.
	* include/bits/std_function.h (_Maybe_unary_or_binary_function): Move
	to <bits/refwrap.h>.
	* include/std/functional (_Pack, _AllConvertible, _NotSame): Remove.
	(_Mem_fn_traits_base, _Mem_fn_traits): Move to <bits/refwrap.h>.
	* testsuite/20_util/bind/83427.cc: New test.
	* testsuite/20_util/bind/refqual.cc: Add noexcept to functions and
	check for weak result types.
	* testsuite/20_util/reference_wrapper/83427.cc: New test.

From-SVN: r255651
parent db811328
2017-12-14 Jonathan Wakely <jwakely@redhat.com> 2017-12-14 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/83427
* include/bits/refwrap.h (_Maybe_unary_or_binary_function): Move here
from <bits/std_function.h>.
(_Mem_fn_traits_base, _Mem_fn_traits): Move here, from <functional>.
(_Weak_result_type_impl, _Reference_wrapper_base): Deduce noexcept
for function types. Remove partial specializations for member
functions.
(_Weak_result_type_impl): Remove unused partial specializations for
non-referenceable function types and for references to functions.
(_Weak_result_type_memfun, _Reference_wrapper_base_memfun): New
helpers to handle member functions via _Mem_fn_traits.
(_Weak_result_type, reference_wrapper): Derive from new helpers.
* include/bits/std_function.h (_Maybe_unary_or_binary_function): Move
to <bits/refwrap.h>.
* include/std/functional (_Pack, _AllConvertible, _NotSame): Remove.
(_Mem_fn_traits_base, _Mem_fn_traits): Move to <bits/refwrap.h>.
* testsuite/20_util/bind/83427.cc: New test.
* testsuite/20_util/bind/refqual.cc: Add noexcept to functions and
check for weak result types.
* testsuite/20_util/reference_wrapper/83427.cc: New test.
* testsuite/26_numerics/complex/inserters_extractors/char/dr2714.cc: * testsuite/26_numerics/complex/inserters_extractors/char/dr2714.cc:
Add tests using noskipws. Add tests using noskipws.
......
...@@ -49,25 +49,6 @@ namespace std _GLIBCXX_VISIBILITY(default) ...@@ -49,25 +49,6 @@ namespace std _GLIBCXX_VISIBILITY(default)
_GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_BEGIN_NAMESPACE_VERSION
/** /**
* Derives from @c unary_function or @c binary_function, or perhaps
* nothing, depending on the number of arguments provided. The
* primary template is the basis case, which derives nothing.
*/
template<typename _Res, typename... _ArgTypes>
struct _Maybe_unary_or_binary_function { };
/// Derives from @c unary_function, as appropriate.
template<typename _Res, typename _T1>
struct _Maybe_unary_or_binary_function<_Res, _T1>
: std::unary_function<_T1, _Res> { };
/// Derives from @c binary_function, as appropriate.
template<typename _Res, typename _T1, typename _T2>
struct _Maybe_unary_or_binary_function<_Res, _T1, _T2>
: std::binary_function<_T1, _T2, _Res> { };
/**
* @brief Exception class thrown when class template function's * @brief Exception class thrown when class template function's
* operator() is called with an empty target. * operator() is called with an empty target.
* @ingroup exceptions * @ingroup exceptions
......
...@@ -55,7 +55,8 @@ ...@@ -55,7 +55,8 @@
#include <type_traits> #include <type_traits>
#include <bits/functional_hash.h> #include <bits/functional_hash.h>
#include <bits/invoke.h> #include <bits/invoke.h>
#include <bits/std_function.h> #include <bits/refwrap.h> // std::reference_wrapper and _Mem_fn_traits
#include <bits/std_function.h> // std::function
#if __cplusplus > 201402L #if __cplusplus > 201402L
# include <unordered_map> # include <unordered_map>
# include <vector> # include <vector>
...@@ -82,68 +83,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -82,68 +83,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
} }
#endif #endif
template<typename... _Types>
struct _Pack : integral_constant<size_t, sizeof...(_Types)>
{ };
template<typename _From, typename _To, bool = _From::value == _To::value>
struct _AllConvertible : false_type
{ };
template<typename... _From, typename... _To>
struct _AllConvertible<_Pack<_From...>, _Pack<_To...>, true>
: __and_<is_convertible<_From, _To>...>
{ };
template<typename _Tp1, typename _Tp2>
using _NotSame = __not_<is_same<typename std::decay<_Tp1>::type,
typename std::decay<_Tp2>::type>>;
template<typename _Signature>
struct _Mem_fn_traits;
template<typename _Res, typename _Class, typename... _ArgTypes>
struct _Mem_fn_traits_base
{
using __result_type = _Res;
using __maybe_type
= _Maybe_unary_or_binary_function<_Res, _Class*, _ArgTypes...>;
using __arity = integral_constant<size_t, sizeof...(_ArgTypes)>;
};
#define _GLIBCXX_MEM_FN_TRAITS2(_CV, _REF, _LVAL, _RVAL) \
template<typename _Res, typename _Class, typename... _ArgTypes> \
struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...) _CV _REF> \
: _Mem_fn_traits_base<_Res, _CV _Class, _ArgTypes...> \
{ \
using __vararg = false_type; \
}; \
template<typename _Res, typename _Class, typename... _ArgTypes> \
struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes... ...) _CV _REF> \
: _Mem_fn_traits_base<_Res, _CV _Class, _ArgTypes...> \
{ \
using __vararg = true_type; \
};
#define _GLIBCXX_MEM_FN_TRAITS(_REF, _LVAL, _RVAL) \
_GLIBCXX_MEM_FN_TRAITS2( , _REF, _LVAL, _RVAL) \
_GLIBCXX_MEM_FN_TRAITS2(const , _REF, _LVAL, _RVAL) \
_GLIBCXX_MEM_FN_TRAITS2(volatile , _REF, _LVAL, _RVAL) \
_GLIBCXX_MEM_FN_TRAITS2(const volatile, _REF, _LVAL, _RVAL)
_GLIBCXX_MEM_FN_TRAITS( , true_type, true_type)
_GLIBCXX_MEM_FN_TRAITS(&, true_type, false_type)
_GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
#if __cplusplus > 201402L
_GLIBCXX_MEM_FN_TRAITS(noexcept, true_type, true_type)
_GLIBCXX_MEM_FN_TRAITS(& noexcept, true_type, false_type)
_GLIBCXX_MEM_FN_TRAITS(&& noexcept, false_type, true_type)
#endif
#undef _GLIBCXX_MEM_FN_TRAITS
#undef _GLIBCXX_MEM_FN_TRAITS2
template<typename _MemFunPtr, template<typename _MemFunPtr,
bool __is_mem_fn = is_member_function_pointer<_MemFunPtr>::value> bool __is_mem_fn = is_member_function_pointer<_MemFunPtr>::value>
class _Mem_fn_base class _Mem_fn_base
......
// 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++17 } }
#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>);
...@@ -22,8 +22,8 @@ ...@@ -22,8 +22,8 @@
struct X struct X
{ {
int f() const& { return 0; } int f() const& noexcept { return 0; }
int g(int i, ...)& { return i; } int g(int i, ...)& noexcept { return i; }
}; };
void void
...@@ -34,6 +34,10 @@ test01() ...@@ -34,6 +34,10 @@ test01()
VERIFY( b() == 0 ); VERIFY( b() == 0 );
auto bb = std::bind(&X::g, &x, 1, 2); auto bb = std::bind(&X::g, &x, 1, 2);
VERIFY( bb() == 1 ); VERIFY( bb() == 1 );
// Check for weak result types:
using T1 = decltype(b)::result_type;
using T2 = decltype(bb)::result_type;
} }
int int
......
// 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++17 } }
#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*>);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment