From 71e699dda5442545e3335f8c07de27c860fe2046 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Mon, 10 Feb 2014 17:40:28 +0000 Subject: [PATCH] Fix for PR17606 - result_of (and INVOKE) works incorrectly for member function pointers with ref qualifiers. Also a drive-by fix for common_type in C++03 mode. Thanks to Michel Morin for the bug report and the proposed fix. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@201101 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/type_traits | 6 +-- .../func.require/invoke.pass.cpp | 50 +++++++++++++++++++ .../meta.trans.other/result_of.pass.cpp | 18 +++++++ 3 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 test/utilities/function.objects/func.require/invoke.pass.cpp diff --git a/include/type_traits b/include/type_traits index 04b4dd48..3e3d8b7b 100644 --- a/include/type_traits +++ b/include/type_traits @@ -1385,7 +1385,7 @@ template struct _LIBCPP_TYPE_VIS_ONLY common_type<_Tp, void, void> { public: - typedef _Tp type; + typedef typename decay<_Tp>::type type; }; template @@ -3079,7 +3079,7 @@ template ::type>::value && - is_base_of::type>::_ClassType, + is_base_of::type>::_ClassType>::type, typename remove_reference<_A0>::type>::value >::type > @@ -3092,7 +3092,7 @@ template ::type>::value && - !is_base_of::type>::_ClassType, + !is_base_of::type>::_ClassType>::type, typename remove_reference<_A0>::type>::value >::type > diff --git a/test/utilities/function.objects/func.require/invoke.pass.cpp b/test/utilities/function.objects/func.require/invoke.pass.cpp new file mode 100644 index 00000000..25681630 --- /dev/null +++ b/test/utilities/function.objects/func.require/invoke.pass.cpp @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// [func.require] + +// INVOKE +#if __cplusplus < 201103L +int main () {} // no __invoke in C++03 +#else + +#include + +template +struct Array +{ + typedef T type[N]; +}; + +struct Type +{ + Array::type& f1(); + Array::type& f2() const; + + Array::type& g1() &; + Array::type& g2() const &; +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + Array::type& g3() &&; + Array::type& g4() const &&; +#endif +}; + +int main() +{ + static_assert(sizeof(std::__invoke(&Type::f1, std::declval())) == 1, ""); + static_assert(sizeof(std::__invoke(&Type::f2, std::declval())) == 2, ""); + + static_assert(sizeof(std::__invoke(&Type::g1, std::declval())) == 1, ""); + static_assert(sizeof(std::__invoke(&Type::g2, std::declval())) == 2, ""); +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + static_assert(sizeof(std::__invoke(&Type::g3, std::declval())) == 3, ""); + static_assert(sizeof(std::__invoke(&Type::g4, std::declval())) == 4, ""); +#endif +} +#endif diff --git a/test/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp b/test/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp index 368a3eb5..bf44c340 100644 --- a/test/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp +++ b/test/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp @@ -34,6 +34,8 @@ struct wat void foo(); }; +struct F {}; + template void test_result_of_imp() { @@ -55,6 +57,14 @@ int main() test_result_of_imp (); #endif test_result_of_imp (); +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + test_result_of_imp (); + test_result_of_imp (); + test_result_of_imp (); + test_result_of_imp (); + test_result_of_imp (); + test_result_of_imp (); +#endif #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES using type1 = std::result_of::type; #endif @@ -74,6 +84,14 @@ int main() static_assert((std::is_same::type, char&&>::value), "Error!"); #endif static_assert((std::is_same::type, const char&>::value), "Error!"); +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + static_assert((std::is_same::type, int>::value), "Error!"); + static_assert((std::is_same::type, int>::value), "Error!"); + static_assert((std::is_same::type, int>::value), "Error!"); + static_assert((std::is_same::type, int>::value), "Error!"); + static_assert((std::is_same::type, int>::value), "Error!"); + static_assert((std::is_same::type, int>::value), "Error!"); +#endif #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES using type = std::result_of::type; #endif