From cbfc117674be7ff70b4682c525d6fcb4827a74ed Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Wed, 7 Mar 2012 12:27:35 +0000 Subject: [PATCH] Try a completely different approach to this type trait to appease older compilers. It seems that GCC 4.3 (and likely older) simply aren't going to do SFINAE on non-type template parameters the way Clang and modern GCCs do... Now we detect the implicit conversion to an integer type, and then blacklist classes, pointers, and floating point types. This seems to work well enough, and I'm hopeful will return the bots to life. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152227 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Support/type_traits.h | 60 +++++++++++++++--------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/include/llvm/Support/type_traits.h b/include/llvm/Support/type_traits.h index 241883a02cb..0cb8e9789dc 100644 --- a/include/llvm/Support/type_traits.h +++ b/include/llvm/Support/type_traits.h @@ -121,46 +121,44 @@ template <> struct is_integral_impl : true_type {}; template struct is_integral : is_integral_impl {}; -namespace dont_use { - // Form a return type that can only be instantiated with an integral or enum - // types (or with nullptr_t in C++11). - template struct check_nontype_temp_param_return_type { - char c[2]; - }; - template - check_nontype_temp_param_return_type check_nontype_temp_param(U*); - template char check_nontype_temp_param(...); - - // Form a return type that can only be instantiated with nullptr_t in C++11 - // mode. It's harmless in C++98 mode, but this allows us to filter nullptr_t - // when building in C++11 mode without having to detect that mode for each - // different compiler. - struct nonce {}; - template - struct check_nullptr_t_like_return_type { char c[2]; }; - template - check_nullptr_t_like_return_type check_nullptr_t_like(U*); - template char check_nullptr_t_like(...); -} // namespace dont_use +/// \brief Metafunction to remove reference from a type. +template struct remove_reference { typedef T type; }; +template struct remove_reference { typedef T type; }; + +/// \brief Metafunction that determines whether the given type is a pointer +/// type. +template struct is_pointer : false_type {}; +template struct is_pointer : true_type {}; +template struct is_pointer : true_type {}; +template struct is_pointer : true_type {}; +template struct is_pointer : true_type {}; /// \brief Metafunction that determines whether the given type is either an /// integral type or an enumeration type. /// /// Note that this accepts potentially more integral types than we whitelist -/// above for is_integral, it should accept essentially anything the compiler -/// believes is an integral type. -template struct is_integral_or_enum { +/// above for is_integral because it is based on merely being convertible +/// implicitly to an integral type. +template class is_integral_or_enum { + // Provide an overload which can be called with anything implicitly + // convertible to an unsigned long long. This should catch integer types and + // enumeration types at least. We blacklist classes with conversion operators + // below. + static double check_int_convertible(unsigned long long); + static char check_int_convertible(...); + + typedef typename remove_reference::type UnderlyingT; + static UnderlyingT &nonce_instance; + +public: enum { - value = (sizeof(char) != sizeof(dont_use::check_nontype_temp_param(0)) && - sizeof(char) == sizeof(dont_use::check_nullptr_t_like(0))) + value = (!is_class::value && !is_pointer::value && + !is_same::value && + !is_same::value && + sizeof(char) != sizeof(check_int_convertible(nonce_instance))) }; }; -/// \brief Metafunction that determines whether the given type is a pointer -/// type. -template struct is_pointer : false_type {}; -template struct is_pointer : true_type {}; - // enable_if_c - Enable/disable a template based on a metafunction template struct enable_if_c { -- 2.34.1