diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2013-07-17 22:17:29 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2013-07-17 22:17:29 +0000 |
commit | 763c066dca324ac4b86e7f014fe580ae5ba29fa0 (patch) | |
tree | 53d2b5421b3b00b505ab2d2f4942823bbed72fa4 /lib/Support | |
parent | a71443a002568e5b2ba8c494f291816b56a0ac08 (diff) | |
download | external_llvm-763c066dca324ac4b86e7f014fe580ae5ba29fa0.zip external_llvm-763c066dca324ac4b86e7f014fe580ae5ba29fa0.tar.gz external_llvm-763c066dca324ac4b86e7f014fe580ae5ba29fa0.tar.bz2 |
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.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@186539 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Support')
-rw-r--r-- | lib/Support/APFloat.cpp | 50 |
1 files changed, 20 insertions, 30 deletions
diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp index 58f1623..ce57442 100644 --- a/lib/Support/APFloat.cpp +++ b/lib/Support/APFloat.cpp @@ -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; } } |