forked from OSchip/llvm-project
Handle '.' correctly in hex float literal parsing.
There were a couple of different loops that were not handling '.' correctly in APFloat::convertFromHexadecimalString; these mistakes could lead to assertion failures and incorrect rounding for overlong hex float literals. Fixes PR16643. llvm-svn: 186539
This commit is contained in:
parent
00cf53520b
commit
d2eb07acae
|
@ -319,8 +319,8 @@ trailingHexadecimalFraction(StringRef::iterator p, StringRef::iterator end,
|
|||
else if (digitValue < 8 && digitValue > 0)
|
||||
return lfLessThanHalf;
|
||||
|
||||
/* Otherwise we need to find the first non-zero digit. */
|
||||
while (*p == '0')
|
||||
// Otherwise we need to find the first non-zero digit.
|
||||
while (p != end && (*p == '0' || *p == '.'))
|
||||
p++;
|
||||
|
||||
assert(p != end && "Invalid trailing hexadecimal fraction!");
|
||||
|
@ -2300,56 +2300,46 @@ APFloat::opStatus
|
|||
APFloat::convertFromHexadecimalString(StringRef s, roundingMode rounding_mode)
|
||||
{
|
||||
lostFraction lost_fraction = lfExactlyZero;
|
||||
integerPart *significand;
|
||||
unsigned int bitPos, partsCount;
|
||||
StringRef::iterator dot, firstSignificantDigit;
|
||||
|
||||
zeroSignificand();
|
||||
exponent = 0;
|
||||
category = fcNormal;
|
||||
|
||||
significand = significandParts();
|
||||
partsCount = partCount();
|
||||
bitPos = partsCount * integerPartWidth;
|
||||
integerPart *significand = significandParts();
|
||||
unsigned partsCount = partCount();
|
||||
unsigned bitPos = partsCount * integerPartWidth;
|
||||
bool computedTrailingFraction = false;
|
||||
|
||||
/* Skip leading zeroes and any (hexa)decimal point. */
|
||||
// Skip leading zeroes and any (hexa)decimal point.
|
||||
StringRef::iterator begin = s.begin();
|
||||
StringRef::iterator end = s.end();
|
||||
StringRef::iterator dot;
|
||||
StringRef::iterator p = skipLeadingZeroesAndAnyDot(begin, end, &dot);
|
||||
firstSignificantDigit = p;
|
||||
StringRef::iterator firstSignificantDigit = p;
|
||||
|
||||
for (; p != end;) {
|
||||
while (p != end) {
|
||||
integerPart hex_value;
|
||||
|
||||
if (*p == '.') {
|
||||
assert(dot == end && "String contains multiple dots");
|
||||
dot = p++;
|
||||
if (p == end) {
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
hex_value = hexDigitValue(*p);
|
||||
if (hex_value == -1U) {
|
||||
if (hex_value == -1U)
|
||||
break;
|
||||
}
|
||||
|
||||
p++;
|
||||
|
||||
if (p == end) {
|
||||
break;
|
||||
} else {
|
||||
/* Store the number whilst 4-bit nibbles remain. */
|
||||
if (bitPos) {
|
||||
bitPos -= 4;
|
||||
hex_value <<= bitPos % integerPartWidth;
|
||||
significand[bitPos / integerPartWidth] |= hex_value;
|
||||
} else {
|
||||
lost_fraction = trailingHexadecimalFraction(p, end, hex_value);
|
||||
while (p != end && hexDigitValue(*p) != -1U)
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
// Store the number while we have space.
|
||||
if (bitPos) {
|
||||
bitPos -= 4;
|
||||
hex_value <<= bitPos % integerPartWidth;
|
||||
significand[bitPos / integerPartWidth] |= hex_value;
|
||||
} else if (!computedTrailingFraction) {
|
||||
lost_fraction = trailingHexadecimalFraction(p, end, hex_value);
|
||||
computedTrailingFraction = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -766,6 +766,8 @@ TEST(APFloatTest, fromDecimalString) {
|
|||
EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "-99e99999").isInfinity());
|
||||
EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "1e-99999").isPosZero());
|
||||
EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "-1e-99999").isNegZero());
|
||||
|
||||
EXPECT_EQ(2.71828, convertToDoubleFromString("2.71828"));
|
||||
}
|
||||
|
||||
TEST(APFloatTest, fromHexadecimalString) {
|
||||
|
@ -849,7 +851,10 @@ TEST(APFloatTest, fromHexadecimalString) {
|
|||
EXPECT_EQ(1.0625, APFloat(APFloat::IEEEdouble, "0x1.1p0").convertToDouble());
|
||||
EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble, "0x1p0").convertToDouble());
|
||||
|
||||
EXPECT_EQ(2.71828, convertToDoubleFromString("2.71828"));
|
||||
EXPECT_EQ(convertToDoubleFromString("0x1p-150"),
|
||||
convertToDoubleFromString("+0x800000000000000001.p-221"));
|
||||
EXPECT_EQ(2251799813685248.5,
|
||||
convertToDoubleFromString("0x80000000000004000000.010p-28"));
|
||||
}
|
||||
|
||||
TEST(APFloatTest, toString) {
|
||||
|
|
Loading…
Reference in New Issue