Commit 005a6c1f authored by Marcelo Juchem's avatar Marcelo Juchem Committed by Jordan DeLong

Fixing clang compatibility issues

Test Plan: all folly unit tests

Reviewed By: andrewjcg@fb.com

FB internal diff: D757374
parent 622fe822
......@@ -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);
}
......
......@@ -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];
......
......@@ -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; \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment