Hi mclow.lists, rsmith, K-ballo,

This patch introduces some black magic to detect const and volatile qualified 
function types such as `void () const`. I'm not quite sure how it works.

This fixes PR20084 - http://llvm.org/bugs/show_bug.cgi?id=20084

http://reviews.llvm.org/D7573

Files:
  include/type_traits
  test/std/utilities/meta/meta.unary/meta.unary.cat/function.pass.cpp

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/type_traits
===================================================================
--- include/type_traits
+++ include/type_traits
@@ -430,9 +430,12 @@
 
 namespace __libcpp_is_function_imp
 {
+struct __dummy_type {};
 template <class _Tp> char  __test(_Tp*);
+template <class _Tp> char __test(__dummy_type);
 template <class _Tp> __two __test(...);
-template <class _Tp> _Tp&  __source();
+template <class _Tp> _Tp&  __source(int);
+template <class _Tp> __dummy_type __source(long);
 }
 
 template <class _Tp, bool = is_class<_Tp>::value ||
@@ -441,7 +444,7 @@
                             is_reference<_Tp>::value ||
                             __is_nullptr_t<_Tp>::value >
 struct __libcpp_is_function
-    : public integral_constant<bool, sizeof(__libcpp_is_function_imp::__test<_Tp>(__libcpp_is_function_imp::__source<_Tp>())) == 1>
+    : public integral_constant<bool, sizeof(__libcpp_is_function_imp::__test<_Tp>(__libcpp_is_function_imp::__source<_Tp>(0))) == 1>
     {};
 template <class _Tp> struct __libcpp_is_function<_Tp, true> : public false_type {};
 
Index: test/std/utilities/meta/meta.unary/meta.unary.cat/function.pass.cpp
===================================================================
--- test/std/utilities/meta/meta.unary/meta.unary.cat/function.pass.cpp
+++ test/std/utilities/meta/meta.unary/meta.unary.cat/function.pass.cpp
@@ -13,8 +13,19 @@
 
 #include <type_traits>
 
+using namespace std;
+
+class Class {};
+
+enum Enum1 {};
+#if __cplusplus >= 201103L
+enum class Enum2 : int {};
+#else
+enum Enum2 {};
+#endif
+
 template <class T>
-void test_function_imp()
+void test()
 {
     static_assert(!std::is_void<T>::value, "");
 #if _LIBCPP_STD_VER > 11
@@ -34,19 +45,104 @@
     static_assert( std::is_function<T>::value, "");
 }
 
+// This function checks that we actually get to the SFINAE test in
+// __libcpp_is_function and check that it fails.
 template <class T>
-void test_function()
+void test_sfinae_failure()
 {
-    test_function_imp<T>();
-    test_function_imp<const T>();
-    test_function_imp<volatile T>();
-    test_function_imp<const volatile T>();
+    // Check that we get the overload of __libcpp_is_function that
+    // evaluates the sfinae
+    static_assert(!std::is_class<T>::value, "");
+    static_assert(!std::is_union<T>::value, "");
+    static_assert(!std::is_void<T>::value, "");
+    static_assert(!std::is_reference<T>::value, "");
+    static_assert(!std::__is_nullptr_t<T>::value, "");
+    // Check that the trait actually works
+    static_assert(!std::is_function<T>::value, "");
 }
 
+// Since we can't actually add the const volatile and ref qualifiers once
+// later let's use a macro to do it.
+#define TEST_REGULAR(...)                 \
+    test<__VA_ARGS__>();                  \
+    test<__VA_ARGS__ const>();            \
+    test<__VA_ARGS__ volatile>();         \
+    test<__VA_ARGS__ const volatile>()
+
+#define TEST_REF_QUALIFIED(...)           \
+    test<__VA_ARGS__ &>();                \
+    test<__VA_ARGS__ const &>();          \
+    test<__VA_ARGS__ volatile &>();       \
+    test<__VA_ARGS__ const volatile &>(); \
+    test<__VA_ARGS__ &&>();               \
+    test<__VA_ARGS__ const &&>();         \
+    test<__VA_ARGS__ volatile &&>();      \
+    test<__VA_ARGS__ const volatile &&>()
+
+#define TEST_SFINAE_FAILURE(...)                       \
+    test_sfinae_failure<__VA_ARGS__>();                \
+    test_sfinae_failure<__VA_ARGS__ const>();          \
+    test_sfinae_failure<__VA_ARGS__ volatile>();       \
+    test_sfinae_failure<__VA_ARGS__ const volatile>()
+
+#define TEST_MEM_FN_REF(...)                               \
+    test_sfinae_failure<__VA_ARGS__ &>();                  \
+    test_sfinae_failure<__VA_ARGS__ const &>();            \
+    test_sfinae_failure<__VA_ARGS__ volatile &>();         \
+    test_sfinae_failure<__VA_ARGS__ const volatile &>();   \
+    test_sfinae_failure<__VA_ARGS__ &&>();                 \
+    test_sfinae_failure<__VA_ARGS__ const &&>();           \
+    test_sfinae_failure<__VA_ARGS__ volatile &&>();        \
+    test_sfinae_failure<__VA_ARGS__ const volatile &&>()
+
 int main()
 {
-    test_function<void ()>();
-    test_function<void (int)>();
-    test_function<int (double)>();
-    test_function<int (double, char)>();
+    TEST_REGULAR( void () );
+    TEST_REGULAR( void (int) );
+    TEST_REGULAR( int (double) );
+    TEST_REGULAR( int (double, char) );
+    TEST_REGULAR( void (...) );
+    TEST_REGULAR( void (int, ...) );
+    TEST_REGULAR( int (double, ...) );
+    TEST_REGULAR( int (double, char, ...) );
+#if __cplusplus >= 201103L
+    TEST_REF_QUALIFIED( void () );
+    TEST_REF_QUALIFIED( void (int) );
+    TEST_REF_QUALIFIED( int (double) );
+    TEST_REF_QUALIFIED( int (double, char) );
+    TEST_REF_QUALIFIED( void (...) );
+    TEST_REF_QUALIFIED( void (int, ...) );
+    TEST_REF_QUALIFIED( int (double, ...) );
+    TEST_REF_QUALIFIED( int (double, char, ...) );
+#endif
+
+    TEST_SFINAE_FAILURE( int );
+    TEST_SFINAE_FAILURE( int* );
+    TEST_SFINAE_FAILURE( int const* );
+    TEST_SFINAE_FAILURE( int volatile* );
+    TEST_SFINAE_FAILURE( int const volatile* );
+    TEST_SFINAE_FAILURE( void* );
+    TEST_SFINAE_FAILURE( Enum1 );
+    TEST_SFINAE_FAILURE( Enum1* );
+    TEST_SFINAE_FAILURE( Enum2 );
+    TEST_SFINAE_FAILURE( Enum2* );
+
+    TEST_SFINAE_FAILURE( void (Class::*)() );
+    TEST_SFINAE_FAILURE( void (Class::*)(int) );
+    TEST_SFINAE_FAILURE( int (Class::*)(double) );
+    TEST_SFINAE_FAILURE( int (Class::*)(double, char) );
+    TEST_SFINAE_FAILURE( void (Class::*)(...) );
+    TEST_SFINAE_FAILURE( void (Class::*)(int, ...) );
+    TEST_SFINAE_FAILURE( int (Class::*)(double, ...) );
+    TEST_SFINAE_FAILURE( int (Class::*)(double, char, ...) );
+#if __cplusplus >= 201103L
+    TEST_MEM_FN_REF( void (Class::*)() );
+    TEST_MEM_FN_REF( void (Class::*)(int) );
+    TEST_MEM_FN_REF( int (Class::*)(double) );
+    TEST_MEM_FN_REF( int (Class::*)(double, char) );
+    TEST_MEM_FN_REF( void (Class::*)(...) );
+    TEST_MEM_FN_REF( void (Class::*)(int, ...) );
+    TEST_MEM_FN_REF( int (Class::*)(double, ...) );
+    TEST_MEM_FN_REF( int (Class::*)(double, char, ...) );
+#endif
 }
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to