Bladeren bron

Fix APInt::operator*= so that it computes the correct result for large integers where there is unsigned overflow. Fix APFloat::toString so that it doesn't depend on the incorrect behavior in common cases (and computes the correct result in some rare cases). Fixes PR11086.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141441 91177308-0d34-0410-b5e6-96231b3b80d8
Eli Friedman 14 jaren geleden
bovenliggende
commit
9eb6b4d91b
3 gewijzigde bestanden met toevoegingen van 12 en 2 verwijderingen
  1. 1 1
      lib/Support/APFloat.cpp
  2. 2 1
      lib/Support/APInt.cpp
  3. 9 0
      unittests/ADT/APIntTest.cpp

+ 1 - 1
lib/Support/APFloat.cpp

@@ -3455,7 +3455,7 @@ void APFloat::toString(SmallVectorImpl<char> &Str,
     //                 <= semantics->precision + e * 137 / 59
     //   (log_2(5) ~ 2.321928 < 2.322034 ~ 137/59)
 
-    unsigned precision = semantics->precision + 137 * texp / 59;
+    unsigned precision = semantics->precision + (137 * texp + 136) / 59;
 
     // Multiply significand by 5^e.
     //   N * 5^0101 == N * 5^(1*1) * 5^(0*2) * 5^(1*4) * 5^(0*8)

+ 2 - 1
lib/Support/APInt.cpp

@@ -386,6 +386,7 @@ APInt& APInt::operator*=(const APInt& RHS) {
   clearAllBits();
   unsigned wordsToCopy = destWords >= getNumWords() ? getNumWords() : destWords;
   memcpy(pVal, dest, wordsToCopy * APINT_WORD_SIZE);
+  clearUnusedBits();
 
   // delete dest array and return
   delete[] dest;
@@ -471,7 +472,7 @@ APInt APInt::operator*(const APInt& RHS) const {
     return APInt(BitWidth, VAL * RHS.VAL);
   APInt Result(*this);
   Result *= RHS;
-  return Result.clearUnusedBits();
+  return Result;
 }
 
 APInt APInt::operator+(const APInt& RHS) const {

+ 9 - 0
unittests/ADT/APIntTest.cpp

@@ -441,4 +441,13 @@ TEST(APIntTest, StringDeath) {
 #endif
 #endif
 
+TEST(APIntTest, mul_clear) {
+  APInt ValA(65, -1ULL);
+  APInt ValB(65, 4);
+  APInt ValC(65, 0);
+  ValC = ValA * ValB;
+  ValA *= ValB;
+  EXPECT_EQ(ValA.toString(10, false), ValC.toString(10, false));
+}
+
 }