From 768d6dd08783440606da83dac490889329619898 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 llvm-svn: 321054 --- llvm/lib/Support/APFloat.cpp | 4 ++-- llvm/lib/Support/StringRef.cpp | 2 +- llvm/unittests/ADT/APFloatTest.cpp | 17 +++++++++++++++++ llvm/unittests/ADT/StringRefTest.cpp | 7 ++++++- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp index f7fb0cef16bf..3489feb93a02 100644 --- a/llvm/lib/Support/APFloat.cpp +++ b/llvm/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/llvm/lib/Support/StringRef.cpp b/llvm/lib/Support/StringRef.cpp index 90992fce0bcc..9ba7a09f9962 100644 --- a/llvm/lib/Support/StringRef.cpp +++ b/llvm/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/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp index 84fb6fad1566..8b88c123b197 100644 --- a/llvm/unittests/ADT/APFloatTest.cpp +++ b/llvm/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/llvm/unittests/ADT/StringRefTest.cpp b/llvm/unittests/ADT/StringRefTest.cpp index 0684afe678f6..0e0b5957f025 100644 --- a/llvm/unittests/ADT/StringRefTest.cpp +++ b/llvm/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) {