From: Eli Friedman Date: Thu, 28 Mar 2019 21:12:28 +0000 (+0000) Subject: [MC] Fix floating-point literal lexing. X-Git-Tag: llvmorg-10-init~8942 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3dd72ea810dbb0c45c5815d2f43cc2b393d274a1;p=platform%2Fupstream%2Fllvm.git [MC] Fix floating-point literal lexing. This patch has three related fixes to improve float literal lexing: 1. Make AsmLexer::LexDigit handle floats without a decimal point more consistently. 2. Make AsmLexer::LexFloatLiteral print an error for floats which are apparently missing an "e". 3. Make APFloat::convertFromString use binutils-compatible exponent parsing. Together, this fixes some cases where a float would be incorrectly rejected, fixes some cases where the compiler would crash, and improves diagnostics in some cases. Patch by Brandon Jones. Differential Revision: https://reviews.llvm.org/D57321 llvm-svn: 357214 --- diff --git a/llvm/lib/MC/MCParser/AsmLexer.cpp b/llvm/lib/MC/MCParser/AsmLexer.cpp index d21bc64..9155ae0 100644 --- a/llvm/lib/MC/MCParser/AsmLexer.cpp +++ b/llvm/lib/MC/MCParser/AsmLexer.cpp @@ -61,8 +61,6 @@ int AsmLexer::getNextChar() { return (unsigned char)*CurPtr++; } -/// LexFloatLiteral: [0-9]*[.][0-9]*([eE][+-]?[0-9]*)? -/// /// The leading integral digit sequence and dot should have already been /// consumed, some or all of the fractional digit sequence *can* have been /// consumed. @@ -71,13 +69,16 @@ AsmToken AsmLexer::LexFloatLiteral() { while (isDigit(*CurPtr)) ++CurPtr; - // Check for exponent; we intentionally accept a slighlty wider set of - // literals here and rely on the upstream client to reject invalid ones (e.g., - // "1e+"). - if (*CurPtr == 'e' || *CurPtr == 'E') { + if (*CurPtr == '-' || *CurPtr == '+') + return ReturnError(CurPtr, "Invalid sign in float literal"); + + // Check for exponent + if ((*CurPtr == 'e' || *CurPtr == 'E')) { ++CurPtr; + if (*CurPtr == '-' || *CurPtr == '+') ++CurPtr; + while (isDigit(*CurPtr)) ++CurPtr; } @@ -145,8 +146,9 @@ AsmToken AsmLexer::LexIdentifier() { // Disambiguate a .1243foo identifier from a floating literal. while (isDigit(*CurPtr)) ++CurPtr; - if (*CurPtr == 'e' || *CurPtr == 'E' || - !IsIdentifierChar(*CurPtr, AllowAtInIdentifier)) + + if (!IsIdentifierChar(*CurPtr, AllowAtInIdentifier) || + *CurPtr == 'e' || *CurPtr == 'E') return LexFloatLiteral(); } @@ -326,8 +328,9 @@ AsmToken AsmLexer::LexDigit() { unsigned Radix = doHexLookAhead(CurPtr, 10, LexMasmIntegers); bool isHex = Radix == 16; // Check for floating point literals. - if (!isHex && (*CurPtr == '.' || *CurPtr == 'e')) { - ++CurPtr; + if (!isHex && (*CurPtr == '.' || *CurPtr == 'e' || *CurPtr == 'E')) { + if (*CurPtr == '.') + ++CurPtr; return LexFloatLiteral(); } diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp index 3ebed5b..208950d 100644 --- a/llvm/lib/Support/APFloat.cpp +++ b/llvm/lib/Support/APFloat.cpp @@ -198,7 +198,10 @@ readExponent(StringRef::iterator begin, StringRef::iterator end) const unsigned int overlargeExponent = 24000; /* FIXME. */ StringRef::iterator p = begin; - assert(p != end && "Exponent has no digits"); + // Treat no exponent as 0 to match binutils + if (p == end || ((*p == '-' || *p == '+') && (p + 1) == end)) { + return 0; + } isNegative = (*p == '-'); if (*p == '-' || *p == '+') { diff --git a/llvm/test/MC/AsmParser/floating-literals.s b/llvm/test/MC/AsmParser/floating-literals.s index 9dca77f..d3a2321 100644 --- a/llvm/test/MC/AsmParser/floating-literals.s +++ b/llvm/test/MC/AsmParser/floating-literals.s @@ -27,7 +27,7 @@ # CHECK: .long 1067928519 .float 1.307 - + # CHECK: .quad 4617315517961601024 # CHECK: .quad 4597526701198935065 # CHECK: .quad -4600933674317040845 @@ -48,10 +48,48 @@ .double 1.e5 # CHECK: .quad 4611686018427387904 .double 2. +# CHECK: .quad 4611686018427387904 +.double 2.e +# CHECK: .quad 4611686018427387904 +.double 2.e+ +# CHECK: .quad 4611686018427387904 +.double 2.e- +# CHECK: .quad -4615288898129284301 +.double -1.2e +# CHECK: .quad 4621819117588971520 +.double 1e1 +# CHECK: .quad 4591870180066957722 +.double 1e-1 + + +# CHECK: .quad -4570379565595099136 +.double -1.2E3 +# CHECK: .quad -4690170861623122860 +.double -1.2E-5 +# CHECK: .quad -4465782973978902528 +.double -1.2E+10 +# CHECK: .quad 4681608360884174848 +.double 1E5 +# CHECK: .quad 4681608360884174848 +.double 1.E5 +# CHECK: .quad 4611686018427387904 +.double 2.E +# CHECK: .quad 4611686018427387904 +.double 2.E+ +# CHECK: .quad 4611686018427387904 +.double 2.E- +# CHECK: .quad -4615288898129284301 +.double -1.2E +# CHECK: .quad 4621819117588971520 +.double 1E1 +# CHECK: .quad 4591870180066957722 +.double 1E-1 -// APFloat should reject these with an error, not crash: -//.double -1.2e+ -//.double -1.2e + +#CHECK-ERROR: unexpected token in '.double' directive +.double 1e1e +# CHECK-ERROR: Invalid sign in float literal +.double 2.+1 # CHECK: .long 1310177520 .float 0x12f7.1ep+17 @@ -83,3 +121,4 @@ # CHECK-ERROR: error: invalid hexadecimal floating-point constant: expected exponent part 'p' .float 0x1.2 + diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp index fb36077..c76347e 100644 --- a/llvm/unittests/ADT/APFloatTest.cpp +++ b/llvm/unittests/ADT/APFloatTest.cpp @@ -868,6 +868,33 @@ TEST(APFloatTest, fromDecimalString) { EXPECT_EQ(2.05e+12, APFloat(APFloat::IEEEdouble(), "002.05000e+12").convertToDouble()); EXPECT_EQ(2.05e-12, APFloat(APFloat::IEEEdouble(), "002.05000e-12").convertToDouble()); + EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "1e").convertToDouble()); + EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "+1e").convertToDouble()); + EXPECT_EQ(-1.0, APFloat(APFloat::IEEEdouble(), "-1e").convertToDouble()); + + EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "1.e").convertToDouble()); + EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "+1.e").convertToDouble()); + EXPECT_EQ(-1.0, APFloat(APFloat::IEEEdouble(), "-1.e").convertToDouble()); + + EXPECT_EQ(0.1, APFloat(APFloat::IEEEdouble(), ".1e").convertToDouble()); + EXPECT_EQ(0.1, APFloat(APFloat::IEEEdouble(), "+.1e").convertToDouble()); + EXPECT_EQ(-0.1, APFloat(APFloat::IEEEdouble(), "-.1e").convertToDouble()); + + EXPECT_EQ(1.1, APFloat(APFloat::IEEEdouble(), "1.1e").convertToDouble()); + EXPECT_EQ(1.1, APFloat(APFloat::IEEEdouble(), "+1.1e").convertToDouble()); + EXPECT_EQ(-1.1, APFloat(APFloat::IEEEdouble(), "-1.1e").convertToDouble()); + + EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "1e+").convertToDouble()); + EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "1e-").convertToDouble()); + + EXPECT_EQ(0.1, APFloat(APFloat::IEEEdouble(), ".1e").convertToDouble()); + EXPECT_EQ(0.1, APFloat(APFloat::IEEEdouble(), ".1e+").convertToDouble()); + EXPECT_EQ(0.1, APFloat(APFloat::IEEEdouble(), ".1e-").convertToDouble()); + + EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "1.0e").convertToDouble()); + EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "1.0e+").convertToDouble()); + EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "1.0e-").convertToDouble()); + // These are "carefully selected" to overflow the fast log-base // calculations in APFloat.cpp EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "99e99999").isInfinity()); @@ -1165,36 +1192,6 @@ TEST(APFloatTest, StringDecimalSignificandDeath) { EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-.e"), "Significand has no digits"); } -TEST(APFloatTest, StringDecimalExponentDeath) { - EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "1e"), "Exponent has no digits"); - EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+1e"), "Exponent has no digits"); - EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-1e"), "Exponent has no digits"); - - EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "1.e"), "Exponent has no digits"); - EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+1.e"), "Exponent has no digits"); - EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-1.e"), "Exponent has no digits"); - - EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), ".1e"), "Exponent has no digits"); - EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+.1e"), "Exponent has no digits"); - EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-.1e"), "Exponent has no digits"); - - EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "1.1e"), "Exponent has no digits"); - EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+1.1e"), "Exponent has no digits"); - EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-1.1e"), "Exponent has no digits"); - - - EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "1e+"), "Exponent has no digits"); - EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "1e-"), "Exponent has no digits"); - - EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), ".1e"), "Exponent has no digits"); - EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), ".1e+"), "Exponent has no digits"); - EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), ".1e-"), "Exponent has no digits"); - - EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "1.0e"), "Exponent has no digits"); - EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "1.0e+"), "Exponent has no digits"); - EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "1.0e-"), "Exponent has no digits"); -} - TEST(APFloatTest, StringHexadecimalDeath) { EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x"), "Invalid string"); EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x"), "Invalid string");