From 643edab2b0ae598f4790b997e8eec5721bd00155 Mon Sep 17 00:00:00 2001 From: Serguei Katkov Date: Tue, 19 Dec 2017 04:27:39 +0000 Subject: [PATCH] Fix APFloat from string conversion for Inf The method IEEEFloat::convertFromStringSpecials() does not recognize the "+Inf" and "-Inf" strings but these strings are printed for the double Infinities by the IEEEFloat::toString(). This patch adds the "+Inf" and "-Inf" strings to the list of recognized patterns in IEEEFloat::convertFromStringSpecials(). Re-landing after fix. Reviewers: sberg, bogner, majnemer, timshen, rnk, skatkov, gottesmm, bkramer, scanon, anna Reviewed By: anna Subscribers: mkazantsev, FlameTop, llvm-commits, reames, apilipenko Differential Revision: https://reviews.llvm.org/D38030 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@321054 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Support/APFloat.cpp | 4 ++-- lib/Support/StringRef.cpp | 2 +- unittests/ADT/APFloatTest.cpp | 17 +++++++++++++++++ unittests/ADT/StringRefTest.cpp | 7 ++++++- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp index f7fb0cef16b..3489feb93a0 100644 --- a/lib/Support/APFloat.cpp +++ b/lib/Support/APFloat.cpp @@ -2546,12 +2546,12 @@ IEEEFloat::convertFromDecimalString(StringRef str, roundingMode rounding_mode) { } bool IEEEFloat::convertFromStringSpecials(StringRef str) { - if (str.equals("inf") || str.equals("INFINITY")) { + if (str.equals("inf") || str.equals("INFINITY") || str.equals("+Inf")) { makeInf(false); return true; } - if (str.equals("-inf") || str.equals("-INFINITY")) { + if (str.equals("-inf") || str.equals("-INFINITY") || str.equals("-Inf")) { makeInf(true); return true; } diff --git a/lib/Support/StringRef.cpp b/lib/Support/StringRef.cpp index 90992fce0bc..9ba7a09f996 100644 --- a/lib/Support/StringRef.cpp +++ b/lib/Support/StringRef.cpp @@ -586,7 +586,7 @@ bool StringRef::getAsDouble(double &Result, bool AllowInexact) const { APFloat::opStatus Status = F.convertFromString(*this, APFloat::rmNearestTiesToEven); if (Status != APFloat::opOK) { - if (!AllowInexact || Status != APFloat::opInexact) + if (!AllowInexact || !(Status & APFloat::opInexact)) return true; } diff --git a/unittests/ADT/APFloatTest.cpp b/unittests/ADT/APFloatTest.cpp index 84fb6fad156..8b88c123b19 100644 --- a/unittests/ADT/APFloatTest.cpp +++ b/unittests/ADT/APFloatTest.cpp @@ -849,6 +849,23 @@ TEST(APFloatTest, fromDecimalString) { EXPECT_EQ(2.71828, convertToDoubleFromString("2.71828")); } +TEST(APFloatTest, fromToStringSpecials) { + auto expects = [] (const char *first, const char *second) { + std::string roundtrip = convertToString(convertToDoubleFromString(second), 0, 3); + EXPECT_STREQ(first, roundtrip.c_str()); + }; + expects("+Inf", "+Inf"); + expects("+Inf", "INFINITY"); + expects("+Inf", "inf"); + expects("-Inf", "-Inf"); + expects("-Inf", "-INFINITY"); + expects("-Inf", "-inf"); + expects("NaN", "NaN"); + expects("NaN", "nan"); + expects("NaN", "-NaN"); + expects("NaN", "-nan"); +} + TEST(APFloatTest, fromHexadecimalString) { EXPECT_EQ( 1.0, APFloat(APFloat::IEEEdouble(), "0x1p0").convertToDouble()); EXPECT_EQ(+1.0, APFloat(APFloat::IEEEdouble(), "+0x1p0").convertToDouble()); diff --git a/unittests/ADT/StringRefTest.cpp b/unittests/ADT/StringRefTest.cpp index 0684afe678f..0e0b5957f02 100644 --- a/unittests/ADT/StringRefTest.cpp +++ b/unittests/ADT/StringRefTest.cpp @@ -875,7 +875,12 @@ struct GetDoubleStrings { {"0.0", false, false, 0.0}, {"-0.0", false, false, -0.0}, {"123.45", false, true, 123.45}, - {"123.45", true, false, 123.45}}; + {"123.45", true, false, 123.45}, + {"1.8e308", true, false, std::numeric_limits::infinity()}, + {"1.8e308", false, true, std::numeric_limits::infinity()}, + {"0x0.0000000000001P-1023", false, true, 0.0}, + {"0x0.0000000000001P-1023", true, false, 0.0}, + }; TEST(StringRefTest, getAsDouble) { for (const auto &Entry : DoubleStrings) { -- 2.50.1