summaryrefslogtreecommitdiffstats
path: root/libcxx/include
diff options
context:
space:
mode:
authorMarshall Clow <mclow.lists@gmail.com>2016-01-21 18:22:43 +0000
committerMarshall Clow <mclow.lists@gmail.com>2016-01-21 18:22:43 +0000
commitfcdb19904c5da82ee72ce2dc76510e936fcc0bf3 (patch)
tree8aeba60c1ea68d13838b3efdf09b5c786eb23a71 /libcxx/include
parented9fec736502adf3a8f35a488243c212d640223d (diff)
downloadbcm5719-llvm-fcdb19904c5da82ee72ce2dc76510e936fcc0bf3.tar.gz
bcm5719-llvm-fcdb19904c5da82ee72ce2dc76510e936fcc0bf3.zip
Implement LWG#2101 'Some transformation types can produce impossible types' Introduced a new (internal) type trait '__is_referenceable' with tests. Use that trait in add_lvalue_reference, add_rvalue_reference and add_pointer.
llvm-svn: 258418
Diffstat (limited to 'libcxx/include')
-rw-r--r--libcxx/include/type_traits63
1 files changed, 51 insertions, 12 deletions
diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits
index b7adfebceeb..3b80a9efa5d 100644
--- a/libcxx/include/type_traits
+++ b/libcxx/include/type_traits
@@ -957,6 +957,38 @@ template <class _Tp> _LIBCPP_CONSTEXPR bool is_compound_v
= is_compound<_Tp>::value;
#endif
+
+// __is_referenceable [defns.referenceable]
+template <class _Tp> struct __is_referenceable
+ : public std::integral_constant<bool, is_object<_Tp>::value || is_reference<_Tp>::value> {};
+
+#ifndef _LIBCPP_HAS_NO_VARIADICS
+template <class _Ret, class... _Args>
+struct __is_referenceable<_Ret(_Args...)> : public std::true_type {};
+
+template <class _Ret, class... _Args>
+struct __is_referenceable<_Ret(_Args..., ...)> : public std::true_type {};
+#else
+template <class _Ret>
+struct __is_referenceable<_Ret()> : public std::true_type {};
+template <class _Ret, class _A0>
+struct __is_referenceable<_Ret(_A0)> : public std::true_type {};
+template <class _Ret, class _A0, class _A1>
+struct __is_referenceable<_Ret(_A0, _A1)> : public std::true_type {};
+template <class _Ret, class _A0, class _A1, class _A2>
+struct __is_referenceable<_Ret(_A0, _A1, _A2)> : public std::true_type {};
+
+template <class _Ret>
+struct __is_referenceable<_Ret(...)> : public std::true_type {};
+template <class _Ret, class _A0>
+struct __is_referenceable<_Ret(_A0, ...)> : public std::true_type {};
+template <class _Ret, class _A0, class _A1>
+struct __is_referenceable<_Ret(_A0, _A1, ...)> : public std::true_type {};
+template <class _Ret, class _A0, class _A1, class _A2>
+struct __is_referenceable<_Ret(_A0, _A1, _A2, ...)> : public std::true_type {};
+#endif
+
+
// add_const
template <class _Tp, bool = is_reference<_Tp>::value ||
@@ -1014,12 +1046,11 @@ template <class _Tp> using remove_reference_t = typename remove_reference<_Tp>::
// add_lvalue_reference
-template <class _Tp> struct _LIBCPP_TYPE_VIS_ONLY add_lvalue_reference {typedef _Tp& type;};
-template <class _Tp> struct _LIBCPP_TYPE_VIS_ONLY add_lvalue_reference<_Tp&> {typedef _Tp& type;}; // for older compiler
-template <> struct _LIBCPP_TYPE_VIS_ONLY add_lvalue_reference<void> {typedef void type;};
-template <> struct _LIBCPP_TYPE_VIS_ONLY add_lvalue_reference<const void> {typedef const void type;};
-template <> struct _LIBCPP_TYPE_VIS_ONLY add_lvalue_reference<volatile void> {typedef volatile void type;};
-template <> struct _LIBCPP_TYPE_VIS_ONLY add_lvalue_reference<const volatile void> {typedef const volatile void type;};
+template <class _Tp, bool = __is_referenceable<_Tp>::value> struct __add_lvalue_reference_impl { typedef _Tp type; };
+template <class _Tp > struct __add_lvalue_reference_impl<_Tp, true> { typedef _Tp& type; };
+
+template <class _Tp> struct _LIBCPP_TYPE_VIS_ONLY add_lvalue_reference
+{typedef typename __add_lvalue_reference_impl<_Tp>::type type;};
#if _LIBCPP_STD_VER > 11
template <class _Tp> using add_lvalue_reference_t = typename add_lvalue_reference<_Tp>::type;
@@ -1027,11 +1058,11 @@ template <class _Tp> using add_lvalue_reference_t = typename add_lvalue_referenc
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-template <class _Tp> struct _LIBCPP_TYPE_VIS_ONLY add_rvalue_reference {typedef _Tp&& type;};
-template <> struct _LIBCPP_TYPE_VIS_ONLY add_rvalue_reference<void> {typedef void type;};
-template <> struct _LIBCPP_TYPE_VIS_ONLY add_rvalue_reference<const void> {typedef const void type;};
-template <> struct _LIBCPP_TYPE_VIS_ONLY add_rvalue_reference<volatile void> {typedef volatile void type;};
-template <> struct _LIBCPP_TYPE_VIS_ONLY add_rvalue_reference<const volatile void> {typedef const volatile void type;};
+template <class _Tp, bool = __is_referenceable<_Tp>::value> struct __add_rvalue_reference_impl { typedef _Tp type; };
+template <class _Tp > struct __add_rvalue_reference_impl<_Tp, true> { typedef _Tp&& type; };
+
+template <class _Tp> struct _LIBCPP_TYPE_VIS_ONLY add_rvalue_reference
+{typedef typename __add_rvalue_reference_impl<_Tp>::type type;};
#if _LIBCPP_STD_VER > 11
template <class _Tp> using add_rvalue_reference_t = typename add_rvalue_reference<_Tp>::type;
@@ -1072,8 +1103,16 @@ template <class _Tp> using remove_pointer_t = typename remove_pointer<_Tp>::type
// add_pointer
-template <class _Tp> struct _LIBCPP_TYPE_VIS_ONLY add_pointer
+template <class _Tp,
+ bool = __is_referenceable<_Tp>::value ||
+ is_same<typename remove_cv<_Tp>::type, void>::value>
+struct __add_pointer_impl
{typedef typename remove_reference<_Tp>::type* type;};
+template <class _Tp> struct __add_pointer_impl<_Tp, false>
+ {typedef _Tp type;};
+
+template <class _Tp> struct _LIBCPP_TYPE_VIS_ONLY add_pointer
+ {typedef typename __add_pointer_impl<_Tp>::type type;};
#if _LIBCPP_STD_VER > 11
template <class _Tp> using add_pointer_t = typename add_pointer<_Tp>::type;
OpenPOWER on IntegriCloud