aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2012-03-07 12:27:35 +0000
committerChandler Carruth <chandlerc@gmail.com>2012-03-07 12:27:35 +0000
commitcbfc117674be7ff70b4682c525d6fcb4827a74ed (patch)
tree87230128016caca8aefd7bf396d35ac62a88df33 /include
parentff12877a6f4db734cf0a156dc2ef815a839a79ec (diff)
downloadexternal_llvm-cbfc117674be7ff70b4682c525d6fcb4827a74ed.zip
external_llvm-cbfc117674be7ff70b4682c525d6fcb4827a74ed.tar.gz
external_llvm-cbfc117674be7ff70b4682c525d6fcb4827a74ed.tar.bz2
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
Diffstat (limited to 'include')
-rw-r--r--include/llvm/Support/type_traits.h60
1 files changed, 29 insertions, 31 deletions
diff --git a/include/llvm/Support/type_traits.h b/include/llvm/Support/type_traits.h
index 241883a..0cb8e97 100644
--- a/include/llvm/Support/type_traits.h
+++ b/include/llvm/Support/type_traits.h
@@ -121,46 +121,44 @@ template <> struct is_integral_impl<unsigned long long> : true_type {};
template <typename T>
struct is_integral : is_integral_impl<T> {};
-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 <typename U, U u = U()> struct check_nontype_temp_param_return_type {
- char c[2];
- };
- template <typename U>
- check_nontype_temp_param_return_type<U> check_nontype_temp_param(U*);
- template <typename U> 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 <typename U, nonce* u = U()>
- struct check_nullptr_t_like_return_type { char c[2]; };
- template <typename U>
- check_nullptr_t_like_return_type<U> check_nullptr_t_like(U*);
- template <typename U> char check_nullptr_t_like(...);
-} // namespace dont_use
+/// \brief Metafunction to remove reference from a type.
+template <typename T> struct remove_reference { typedef T type; };
+template <typename T> struct remove_reference<T&> { typedef T type; };
+
+/// \brief Metafunction that determines whether the given type is a pointer
+/// type.
+template <typename T> struct is_pointer : false_type {};
+template <typename T> struct is_pointer<T*> : true_type {};
+template <typename T> struct is_pointer<T* const> : true_type {};
+template <typename T> struct is_pointer<T* volatile> : true_type {};
+template <typename T> struct is_pointer<T* const volatile> : 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 <typename T> struct is_integral_or_enum {
+/// above for is_integral because it is based on merely being convertible
+/// implicitly to an integral type.
+template <typename T> 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<T>::type UnderlyingT;
+ static UnderlyingT &nonce_instance;
+
+public:
enum {
- value = (sizeof(char) != sizeof(dont_use::check_nontype_temp_param<T>(0)) &&
- sizeof(char) == sizeof(dont_use::check_nullptr_t_like<T>(0)))
+ value = (!is_class<UnderlyingT>::value && !is_pointer<UnderlyingT>::value &&
+ !is_same<UnderlyingT, float>::value &&
+ !is_same<UnderlyingT, double>::value &&
+ sizeof(char) != sizeof(check_int_convertible(nonce_instance)))
};
};
-/// \brief Metafunction that determines whether the given type is a pointer
-/// type.
-template <typename T> struct is_pointer : false_type {};
-template <typename T> struct is_pointer<T*> : true_type {};
-
// enable_if_c - Enable/disable a template based on a metafunction
template<bool Cond, typename T = void>
struct enable_if_c {