diff options
author | Antony Polukhin <antoshkka@gmail.com> | 2020-08-19 12:10:57 +0100 |
---|---|---|
committer | Jonathan Wakely <jwakely@redhat.com> | 2020-08-19 12:12:40 +0100 |
commit | 69f571ffc513b689fa26e4c9fceba17c2c989ab3 (patch) | |
tree | fc2a28c5020330413c5cbd0a0e3aed069ed46c72 /libstdc++-v3/include/std | |
parent | a5a635fc4331b6d5f1a1e688e1153abd2ff194a5 (diff) | |
download | gcc-69f571ffc513b689fa26e4c9fceba17c2c989ab3.zip gcc-69f571ffc513b689fa26e4c9fceba17c2c989ab3.tar.gz gcc-69f571ffc513b689fa26e4c9fceba17c2c989ab3.tar.bz2 |
libstdc++: assert that type traits are not misused with incomplete types [PR 71579]
libstdc++-v3/ChangeLog:
2020-08-19 Antony Polukhin <antoshkka@gmail.com>
PR libstdc++/71579
* include/std/type_traits (invoke_result, is_nothrow_invocable_r)
Add static_asserts to make sure that the argument of the type
trait is not misused with incomplete types.
(is_swappable_with, is_nothrow_swappable_with): Add static_asserts
to make sure that the first and second arguments of the type trait
are not misused with incomplete types.
* testsuite/20_util/invoke_result/incomplete_neg.cc: New test.
* testsuite/20_util/is_nothrow_invocable/incomplete_neg.cc: New test.
* testsuite/20_util/is_nothrow_swappable/incomplete_neg.cc: New test.
* testsuite/20_util/is_nothrow_swappable_with/incomplete_neg.cc: New
test.
* testsuite/20_util/is_swappable_with/incomplete_neg.cc: New test.
Diffstat (limited to 'libstdc++-v3/include/std')
-rw-r--r-- | libstdc++-v3/include/std/type_traits | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 426febc..62f1190 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -2811,13 +2811,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp, typename _Up> struct is_swappable_with : public __is_swappable_with_impl<_Tp, _Up>::type - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "first template argument must be a complete class or an unbounded array"); + static_assert(std::__is_complete_or_unbounded(__type_identity<_Up>{}), + "second template argument must be a complete class or an unbounded array"); + }; /// is_nothrow_swappable_with template<typename _Tp, typename _Up> struct is_nothrow_swappable_with : public __is_nothrow_swappable_with_impl<_Tp, _Up>::type - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "first template argument must be a complete class or an unbounded array"); + static_assert(std::__is_complete_or_unbounded(__type_identity<_Up>{}), + "second template argument must be a complete class or an unbounded array"); + }; #if __cplusplus >= 201402L /// is_swappable_with_v @@ -2952,7 +2962,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Functor, typename... _ArgTypes> struct invoke_result : public __invoke_result<_Functor, _ArgTypes...> - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Functor>{}), + "_Functor must be a complete class or an unbounded array"); + }; /// std::invoke_result_t template<typename _Fn, typename... _Args> @@ -3001,7 +3014,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct is_nothrow_invocable_r : __and_<__is_nt_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, _Ret>, __call_is_nothrow_<_Fn, _ArgTypes...>>::type - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}), + "_Fn must be a complete class or an unbounded array"); + }; /// std::is_invocable_v template<typename _Fn, typename... _Args> |