X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FSupport%2Ftype_traits.h;h=7b97547be52af409574587e6d3c1e9ff321e9c65;hb=55907d1274ce715b92d584e305e0708e333a33c0;hp=241883a02cbb38ab7588daf3205aa2718982702c;hpb=ff12877a6f4db734cf0a156dc2ef815a839a79ec;p=oota-llvm.git diff --git a/include/llvm/Support/type_traits.h b/include/llvm/Support/type_traits.h index 241883a02cb..7b97547be52 100644 --- a/include/llvm/Support/type_traits.h +++ b/include/llvm/Support/type_traits.h @@ -21,6 +21,11 @@ #include #include +#ifndef __has_feature +#define LLVM_DEFINED_HAS_FEATURE +#define __has_feature(x) 0 +#endif + // This is actually the conforming implementation which works with abstract // classes. However, enough compilers have trouble with it that most will use // the one in boost/type_traits/object_traits.hpp. This implementation actually @@ -58,15 +63,21 @@ struct is_class /// type can be copied around with memcpy instead of running ctors etc. template struct isPodLike { +#if __has_feature(is_trivially_copyable) + // If the compiler supports the is_trivially_copyable trait use it, as it + // matches the definition of isPodLike closely. + static const bool value = __is_trivially_copyable(T); +#else // If we don't know anything else, we can (at least) assume that all non-class // types are PODs. static const bool value = !is_class::value; +#endif }; // std::pair's are pod-like if their elements are. template struct isPodLike > { - static const bool value = isPodLike::value & isPodLike::value; + static const bool value = isPodLike::value && isPodLike::value; }; @@ -121,46 +132,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 { @@ -204,4 +213,8 @@ struct conditional { typedef F type; }; } +#ifdef LLVM_DEFINED_HAS_FEATURE +#undef __has_feature +#endif + #endif