Index: llvm/lib/Support/APFloat.cpp =================================================================== --- llvm/lib/Support/APFloat.cpp +++ llvm/lib/Support/APFloat.cpp @@ -2660,27 +2660,96 @@ } bool IEEEFloat::convertFromStringSpecials(StringRef str) { - if (str.equals("inf") || str.equals("INFINITY") || str.equals("+Inf")) { - makeInf(false); - return true; - } + if (str.size() < 3) + return false; - if (str.equals("-inf") || str.equals("-INFINITY") || str.equals("-Inf")) { - makeInf(true); - return true; - } + bool SNaN = false; + char NDiff = 'N' - 'Q'; + char C = str[0]; + str = str.drop_front(); + switch (C) { + case 'I': + // Check for one of: INF, INFINITY. + if (str.startswith("NF")) { + str = str.drop_front(2); + if (!str.empty() && !str.equals("INITY")) + return false; + + makeInf(isNegative()); + return true; + } + LLVM_FALLTHROUGH; + case 'i': + // Check for one of: inf, Inf, infinity, Infinity. + if (!str.startswith("nf")) + return false; - if (str.equals("nan") || str.equals("NaN")) { - makeNaN(false, false); - return true; - } + str = str.drop_front(2); + if (!str.empty() && !str.equals("inity")) + return false; - if (str.equals("-nan") || str.equals("-NaN")) { - makeNaN(false, true); + makeInf(isNegative()); return true; - } - return false; + case 'S': + case 's': + SNaN = true; + NDiff = 'N' - 'S'; + LLVM_FALLTHROUGH; + case 'Q': + case 'q': + if (str.size() < 3) + return false; + + // If the next character is not 'n' or 'N' (if the last character was 'S' or + // 'Q'). + if (str[0] != 'n' && str[0] != (C + NDiff)) + return false; + + C = str[0]; + str = str.drop_front(); + LLVM_FALLTHROUGH; + case 'N': + case 'n': + // Check for one of: nan, NaN, NAN. + if ((str[0] == 'a' || str[0] == (C - ('N' - 'A'))) && str[1] == C) { + str = str.drop_front(2); + if (str.empty()) { + makeNaN(SNaN, isNegative()); + return true; + } + + // Allow the payload to be inside parentheses. + if (str[0] == '(') { + if (!(str.size() > 2 && str.back() == ')')) + return false; + + str = str.substr(1, str.size() - 2); + } + + // Determine the payload number's radix. + unsigned Radix; + if (str[0] == '0') { + if (str.size() > 2 && (str[1] == 'x' || str[1] == 'X')) { + str = str.drop_front(2); + Radix = 16; + } else + Radix = 8; + } else + Radix = 10; + + // Parse the payload and make the NaN.. + APInt Payload; + if (!str.getAsInteger(Radix, Payload)) { + makeNaN(SNaN, isNegative(), &Payload); + return true; + } + } + LLVM_FALLTHROUGH; + + default: + return false; + } } Expected @@ -2688,29 +2757,28 @@ if (str.empty()) return createError("Invalid string length"); + // Handle a leading plus/minus sign. + bool Negative = str[0] == '-'; + if (Negative || str[0] == '+') { + str = str.drop_front(); + if (str.empty()) + return createError("String has no digits"); + } + + sign = Negative; + // Handle special cases. if (convertFromStringSpecials(str)) return opOK; - /* Handle a leading minus sign. */ - StringRef::iterator p = str.begin(); - size_t slen = str.size(); - sign = *p == '-' ? 1 : 0; - if (*p == '-' || *p == '+') { - p++; - slen--; - if (!slen) - return createError("String has no digits"); - } - - if (slen >= 2 && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { - if (slen == 2) + if (str.size() >= 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) { + str = str.drop_front(2); + if (str.empty()) return createError("Invalid string"); - return convertFromHexadecimalString(StringRef(p + 2, slen - 2), - rounding_mode); + return convertFromHexadecimalString(str, rounding_mode); } - return convertFromDecimalString(StringRef(p, slen), rounding_mode); + return convertFromDecimalString(str, rounding_mode); } /* Write out a hexadecimal representation of the floating point value