summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/ADT/APSInt.h9
-rw-r--r--llvm/lib/AsmParser/LLLexer.cpp15
-rw-r--r--llvm/lib/Support/APSInt.cpp19
-rw-r--r--llvm/unittests/ADT/APSIntTest.cpp19
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
OpenPOWER on IntegriCloud