[libcxx] r266836 - Add 'is_callable' and 'is_nothrow_callable' traits and cleanup INVOKE.

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Tue Apr 19 17:14:33 PDT 2016


Author: ericwf
Date: Tue Apr 19 19:14:32 2016
New Revision: 266836

URL: http://llvm.org/viewvc/llvm-project?rev=266836&view=rev
Log:
Add 'is_callable' and 'is_nothrow_callable' traits and cleanup INVOKE.

The primary purpose of this patch is to add the 'is_callable' traits.
Since 'is_nothrow_callable' required making 'INVOKE' conditionally noexcept
I also took this oppertunity to implement a constexpr version of INVOKE.
This fixes 'std::experimental::apply' which required constexpr 'INVOKE support'.

This patch will be followed up with some cleanup. Primarly removing most
of "__member_function_traits" since it's no longer used by INVOKE (in C++11 at least).

Added:
    libcxx/trunk/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/PR23141_invoke_not_constexpr.pass.cpp
    libcxx/trunk/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared_cxx03.pass.cpp
    libcxx/trunk/test/std/utilities/meta/meta.rel/is_callable.pass.cpp
    libcxx/trunk/test/std/utilities/meta/meta.rel/is_nothrow_callable.pass.cpp
Removed:
    libcxx/trunk/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared_no_variadics.pass.cpp
Modified:
    libcxx/trunk/include/__functional_base
    libcxx/trunk/include/experimental/tuple
    libcxx/trunk/include/type_traits
    libcxx/trunk/test/std/experimental/utilities/tuple/tuple.apply/constexpr_types.pass.cpp
    libcxx/trunk/test/std/utilities/function.objects/func.require/bullet_1_2_3.pass.cpp
    libcxx/trunk/test/std/utilities/function.objects/func.require/bullet_4_5_6.pass.cpp
    libcxx/trunk/test/std/utilities/function.objects/func.require/invoke_helpers.h
    libcxx/trunk/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.pass.cpp
    libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp
    libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/result_of11.pass.cpp
    libcxx/trunk/www/cxx1z_status.html

Modified: libcxx/trunk/include/__functional_base
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__functional_base?rev=266836&r1=266835&r2=266836&view=diff
==============================================================================
--- libcxx/trunk/include/__functional_base (original)
+++ libcxx/trunk/include/__functional_base Tue Apr 19 19:14:32 2016
@@ -306,97 +306,19 @@ struct __weak_result_type<_Rp (_Cp::*)(_
 
 #endif // _LIBCPP_HAS_NO_VARIADICS
 
-// __invoke
+#ifndef _LIBCPP_CXX03_LANG
 
-#ifndef _LIBCPP_HAS_NO_VARIADICS
-
-// bullets 1 and 2
-
-template <class _Fp, class _A0, class ..._Args,
-            class>
-inline _LIBCPP_INLINE_VISIBILITY
-auto
-__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
-    -> decltype((_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_Args>(__args)...))
-{
-    return (_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_Args>(__args)...);
-}
-
-
-template <class _Fp, class _A0, class ..._Args,
-            class>
-inline _LIBCPP_INLINE_VISIBILITY
-auto
-__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
-    -> decltype((__a0.get().*__f)(_VSTD::forward<_Args>(__args)...))
-{
-    return (__a0.get().*__f)(_VSTD::forward<_Args>(__args)...);
-}
-
-template <class _Fp, class _A0, class ..._Args,
-            class>
-inline _LIBCPP_INLINE_VISIBILITY
-auto
-__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
-    -> decltype(((*_VSTD::forward<_A0>(__a0)).*__f)(_VSTD::forward<_Args>(__args)...))
-{
-    return ((*_VSTD::forward<_A0>(__a0)).*__f)(_VSTD::forward<_Args>(__args)...);
-}
-
-// bullets 3 and 4
-
-template <class _Fp, class _A0,
-            class>
-inline _LIBCPP_INLINE_VISIBILITY
-auto
-__invoke(_Fp&& __f, _A0&& __a0)
-    -> decltype(_VSTD::forward<_A0>(__a0).*__f)
-{
-    return _VSTD::forward<_A0>(__a0).*__f;
-}
-
-
-template <class _Fp, class _A0,
-            class>
-inline _LIBCPP_INLINE_VISIBILITY
-auto
-__invoke(_Fp&& __f, _A0&& __a0)
-    -> decltype(__a0.get().*__f)
-{
-    return __a0.get().*__f;
-}
-
-template <class _Fp, class _A0,
-            class>
-inline _LIBCPP_INLINE_VISIBILITY
-auto
-__invoke(_Fp&& __f, _A0&& __a0)
-    -> decltype((*_VSTD::forward<_A0>(__a0)).*__f)
-{
-    return (*_VSTD::forward<_A0>(__a0)).*__f;
-}
-
-// bullet 5
-
-template <class _Fp, class ..._Args>
-inline _LIBCPP_INLINE_VISIBILITY
-auto
-__invoke(_Fp&& __f, _Args&& ...__args)
-    -> decltype(_VSTD::forward<_Fp>(__f)(_VSTD::forward<_Args>(__args)...))
-{
-    return _VSTD::forward<_Fp>(__f)(_VSTD::forward<_Args>(__args)...);
-}
 template <class _Tp, class ..._Args>
 struct __invoke_return
 {
     typedef decltype(__invoke(_VSTD::declval<_Tp>(), _VSTD::declval<_Args>()...)) type;
 };
 
-#else // _LIBCPP_HAS_NO_VARIADICS
+#else // defined(_LIBCPP_CXX03_LANG)
 
 #include <__functional_base_03>
 
-#endif  // _LIBCPP_HAS_NO_VARIADICS
+#endif  // !defined(_LIBCPP_CXX03_LANG)
 
 
 template <class _Ret>

Modified: libcxx/trunk/include/experimental/tuple
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/experimental/tuple?rev=266836&r1=266835&r2=266836&view=diff
==============================================================================
--- libcxx/trunk/include/experimental/tuple (original)
+++ libcxx/trunk/include/experimental/tuple Tue Apr 19 19:14:32 2016
@@ -57,9 +57,10 @@ _LIBCPP_CONSTEXPR size_t tuple_size_v =
 
 template <class _Fn, class _Tuple, size_t ..._Id>
 inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_CONSTEXPR_AFTER_CXX11
 decltype(auto) __apply_tuple_impl(_Fn && __f, _Tuple && __t,
                                   integer_sequence<size_t, _Id...>) {
-    return _VSTD::__invoke(
+    return _VSTD::__invoke_constexpr(
         _VSTD::forward<_Fn>(__f),
         _VSTD::get<_Id>(_VSTD::forward<_Tuple>(__t))...
     );

Modified: libcxx/trunk/include/type_traits
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/type_traits?rev=266836&r1=266835&r2=266836&view=diff
==============================================================================
--- libcxx/trunk/include/type_traits (original)
+++ libcxx/trunk/include/type_traits Tue Apr 19 19:14:32 2016
@@ -132,6 +132,14 @@ namespace std
     template <class Base, class Derived> struct is_base_of;
     template <class From, class To> struct is_convertible;
 
+    template <class, class R = void> struct is_callable; // not defined
+    template <class Fn, class... ArgTypes, class R>
+      struct is_callable<Fn(ArgTypes...), R>;
+
+    template <class, class R = void> struct is_nothrow_callable; // not defined
+    template <class Fn, class... ArgTypes, class R>
+      struct is_nothrow_callable<Fn(ArgTypes...), R>;
+
     // Alignment properties and transformations:
     template <class T> struct alignment_of;
     template <size_t Len, size_t Align = most_stringent_alignment_requirement>
@@ -344,6 +352,10 @@ namespace std
         = is_base_of<Base, Derived>::value;                              // C++17
       template <class From, class To> constexpr bool is_convertible_v
         = is_convertible<From, To>::value;                               // C++17
+      template <class T, class R = void> constexpr bool is_callable_v
+        = is_callable<T, R>::value;                                      // C++17
+      template <class T, class R = void> constexpr bool is_nothrow_callable_v
+        = is_nothrow_callable<T, R>::value;                              // C++17
 
       // [meta.logical], logical operator traits:
       template<class... B> struct conjunction;                           // C++17
@@ -2739,6 +2751,15 @@ struct __member_pointer_traits
 //     typedef ... _FnType;
 };
 
+
+template <class _DecayedFp>
+struct __member_pointer_class_type {};
+
+template <class _Ret, class _ClassType>
+struct __member_pointer_class_type<_Ret _ClassType::*> {
+  typedef _ClassType type;
+};
+
 // result_of
 
 template <class _Callable> class result_of;
@@ -3971,7 +3992,7 @@ template <class _Tp> struct __is_referen
 template <class _Tp> struct __is_reference_wrapper
     : public __is_reference_wrapper_impl<typename remove_cv<_Tp>::type> {};
 
-#ifndef _LIBCPP_HAS_NO_VARIADICS
+#ifndef _LIBCPP_CXX03_LANG
 
 // Check for complete types
 
@@ -4059,8 +4080,6 @@ struct __check_complete<_Rp (_Class::*)(
 {
 };
 
-#if __has_feature(cxx_reference_qualified_functions)
-
 template <class _Rp, class _Class, class ..._Param>
 struct __check_complete<_Rp (_Class::*)(_Param...) &>
     : private __check_complete<_Class>
@@ -4109,8 +4128,6 @@ struct __check_complete<_Rp (_Class::*)(
 {
 };
 
-#endif
-
 template <class _Rp, class _Class>
 struct __check_complete<_Rp _Class::*>
     : private __check_complete<_Class>
@@ -4118,149 +4135,250 @@ struct __check_complete<_Rp _Class::*>
 };
 
 
-template <class _Fp, class _A0>
-using __arg_is_base_of_ptm =
-    is_base_of<typename remove_reference<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType>::type,
-               typename remove_reference<_A0>::type>;
+template <class _Fp, class _A0,
+         class _DecayFp = typename decay<_Fp>::type,
+         class _DecayA0 = typename decay<_A0>::type,
+         class _ClassT = typename __member_pointer_class_type<_DecayFp>::type>
+using __enable_if_bullet1 = typename enable_if
+    <
+        is_member_function_pointer<_DecayFp>::value
+        && is_base_of<_ClassT, _DecayA0>::value
+    >::type;
 
-template <class _A0>
-using __arg_is_reference_wrapper = __is_reference_wrapper<typename decay<_A0>::type>;
+template <class _Fp, class _A0,
+         class _DecayFp = typename decay<_Fp>::type,
+         class _DecayA0 = typename decay<_A0>::type>
+using __enable_if_bullet2 = typename enable_if
+    <
+        is_member_function_pointer<_DecayFp>::value
+        && __is_reference_wrapper<_DecayA0>::value
+    >::type;
+
+template <class _Fp, class _A0,
+         class _DecayFp = typename decay<_Fp>::type,
+         class _DecayA0 = typename decay<_A0>::type,
+         class _ClassT = typename __member_pointer_class_type<_DecayFp>::type>
+using __enable_if_bullet3 = typename enable_if
+    <
+        is_member_function_pointer<_DecayFp>::value
+        && !is_base_of<_ClassT, _DecayA0>::value
+        && !__is_reference_wrapper<_DecayA0>::value
+    >::type;
+
+template <class _Fp, class _A0,
+         class _DecayFp = typename decay<_Fp>::type,
+         class _DecayA0 = typename decay<_A0>::type,
+         class _ClassT = typename __member_pointer_class_type<_DecayFp>::type>
+using __enable_if_bullet4 = typename enable_if
+    <
+        is_member_object_pointer<_DecayFp>::value
+        && is_base_of<_ClassT, _DecayA0>::value
+    >::type;
+
+template <class _Fp, class _A0,
+         class _DecayFp = typename decay<_Fp>::type,
+         class _DecayA0 = typename decay<_A0>::type>
+using __enable_if_bullet5 = typename enable_if
+    <
+        is_member_object_pointer<_DecayFp>::value
+        && __is_reference_wrapper<_DecayA0>::value
+    >::type;
+
+template <class _Fp, class _A0,
+         class _DecayFp = typename decay<_Fp>::type,
+         class _DecayA0 = typename decay<_A0>::type,
+         class _ClassT = typename __member_pointer_class_type<_DecayFp>::type>
+using __enable_if_bullet6 = typename enable_if
+    <
+        is_member_object_pointer<_DecayFp>::value
+        && !is_base_of<_ClassT, _DecayA0>::value
+        && !__is_reference_wrapper<_DecayA0>::value
+    >::type;
 
 // __invoke forward declarations
 
 // fall back - none of the bullets
 
+#define _LIBCPP_INVOKE_RETURN(...) \
+    noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) \
+    { return __VA_ARGS__; }
+
 template <class ..._Args>
-auto
-__invoke(__any, _Args&& ...__args)
-    -> __nat;
+auto __invoke(__any, _Args&& ...__args) -> __nat;
+
+template <class ..._Args>
+auto __invoke_constexpr(__any, _Args&& ...__args) -> __nat;
 
 // bullets 1, 2 and 3
 
 template <class _Fp, class _A0, class ..._Args,
-            class = typename enable_if
-            <
-                is_member_function_pointer<typename remove_reference<_Fp>::type>::value &&
-                __arg_is_base_of_ptm<_Fp, _A0>::value
-            >::type
-         >
-_LIBCPP_INLINE_VISIBILITY
+          class = __enable_if_bullet1<_Fp, _A0>>
+inline _LIBCPP_INLINE_VISIBILITY
 auto
 __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
-    -> decltype((_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_Args>(__args)...));
+_LIBCPP_INVOKE_RETURN((_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_Args>(__args)...))
 
+template <class _Fp, class _A0, class ..._Args,
+          class = __enable_if_bullet1<_Fp, _A0>>
+inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_CONSTEXPR auto
+__invoke_constexpr(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
+_LIBCPP_INVOKE_RETURN((_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_Args>(__args)...))
 
 template <class _Fp, class _A0, class ..._Args,
-            class = typename enable_if
-            <
-                is_member_function_pointer<typename remove_reference<_Fp>::type>::value &&
-                __arg_is_reference_wrapper<_A0>::value
-            >::type
-         >
-_LIBCPP_INLINE_VISIBILITY
+          class = __enable_if_bullet2<_Fp, _A0>>
+inline _LIBCPP_INLINE_VISIBILITY
 auto
 __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
-    -> decltype((__a0.get().*__f)(_VSTD::forward<_Args>(__args)...));
+_LIBCPP_INVOKE_RETURN((__a0.get().*__f)(_VSTD::forward<_Args>(__args)...))
 
 template <class _Fp, class _A0, class ..._Args,
-            class = typename enable_if
-            <
-                is_member_function_pointer<typename remove_reference<_Fp>::type>::value &&
-                !__arg_is_base_of_ptm<_Fp, _A0>::value &&
-                !__arg_is_reference_wrapper<_A0>::value
-            >::type
-         >
-_LIBCPP_INLINE_VISIBILITY
+          class = __enable_if_bullet2<_Fp, _A0>>
+inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_CONSTEXPR auto
+__invoke_constexpr(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
+_LIBCPP_INVOKE_RETURN((__a0.get().*__f)(_VSTD::forward<_Args>(__args)...))
+
+template <class _Fp, class _A0, class ..._Args,
+          class = __enable_if_bullet3<_Fp, _A0>>
+inline _LIBCPP_INLINE_VISIBILITY
 auto
 __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
-    -> decltype(((*_VSTD::forward<_A0>(__a0)).*__f)(_VSTD::forward<_Args>(__args)...));
+_LIBCPP_INVOKE_RETURN(((*_VSTD::forward<_A0>(__a0)).*__f)(_VSTD::forward<_Args>(__args)...))
+
+template <class _Fp, class _A0, class ..._Args,
+          class = __enable_if_bullet3<_Fp, _A0>>
+inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_CONSTEXPR auto
+__invoke_constexpr(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
+_LIBCPP_INVOKE_RETURN(((*_VSTD::forward<_A0>(__a0)).*__f)(_VSTD::forward<_Args>(__args)...))
 
 // bullets 4, 5 and 6
 
 template <class _Fp, class _A0,
-            class = typename enable_if
-            <
-                is_member_object_pointer<typename remove_reference<_Fp>::type>::value &&
-                __arg_is_base_of_ptm<_Fp, _A0>::value
-            >::type
-         >
-_LIBCPP_INLINE_VISIBILITY
+          class = __enable_if_bullet4<_Fp, _A0>>
+inline _LIBCPP_INLINE_VISIBILITY
 auto
 __invoke(_Fp&& __f, _A0&& __a0)
-    -> decltype(_VSTD::forward<_A0>(__a0).*__f);
+_LIBCPP_INVOKE_RETURN(_VSTD::forward<_A0>(__a0).*__f)
 
+template <class _Fp, class _A0,
+          class = __enable_if_bullet4<_Fp, _A0>>
+inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_CONSTEXPR auto
+__invoke_constexpr(_Fp&& __f, _A0&& __a0)
+_LIBCPP_INVOKE_RETURN(_VSTD::forward<_A0>(__a0).*__f)
 
 template <class _Fp, class _A0,
-            class = typename enable_if
-            <
-                is_member_object_pointer<typename remove_reference<_Fp>::type>::value &&
-                __arg_is_reference_wrapper<_A0>::value
-            >::type
-         >
-_LIBCPP_INLINE_VISIBILITY
+          class = __enable_if_bullet5<_Fp, _A0>>
+inline _LIBCPP_INLINE_VISIBILITY
 auto
 __invoke(_Fp&& __f, _A0&& __a0)
-    -> decltype(__a0.get().*__f);
+_LIBCPP_INVOKE_RETURN(__a0.get().*__f)
 
 template <class _Fp, class _A0,
-            class = typename enable_if
-            <
-                is_member_object_pointer<typename remove_reference<_Fp>::type>::value &&
-                !__arg_is_base_of_ptm<_Fp, _A0>::value &&
-                !__arg_is_reference_wrapper<_A0>::value
-            >::type
-         >
-_LIBCPP_INLINE_VISIBILITY
+          class = __enable_if_bullet5<_Fp, _A0>>
+inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_CONSTEXPR auto
+__invoke_constexpr(_Fp&& __f, _A0&& __a0)
+_LIBCPP_INVOKE_RETURN(__a0.get().*__f)
+
+template <class _Fp, class _A0,
+          class = __enable_if_bullet6<_Fp, _A0>>
+inline _LIBCPP_INLINE_VISIBILITY
 auto
 __invoke(_Fp&& __f, _A0&& __a0)
-    -> decltype((*_VSTD::forward<_A0>(__a0)).*__f);
+_LIBCPP_INVOKE_RETURN((*_VSTD::forward<_A0>(__a0)).*__f)
+
+template <class _Fp, class _A0,
+          class = __enable_if_bullet6<_Fp, _A0>>
+inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_CONSTEXPR auto
+__invoke_constexpr(_Fp&& __f, _A0&& __a0)
+_LIBCPP_INVOKE_RETURN((*_VSTD::forward<_A0>(__a0)).*__f)
 
 // bullet 7
 
 template <class _Fp, class ..._Args>
-_LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY
 auto
 __invoke(_Fp&& __f, _Args&& ...__args)
-    -> decltype(_VSTD::forward<_Fp>(__f)(_VSTD::forward<_Args>(__args)...));
+_LIBCPP_INVOKE_RETURN(_VSTD::forward<_Fp>(__f)(_VSTD::forward<_Args>(__args)...))
+
+template <class _Fp, class ..._Args>
+inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_CONSTEXPR auto
+__invoke_constexpr(_Fp&& __f, _Args&& ...__args)
+_LIBCPP_INVOKE_RETURN(_VSTD::forward<_Fp>(__f)(_VSTD::forward<_Args>(__args)...))
+
+#undef _LIBCPP_INVOKE_RETURN
 
 // __invokable
 
-template <class _Fp, class ..._Args>
-struct __invokable_imp
+template <class _Ret, class _Fp, class ..._Args>
+struct __invokable_r
     : private __check_complete<_Fp>
 {
-    typedef decltype(
-            __invoke(_VSTD::declval<_Fp>(), _VSTD::declval<_Args>()...)
-                    ) type;
-    static const bool value = !is_same<type, __nat>::value;
+    using _Result = decltype(
+        _VSTD::__invoke(_VSTD::declval<_Fp>(), _VSTD::declval<_Args>()...));
+
+    static const bool value =
+        conditional<
+            !is_same<_Result, __nat>::value,
+            typename conditional<
+                is_void<_Ret>::value,
+                true_type,
+                is_convertible<_Result, _Ret>
+            >::type,
+            false_type
+        >::type::value;
 };
 
 template <class _Fp, class ..._Args>
-struct __invokable
-    : public integral_constant<bool,
-          __invokable_imp<_Fp, _Args...>::value>
-{
-};
+using __invokable = __invokable_r<void, _Fp, _Args...>;
 
-// __invoke_of
+template <bool _IsInvokable, bool _IsCVVoid, class _Ret, class _Fp, class ..._Args>
+struct __nothrow_invokable_r_imp {
+  static const bool value = false;
+};
 
-template <bool _Invokable, class _Fp, class ..._Args>
-struct __invoke_of_imp  // false
+template <class _Ret, class _Fp, class ..._Args>
+struct __nothrow_invokable_r_imp<true, false, _Ret, _Fp, _Args...>
 {
+    typedef __nothrow_invokable_r_imp _ThisT;
+
+    template <class _Tp>
+    static void __test_noexcept(_Tp) noexcept;
+
+    static const bool value = noexcept(_ThisT::__test_noexcept<_Ret>(
+        _VSTD::__invoke(_VSTD::declval<_Fp>(), _VSTD::declval<_Args>()...)));
 };
 
-template <class _Fp, class ..._Args>
-struct __invoke_of_imp<true, _Fp, _Args...>
+template <class _Ret, class _Fp, class ..._Args>
+struct __nothrow_invokable_r_imp<true, true, _Ret, _Fp, _Args...>
 {
-    typedef typename __invokable_imp<_Fp, _Args...>::type type;
+    static const bool value = noexcept(
+        _VSTD::__invoke(_VSTD::declval<_Fp>(), _VSTD::declval<_Args>()...));
 };
 
+template <class _Ret, class _Fp, class ..._Args>
+using __nothrow_invokable_r =
+    __nothrow_invokable_r_imp<
+            __invokable_r<_Ret, _Fp, _Args...>::value,
+            is_void<_Ret>::value,
+            _Ret, _Fp, _Args...
+    >;
+
 template <class _Fp, class ..._Args>
 struct __invoke_of
-    : public __invoke_of_imp<__invokable<_Fp, _Args...>::value, _Fp, _Args...>
+    : public enable_if<
+        __invokable<_Fp, _Args...>::value,
+        typename __invokable_r<void, _Fp, _Args...>::_Result>
 {
 };
 
+// result_of
+
 template <class _Fp, class ..._Args>
 class _LIBCPP_TYPE_VIS_ONLY result_of<_Fp(_Args...)>
     : public __invoke_of<_Fp, _Args...>
@@ -4271,7 +4389,36 @@ class _LIBCPP_TYPE_VIS_ONLY result_of<_F
 template <class _Tp> using result_of_t = typename result_of<_Tp>::type;
 #endif
 
-#endif  // _LIBCPP_HAS_NO_VARIADICS
+#if _LIBCPP_STD_VER > 14
+
+// is_callable
+
+template <class _Fn, class _Ret = void>
+struct _LIBCPP_TYPE_VIS_ONLY is_callable;
+
+template <class _Fn, class ..._Args, class _Ret>
+struct _LIBCPP_TYPE_VIS_ONLY is_callable<_Fn(_Args...), _Ret>
+    : integral_constant<bool, __invokable_r<_Ret, _Fn, _Args...>::value> {};
+
+template <class _Fn, class _Ret = void>
+constexpr bool is_callable_v = is_callable<_Fn, _Ret>::value;
+
+// is_nothrow_callable
+
+template <class _Fn, class _Ret = void>
+struct _LIBCPP_TYPE_VIS_ONLY is_nothrow_callable;
+
+template <class _Fn, class ..._Args, class _Ret>
+struct _LIBCPP_TYPE_VIS_ONLY is_nothrow_callable<_Fn(_Args...), _Ret>
+    : integral_constant<bool, __nothrow_invokable_r<_Ret, _Fn, _Args...>::value>
+{};
+
+template <class _Fn, class _Ret = void>
+constexpr bool is_nothrow_callable_v = is_nothrow_callable<_Fn, _Ret>::value;
+
+#endif // _LIBCPP_STD_VER > 14
+
+#endif  // !defined(_LIBCPP_CXX03_LANG)
 
 template <class _Tp>
 inline _LIBCPP_INLINE_VISIBILITY

Modified: libcxx/trunk/test/std/experimental/utilities/tuple/tuple.apply/constexpr_types.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/utilities/tuple/tuple.apply/constexpr_types.pass.cpp?rev=266836&r1=266835&r2=266836&view=diff
==============================================================================
--- libcxx/trunk/test/std/experimental/utilities/tuple/tuple.apply/constexpr_types.pass.cpp (original)
+++ libcxx/trunk/test/std/experimental/utilities/tuple/tuple.apply/constexpr_types.pass.cpp Tue Apr 19 19:14:32 2016
@@ -9,11 +9,6 @@
 
 // UNSUPPORTED: c++98, c++03, c++11
 
-// TODO(ericwf)
-// constexpr support temporarily reverted due to bug:
-// https://llvm.org/bugs/show_bug.cgi?id=23141
-// XFAIL: *
-
 // <experimental/tuple>
 
 // template <class F, class T> constexpr decltype(auto) apply(F &&, T &&)

Added: libcxx/trunk/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/PR23141_invoke_not_constexpr.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/PR23141_invoke_not_constexpr.pass.cpp?rev=266836&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/PR23141_invoke_not_constexpr.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/PR23141_invoke_not_constexpr.pass.cpp Tue Apr 19 19:14:32 2016
@@ -0,0 +1,35 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <functional>
+
+// template<CopyConstructible Fn, CopyConstructible... Types>
+//   unspecified bind(Fn, Types...);
+// template<Returnable R, CopyConstructible Fn, CopyConstructible... Types>
+//   unspecified bind(Fn, Types...);
+
+// https://llvm.org/bugs/show_bug.cgi?id=23141
+#include <functional>
+#include <type_traits>
+
+struct Fun
+{
+  template<typename T, typename U>
+  void operator()(T && t, U && u) const
+  {
+    static_assert(std::is_same<U, int &>::value, "");
+  }
+};
+
+int main()
+{
+    std::bind(Fun{}, std::placeholders::_1, 42)("hello");
+}

Modified: libcxx/trunk/test/std/utilities/function.objects/func.require/bullet_1_2_3.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/function.objects/func.require/bullet_1_2_3.pass.cpp?rev=266836&r1=266835&r2=266836&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/function.objects/func.require/bullet_1_2_3.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/function.objects/func.require/bullet_1_2_3.pass.cpp Tue Apr 19 19:14:32 2016
@@ -260,8 +260,11 @@ void test_derived_from_ref_wrap() {
     DerivedFromRefWrap<int> d(x);
     auto get_fn = &std::reference_wrapper<int>::get;
     auto& ret = std::__invoke(get_fn, r);
+    auto& cret = std::__invoke_constexpr(get_fn, r);
     assert(&ret == &x);
+    assert(&cret == &x);
     auto& ret2 = std::__invoke(get_fn, d);
+    auto& cret2 = std::__invoke_constexpr(get_fn, d);
     assert(&ret2 == &x);
     auto& ret3 = std::__invoke(get_fn, r2);
     assert(&ret3 == &x);

Modified: libcxx/trunk/test/std/utilities/function.objects/func.require/bullet_4_5_6.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/function.objects/func.require/bullet_4_5_6.pass.cpp?rev=266836&r1=266835&r2=266836&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/function.objects/func.require/bullet_4_5_6.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/function.objects/func.require/bullet_4_5_6.pass.cpp Tue Apr 19 19:14:32 2016
@@ -185,11 +185,22 @@ private:
 #else
     void runTest(Fn M, T& obj, ObjectType* expect ) {
 #endif
-        static_assert((std::is_same<
-            decltype(std::__invoke(M, std::forward<T>(obj))), Expect
-          >::value), "");
-        Expect e = std::__invoke(M, std::forward<T>(obj));
-        assert(&e == expect);
+        {
+            static_assert((std::is_same<
+                decltype(std::__invoke(M, std::forward<T>(obj))), Expect
+              >::value), "");
+            Expect e = std::__invoke(M, std::forward<T>(obj));
+            assert(&e == expect);
+        }
+#if TEST_STD_VER >= 11
+        {
+            static_assert((std::is_same<
+                decltype(std::__invoke_constexpr(M, std::forward<T>(obj))), Expect
+              >::value), "");
+            Expect e = std::__invoke_constexpr(M, std::forward<T>(obj));
+            assert(&e == expect);
+        }
+#endif
     }
 };
 

Modified: libcxx/trunk/test/std/utilities/function.objects/func.require/invoke_helpers.h
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/function.objects/func.require/invoke_helpers.h?rev=266836&r1=266835&r2=266836&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/function.objects/func.require/invoke_helpers.h (original)
+++ libcxx/trunk/test/std/utilities/function.objects/func.require/invoke_helpers.h Tue Apr 19 19:14:32 2016
@@ -271,89 +271,185 @@ private:
     ArgType a0, a1, a2;
 
     //==========================================================================
-    //                       BULLET 1 AND 2 TEST METHODS
+    //                       BULLET 1, 2 AND 3 TEST METHODS
     //==========================================================================
     template <class MethodPtr, class ObjectT>
     void runTestImp(Int<0>, MethodPtr ptr, ObjectT& object) {
-        static_assert((std::is_same<
-            decltype(std::__invoke(ptr, object_cast(object)))
-          , CallRet>::value), "");
-        assert(ID::unchecked_call == false);
-        CallRet ret = std::__invoke(ptr, object_cast(object));
-        assert(ID::checkCalled(ret));
+        {
+            static_assert((std::is_same<
+                decltype(std::__invoke(ptr, object_cast(object)))
+              , CallRet>::value), "");
+            assert(ID::unchecked_call == false);
+            CallRet ret = std::__invoke(ptr, object_cast(object));
+            assert(ID::checkCalled(ret));
+        }
+#if TEST_STD_VER >= 11
+        {
+            static_assert((std::is_same<
+                decltype(std::__invoke_constexpr(ptr, object_cast(object)))
+              , CallRet>::value), "");
+            assert(ID::unchecked_call == false);
+            CallRet ret = std::__invoke_constexpr(ptr, object_cast(object));
+            assert(ID::checkCalled(ret));
+        }
+#endif
     }
 
     template <class MethodPtr, class ObjectT>
     void runTestImp(Int<1>, MethodPtr ptr, ObjectT& object) {
-        static_assert((std::is_same<
-            decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0)))
-          , CallRet>::value), "");
-        assert(ID::unchecked_call == false);
-        CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0));
-        assert(ID::checkCalled(ret));
+        {
+            static_assert((std::is_same<
+                decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0)))
+              , CallRet>::value), "");
+            assert(ID::unchecked_call == false);
+            CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0));
+            assert(ID::checkCalled(ret));
+        }
+#if TEST_STD_VER >= 11
+        {
+            static_assert((std::is_same<
+                decltype(std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0)))
+              , CallRet>::value), "");
+            assert(ID::unchecked_call == false);
+            CallRet ret = std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0));
+            assert(ID::checkCalled(ret));
+        }
+#endif
     }
 
     template <class MethodPtr, class ObjectT>
     void runTestImp(Int<2>, MethodPtr ptr, ObjectT& object) {
-        static_assert((std::is_same<
-            decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1)))
-          , CallRet>::value), "");
-        assert(ID::unchecked_call == false);
-        CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1));
-        assert(ID::checkCalled(ret));
+        {
+            static_assert((std::is_same<
+                decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1)))
+              , CallRet>::value), "");
+            assert(ID::unchecked_call == false);
+            CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1));
+            assert(ID::checkCalled(ret));
+        }
+#if TEST_STD_VER >= 11
+        {
+            static_assert((std::is_same<
+                decltype(std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0), arg_cast(a1)))
+              , CallRet>::value), "");
+            assert(ID::unchecked_call == false);
+            CallRet ret = std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0), arg_cast(a1));
+            assert(ID::checkCalled(ret));
+        }
+#endif
     }
 
     template <class MethodPtr, class ObjectT>
     void runTestImp(Int<3>, MethodPtr ptr, ObjectT& object) {
-        static_assert((std::is_same<
-            decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
-          , CallRet>::value), "");
-        assert(ID::unchecked_call == false);
-        CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
-        assert(ID::checkCalled(ret));
+        {
+            static_assert((std::is_same<
+                decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
+              , CallRet>::value), "");
+            assert(ID::unchecked_call == false);
+            CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
+            assert(ID::checkCalled(ret));
+        }
+#if TEST_STD_VER >= 11
+        {
+            static_assert((std::is_same<
+                decltype(std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
+              , CallRet>::value), "");
+            assert(ID::unchecked_call == false);
+            CallRet ret = std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
+            assert(ID::checkCalled(ret));
+        }
+#endif
     }
 
     //==========================================================================
-    //                       BULLET 5 TEST METHODS
+    //                       BULLET 7 TEST METHODS
     //==========================================================================
     template <class ObjectT>
     void runTestImp(Int<0>, ObjectT& object) {
-        static_assert((std::is_same<
-            decltype(std::__invoke(object_cast(object)))
-          , CallRet>::value), "");
-        assert(ID::unchecked_call == false);
-        CallRet ret = std::__invoke(object_cast(object));
-        assert(ID::checkCalled(ret));
+        {
+            static_assert((std::is_same<
+                decltype(std::__invoke(object_cast(object)))
+              , CallRet>::value), "");
+            assert(ID::unchecked_call == false);
+            CallRet ret = std::__invoke(object_cast(object));
+            assert(ID::checkCalled(ret));
+        }
+#if TEST_STD_VER >= 11
+        {
+            static_assert((std::is_same<
+                decltype(std::__invoke_constexpr(object_cast(object)))
+              , CallRet>::value), "");
+            assert(ID::unchecked_call == false);
+            CallRet ret = std::__invoke_constexpr(object_cast(object));
+            assert(ID::checkCalled(ret));
+        }
+#endif
     }
 
     template <class ObjectT>
     void runTestImp(Int<1>, ObjectT& object) {
-        static_assert((std::is_same<
-            decltype(std::__invoke(object_cast(object), arg_cast(a0)))
-          , CallRet>::value), "");
-        assert(ID::unchecked_call == false);
-        CallRet ret = std::__invoke(object_cast(object), arg_cast(a0));
-        assert(ID::checkCalled(ret));
+        {
+            static_assert((std::is_same<
+                decltype(std::__invoke(object_cast(object), arg_cast(a0)))
+              , CallRet>::value), "");
+            assert(ID::unchecked_call == false);
+            CallRet ret = std::__invoke(object_cast(object), arg_cast(a0));
+            assert(ID::checkCalled(ret));
+        }
+#if TEST_STD_VER >= 11
+        {
+            static_assert((std::is_same<
+                decltype(std::__invoke_constexpr(object_cast(object), arg_cast(a0)))
+              , CallRet>::value), "");
+            assert(ID::unchecked_call == false);
+            CallRet ret = std::__invoke_constexpr(object_cast(object), arg_cast(a0));
+            assert(ID::checkCalled(ret));
+        }
+#endif
     }
 
     template <class ObjectT>
     void runTestImp(Int<2>, ObjectT& object) {
-        static_assert((std::is_same<
-            decltype(std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1)))
-          , CallRet>::value), "");
-        assert(ID::unchecked_call == false);
-        CallRet ret = std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1));
-        assert(ID::checkCalled(ret));
+        {
+            static_assert((std::is_same<
+                decltype(std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1)))
+              , CallRet>::value), "");
+            assert(ID::unchecked_call == false);
+            CallRet ret = std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1));
+            assert(ID::checkCalled(ret));
+        }
+#if TEST_STD_VER >= 11
+        {
+            static_assert((std::is_same<
+                decltype(std::__invoke_constexpr(object_cast(object), arg_cast(a0), arg_cast(a1)))
+              , CallRet>::value), "");
+            assert(ID::unchecked_call == false);
+            CallRet ret = std::__invoke_constexpr(object_cast(object), arg_cast(a0), arg_cast(a1));
+            assert(ID::checkCalled(ret));
+        }
+#endif
     }
 
     template <class ObjectT>
     void runTestImp(Int<3>, ObjectT& object) {
-        static_assert((std::is_same<
-            decltype(std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
-          , CallRet>::value), "");
-        assert(ID::unchecked_call == false);
-        CallRet ret = std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
-        assert(ID::checkCalled(ret));
+        {
+            static_assert((std::is_same<
+                decltype(std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
+              , CallRet>::value), "");
+            assert(ID::unchecked_call == false);
+            CallRet ret = std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
+            assert(ID::checkCalled(ret));
+        }
+#if TEST_STD_VER >= 11
+        {
+            static_assert((std::is_same<
+                decltype(std::__invoke_constexpr(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
+              , CallRet>::value), "");
+            assert(ID::unchecked_call == false);
+            CallRet ret = std::__invoke_constexpr(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
+            assert(ID::checkCalled(ret));
+        }
+#endif
     }
 };
 

Modified: libcxx/trunk/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.pass.cpp?rev=266836&r1=266835&r2=266836&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.pass.cpp Tue Apr 19 19:14:32 2016
@@ -7,6 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+// UNSUPPORTED: c++98, c++03
+
 // <memory>
 
 // shared_ptr
@@ -55,7 +57,6 @@ int main()
     }
     assert(A::count == 0);
     assert(test_allocator<A>::alloc_count == 0);
-#if __cplusplus >= 201103L
     {
     int i = 67;
     char c = 'e';
@@ -74,5 +75,4 @@ int main()
     assert(p->get_char() == 'f');
     }
     assert(A::count == 0);
-#endif
 }

Added: libcxx/trunk/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared_cxx03.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared_cxx03.pass.cpp?rev=266836&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared_cxx03.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared_cxx03.pass.cpp Tue Apr 19 19:14:32 2016
@@ -0,0 +1,118 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// <memory>
+
+// shared_ptr
+
+// template<class T, class A, class... Args>
+//    shared_ptr<T> allocate_shared(const A& a, Args&&... args);
+
+
+#include <memory>
+#include <new>
+#include <cstdlib>
+#include <cassert>
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+struct Zero
+{
+    static int count;
+    Zero() {++count;}
+    Zero(Zero const &) {++count;}
+    ~Zero() {--count;}
+};
+
+int Zero::count = 0;
+
+struct One
+{
+    static int count;
+    int value;
+    explicit One(int v) : value(v) {++count;}
+    One(One const & o) : value(o.value) {++count;}
+    ~One() {--count;}
+};
+
+int One::count = 0;
+
+
+struct Two
+{
+    static int count;
+    int value;
+    Two(int v, int) : value(v) {++count;}
+    Two(Two const & o) : value(o.value) {++count;}
+    ~Two() {--count;}
+};
+
+int Two::count = 0;
+
+struct Three
+{
+    static int count;
+    int value;
+    Three(int v, int, int) : value(v) {++count;}
+    Three(Three const & o) : value(o.value) {++count;}
+    ~Three() {--count;}
+};
+
+int Three::count = 0;
+
+template <class Alloc>
+void test()
+{
+    int const bad = -1;
+    {
+    std::shared_ptr<Zero> p = std::allocate_shared<Zero>(Alloc());
+    assert(Zero::count == 1);
+    }
+    assert(Zero::count == 0);
+    {
+    int const i = 42;
+    std::shared_ptr<One> p = std::allocate_shared<One>(Alloc(), i);
+    assert(One::count == 1);
+    assert(p->value == i);
+    }
+    assert(One::count == 0);
+    {
+    int const i = 42;
+    std::shared_ptr<Two> p = std::allocate_shared<Two>(Alloc(), i, bad);
+    assert(Two::count == 1);
+    assert(p->value == i);
+    }
+    assert(Two::count == 0);
+    {
+    int const i = 42;
+    std::shared_ptr<Three> p = std::allocate_shared<Three>(Alloc(), i, bad, bad);
+    assert(Three::count == 1);
+    assert(p->value == i);
+    }
+    assert(Three::count == 0);
+}
+
+int main()
+{
+    {
+    int i = 67;
+    int const bad = -1;
+    std::shared_ptr<Two> p = std::allocate_shared<Two>(test_allocator<Two>(54), i, bad);
+    assert(test_allocator<Two>::alloc_count == 1);
+    assert(Two::count == 1);
+    assert(p->value == 67);
+    }
+    assert(Two::count == 0);
+    assert(test_allocator<Two>::alloc_count == 0);
+
+    test<bare_allocator<void> >();
+#if __cplusplus >= 201103L
+    test<min_allocator<void> >();
+#endif
+}

Removed: libcxx/trunk/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared_no_variadics.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared_no_variadics.pass.cpp?rev=266835&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared_no_variadics.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared_no_variadics.pass.cpp (removed)
@@ -1,118 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-//                     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.
-//
-//===----------------------------------------------------------------------===//
-
-// <memory>
-
-// shared_ptr
-
-// template<class T, class A, class... Args>
-//    shared_ptr<T> allocate_shared(const A& a, Args&&... args);
-
-#define _LIBCPP_HAS_NO_VARIADICS
-#include <memory>
-#include <new>
-#include <cstdlib>
-#include <cassert>
-#include "test_allocator.h"
-#include "min_allocator.h"
-
-struct Zero
-{
-    static int count;
-    Zero() {++count;}
-    Zero(Zero const &) {++count;}
-    ~Zero() {--count;}
-};
-
-int Zero::count = 0;
-
-struct One
-{
-    static int count;
-    int value;
-    explicit One(int v) : value(v) {++count;}
-    One(One const & o) : value(o.value) {++count;}
-    ~One() {--count;}
-};
-
-int One::count = 0;
-
-
-struct Two
-{
-    static int count;
-    int value;
-    Two(int v, int) : value(v) {++count;}
-    Two(Two const & o) : value(o.value) {++count;}
-    ~Two() {--count;}
-};
-
-int Two::count = 0;
-
-struct Three
-{
-    static int count;
-    int value;
-    Three(int v, int, int) : value(v) {++count;}
-    Three(Three const & o) : value(o.value) {++count;}
-    ~Three() {--count;}
-};
-
-int Three::count = 0;
-
-template <class Alloc>
-void test()
-{
-    int const bad = -1;
-    {
-    std::shared_ptr<Zero> p = std::allocate_shared<Zero>(Alloc());
-    assert(Zero::count == 1);
-    }
-    assert(Zero::count == 0);
-    {
-    int const i = 42;
-    std::shared_ptr<One> p = std::allocate_shared<One>(Alloc(), i);
-    assert(One::count == 1);
-    assert(p->value == i);
-    }
-    assert(One::count == 0);
-    {
-    int const i = 42;
-    std::shared_ptr<Two> p = std::allocate_shared<Two>(Alloc(), i, bad);
-    assert(Two::count == 1);
-    assert(p->value == i);
-    }
-    assert(Two::count == 0);
-    {
-    int const i = 42;
-    std::shared_ptr<Three> p = std::allocate_shared<Three>(Alloc(), i, bad, bad);
-    assert(Three::count == 1);
-    assert(p->value == i);
-    }
-    assert(Three::count == 0);
-}
-
-int main()
-{
-    {
-    int i = 67;
-    int const bad = -1;
-    std::shared_ptr<Two> p = std::allocate_shared<Two>(test_allocator<Two>(54), i, bad);
-    assert(test_allocator<Two>::alloc_count == 1);
-    assert(Two::count == 1);
-    assert(p->value == 67);
-    }
-    assert(Two::count == 0);
-    assert(test_allocator<Two>::alloc_count == 0);
-
-    test<bare_allocator<void> >();
-#if __cplusplus >= 201103L
-    test<min_allocator<void> >();
-#endif
-}

Added: libcxx/trunk/test/std/utilities/meta/meta.rel/is_callable.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/meta/meta.rel/is_callable.pass.cpp?rev=266836&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/meta/meta.rel/is_callable.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/meta/meta.rel/is_callable.pass.cpp Tue Apr 19 19:14:32 2016
@@ -0,0 +1,159 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// type_traits
+
+// is_callable
+
+// Most testing of is_callable is done within the [meta.trans.other] result_of
+// tests.
+
+#include <type_traits>
+#include <functional>
+
+#include "test_macros.h"
+
+struct Tag {};
+struct DerFromTag : Tag {};
+
+struct Implicit {
+  Implicit(int) {}
+};
+
+struct Explicit {
+  explicit Explicit(int) {}
+};
+
+struct NotCallableWithInt {
+  int operator()(int) = delete;
+  int operator()(Tag) { return 42; }
+};
+
+int main()
+{
+    {
+        using Fn = int(Tag::*)(int);
+        using RFn = int(Tag::*)(int) &&;
+        // INVOKE bullet 1, 2 and 3
+        {
+            // Bullet 1
+            static_assert(std::is_callable<Fn(Tag&, int)>::value);
+            static_assert(std::is_callable<Fn(DerFromTag&, int)>::value);
+            static_assert(std::is_callable<RFn(Tag&&, int)>::value);
+            static_assert(!std::is_callable<RFn(Tag&, int)>::value);
+            static_assert(!std::is_callable<Fn(Tag&)>::value);
+            static_assert(!std::is_callable<Fn(Tag const&, int)>::value);
+        }
+        {
+            // Bullet 2
+            using T = std::reference_wrapper<Tag>;
+            using DT = std::reference_wrapper<DerFromTag>;
+            using CT = std::reference_wrapper<const Tag>;
+            static_assert(std::is_callable<Fn(T&, int)>::value);
+            static_assert(std::is_callable<Fn(DT&, int)>::value);
+            static_assert(std::is_callable<Fn(const T&, int)>::value);
+            static_assert(std::is_callable<Fn(T&&, int)>::value);
+            static_assert(!std::is_callable<Fn(CT&, int)>::value);
+            static_assert(!std::is_callable<RFn(T, int)>::value);
+        }
+        {
+            // Bullet 3
+            using T = Tag*;
+            using DT = DerFromTag*;
+            using CT = const Tag*;
+            using ST = std::unique_ptr<Tag>;
+            static_assert(std::is_callable<Fn(T&, int)>::value);
+            static_assert(std::is_callable<Fn(DT&, int)>::value);
+            static_assert(std::is_callable<Fn(const T&, int)>::value);
+            static_assert(std::is_callable<Fn(T&&, int)>::value);
+            static_assert(std::is_callable<Fn(ST, int)>::value);
+            static_assert(!std::is_callable<Fn(CT&, int)>::value);
+            static_assert(!std::is_callable<RFn(T, int)>::value);
+        }
+    }
+    {
+        // Bullets 4, 5 and 6
+        using Fn = int (Tag::*);
+        static_assert(!std::is_callable<Fn()>::value);
+        {
+            // Bullet 4
+            static_assert(std::is_callable<Fn(Tag&)>::value);
+            static_assert(std::is_callable<Fn(DerFromTag&)>::value);
+            static_assert(std::is_callable<Fn(Tag&&)>::value);
+            static_assert(std::is_callable<Fn(Tag const&)>::value);
+        }
+        {
+            // Bullet 5
+            using T = std::reference_wrapper<Tag>;
+            using DT = std::reference_wrapper<DerFromTag>;
+            using CT = std::reference_wrapper<const Tag>;
+            static_assert(std::is_callable<Fn(T&)>::value);
+            static_assert(std::is_callable<Fn(DT&)>::value);
+            static_assert(std::is_callable<Fn(const T&)>::value);
+            static_assert(std::is_callable<Fn(T&&)>::value);
+            static_assert(std::is_callable<Fn(CT&)>::value);
+        }
+        {
+            // Bullet 6
+            using T = Tag*;
+            using DT = DerFromTag*;
+            using CT = const Tag*;
+            using ST = std::unique_ptr<Tag>;
+            static_assert(std::is_callable<Fn(T&)>::value);
+            static_assert(std::is_callable<Fn(DT&)>::value);
+            static_assert(std::is_callable<Fn(const T&)>::value);
+            static_assert(std::is_callable<Fn(T&&)>::value);
+            static_assert(std::is_callable<Fn(ST)>::value);
+            static_assert(std::is_callable<Fn(CT&)>::value);
+        }
+    }
+    {
+        // INVOKE bullet 7
+        {
+            // Function pointer
+            using Fp = void(*)(Tag&, int);
+            static_assert(std::is_callable<Fp(Tag&, int)>::value);
+            static_assert(std::is_callable<Fp(DerFromTag&, int)>::value);
+            static_assert(!std::is_callable<Fp(const Tag&, int)>::value);
+            static_assert(!std::is_callable<Fp()>::value);
+            static_assert(!std::is_callable<Fp(Tag&)>::value);
+        }
+        {
+            // Function reference
+            using Fp = void(&)(Tag&, int);
+            static_assert(std::is_callable<Fp(Tag&, int)>::value);
+            static_assert(std::is_callable<Fp(DerFromTag&, int)>::value);
+            static_assert(!std::is_callable<Fp(const Tag&, int)>::value);
+            static_assert(!std::is_callable<Fp()>::value);
+            static_assert(!std::is_callable<Fp(Tag&)>::value);
+        }
+        {
+            // Function object
+            using Fn = NotCallableWithInt;
+            static_assert(std::is_callable<Fn(Tag)>::value, "");
+            static_assert(!std::is_callable<Fn(int)>::value, "");
+        }
+    }
+    {
+        // Check that the conversion to the return type is properly checked
+        using Fn = int(*)();
+        static_assert(std::is_callable<Fn(), Implicit>::value);
+        static_assert(std::is_callable<Fn(), double>::value);
+        static_assert(std::is_callable<Fn(), const volatile void>::value);
+        static_assert(!std::is_callable<Fn(), Explicit>::value);
+    }
+    {
+        // Check for is_callable_v
+        using Fn = void(*)();
+        static_assert(std::is_callable_v<Fn()>);
+        static_assert(!std::is_callable_v<Fn(int)>);
+    }
+}

Added: libcxx/trunk/test/std/utilities/meta/meta.rel/is_nothrow_callable.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/meta/meta.rel/is_nothrow_callable.pass.cpp?rev=266836&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/meta/meta.rel/is_nothrow_callable.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/meta/meta.rel/is_nothrow_callable.pass.cpp Tue Apr 19 19:14:32 2016
@@ -0,0 +1,115 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// type_traits
+
+// is_nothrow_callable
+
+#include <type_traits>
+#include <functional>
+
+#include "test_macros.h"
+
+struct Tag {};
+
+struct Implicit {
+  Implicit(int) noexcept {}
+};
+
+struct ThrowsImplicit {
+  ThrowsImplicit(int) {}
+};
+
+struct Explicit {
+  explicit Explicit(int) noexcept {}
+};
+
+template <bool IsNoexcept, class Ret, class ...Args>
+struct CallObject {
+  Ret operator()(Args&&...) const noexcept(IsNoexcept);
+};
+
+template <class Fn>
+constexpr bool throws_callable() {
+    return std::is_callable<Fn>::value &&
+        !std::is_nothrow_callable<Fn>::value;
+}
+
+template <class Fn, class Ret>
+constexpr bool throws_callable() {
+    return std::is_callable<Fn, Ret>::value &&
+        !std::is_nothrow_callable<Fn, Ret>::value;
+}
+
+// FIXME(EricWF) Don't test the where noexcept is *not* part of the type system
+// once implementations have caught up.
+void test_noexcept_function_pointers()
+{
+    struct Dummy { void foo() noexcept; static void bar() noexcept; };
+#if !defined(__cpp_noexcept_function_type)
+    {
+        // Check that PMF's and function pointers *work*. is_nothrow_callable will always
+        // return false because 'noexcept' is not part of the function type.
+        static_assert(throws_callable<decltype(&Dummy::foo)(Dummy&)>());
+        static_assert(throws_callable<decltype(&Dummy::bar)()>());
+    }
+#else
+    {
+        // Check that PMF's and function pointers actually work and that
+        // is_nothrow_callable returns true for noexcept PMF's and function
+        // pointers.
+        static_assert(std::is_nothrow_callable<decltype(&Dummy::foo)(Dummy&)>::value);
+        static_assert(std::is_nothrow_callable<decltype(&Dummy::bar)()>::value);
+    }
+#endif
+}
+
+int main()
+{
+    {
+        // Check that the conversion to the return type is properly checked
+        using Fn = CallObject<true, int>;
+        static_assert(std::is_nothrow_callable<Fn(), Implicit>::value);
+        static_assert(std::is_nothrow_callable<Fn(), double>::value);
+        static_assert(std::is_nothrow_callable<Fn(), const volatile void>::value);
+        static_assert(throws_callable<Fn(), ThrowsImplicit>());
+        static_assert(!std::is_nothrow_callable<Fn(), Explicit>());
+    }
+    {
+        // Check that the conversion to the parameters is properly checked
+        using Fn = CallObject<true, void, const Implicit&, const ThrowsImplicit&>;
+        static_assert(std::is_nothrow_callable<Fn(Implicit&, ThrowsImplicit&)>::value);
+        static_assert(std::is_nothrow_callable<Fn(int, ThrowsImplicit&)>::value);
+        static_assert(throws_callable<Fn(int, int)>());
+        static_assert(!std::is_nothrow_callable<Fn()>::value);
+    }
+    {
+        // Check that the noexcept-ness of function objects is checked.
+        using Fn = CallObject<true, void>;
+        using Fn2 = CallObject<false, void>;
+        static_assert(std::is_nothrow_callable<Fn()>::value);
+        static_assert(throws_callable<Fn2()>());
+    }
+    {
+        // Check that PMD derefs are noexcept
+        using Fn = int (Tag::*);
+        static_assert(std::is_nothrow_callable<Fn(Tag&)>::value);
+        static_assert(std::is_nothrow_callable<Fn(Tag&), Implicit>::value);
+        static_assert(throws_callable<Fn(Tag&), ThrowsImplicit>());
+    }
+    {
+        // Check for is_nothrow_callable_v
+        using Fn = CallObject<true, int>;
+        static_assert(std::is_nothrow_callable_v<Fn()>);
+        static_assert(!std::is_nothrow_callable_v<Fn(int)>);
+    }
+    test_noexcept_function_pointers();
+}

Modified: libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp?rev=266836&r1=266835&r2=266836&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp Tue Apr 19 19:14:32 2016
@@ -45,6 +45,10 @@ struct HasType<T, typename Voider<typena
 template <class T, class U>
 void test_result_of()
 {
+#if TEST_STD_VER > 14
+    static_assert(std::is_callable<T>::value, "");
+    static_assert(std::is_callable<T, U>::value, "");
+#endif
     static_assert((std::is_same<typename std::result_of<T>::type, U>::value), "");
 }
 
@@ -54,6 +58,9 @@ void test_no_result()
 #if TEST_STD_VER >= 11
     static_assert((!HasType<std::result_of<T> >::value), "");
 #endif
+#if TEST_STD_VER > 14
+    static_assert(std::is_callable<T>::value == false, "");
+#endif
 }
 
 int main()

Modified: libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/result_of11.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/result_of11.pass.cpp?rev=266836&r1=266835&r2=266836&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/result_of11.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/result_of11.pass.cpp Tue Apr 19 19:14:32 2016
@@ -35,6 +35,10 @@ void test_result_of_imp()
 #if TEST_STD_VER > 11
     static_assert((std::is_same<std::result_of_t<T>, U>::value), "");
 #endif
+#if TEST_STD_VER > 14
+    static_assert(std::is_callable<T>::value, "");
+    static_assert(std::is_callable<T, U>::value, "");
+#endif
 }
 
 int main()

Modified: libcxx/trunk/www/cxx1z_status.html
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/www/cxx1z_status.html?rev=266836&r1=266835&r2=266836&view=diff
==============================================================================
--- libcxx/trunk/www/cxx1z_status.html (original)
+++ libcxx/trunk/www/cxx1z_status.html Tue Apr 19 19:14:32 2016
@@ -92,7 +92,7 @@
 	<tr><td><a href="http://wg21.link/P0030R1">P0030R1</a></td><td>LWG</td><td>Proposal to Introduce a 3-Argument Overload to std::hypot</td><td>Jacksonville</td><td></td><td></td></tr>
 	<tr><td><a href="http://wg21.link/P0031R0">P0031R0</a></td><td>LWG</td><td>A Proposal to Add Constexpr Modifiers to reverse_iterator, move_iterator, array and Range Access</td><td>Jacksonville</td><td></td><td></td></tr>
 	<tr><td><a href="http://wg21.link/P0272R1">P0272R1</a></td><td>LWG</td><td>Give <tt>std::string</tt> a non-const <tt>.data()</tt> member function</td><td>Jacksonville</td><td>Complete</td><td>3.9</td></tr>
-	<tr><td><a href="http://wg21.link/P0077R2">P0077R2</a></td><td>LWG</td><td><tt>is_callable</tt>, the missing INVOKE related trait</td><td>Jacksonville</td><td></td><td></td></tr>
+	<tr><td><a href="http://wg21.link/P0077R2">P0077R2</a></td><td>LWG</td><td><tt>is_callable</tt>, the missing INVOKE related trait</td><td>Jacksonville</td><td>Complete</td><td>3.9</td></tr>
 <!--  	<tr><td></td><td></td><td></td><td></td><td></td><td></td></tr> -->
   </table>
 




More information about the cfe-commits mailing list