Fix folly conversions for Clang with GCC5's libstdc++
authorPhil Willoughby <philwill@fb.com>
Thu, 1 Sep 2016 20:09:24 +0000 (13:09 -0700)
committerFacebook Github Bot 5 <facebook-github-bot-5-bot@fb.com>
Thu, 1 Sep 2016 20:23:28 +0000 (13:23 -0700)
Summary: Now builds correctly

Reviewed By: meyering

Differential Revision: D3763879

fbshipit-source-id: e272fbcc28a74fcf36b63a0135534c5063a7c4ee

folly/Conv.h
folly/Traits.h
folly/configure.ac
folly/test/TraitsTest.cpp

index 468d33cb08a74d467b9ed9366499f30aa87dc88e..890b2592869ae1182dca8c69865409c1755925e8 100644 (file)
@@ -43,6 +43,7 @@
 #include <folly/FBString.h>
 #include <folly/Likely.h>
 #include <folly/Range.h>
+#include <folly/Traits.h>
 #include <folly/Unit.h>
 #include <folly/portability/Math.h>
 
index fc3cba9c98827d100d8fc56b3609cc6324ca3d86..ece58c30b60c0e0b9de212479cf4702796f5451e 100644 (file)
@@ -673,3 +673,45 @@ FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(boost::shared_ptr)
       classname, func_name, /* nolint */ volatile); \
   FOLLY_CREATE_HAS_MEMBER_FN_TRAITS_IMPL( \
       classname, func_name, /* nolint */ volatile const)
+
+/* Some combinations of compilers and C++ libraries make __int128 and
+ * unsigned __int128 available but do not correctly define their standard type
+ * traits.
+ *
+ * If FOLLY_SUPPLY_MISSING_INT128_TRAITS is defined, we define these traits
+ * here.
+ *
+ * @author: Phil Willoughby <philwill@fb.com>
+ */
+#if FOLLY_SUPPLY_MISSING_INT128_TRAITS
+FOLLY_NAMESPACE_STD_BEGIN
+template <>
+struct is_arithmetic<__int128> : ::std::true_type {};
+template <>
+struct is_arithmetic<unsigned __int128> : ::std::true_type {};
+template <>
+struct is_integral<__int128> : ::std::true_type {};
+template <>
+struct is_integral<unsigned __int128> : ::std::true_type {};
+template <>
+struct make_unsigned<__int128> {
+  typedef unsigned __int128 type;
+};
+template <>
+struct make_signed<__int128> {
+  typedef __int128 type;
+};
+template <>
+struct make_unsigned<unsigned __int128> {
+  typedef unsigned __int128 type;
+};
+template <>
+struct make_signed<unsigned __int128> {
+  typedef __int128 type;
+};
+template <>
+struct is_signed<__int128> : ::std::true_type {};
+template <>
+struct is_unsigned<unsigned __int128> : ::std::true_type {};
+FOLLY_NAMESPACE_STD_END
+#endif // FOLLY_SUPPLY_MISSING_INT128_TRAITS
index 963ccda074d75575407ca08a1b7ab7709383ed7f..3786c00ea4713f14b2f02a79499e76693e5f2279 100644 (file)
@@ -153,7 +153,28 @@ AC_C_INLINE
 AC_TYPE_SIZE_T
 AC_HEADER_TIME
 AC_C_VOLATILE
-AC_CHECK_TYPE([__int128], AC_DEFINE([HAVE_INT128_T], [1], [Define if we have __int128]))
+AC_CHECK_TYPE([__int128], [folly_cv_prog_cc_int128=yes],
+    [folly_cv_prog_cc_int128=no])
+if test "$folly_cv_prog_cc_int128" = "yes"; then
+  AC_DEFINE([HAVE_INT128_T], [1], [Define if we have __int128])
+  AC_CACHE_CHECK(
+    [for __int128 type traits],
+    [folly_cv_prog_cc_int128traits],
+    [AC_COMPILE_IFELSE(
+      [AC_LANG_SOURCE([[
+#include <type_traits>
+static_assert(
+  ::std::is_same<::std::make_signed<unsigned __int128>::type, __int128>::value,
+  "signed form of `unsigned __uint128` must be `__int128`.");
+      ]])],
+      [folly_cv_prog_cc_int128traits=yes],
+      [folly_cv_prog_cc_int128traits=no])
+    ])
+  if test "$folly_cv_prog_cc_int128traits" = "no"; then
+    AC_DEFINE([FOLLY_SUPPLY_MISSING_INT128_TRAITS], [1], [Define if we need the standard integer traits defined for the type `__int128'.])
+  fi
+fi
+
 AC_CHECK_TYPES([ptrdiff_t, pthread_spinlock_t])
 
 AC_CACHE_CHECK(
@@ -523,7 +544,7 @@ AC_CHECK_HEADER([zlib.h], AC_CHECK_LIB([z], [main]))
 AC_CHECK_HEADER([lzma.h], AC_CHECK_LIB([lzma], [main]))
 AC_CHECK_HEADER([zstd.h], AC_CHECK_LIB([zstd], [main]))
 AC_CHECK_HEADER([linux/membarrier.h], AC_DEFINE([HAVE_LINUX_MEMBARRIER_H], [1], [Define to 1 if membarrier.h is available]))
+
 AC_ARG_ENABLE([follytestmain],
    AS_HELP_STRING([--enable-follytestmain], [enables using main function from folly for tests]),
    [follytestmain=${enableval}], [follytestmain=no])
index 402d1d2cfeb3d525df73ff36a1d686cac30c5e31..71b6a17643e63bfeea02df7f610e2a90c5805d1e 100644 (file)
@@ -133,6 +133,36 @@ TEST(Traits, relational) {
   EXPECT_FALSE((folly::greater_than<uint8_t, 255u, uint8_t>(254u)));
 }
 
+#if FOLLY_HAVE_INT128_T
+
+TEST(Traits, int128) {
+  EXPECT_TRUE(
+      (::std::is_same<::std::make_unsigned<__int128_t>::type, __uint128_t>::
+           value));
+  EXPECT_TRUE((
+      ::std::is_same<::std::make_signed<__int128_t>::type, __int128_t>::value));
+  EXPECT_TRUE(
+      (::std::is_same<::std::make_unsigned<__uint128_t>::type, __uint128_t>::
+           value));
+  EXPECT_TRUE(
+      (::std::is_same<::std::make_signed<__uint128_t>::type, __int128_t>::
+           value));
+  EXPECT_TRUE((::std::is_arithmetic<__int128_t>::value));
+  EXPECT_TRUE((::std::is_arithmetic<__uint128_t>::value));
+  EXPECT_TRUE((::std::is_integral<__int128_t>::value));
+  EXPECT_TRUE((::std::is_integral<__uint128_t>::value));
+  EXPECT_FALSE((::std::is_unsigned<__int128_t>::value));
+  EXPECT_TRUE((::std::is_signed<__int128_t>::value));
+  EXPECT_TRUE((::std::is_unsigned<__uint128_t>::value));
+  EXPECT_FALSE((::std::is_signed<__uint128_t>::value));
+  EXPECT_TRUE((::std::is_fundamental<__int128_t>::value));
+  EXPECT_TRUE((::std::is_fundamental<__uint128_t>::value));
+  EXPECT_TRUE((::std::is_scalar<__int128_t>::value));
+  EXPECT_TRUE((::std::is_scalar<__uint128_t>::value));
+}
+
+#endif // FOLLY_HAVE_INT128_T
+
 template <typename T, typename... Args>
 void testIsRelocatable(Args&&... args) {
   if (!IsRelocatable<T>::value) return;