[clang] [clang] Avoid printing overly large integer/_BitInt numbers in static assertion failure diagnostics #71675 (PR #145053)
Erich Keane via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 30 06:36:05 PDT 2025
================
@@ -17575,7 +17576,21 @@ static bool ConvertAPValueToString(const APValue &V, QualType T,
break;
}
}
- V.getInt().toString(Str);
+
+ llvm::APSInt vInt = V.getInt();
+ if (llvm::APSInt::compareValues(
+ vInt, llvm::APSInt::getUnsigned(
+ std::numeric_limits<uint64_t>::max())) >= 0 ||
+ vInt < std::numeric_limits<int64_t>::min()) {
+ // The value of cutSize is not special, it is just a number of
+ // characters that gives us enough info without losing readability
+ const int cutSize = 20;
+ vInt.toString(Str, 16);
+ Str.erase(Str.begin() + cutSize, Str.end() - cutSize);
----------------
erichkeane wrote:
> Hi just wanted to run something by you before I make further changes. Before, we were using the value of the APInt to decide if we would truncate or not. I am tempted since we will be looking at the number of digits anyway to decide how many to skip to instead use that as the deciding factor, so something like, if the number of digits in the APInt value is larger than 40 (This is if we want to keep N=20) then we truncate keeping the first and last 20. Were you thinking of some other way to decide what N should be by the way?
I had no problem with the "around 20 digits" on each side. My suggestion was to have the actual printing in `APInt` do the magic (via separate function). So algorithmically, it is something like:
```
unsigned end_digits_printed = 0;
// Print the 'end digits'.
while(value != 0 && end_digits_printed <20) {
APInt temp;
int64_t rem;
APInt::udivrem(value, 10, temp, rem);//udiv becasue before this we figured out 'negative' and made it positive.
//add-rem-to-buffer
value = temp;
}
// print the '...'
if (value == 0) return;
// This gives more of a log-base-16 by dividing it by 4 I think (or should this be a multiply?), but gives us an approximation.
unsigned ApproxDigitsLeft = value.logBase2() / 4;
if (ApproxDigitsLeft > 20)
value = value.udiv( 10 * (ApproxDigitsLeft - 20)); // removes the 'middle' approx all-but-20.
// print the leading part.
while (value != 0) {
// same stuff as above.
}
```
So basically, we don't have to calculate the whole thing to figure out how many to remove, but we can be 'reasonably accurate' here. WDYT? ALSO, the base-16 to base-10 approximation might need some tweeking so that we always print some of the leading digits (though I think 'at least 20 hex digits' is... a lot to make sure of that.). We MIGHT want to make the top-half a little smaller since there is a hex->decimal relationship, so maybe make sure we're printing the top 16 hex-digit-worth?
https://github.com/llvm/llvm-project/pull/145053
More information about the cfe-commits
mailing list