diff options
-rw-r--r-- | llvm/include/llvm/ADT/APSInt.h | 9 | ||||
-rw-r--r-- | llvm/lib/AsmParser/LLLexer.cpp | 15 | ||||
-rw-r--r-- | llvm/lib/Support/APSInt.cpp | 19 | ||||
-rw-r--r-- | llvm/unittests/ADT/APSIntTest.cpp | 19 |
4 files changed, 48 insertions, 14 deletions
diff --git a/llvm/include/llvm/ADT/APSInt.h b/llvm/include/llvm/ADT/APSInt.h index 91ccda22f2f..a187515f859 100644 --- a/llvm/include/llvm/ADT/APSInt.h +++ b/llvm/include/llvm/ADT/APSInt.h @@ -33,6 +33,15 @@ public: explicit APSInt(APInt I, bool isUnsigned = true) : APInt(std::move(I)), IsUnsigned(isUnsigned) {} + /// Construct an APSInt from a string representation. + /// + /// This constructor interprets the string \p Str using the radix of 10. + /// The interpretation stops at the end of the string. The bit width of the + /// constructed APSInt is determined automatically. + /// + /// \param Str the string to be interpreted. + explicit APSInt(StringRef Str); + APSInt &operator=(APInt RHS) { // Retain our current sign. APInt::operator=(std::move(RHS)); diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index 0bdc3506a30..88f359d4fd5 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -903,20 +903,7 @@ lltok::Kind LLLexer::LexDigitOrNegative() { if (CurPtr[0] != '.') { if (TokStart[0] == '0' && TokStart[1] == 'x') return Lex0x(); - unsigned Len = CurPtr-TokStart; - uint32_t numBits = ((Len * 64) / 19) + 2; - APInt Tmp(numBits, StringRef(TokStart, Len), 10); - if (TokStart[0] == '-') { - uint32_t minBits = Tmp.getMinSignedBits(); - if (minBits > 0 && minBits < numBits) - Tmp = Tmp.trunc(minBits); - APSIntVal = APSInt(Tmp, false); - } else { - uint32_t activeBits = Tmp.getActiveBits(); - if (activeBits > 0 && activeBits < numBits) - Tmp = Tmp.trunc(activeBits); - APSIntVal = APSInt(Tmp, true); - } + APSIntVal = APSInt(StringRef(TokStart, CurPtr - TokStart)); return lltok::APSInt; } diff --git a/llvm/lib/Support/APSInt.cpp b/llvm/lib/Support/APSInt.cpp index 73acafa690c..975457c070a 100644 --- a/llvm/lib/Support/APSInt.cpp +++ b/llvm/lib/Support/APSInt.cpp @@ -17,6 +17,25 @@ using namespace llvm; +APSInt::APSInt(StringRef Str) { + assert(!Str.empty() && "Invalid string length"); + + // (Over-)estimate the required number of bits. + unsigned NumBits = ((Str.size() * 64) / 19) + 2; + APInt Tmp(NumBits, Str, /*Radix=*/10); + if (Str[0] == '-') { + unsigned MinBits = Tmp.getMinSignedBits(); + if (MinBits > 0 && MinBits < NumBits) + Tmp = Tmp.trunc(MinBits); + *this = APSInt(Tmp, /*IsUnsigned=*/false); + return; + } + unsigned ActiveBits = Tmp.getActiveBits(); + if (ActiveBits > 0 && ActiveBits < NumBits) + Tmp = Tmp.trunc(ActiveBits); + *this = APSInt(Tmp, /*IsUnsigned=*/true); +} + void APSInt::Profile(FoldingSetNodeID& ID) const { ID.AddInteger((unsigned) (IsUnsigned ? 1 : 0)); APInt::Profile(ID); diff --git a/llvm/unittests/ADT/APSIntTest.cpp b/llvm/unittests/ADT/APSIntTest.cpp index 5e4e87440bd..44430055e90 100644 --- a/llvm/unittests/ADT/APSIntTest.cpp +++ b/llvm/unittests/ADT/APSIntTest.cpp @@ -143,4 +143,23 @@ TEST(APSIntTest, compareValues) { EXPECT_TRUE(APSInt::compareValues(U(8), S(-7).trunc(32)) > 0); } +TEST(APSIntTest, FromString) { + EXPECT_EQ(APSInt("1").getExtValue(), 1); + EXPECT_EQ(APSInt("-1").getExtValue(), -1); + EXPECT_EQ(APSInt("0").getExtValue(), 0); + EXPECT_EQ(APSInt("56789").getExtValue(), 56789); + EXPECT_EQ(APSInt("-1234").getExtValue(), -1234); } + +#ifdef GTEST_HAS_DEATH_TEST +#ifndef NDEBUG + +TEST(APSIntTest, StringDeath) { + EXPECT_DEATH(APSInt(""), "Invalid string length"); + EXPECT_DEATH(APSInt("1a"), "Invalid character in digit string"); +} + +#endif +#endif + +} // end anonymous namespace |