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
This commit is contained in:
@@ -1385,7 +1385,7 @@ template <class _Tp>
|
|||||||
struct _LIBCPP_TYPE_VIS_ONLY common_type<_Tp, void, void>
|
struct _LIBCPP_TYPE_VIS_ONLY common_type<_Tp, void, void>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef _Tp type;
|
typedef typename decay<_Tp>::type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class _Tp, class _Up>
|
template <class _Tp, class _Up>
|
||||||
@@ -3079,7 +3079,7 @@ template <class _Fp, class _A0, class ..._Args,
|
|||||||
class = typename enable_if
|
class = typename enable_if
|
||||||
<
|
<
|
||||||
is_member_function_pointer<typename remove_reference<_Fp>::type>::value &&
|
is_member_function_pointer<typename remove_reference<_Fp>::type>::value &&
|
||||||
is_base_of<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType,
|
is_base_of<typename remove_reference<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType>::type,
|
||||||
typename remove_reference<_A0>::type>::value
|
typename remove_reference<_A0>::type>::value
|
||||||
>::type
|
>::type
|
||||||
>
|
>
|
||||||
@@ -3092,7 +3092,7 @@ template <class _Fp, class _A0, class ..._Args,
|
|||||||
class = typename enable_if
|
class = typename enable_if
|
||||||
<
|
<
|
||||||
is_member_function_pointer<typename remove_reference<_Fp>::type>::value &&
|
is_member_function_pointer<typename remove_reference<_Fp>::type>::value &&
|
||||||
!is_base_of<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType,
|
!is_base_of<typename remove_reference<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType>::type,
|
||||||
typename remove_reference<_A0>::type>::value
|
typename remove_reference<_A0>::type>::value
|
||||||
>::type
|
>::type
|
||||||
>
|
>
|
||||||
|
50
test/utilities/function.objects/func.require/invoke.pass.cpp
Normal file
50
test/utilities/function.objects/func.require/invoke.pass.cpp
Normal file
@@ -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 <type_traits>
|
||||||
|
|
||||||
|
template <typename T, int N>
|
||||||
|
struct Array
|
||||||
|
{
|
||||||
|
typedef T type[N];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Type
|
||||||
|
{
|
||||||
|
Array<char, 1>::type& f1();
|
||||||
|
Array<char, 2>::type& f2() const;
|
||||||
|
|
||||||
|
Array<char, 1>::type& g1() &;
|
||||||
|
Array<char, 2>::type& g2() const &;
|
||||||
|
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||||
|
Array<char, 3>::type& g3() &&;
|
||||||
|
Array<char, 4>::type& g4() const &&;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
static_assert(sizeof(std::__invoke(&Type::f1, std::declval<Type >())) == 1, "");
|
||||||
|
static_assert(sizeof(std::__invoke(&Type::f2, std::declval<Type const >())) == 2, "");
|
||||||
|
|
||||||
|
static_assert(sizeof(std::__invoke(&Type::g1, std::declval<Type &>())) == 1, "");
|
||||||
|
static_assert(sizeof(std::__invoke(&Type::g2, std::declval<Type const &>())) == 2, "");
|
||||||
|
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||||
|
static_assert(sizeof(std::__invoke(&Type::g3, std::declval<Type &&>())) == 3, "");
|
||||||
|
static_assert(sizeof(std::__invoke(&Type::g4, std::declval<Type const&&>())) == 4, "");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
@@ -34,6 +34,8 @@ struct wat
|
|||||||
void foo();
|
void foo();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct F {};
|
||||||
|
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
void test_result_of_imp()
|
void test_result_of_imp()
|
||||||
{
|
{
|
||||||
@@ -55,6 +57,14 @@ int main()
|
|||||||
test_result_of_imp<PMD(S), char&&> ();
|
test_result_of_imp<PMD(S), char&&> ();
|
||||||
#endif
|
#endif
|
||||||
test_result_of_imp<PMD(const S*), const char&> ();
|
test_result_of_imp<PMD(const S*), const char&> ();
|
||||||
|
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||||
|
test_result_of_imp<int (F::* (F &)) () &, int> ();
|
||||||
|
test_result_of_imp<int (F::* (F &)) () const &, int> ();
|
||||||
|
test_result_of_imp<int (F::* (F const &)) () const &, int> ();
|
||||||
|
test_result_of_imp<int (F::* (F &&)) () &&, int> ();
|
||||||
|
test_result_of_imp<int (F::* (F &&)) () const&&, int> ();
|
||||||
|
test_result_of_imp<int (F::* (F const&&)) () const&&, int> ();
|
||||||
|
#endif
|
||||||
#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
|
#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
|
||||||
using type1 = std::result_of<decltype(&wat::foo)(wat)>::type;
|
using type1 = std::result_of<decltype(&wat::foo)(wat)>::type;
|
||||||
#endif
|
#endif
|
||||||
@@ -74,6 +84,14 @@ int main()
|
|||||||
static_assert((std::is_same<std::result_of<PMD(S)>::type, char&&>::value), "Error!");
|
static_assert((std::is_same<std::result_of<PMD(S)>::type, char&&>::value), "Error!");
|
||||||
#endif
|
#endif
|
||||||
static_assert((std::is_same<std::result_of<PMD(const S*)>::type, const char&>::value), "Error!");
|
static_assert((std::is_same<std::result_of<PMD(const S*)>::type, const char&>::value), "Error!");
|
||||||
|
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||||
|
static_assert((std::is_same<std::result_of<int (F::* (F &)) () &>::type, int>::value), "Error!");
|
||||||
|
static_assert((std::is_same<std::result_of<int (F::* (F &)) () const &>::type, int>::value), "Error!");
|
||||||
|
static_assert((std::is_same<std::result_of<int (F::* (F const &)) () const &>::type, int>::value), "Error!");
|
||||||
|
static_assert((std::is_same<std::result_of<int (F::* (F &&)) () &&>::type, int>::value), "Error!");
|
||||||
|
static_assert((std::is_same<std::result_of<int (F::* (F &&)) () const&&>::type, int>::value), "Error!");
|
||||||
|
static_assert((std::is_same<std::result_of<int (F::* (F const&&)) () const&&>::type, int>::value), "Error!");
|
||||||
|
#endif
|
||||||
#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
|
#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
|
||||||
using type = std::result_of<decltype(&wat::foo)(wat)>::type;
|
using type = std::result_of<decltype(&wat::foo)(wat)>::type;
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user