Fixing clang compatibility issues
authorMarcelo Juchem <marcelo@fb.com>
Sat, 30 Mar 2013 07:13:31 +0000 (00:13 -0700)
committerJordan DeLong <jdelong@fb.com>
Sun, 21 Apr 2013 20:20:56 +0000 (13:20 -0700)
Test Plan: all folly unit tests

Reviewed By: andrewjcg@fb.com

FB internal diff: D757374

folly/Conv.h
folly/Format-inl.h
folly/Traits.h

index 4ccacf226185c3e9a37924b97219279d6cec0cf3..c8360a6d7675b21f1506404c372cde0cd77eb10c 100644 (file)
@@ -64,13 +64,17 @@ typename std::enable_if<
 to(const Src & value) {
   /* static */ if (std::numeric_limits<Tgt>::max()
                    < std::numeric_limits<Src>::max()) {
-    FOLLY_RANGE_CHECK(value <= std::numeric_limits<Tgt>::max(),
-                      "Overflow");
+    FOLLY_RANGE_CHECK(
+      (!greater_than<Tgt, std::numeric_limits<Tgt>::max()>(value)),
+      "Overflow"
+    );
   }
   /* static */ if (std::is_signed<Src>::value &&
                    (!std::is_signed<Tgt>::value || sizeof(Src) > sizeof(Tgt))) {
-    FOLLY_RANGE_CHECK(value >= std::numeric_limits<Tgt>::min(),
-                      "Negative overflow");
+    FOLLY_RANGE_CHECK(
+      (!less_than<Tgt, std::numeric_limits<Tgt>::min()>(value)),
+      "Negative overflow"
+    );
   }
   return static_cast<Tgt>(value);
 }
index c8c90418693ec75b2254042bb51bdc0591eb6d1c..70672d476ebedc710194fe14abdb67c239e8984b 100644 (file)
@@ -18,6 +18,8 @@
 #error This file may only be included from Format.h.
 #endif
 
+#include "folly/Traits.h"
+
 namespace folly {
 
 namespace detail {
@@ -45,7 +47,7 @@ size_t uintToHex(char* buffer, size_t bufLen, Uint v,
                  const char (&repr)[256][2]) {
   // 'v >>= 7, v >>= 1' is no more than a work around to get rid of shift size
   // warning when Uint = uint8_t (it's false as v >= 256 implies sizeof(v) > 1).
-  for (; v >= 256; v >>= 7, v >>= 1) {
+  for (; !less_than<unsigned, 256>(v); v >>= 7, v >>= 1) {
     auto b = v & 0xff;
     bufLen -= 2;
     buffer[bufLen] = repr[b][0];
@@ -89,7 +91,7 @@ size_t uintToOctal(char* buffer, size_t bufLen, Uint v) {
   auto& repr = formatOctal;
   // 'v >>= 7, v >>= 2' is no more than a work around to get rid of shift size
   // warning when Uint = uint8_t (it's false as v >= 512 implies sizeof(v) > 1).
-  for (; v >= 512; v >>= 7, v >>= 2) {
+  for (; !less_than<unsigned, 512>(v); v >>= 7, v >>= 2) {
     auto b = v & 0x1ff;
     bufLen -= 3;
     buffer[bufLen] = repr[b][0];
index ebdb84d1e28ac0ac2856fac14bdb3da18391795e..db8bd33a3229d9b5d0abd8141c45a0418894f8c1 100644 (file)
@@ -20,6 +20,7 @@
 #define FOLLY_BASE_TRAITS_H_
 
 #include <memory>
+#include <limits>
 #include <type_traits>
 
 #include <bits/c++config.h>
@@ -306,9 +307,13 @@ public:
 };
 
 /*
- * Complementary type traits to check for a negative/non-positive value.
+ * Complementary type traits for integral comparisons.
  *
- * `if(x < 0)` yields an error in clang for unsigned types when -Werror is used
+ * For instance, `if(x < 0)` yields an error in clang for unsigned types
+ *  when -Werror is used due to -Wtautological-compare
+ *
+ *
+ * @author: Marcelo Juchem <marcelo@fb.com>
  */
 
 namespace detail {
@@ -323,6 +328,68 @@ struct is_negative_impl<T, false> {
   constexpr static bool check(T x) { return false; }
 };
 
+template <typename RHS, RHS rhs, typename LHS>
+bool less_than_impl(
+  typename std::enable_if<
+    (rhs <= std::numeric_limits<LHS>::max()
+      && rhs >= std::numeric_limits<LHS>::min()),
+    LHS
+  >::type const lhs
+) {
+  return lhs < rhs;
+}
+
+template <typename RHS, RHS rhs, typename LHS>
+bool less_than_impl(
+  typename std::enable_if<
+    (rhs > std::numeric_limits<LHS>::max()),
+    LHS
+  >::type const
+) {
+  return true;
+}
+
+template <typename RHS, RHS rhs, typename LHS>
+bool less_than_impl(
+  typename std::enable_if<
+    (rhs < std::numeric_limits<LHS>::min()),
+    LHS
+  >::type const
+) {
+  return false;
+}
+
+template <typename LHS, LHS lhs, typename RHS>
+bool greater_than_impl(
+  typename std::enable_if<
+    (lhs <= std::numeric_limits<RHS>::max()
+      && lhs >= std::numeric_limits<RHS>::min()),
+    RHS
+  >::type const rhs
+) {
+  return lhs < rhs;
+}
+
+template <typename LHS, LHS lhs, typename RHS>
+bool greater_than_impl(
+  typename std::enable_if<
+    (lhs > std::numeric_limits<RHS>::max()),
+    RHS
+  >::type const
+) {
+  return false;
+}
+
+template <typename LHS, LHS lhs, typename RHS>
+bool greater_than_impl(
+  typename std::enable_if<
+    (lhs < std::numeric_limits<RHS>::min()),
+    RHS
+  >::type const
+) {
+  return true;
+}
+
 } // namespace detail {
 
 // same as `x < 0`
@@ -335,6 +402,20 @@ constexpr bool is_negative(T x) {
 template <typename T>
 constexpr bool is_non_positive(T x) { return !x || folly::is_negative(x); }
 
+template <typename RHS, RHS rhs, typename LHS>
+bool less_than(LHS const lhs) {
+  return detail::less_than_impl<
+    RHS, rhs, typename std::remove_reference<LHS>::type
+  >(lhs);
+}
+
+template <typename LHS, LHS lhs, typename RHS>
+bool greater_than(RHS const rhs) {
+  return detail::greater_than_impl<
+    LHS, lhs, typename std::remove_reference<RHS>::type
+  >(rhs);
+}
+
 } // namespace folly
 
 FOLLY_ASSUME_FBVECTOR_COMPATIBLE_3(std::basic_string);
@@ -410,6 +491,8 @@ FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(boost::shared_ptr);
  *   cout << "Does class Bar have a member double test(const string&, long)? "
  *     << boolalpha << has_test_traits<Bar, double(const string&, long)>::value;
  * }
+ *
+ * @author: Marcelo Juchem <marcelo@fb.com>
  */
 #define FOLLY_CREATE_HAS_MEMBER_FN_TRAITS(classname, func_name) \
   template <typename, typename> class classname; \