[APFloat] Add recoverable string parsing errors to APFloat

Implementing the APFloat part in PR4745.

Differential Revision: https://reviews.llvm.org/D69770
This commit is contained in:
Ehud Katz 2020-01-06 10:05:00 +02:00
parent a792953330
commit c5fb73c5d1
8 changed files with 301 additions and 241 deletions

View File

@ -1051,7 +1051,10 @@ NumericLiteralParser::GetFloatValue(llvm::APFloat &Result) {
Str = Buffer; Str = Buffer;
} }
return Result.convertFromString(Str, APFloat::rmNearestTiesToEven); auto StatusOrErr =
Result.convertFromString(Str, APFloat::rmNearestTiesToEven);
assert(StatusOrErr && "Invalid floating point representation");
return StatusOrErr ? *StatusOrErr : APFloat::opInvalidOp;
} }
static inline bool IsExponentPart(char c) { static inline bool IsExponentPart(char c) {

View File

@ -38,6 +38,7 @@ class StringRef;
class APFloat; class APFloat;
class raw_ostream; class raw_ostream;
template <typename T> class Expected;
template <typename T> class SmallVectorImpl; template <typename T> class SmallVectorImpl;
/// Enum that represents what fraction of the LSB truncated bits of an fp number /// Enum that represents what fraction of the LSB truncated bits of an fp number
@ -299,7 +300,7 @@ public:
bool, roundingMode); bool, roundingMode);
opStatus convertFromZeroExtendedInteger(const integerPart *, unsigned int, opStatus convertFromZeroExtendedInteger(const integerPart *, unsigned int,
bool, roundingMode); bool, roundingMode);
opStatus convertFromString(StringRef, roundingMode); Expected<opStatus> convertFromString(StringRef, roundingMode);
APInt bitcastToAPInt() const; APInt bitcastToAPInt() const;
double convertToDouble() const; double convertToDouble() const;
float convertToFloat() const; float convertToFloat() const;
@ -525,8 +526,8 @@ private:
bool *) const; bool *) const;
opStatus convertFromUnsignedParts(const integerPart *, unsigned int, opStatus convertFromUnsignedParts(const integerPart *, unsigned int,
roundingMode); roundingMode);
opStatus convertFromHexadecimalString(StringRef, roundingMode); Expected<opStatus> convertFromHexadecimalString(StringRef, roundingMode);
opStatus convertFromDecimalString(StringRef, roundingMode); Expected<opStatus> convertFromDecimalString(StringRef, roundingMode);
char *convertNormalToHexString(char *, unsigned int, bool, char *convertNormalToHexString(char *, unsigned int, bool,
roundingMode) const; roundingMode) const;
opStatus roundSignificandWithExponent(const integerPart *, unsigned int, int, opStatus roundSignificandWithExponent(const integerPart *, unsigned int, int,
@ -648,7 +649,7 @@ public:
cmpResult compare(const DoubleAPFloat &RHS) const; cmpResult compare(const DoubleAPFloat &RHS) const;
bool bitwiseIsEqual(const DoubleAPFloat &RHS) const; bool bitwiseIsEqual(const DoubleAPFloat &RHS) const;
APInt bitcastToAPInt() const; APInt bitcastToAPInt() const;
opStatus convertFromString(StringRef, roundingMode); Expected<opStatus> convertFromString(StringRef, roundingMode);
opStatus next(bool nextDown); opStatus next(bool nextDown);
opStatus convertToInteger(MutableArrayRef<integerPart> Input, opStatus convertToInteger(MutableArrayRef<integerPart> Input,
@ -1108,7 +1109,7 @@ public:
APFLOAT_DISPATCH_ON_SEMANTICS( APFLOAT_DISPATCH_ON_SEMANTICS(
convertFromZeroExtendedInteger(Input, InputSize, IsSigned, RM)); convertFromZeroExtendedInteger(Input, InputSize, IsSigned, RM));
} }
opStatus convertFromString(StringRef, roundingMode); Expected<opStatus> convertFromString(StringRef, roundingMode);
APInt bitcastToAPInt() const { APInt bitcastToAPInt() const {
APFLOAT_DISPATCH_ON_SEMANTICS(bitcastToAPInt()); APFLOAT_DISPATCH_ON_SEMANTICS(bitcastToAPInt());
} }

View File

@ -3130,8 +3130,7 @@ bool AsmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) {
Value = APFloat::getNaN(Semantics, false, ~0); Value = APFloat::getNaN(Semantics, false, ~0);
else else
return TokError("invalid floating point literal"); return TokError("invalid floating point literal");
} else if (Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven) == } else if (!Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven))
APFloat::opInvalidOp)
return TokError("invalid floating point literal"); return TokError("invalid floating point literal");
if (IsNeg) if (IsNeg)
Value.changeSign(); Value.changeSign();

View File

@ -20,7 +20,7 @@
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/Config/llvm-config.h" #include "llvm/Config/llvm-config.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Error.h"
#include "llvm/Support/MathExtras.h" #include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include <cstring> #include <cstring>
@ -208,6 +208,10 @@ namespace llvm {
/* A bunch of private, handy routines. */ /* A bunch of private, handy routines. */
static inline Error createError(const Twine &Err) {
return make_error<StringError>(Err, inconvertibleErrorCode());
}
static inline unsigned int static inline unsigned int
partCountForBits(unsigned int bits) partCountForBits(unsigned int bits)
{ {
@ -226,9 +230,8 @@ decDigitValue(unsigned int c)
If the exponent overflows, returns a large exponent with the If the exponent overflows, returns a large exponent with the
appropriate sign. */ appropriate sign. */
static int static Expected<int> readExponent(StringRef::iterator begin,
readExponent(StringRef::iterator begin, StringRef::iterator end) StringRef::iterator end) {
{
bool isNegative; bool isNegative;
unsigned int absExponent; unsigned int absExponent;
const unsigned int overlargeExponent = 24000; /* FIXME. */ const unsigned int overlargeExponent = 24000; /* FIXME. */
@ -242,29 +245,28 @@ readExponent(StringRef::iterator begin, StringRef::iterator end)
isNegative = (*p == '-'); isNegative = (*p == '-');
if (*p == '-' || *p == '+') { if (*p == '-' || *p == '+') {
p++; p++;
assert(p != end && "Exponent has no digits"); if (p == end)
return createError("Exponent has no digits");
} }
absExponent = decDigitValue(*p++); absExponent = decDigitValue(*p++);
assert(absExponent < 10U && "Invalid character in exponent"); if (absExponent >= 10U)
return createError("Invalid character in exponent");
for (; p != end; ++p) { for (; p != end; ++p) {
unsigned int value; unsigned int value;
value = decDigitValue(*p); value = decDigitValue(*p);
assert(value < 10U && "Invalid character in exponent"); if (value >= 10U)
return createError("Invalid character in exponent");
value += absExponent * 10; absExponent = absExponent * 10U + value;
if (absExponent >= overlargeExponent) { if (absExponent >= overlargeExponent) {
absExponent = overlargeExponent; absExponent = overlargeExponent;
p = end; /* outwit assert below */
break; break;
} }
absExponent = value;
} }
assert(p == end && "Invalid exponent in exponent");
if (isNegative) if (isNegative)
return -(int) absExponent; return -(int) absExponent;
else else
@ -273,20 +275,21 @@ readExponent(StringRef::iterator begin, StringRef::iterator end)
/* This is ugly and needs cleaning up, but I don't immediately see /* This is ugly and needs cleaning up, but I don't immediately see
how whilst remaining safe. */ how whilst remaining safe. */
static int static Expected<int> totalExponent(StringRef::iterator p,
totalExponent(StringRef::iterator p, StringRef::iterator end, StringRef::iterator end,
int exponentAdjustment) int exponentAdjustment) {
{
int unsignedExponent; int unsignedExponent;
bool negative, overflow; bool negative, overflow;
int exponent = 0; int exponent = 0;
assert(p != end && "Exponent has no digits"); if (p == end)
return createError("Exponent has no digits");
negative = *p == '-'; negative = *p == '-';
if (*p == '-' || *p == '+') { if (*p == '-' || *p == '+') {
p++; p++;
assert(p != end && "Exponent has no digits"); if (p == end)
return createError("Exponent has no digits");
} }
unsignedExponent = 0; unsignedExponent = 0;
@ -295,7 +298,8 @@ totalExponent(StringRef::iterator p, StringRef::iterator end,
unsigned int value; unsigned int value;
value = decDigitValue(*p); value = decDigitValue(*p);
assert(value < 10U && "Invalid character in exponent"); if (value >= 10U)
return createError("Invalid character in exponent");
unsignedExponent = unsignedExponent * 10 + value; unsignedExponent = unsignedExponent * 10 + value;
if (unsignedExponent > 32767) { if (unsignedExponent > 32767) {
@ -322,10 +326,9 @@ totalExponent(StringRef::iterator p, StringRef::iterator end,
return exponent; return exponent;
} }
static StringRef::iterator static Expected<StringRef::iterator>
skipLeadingZeroesAndAnyDot(StringRef::iterator begin, StringRef::iterator end, skipLeadingZeroesAndAnyDot(StringRef::iterator begin, StringRef::iterator end,
StringRef::iterator *dot) StringRef::iterator *dot) {
{
StringRef::iterator p = begin; StringRef::iterator p = begin;
*dot = end; *dot = end;
while (p != end && *p == '0') while (p != end && *p == '0')
@ -334,7 +337,8 @@ skipLeadingZeroesAndAnyDot(StringRef::iterator begin, StringRef::iterator end,
if (p != end && *p == '.') { if (p != end && *p == '.') {
*dot = p++; *dot = p++;
assert(end - begin != 1 && "Significand has no digits"); if (end - begin == 1)
return createError("Significand has no digits");
while (p != end && *p == '0') while (p != end && *p == '0')
p++; p++;
@ -363,12 +367,14 @@ struct decimalInfo {
int normalizedExponent; int normalizedExponent;
}; };
static void static Error interpretDecimal(StringRef::iterator begin,
interpretDecimal(StringRef::iterator begin, StringRef::iterator end, StringRef::iterator end, decimalInfo *D) {
decimalInfo *D)
{
StringRef::iterator dot = end; StringRef::iterator dot = end;
StringRef::iterator p = skipLeadingZeroesAndAnyDot (begin, end, &dot);
auto PtrOrErr = skipLeadingZeroesAndAnyDot(begin, end, &dot);
if (!PtrOrErr)
return PtrOrErr.takeError();
StringRef::iterator p = *PtrOrErr;
D->firstSigDigit = p; D->firstSigDigit = p;
D->exponent = 0; D->exponent = 0;
@ -376,7 +382,8 @@ interpretDecimal(StringRef::iterator begin, StringRef::iterator end,
for (; p != end; ++p) { for (; p != end; ++p) {
if (*p == '.') { if (*p == '.') {
assert(dot == end && "String contains multiple dots"); if (dot != end)
return createError("String contains multiple dots");
dot = p++; dot = p++;
if (p == end) if (p == end)
break; break;
@ -386,12 +393,18 @@ interpretDecimal(StringRef::iterator begin, StringRef::iterator end,
} }
if (p != end) { if (p != end) {
assert((*p == 'e' || *p == 'E') && "Invalid character in significand"); if (*p != 'e' && *p != 'E')
assert(p != begin && "Significand has no digits"); return createError("Invalid character in significand");
assert((dot == end || p - begin != 1) && "Significand has no digits"); if (p == begin)
return createError("Significand has no digits");
if (dot != end && p - begin == 1)
return createError("Significand has no digits");
/* p points to the first non-digit in the string */ /* p points to the first non-digit in the string */
D->exponent = readExponent(p + 1, end); auto ExpOrErr = readExponent(p + 1, end);
if (!ExpOrErr)
return ExpOrErr.takeError();
D->exponent = *ExpOrErr;
/* Implied decimal point? */ /* Implied decimal point? */
if (dot == end) if (dot == end)
@ -417,15 +430,15 @@ interpretDecimal(StringRef::iterator begin, StringRef::iterator end,
} }
D->lastSigDigit = p; D->lastSigDigit = p;
return Error::success();
} }
/* Return the trailing fraction of a hexadecimal number. /* Return the trailing fraction of a hexadecimal number.
DIGITVALUE is the first hex digit of the fraction, P points to DIGITVALUE is the first hex digit of the fraction, P points to
the next digit. */ the next digit. */
static lostFraction static Expected<lostFraction>
trailingHexadecimalFraction(StringRef::iterator p, StringRef::iterator end, trailingHexadecimalFraction(StringRef::iterator p, StringRef::iterator end,
unsigned int digitValue) unsigned int digitValue) {
{
unsigned int hexDigit; unsigned int hexDigit;
/* If the first trailing digit isn't 0 or 8 we can work out the /* If the first trailing digit isn't 0 or 8 we can work out the
@ -439,7 +452,8 @@ trailingHexadecimalFraction(StringRef::iterator p, StringRef::iterator end,
while (p != end && (*p == '0' || *p == '.')) while (p != end && (*p == '0' || *p == '.'))
p++; p++;
assert(p != end && "Invalid trailing hexadecimal fraction!"); if (p == end)
return createError("Invalid trailing hexadecimal fraction!");
hexDigit = hexDigitValue(*p); hexDigit = hexDigitValue(*p);
@ -2299,7 +2313,7 @@ IEEEFloat::convertFromZeroExtendedInteger(const integerPart *parts,
return convertFromUnsignedParts(api.getRawData(), partCount, rounding_mode); return convertFromUnsignedParts(api.getRawData(), partCount, rounding_mode);
} }
IEEEFloat::opStatus Expected<IEEEFloat::opStatus>
IEEEFloat::convertFromHexadecimalString(StringRef s, IEEEFloat::convertFromHexadecimalString(StringRef s,
roundingMode rounding_mode) { roundingMode rounding_mode) {
lostFraction lost_fraction = lfExactlyZero; lostFraction lost_fraction = lfExactlyZero;
@ -2317,14 +2331,18 @@ IEEEFloat::convertFromHexadecimalString(StringRef s,
StringRef::iterator begin = s.begin(); StringRef::iterator begin = s.begin();
StringRef::iterator end = s.end(); StringRef::iterator end = s.end();
StringRef::iterator dot; StringRef::iterator dot;
StringRef::iterator p = skipLeadingZeroesAndAnyDot(begin, end, &dot); auto PtrOrErr = skipLeadingZeroesAndAnyDot(begin, end, &dot);
if (!PtrOrErr)
return PtrOrErr.takeError();
StringRef::iterator p = *PtrOrErr;
StringRef::iterator firstSignificantDigit = p; StringRef::iterator firstSignificantDigit = p;
while (p != end) { while (p != end) {
integerPart hex_value; integerPart hex_value;
if (*p == '.') { if (*p == '.') {
assert(dot == end && "String contains multiple dots"); if (dot != end)
return createError("String contains multiple dots");
dot = p++; dot = p++;
continue; continue;
} }
@ -2341,16 +2359,23 @@ IEEEFloat::convertFromHexadecimalString(StringRef s,
hex_value <<= bitPos % integerPartWidth; hex_value <<= bitPos % integerPartWidth;
significand[bitPos / integerPartWidth] |= hex_value; significand[bitPos / integerPartWidth] |= hex_value;
} else if (!computedTrailingFraction) { } else if (!computedTrailingFraction) {
lost_fraction = trailingHexadecimalFraction(p, end, hex_value); auto FractOrErr = trailingHexadecimalFraction(p, end, hex_value);
if (!FractOrErr)
return FractOrErr.takeError();
lost_fraction = *FractOrErr;
computedTrailingFraction = true; computedTrailingFraction = true;
} }
} }
/* Hex floats require an exponent but not a hexadecimal point. */ /* Hex floats require an exponent but not a hexadecimal point. */
assert(p != end && "Hex strings require an exponent"); if (p == end)
assert((*p == 'p' || *p == 'P') && "Invalid character in significand"); return createError("Hex strings require an exponent");
assert(p != begin && "Significand has no digits"); if (*p != 'p' && *p != 'P')
assert((dot == end || p - begin != 1) && "Significand has no digits"); return createError("Invalid character in significand");
if (p == begin)
return createError("Significand has no digits");
if (dot != end && p - begin == 1)
return createError("Significand has no digits");
/* Ignore the exponent if we are zero. */ /* Ignore the exponent if we are zero. */
if (p != firstSignificantDigit) { if (p != firstSignificantDigit) {
@ -2373,7 +2398,10 @@ IEEEFloat::convertFromHexadecimalString(StringRef s,
expAdjustment -= partsCount * integerPartWidth; expAdjustment -= partsCount * integerPartWidth;
/* Adjust for the given exponent. */ /* Adjust for the given exponent. */
exponent = totalExponent(p + 1, end, expAdjustment); auto ExpOrErr = totalExponent(p + 1, end, expAdjustment);
if (!ExpOrErr)
return ExpOrErr.takeError();
exponent = *ExpOrErr;
} }
return normalize(rounding_mode, lost_fraction); return normalize(rounding_mode, lost_fraction);
@ -2464,14 +2492,15 @@ IEEEFloat::roundSignificandWithExponent(const integerPart *decSigParts,
} }
} }
IEEEFloat::opStatus Expected<IEEEFloat::opStatus>
IEEEFloat::convertFromDecimalString(StringRef str, roundingMode rounding_mode) { IEEEFloat::convertFromDecimalString(StringRef str, roundingMode rounding_mode) {
decimalInfo D; decimalInfo D;
opStatus fs; opStatus fs;
/* Scan the text. */ /* Scan the text. */
StringRef::iterator p = str.begin(); StringRef::iterator p = str.begin();
interpretDecimal(p, str.end(), &D); if (Error Err = interpretDecimal(p, str.end(), &D))
return std::move(Err);
/* Handle the quick cases. First the case of no significant digits, /* Handle the quick cases. First the case of no significant digits,
i.e. zero, and then exponents that are obviously too large or too i.e. zero, and then exponents that are obviously too large or too
@ -2554,7 +2583,10 @@ IEEEFloat::convertFromDecimalString(StringRef str, roundingMode rounding_mode) {
} }
} }
decValue = decDigitValue(*p++); decValue = decDigitValue(*p++);
assert(decValue < 10U && "Invalid character in significand"); if (decValue >= 10U) {
delete[] decSignificand;
return createError("Invalid character in significand");
}
multiplier *= 10; multiplier *= 10;
val = val * 10 + decValue; val = val * 10 + decValue;
/* The maximum number that can be multiplied by ten with any /* The maximum number that can be multiplied by ten with any
@ -2605,9 +2637,10 @@ bool IEEEFloat::convertFromStringSpecials(StringRef str) {
return false; return false;
} }
IEEEFloat::opStatus IEEEFloat::convertFromString(StringRef str, Expected<IEEEFloat::opStatus>
roundingMode rounding_mode) { IEEEFloat::convertFromString(StringRef str, roundingMode rounding_mode) {
assert(!str.empty() && "Invalid string length"); if (str.empty())
return createError("Invalid string length");
// Handle special cases. // Handle special cases.
if (convertFromStringSpecials(str)) if (convertFromStringSpecials(str))
@ -2620,11 +2653,13 @@ IEEEFloat::opStatus IEEEFloat::convertFromString(StringRef str,
if (*p == '-' || *p == '+') { if (*p == '-' || *p == '+') {
p++; p++;
slen--; slen--;
assert(slen && "String has no digits"); if (!slen)
return createError("String has no digits");
} }
if (slen >= 2 && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { if (slen >= 2 && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
assert(slen - 2 && "Invalid string"); if (slen == 2)
return createError("Invalid string");
return convertFromHexadecimalString(StringRef(p + 2, slen - 2), return convertFromHexadecimalString(StringRef(p + 2, slen - 2),
rounding_mode); rounding_mode);
} }
@ -4312,8 +4347,8 @@ APInt DoubleAPFloat::bitcastToAPInt() const {
return APInt(128, 2, Data); return APInt(128, 2, Data);
} }
APFloat::opStatus DoubleAPFloat::convertFromString(StringRef S, Expected<APFloat::opStatus> DoubleAPFloat::convertFromString(StringRef S,
roundingMode RM) { roundingMode RM) {
assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics"); assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
APFloat Tmp(semPPCDoubleDoubleLegacy); APFloat Tmp(semPPCDoubleDoubleLegacy);
auto Ret = Tmp.convertFromString(S, RM); auto Ret = Tmp.convertFromString(S, RM);
@ -4460,7 +4495,8 @@ APFloat::Storage::Storage(IEEEFloat F, const fltSemantics &Semantics) {
llvm_unreachable("Unexpected semantics"); llvm_unreachable("Unexpected semantics");
} }
APFloat::opStatus APFloat::convertFromString(StringRef Str, roundingMode RM) { Expected<APFloat::opStatus> APFloat::convertFromString(StringRef Str,
roundingMode RM) {
APFLOAT_DISPATCH_ON_SEMANTICS(convertFromString(Str, RM)); APFLOAT_DISPATCH_ON_SEMANTICS(convertFromString(Str, RM));
} }
@ -4474,7 +4510,8 @@ hash_code hash_value(const APFloat &Arg) {
APFloat::APFloat(const fltSemantics &Semantics, StringRef S) APFloat::APFloat(const fltSemantics &Semantics, StringRef S)
: APFloat(Semantics) { : APFloat(Semantics) {
convertFromString(S, rmNearestTiesToEven); auto StatusOrErr = convertFromString(S, rmNearestTiesToEven);
assert(StatusOrErr && "Invalid floating point representation");
} }
APFloat::opStatus APFloat::convert(const fltSemantics &ToSemantics, APFloat::opStatus APFloat::convert(const fltSemantics &ToSemantics,

View File

@ -12,6 +12,7 @@
#include "llvm/ADT/Hashing.h" #include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/edit_distance.h" #include "llvm/ADT/edit_distance.h"
#include "llvm/Support/Error.h"
#include <bitset> #include <bitset>
using namespace llvm; using namespace llvm;
@ -587,8 +588,13 @@ bool StringRef::getAsInteger(unsigned Radix, APInt &Result) const {
bool StringRef::getAsDouble(double &Result, bool AllowInexact) const { bool StringRef::getAsDouble(double &Result, bool AllowInexact) const {
APFloat F(0.0); APFloat F(0.0);
APFloat::opStatus Status = auto ErrOrStatus = F.convertFromString(*this, APFloat::rmNearestTiesToEven);
F.convertFromString(*this, APFloat::rmNearestTiesToEven); if (!ErrOrStatus) {
assert("Invalid floating point representation");
return true;
}
APFloat::opStatus Status = *ErrOrStatus;
if (Status != APFloat::opOK) { if (Status != APFloat::opOK) {
if (!AllowInexact || !(Status & APFloat::opInexact)) if (!AllowInexact || !(Status & APFloat::opInexact))
return true; return true;

View File

@ -1221,8 +1221,9 @@ public:
// Calculate its FP value. // Calculate its FP value.
APFloat RealVal(APFloat::IEEEdouble()); APFloat RealVal(APFloat::IEEEdouble());
if (RealVal.convertFromString(Desc->Repr, APFloat::rmTowardZero) != auto StatusOrErr =
APFloat::opOK) RealVal.convertFromString(Desc->Repr, APFloat::rmTowardZero);
if (!StatusOrErr || *StatusOrErr != APFloat::opOK)
llvm_unreachable("FP immediate is not exact"); llvm_unreachable("FP immediate is not exact");
if (getFPImm().bitwiseIsEqual(RealVal)) if (getFPImm().bitwiseIsEqual(RealVal))
@ -2577,8 +2578,13 @@ AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
} else { } else {
// Parse FP representation. // Parse FP representation.
APFloat RealVal(APFloat::IEEEdouble()); APFloat RealVal(APFloat::IEEEdouble());
auto Status = auto StatusOrErr =
RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero); RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
if (!StatusOrErr) {
TokError("invalid floating point representation");
return MatchOperand_ParseFail;
}
if (isNegative) if (isNegative)
RealVal.changeSign(); RealVal.changeSign();
@ -2589,7 +2595,7 @@ AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
AArch64Operand::CreateToken(".0", false, S, getContext())); AArch64Operand::CreateToken(".0", false, S, getContext()));
} else } else
Operands.push_back(AArch64Operand::CreateFPImm( Operands.push_back(AArch64Operand::CreateFPImm(
RealVal, Status == APFloat::opOK, S, getContext())); RealVal, *StatusOrErr == APFloat::opOK, S, getContext()));
} }
Parser.Lex(); // Eat the token. Parser.Lex(); // Eat the token.

View File

@ -45,7 +45,7 @@
#include "llvm/Support/AMDHSAKernelDescriptor.h" #include "llvm/Support/AMDHSAKernelDescriptor.h"
#include "llvm/Support/Casting.h" #include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h" #include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Error.h"
#include "llvm/Support/MachineValueType.h" #include "llvm/Support/MachineValueType.h"
#include "llvm/Support/MathExtras.h" #include "llvm/Support/MathExtras.h"
#include "llvm/Support/SMLoc.h" #include "llvm/Support/SMLoc.h"
@ -2363,7 +2363,7 @@ AMDGPUAsmParser::parseImm(OperandVector &Operands, bool HasSP3AbsModifier) {
APFloat RealVal(APFloat::IEEEdouble()); APFloat RealVal(APFloat::IEEEdouble());
auto roundMode = APFloat::rmNearestTiesToEven; auto roundMode = APFloat::rmNearestTiesToEven;
if (RealVal.convertFromString(Num, roundMode) == APFloat::opInvalidOp) { if (!RealVal.convertFromString(Num, roundMode)) {
return MatchOperand_ParseFail; return MatchOperand_ParseFail;
} }
if (Negate) if (Negate)

View File

@ -10,8 +10,8 @@
#include "llvm/ADT/APSInt.h" #include "llvm/ADT/APSInt.h"
#include "llvm/ADT/Hashing.h" #include "llvm/ADT/Hashing.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/raw_ostream.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include <cmath> #include <cmath>
#include <ostream> #include <ostream>
@ -20,9 +20,17 @@
using namespace llvm; using namespace llvm;
static double convertToDoubleFromString(const char *Str) { static std::string convertToErrorFromString(StringRef Str) {
llvm::APFloat F(0.0); llvm::APFloat F(0.0);
F.convertFromString(Str, llvm::APFloat::rmNearestTiesToEven); auto ErrOrStatus =
F.convertFromString(Str, llvm::APFloat::rmNearestTiesToEven);
EXPECT_TRUE(!ErrOrStatus);
return toString(ErrOrStatus.takeError());
}
static double convertToDoubleFromString(StringRef Str) {
llvm::APFloat F(0.0);
EXPECT_FALSE(!F.convertFromString(Str, llvm::APFloat::rmNearestTiesToEven));
return F.convertToDouble(); return F.convertToDouble();
} }
@ -1156,173 +1164,173 @@ TEST(APFloatTest, SemanticsDeath) {
EXPECT_DEATH(APFloat(APFloat::IEEEsingle(), 0).convertToDouble(), "Float semantics are not IEEEdouble"); EXPECT_DEATH(APFloat(APFloat::IEEEsingle(), 0).convertToDouble(), "Float semantics are not IEEEdouble");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), 0).convertToFloat(), "Float semantics are not IEEEsingle"); EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), 0).convertToFloat(), "Float semantics are not IEEEsingle");
} }
TEST(APFloatTest, StringDecimalDeath) {
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), ""), "Invalid string length");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+"), "String has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-"), "String has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("\0", 1)), "Invalid character in significand");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("1\0", 2)), "Invalid character in significand");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("1" "\0" "2", 3)), "Invalid character in significand");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("1" "\0" "2e1", 5)), "Invalid character in significand");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("1e\0", 3)), "Invalid character in exponent");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("1e1\0", 4)), "Invalid character in exponent");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("1e1" "\0" "2", 5)), "Invalid character in exponent");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "1.0f"), "Invalid character in significand");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), ".."), "String contains multiple dots");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "..0"), "String contains multiple dots");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "1.0.0"), "String contains multiple dots");
}
TEST(APFloatTest, StringDecimalSignificandDeath) {
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "."), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+."), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-."), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "e"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+e"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-e"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "e1"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+e1"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-e1"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), ".e1"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+.e1"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-.e1"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), ".e"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+.e"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-.e"), "Significand has no digits");
}
TEST(APFloatTest, StringHexadecimalDeath) {
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x"), "Invalid string");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x"), "Invalid string");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x"), "Invalid string");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x0"), "Hex strings require an exponent");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x0"), "Hex strings require an exponent");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x0"), "Hex strings require an exponent");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x0."), "Hex strings require an exponent");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x0."), "Hex strings require an exponent");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x0."), "Hex strings require an exponent");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x.0"), "Hex strings require an exponent");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x.0"), "Hex strings require an exponent");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x.0"), "Hex strings require an exponent");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x0.0"), "Hex strings require an exponent");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x0.0"), "Hex strings require an exponent");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x0.0"), "Hex strings require an exponent");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("0x\0", 3)), "Invalid character in significand");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("0x1\0", 4)), "Invalid character in significand");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("0x1" "\0" "2", 5)), "Invalid character in significand");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("0x1" "\0" "2p1", 7)), "Invalid character in significand");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("0x1p\0", 5)), "Invalid character in exponent");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("0x1p1\0", 6)), "Invalid character in exponent");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("0x1p1" "\0" "2", 7)), "Invalid character in exponent");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x1p0f"), "Invalid character in exponent");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x..p1"), "String contains multiple dots");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x..0p1"), "String contains multiple dots");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x1.0.0p1"), "String contains multiple dots");
}
TEST(APFloatTest, StringHexadecimalSignificandDeath) {
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x."), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x."), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x."), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0xp"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0xp"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0xp"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0xp+"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0xp+"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0xp+"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0xp-"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0xp-"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0xp-"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x.p"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x.p"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x.p"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x.p+"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x.p+"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x.p+"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x.p-"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x.p-"), "Significand has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x.p-"), "Significand has no digits");
}
TEST(APFloatTest, StringHexadecimalExponentDeath) {
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x1p"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x1p"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x1p"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x1p+"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x1p+"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x1p+"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x1p-"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x1p-"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x1p-"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x1.p"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x1.p"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x1.p"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x1.p+"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x1.p+"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x1.p+"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x1.p-"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x1.p-"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x1.p-"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x.1p"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x.1p"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x.1p"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x.1p+"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x.1p+"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x.1p+"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x.1p-"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x.1p-"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x.1p-"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x1.1p"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x1.1p"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x1.1p"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x1.1p+"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x1.1p+"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x1.1p+"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x1.1p-"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x1.1p-"), "Exponent has no digits");
EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x1.1p-"), "Exponent has no digits");
}
#endif #endif
#endif #endif
TEST(APFloatTest, StringDecimalError) {
EXPECT_EQ("Invalid string length", convertToErrorFromString(""));
EXPECT_EQ("String has no digits", convertToErrorFromString("+"));
EXPECT_EQ("String has no digits", convertToErrorFromString("-"));
EXPECT_EQ("Invalid character in significand", convertToErrorFromString(StringRef("\0", 1)));
EXPECT_EQ("Invalid character in significand", convertToErrorFromString(StringRef("1\0", 2)));
EXPECT_EQ("Invalid character in significand", convertToErrorFromString(StringRef("1" "\0" "2", 3)));
EXPECT_EQ("Invalid character in significand", convertToErrorFromString(StringRef("1" "\0" "2e1", 5)));
EXPECT_EQ("Invalid character in exponent", convertToErrorFromString(StringRef("1e\0", 3)));
EXPECT_EQ("Invalid character in exponent", convertToErrorFromString(StringRef("1e1\0", 4)));
EXPECT_EQ("Invalid character in exponent", convertToErrorFromString(StringRef("1e1" "\0" "2", 5)));
EXPECT_EQ("Invalid character in significand", convertToErrorFromString("1.0f"));
EXPECT_EQ("String contains multiple dots", convertToErrorFromString(".."));
EXPECT_EQ("String contains multiple dots", convertToErrorFromString("..0"));
EXPECT_EQ("String contains multiple dots", convertToErrorFromString("1.0.0"));
}
TEST(APFloatTest, StringDecimalSignificandError) {
EXPECT_EQ("Significand has no digits", convertToErrorFromString( "."));
EXPECT_EQ("Significand has no digits", convertToErrorFromString("+."));
EXPECT_EQ("Significand has no digits", convertToErrorFromString("-."));
EXPECT_EQ("Significand has no digits", convertToErrorFromString( "e"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString("+e"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString("-e"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString( "e1"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString("+e1"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString("-e1"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString( ".e1"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString("+.e1"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString("-.e1"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString( ".e"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString("+.e"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString("-.e"));
}
TEST(APFloatTest, StringHexadecimalError) {
EXPECT_EQ("Invalid string", convertToErrorFromString( "0x"));
EXPECT_EQ("Invalid string", convertToErrorFromString("+0x"));
EXPECT_EQ("Invalid string", convertToErrorFromString("-0x"));
EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString( "0x0"));
EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString("+0x0"));
EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString("-0x0"));
EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString( "0x0."));
EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString("+0x0."));
EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString("-0x0."));
EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString( "0x.0"));
EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString("+0x.0"));
EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString("-0x.0"));
EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString( "0x0.0"));
EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString("+0x0.0"));
EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString("-0x0.0"));
EXPECT_EQ("Invalid character in significand", convertToErrorFromString(StringRef("0x\0", 3)));
EXPECT_EQ("Invalid character in significand", convertToErrorFromString(StringRef("0x1\0", 4)));
EXPECT_EQ("Invalid character in significand", convertToErrorFromString(StringRef("0x1" "\0" "2", 5)));
EXPECT_EQ("Invalid character in significand", convertToErrorFromString(StringRef("0x1" "\0" "2p1", 7)));
EXPECT_EQ("Invalid character in exponent", convertToErrorFromString(StringRef("0x1p\0", 5)));
EXPECT_EQ("Invalid character in exponent", convertToErrorFromString(StringRef("0x1p1\0", 6)));
EXPECT_EQ("Invalid character in exponent", convertToErrorFromString(StringRef("0x1p1" "\0" "2", 7)));
EXPECT_EQ("Invalid character in exponent", convertToErrorFromString("0x1p0f"));
EXPECT_EQ("String contains multiple dots", convertToErrorFromString("0x..p1"));
EXPECT_EQ("String contains multiple dots", convertToErrorFromString("0x..0p1"));
EXPECT_EQ("String contains multiple dots", convertToErrorFromString("0x1.0.0p1"));
}
TEST(APFloatTest, StringHexadecimalSignificandError) {
EXPECT_EQ("Significand has no digits", convertToErrorFromString( "0x."));
EXPECT_EQ("Significand has no digits", convertToErrorFromString("+0x."));
EXPECT_EQ("Significand has no digits", convertToErrorFromString("-0x."));
EXPECT_EQ("Significand has no digits", convertToErrorFromString( "0xp"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString("+0xp"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString("-0xp"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString( "0xp+"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString("+0xp+"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString("-0xp+"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString( "0xp-"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString("+0xp-"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString("-0xp-"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString( "0x.p"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString("+0x.p"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString("-0x.p"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString( "0x.p+"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString("+0x.p+"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString("-0x.p+"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString( "0x.p-"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString("+0x.p-"));
EXPECT_EQ("Significand has no digits", convertToErrorFromString("-0x.p-"));
}
TEST(APFloatTest, StringHexadecimalExponentError) {
EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x1p"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x1p"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x1p"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x1p+"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x1p+"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x1p+"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x1p-"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x1p-"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x1p-"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x1.p"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x1.p"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x1.p"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x1.p+"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x1.p+"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x1.p+"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x1.p-"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x1.p-"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x1.p-"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x.1p"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x.1p"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x.1p"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x.1p+"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x.1p+"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x.1p+"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x.1p-"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x.1p-"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x.1p-"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x1.1p"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x1.1p"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x1.1p"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x1.1p+"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x1.1p+"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x1.1p+"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x1.1p-"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x1.1p-"));
EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x1.1p-"));
}
TEST(APFloatTest, exactInverse) { TEST(APFloatTest, exactInverse) {
APFloat inv(0.0f); APFloat inv(0.0f);