Remove isinf workaround

This commit is contained in:
Victor Zverovich 2019-03-17 14:49:19 -07:00
parent 17c6900f83
commit 294fd7df96
3 changed files with 9 additions and 41 deletions

View File

@ -286,17 +286,6 @@ template <typename Result> struct function {
template <typename T> struct result { typedef Result type; };
};
struct dummy_int {
int data[2];
operator int() const { return 0; }
};
typedef std::numeric_limits<internal::dummy_int> fputil;
// Dummy implementations of system functions called if the latter are not
// available.
inline dummy_int isinf(...) { return dummy_int(); }
inline dummy_int _finite(...) { return dummy_int(); }
template <typename Allocator>
typename Allocator::value_type* allocate(Allocator& alloc, std::size_t n) {
#if __cplusplus >= 201103L || FMT_MSC_VER >= 1700
@ -305,34 +294,9 @@ typename Allocator::value_type* allocate(Allocator& alloc, std::size_t n) {
return alloc.allocate(n);
#endif
}
// A helper function to suppress bogus "conditional expression is constant"
// warnings.
template <typename T> inline T const_check(T value) { return value; }
} // namespace internal
FMT_END_NAMESPACE
namespace std {
// Standard permits specialization of std::numeric_limits. This specialization
// is used to resolve ambiguity between isinf and std::isinf in glibc:
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=48891
// and the same for isnan.
template <>
class numeric_limits<fmt::internal::dummy_int>
: public std::numeric_limits<int> {
public:
// Portable version of isinf.
template <typename T> static bool isinfinity(T x) {
using namespace fmt::internal;
// The resolution "priority" is:
// isinf macro > std::isinf > ::isinf > fmt::internal::isinf
if (const_check(sizeof(isinf(x)) != sizeof(fmt::internal::dummy_int)))
return isinf(x) != 0;
return !_finite(static_cast<double>(x));
}
};
} // namespace std
FMT_BEGIN_NAMESPACE
template <typename Range> class basic_writer;
@ -2841,9 +2805,8 @@ void basic_writer<Range>::write_double(T value, const format_specs& spec) {
if (!std::isfinite(value)) {
// Format infinity and NaN ourselves because sprintf's output is not
// consistent across platforms.
const char* str = internal::fputil::isinfinity(value)
? (handler.upper ? "INF" : "inf")
: (handler.upper ? "NAN" : "nan");
const char* str = std::isinf(value) ? (handler.upper ? "INF" : "inf")
: (handler.upper ? "NAN" : "nan");
return write_padded(spec,
inf_or_nan_writer{sign, handler.as_percentage, str});
}

View File

@ -16,6 +16,10 @@
FMT_BEGIN_NAMESPACE
namespace internal {
// A helper function to suppress bogus "conditional expression is constant"
// warnings.
template <typename T> inline T const_check(T value) { return value; }
// Checks if a value fits in int - used to avoid warnings about comparing
// signed and unsigned integers.
template <bool IsSigned> struct int_checker {

View File

@ -1107,6 +1107,7 @@ TEST(FormatterTest, Width) {
EXPECT_EQ("x ", format("{0:11}", 'x'));
EXPECT_EQ("str ", format("{0:12}", "str"));
}
template <typename T> inline T const_check(T value) { return value; }
TEST(FormatterTest, RuntimeWidth) {
char format_str[BUFFER_SIZE];
@ -1135,7 +1136,7 @@ TEST(FormatterTest, RuntimeWidth) {
EXPECT_THROW_MSG(format("{0:{1}}", 0, (INT_MAX + 1u)), format_error,
"number is too big");
EXPECT_THROW_MSG(format("{0:{1}}", 0, -1l), format_error, "negative width");
if (fmt::internal::const_check(sizeof(long) > sizeof(int))) {
if (const_check(sizeof(long) > sizeof(int))) {
long value = INT_MAX;
EXPECT_THROW_MSG(format("{0:{1}}", 0, (value + 1)), format_error,
"number is too big");
@ -1257,7 +1258,7 @@ TEST(FormatterTest, RuntimePrecision) {
"number is too big");
EXPECT_THROW_MSG(format("{0:.{1}}", 0, -1l), format_error,
"negative precision");
if (fmt::internal::const_check(sizeof(long) > sizeof(int))) {
if (const_check(sizeof(long) > sizeof(int))) {
long value = INT_MAX;
EXPECT_THROW_MSG(format("{0:.{1}}", 0, (value + 1)), format_error,
"number is too big");