aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2016-10-13 11:19:24 +0100
committerJonathan Wakely <redi@gcc.gnu.org>2016-10-13 11:19:24 +0100
commitcc06c7f652d7fede4844eb1cc21b65d5c8e4efcc (patch)
treee4fb0f98937daac4b0a52cdba15d6ed65d72cfe8
parent27947670631d8a44fd8c2984da601154b614fa81 (diff)
downloadgcc-cc06c7f652d7fede4844eb1cc21b65d5c8e4efcc.zip
gcc-cc06c7f652d7fede4844eb1cc21b65d5c8e4efcc.tar.gz
gcc-cc06c7f652d7fede4844eb1cc21b65d5c8e4efcc.tar.bz2
Fix exception-specifications for std::_Not_fn
* include/std/functional (_Not_fn): Make exception specifications depend on whether negating the result can throw. * testsuite/20_util/not_fn/1.cc: Move to ... * testsuite/20_util/function_objects/not_fn/1.cc: ... here. Add tests for types that can throw when negated and that cannot be negated. From-SVN: r241091
-rw-r--r--libstdc++-v3/ChangeLog6
-rw-r--r--libstdc++-v3/include/std/functional18
-rw-r--r--libstdc++-v3/testsuite/20_util/function_objects/not_fn/1.cc (renamed from libstdc++-v3/testsuite/20_util/not_fn/1.cc)31
3 files changed, 51 insertions, 4 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 5ee2626..ffb78ea 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,5 +1,11 @@
2016-10-13 Jonathan Wakely <jwakely@redhat.com>
+ * include/std/functional (_Not_fn): Make exception specifications
+ depend on whether negating the result can throw.
+ * testsuite/20_util/not_fn/1.cc: Move to ...
+ * testsuite/20_util/function_objects/not_fn/1.cc: ... here. Add tests
+ for types that can throw when negated and that cannot be negated.
+
* include/bits/invoke.h (__invoke): Fix exception-specification.
* include/std/functional (invoke): Likewise.
* testsuite/20_util/function_objects/invoke/1.cc: New test.
diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional
index 6a45314..58134b7 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -2140,6 +2140,16 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
template<typename _Fn>
class _Not_fn
{
+ template<typename _Tp>
+ using __is_nothrow_negatable
+ = __bool_constant<noexcept(!std::declval<_Tp>())>;
+
+ template<typename _Fn2, typename... _Args>
+ using __noexcept_cond = __and_<
+ __is_nothrow_callable<_Fn2(_Args&&...)>,
+ __is_nothrow_negatable<result_of_t<_Fn2(_Args&&...)>>
+ >;
+
public:
template<typename _Fn2>
_Not_fn(_Fn2&& __fn, int)
@@ -2152,21 +2162,21 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
template<typename... _Args>
auto
operator()(_Args&&... __args) &
- noexcept(__is_nothrow_callable<_Fn&(_Args&&...)>::value)
+ noexcept(__noexcept_cond<_Fn&, _Args&&...>::value)
-> decltype(!std::declval<result_of_t<_Fn&(_Args&&...)>>())
{ return !std::__invoke(_M_fn, std::forward<_Args>(__args)...); }
template<typename... _Args>
auto
operator()(_Args&&... __args) const &
- noexcept(__is_nothrow_callable<const _Fn&(_Args&&...)>::value)
+ noexcept(__noexcept_cond<const _Fn&, _Args&&...>::value)
-> decltype(!std::declval<result_of_t<const _Fn&(_Args&&...)>>())
{ return !std::__invoke(_M_fn, std::forward<_Args>(__args)...); }
template<typename... _Args>
auto
operator()(_Args&&... __args) &&
- noexcept(__is_nothrow_callable<_Fn&&(_Args&&...)>::value)
+ noexcept(__noexcept_cond<_Fn&&, _Args&&...>::value)
-> decltype(!std::declval<result_of_t<_Fn&&(_Args&&...)>>())
{
return !std::__invoke(std::move(_M_fn),
@@ -2176,7 +2186,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
template<typename... _Args>
auto
operator()(_Args&&... __args) const &&
- noexcept(__is_nothrow_callable<const _Fn&&(_Args&&...)>::value)
+ noexcept(__noexcept_cond<const _Fn&&, _Args&&...>::value)
-> decltype(!std::declval<result_of_t<const _Fn&&(_Args&&...)>>())
{
return !std::__invoke(std::move(_M_fn),
diff --git a/libstdc++-v3/testsuite/20_util/not_fn/1.cc b/libstdc++-v3/testsuite/20_util/function_objects/not_fn/1.cc
index 233a6d3..246b962 100644
--- a/libstdc++-v3/testsuite/20_util/not_fn/1.cc
+++ b/libstdc++-v3/testsuite/20_util/function_objects/not_fn/1.cc
@@ -91,6 +91,35 @@ test05()
auto copy(nf); // PR libstdc++/70564
}
+void
+test06()
+{
+ struct Boolean {
+ Boolean operator!() noexcept(false) { return *this; }
+ };
+ struct F {
+ Boolean operator()() { return {}; }
+ };
+ F f;
+ auto notf = std::not_fn(f);
+ using NotF = decltype(notf);
+ static_assert( std::is_callable<NotF()>::value, "cannot negate" );
+ static_assert( !noexcept(notf()), "conversion to bool affects noexcept" );
+}
+
+void
+test07()
+{
+ struct NonNegatable { };
+ struct F {
+ NonNegatable operator()() { return {}; }
+ };
+ F f;
+ auto notf = std::not_fn(f);
+ using NotF = decltype(notf);
+ static_assert( !std::is_callable<NotF()>::value, "cannot negate" );
+}
+
int
main()
{
@@ -99,4 +128,6 @@ main()
test03();
test04();
test05();
+ test06();
+ test07();
}