diff options
| author | Howard Hinnant <hhinnant@apple.com> | 2013-05-07 23:40:12 +0000 |
|---|---|---|
| committer | Howard Hinnant <hhinnant@apple.com> | 2013-05-07 23:40:12 +0000 |
| commit | 866ed94db1b9ca8ec0cb2e21be845daddac64660 (patch) | |
| tree | 6e40cfeeaa193e93d4013fcaaf27712ddf1ee7d2 /libcxx | |
| parent | 861b5b5aed6b45d322d9cb0a730667800e8351e4 (diff) | |
| download | bcm5719-llvm-866ed94db1b9ca8ec0cb2e21be845daddac64660.tar.gz bcm5719-llvm-866ed94db1b9ca8ec0cb2e21be845daddac64660.zip | |
Constrain __invoke functions more accurately. This fixes http://llvm.org/bugs/show_bug.cgi?id=15861 .
llvm-svn: 181377
Diffstat (limited to 'libcxx')
| -rw-r--r-- | libcxx/include/__functional_base | 12 | ||||
| -rw-r--r-- | libcxx/include/type_traits | 36 | ||||
| -rw-r--r-- | libcxx/test/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp | 7 |
3 files changed, 47 insertions, 8 deletions
diff --git a/libcxx/include/__functional_base b/libcxx/include/__functional_base index 40a63a853d2..5b0d7201d6f 100644 --- a/libcxx/include/__functional_base +++ b/libcxx/include/__functional_base @@ -292,7 +292,8 @@ struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...) const volatile> // bullets 1 and 2 -template <class _Fp, class _A0, class ..._Args> +template <class _Fp, class _A0, class ..._Args, + class> inline _LIBCPP_INLINE_VISIBILITY auto __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) @@ -301,7 +302,8 @@ __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) return (_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_Args>(__args)...); } -template <class _Fp, class _A0, class ..._Args> +template <class _Fp, class _A0, class ..._Args, + class> inline _LIBCPP_INLINE_VISIBILITY auto __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) @@ -312,7 +314,8 @@ __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) // bullets 3 and 4 -template <class _Fp, class _A0> +template <class _Fp, class _A0, + class> inline _LIBCPP_INLINE_VISIBILITY auto __invoke(_Fp&& __f, _A0&& __a0) @@ -321,7 +324,8 @@ __invoke(_Fp&& __f, _A0&& __a0) return _VSTD::forward<_A0>(__a0).*__f; } -template <class _Fp, class _A0> +template <class _Fp, class _A0, + class> inline _LIBCPP_INLINE_VISIBILITY auto __invoke(_Fp&& __f, _A0&& __a0) diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits index ab0e2220162..cc8a68ecc6f 100644 --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -2878,13 +2878,27 @@ __invoke(__any, _Args&& ...__args) // bullets 1 and 2 -template <class _Fp, class _A0, class ..._Args> +template <class _Fp, class _A0, class ..._Args, + class = typename enable_if + < + is_member_function_pointer<typename remove_reference<_Fp>::type>::value && + is_base_of<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType, + typename remove_reference<_A0>::type>::value + >::type + > _LIBCPP_INLINE_VISIBILITY auto __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) -> decltype((_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_Args>(__args)...)); -template <class _Fp, class _A0, class ..._Args> +template <class _Fp, class _A0, class ..._Args, + class = typename enable_if + < + is_member_function_pointer<typename remove_reference<_Fp>::type>::value && + !is_base_of<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType, + typename remove_reference<_A0>::type>::value + >::type + > _LIBCPP_INLINE_VISIBILITY auto __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) @@ -2892,13 +2906,27 @@ __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) // bullets 3 and 4 -template <class _Fp, class _A0> +template <class _Fp, class _A0, + class = typename enable_if + < + is_member_object_pointer<typename remove_reference<_Fp>::type>::value && + is_base_of<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType, + typename remove_reference<_A0>::type>::value + >::type + > _LIBCPP_INLINE_VISIBILITY auto __invoke(_Fp&& __f, _A0&& __a0) -> decltype(_VSTD::forward<_A0>(__a0).*__f); -template <class _Fp, class _A0> +template <class _Fp, class _A0, + class = typename enable_if + < + is_member_object_pointer<typename remove_reference<_Fp>::type>::value && + !is_base_of<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType, + typename remove_reference<_A0>::type>::value + >::type + > _LIBCPP_INLINE_VISIBILITY auto __invoke(_Fp&& __f, _A0&& __a0) diff --git a/libcxx/test/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp b/libcxx/test/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp index eac8ba0c36d..33c0ed4af22 100644 --- a/libcxx/test/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp +++ b/libcxx/test/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp @@ -28,6 +28,12 @@ struct S typedef void (S::*PMS)(long) const; typedef char S::*PMD; +struct wat +{ + wat& operator*() { return *this; } + void foo(); +}; + int main() { static_assert((std::is_same<std::result_of<S(int)>::type, short>::value), "Error!"); @@ -40,4 +46,5 @@ int main() static_assert((std::is_same<std::result_of<PMD(S)>::type, char&&>::value), "Error!"); #endif static_assert((std::is_same<std::result_of<PMD(const S*)>::type, const char&>::value), "Error!"); + using type = std::result_of<decltype(&wat::foo)(wat)>::type; } |

