aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Support
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2013-07-17 22:17:29 +0000
committerEli Friedman <eli.friedman@gmail.com>2013-07-17 22:17:29 +0000
commit763c066dca324ac4b86e7f014fe580ae5ba29fa0 (patch)
tree53d2b5421b3b00b505ab2d2f4942823bbed72fa4 /lib/Support
parenta71443a002568e5b2ba8c494f291816b56a0ac08 (diff)
downloadexternal_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.cpp50
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;
}
}