-
Notifications
You must be signed in to change notification settings - Fork 14.4k
[clang] Avoid printing overly large integer/_BitInt numbers in static assertion failure diagnostics #71675 #145053
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -647,7 +647,11 @@ Improvements to Clang's diagnostics | |||||
#GH69470, #GH59391, #GH58172, #GH46215, #GH45915, #GH45891, #GH44490, | ||||||
#GH36703, #GH32903, #GH23312, #GH69874. | ||||||
|
||||||
|
||||||
- Improved the performance of static assertions envolving large integers by | ||||||
using hex format instead of string. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't do a newline here I think? If you do it separates the things during rendering. |
||||||
Fixes #GH71675 | ||||||
|
||||||
Improvements to Clang's time-trace | ||||||
---------------------------------- | ||||||
|
||||||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -47,6 +47,7 @@ | |||||
#include "clang/Sema/SemaOpenMP.h" | ||||||
#include "clang/Sema/Template.h" | ||||||
#include "clang/Sema/TemplateDeduction.h" | ||||||
#include "llvm/ADT/APSInt.h" | ||||||
#include "llvm/ADT/ArrayRef.h" | ||||||
#include "llvm/ADT/STLExtras.h" | ||||||
#include "llvm/ADT/StringExtras.h" | ||||||
|
@@ -17575,7 +17576,21 @@ static bool ConvertAPValueToString(const APValue &V, QualType T, | |||||
break; | ||||||
} | ||||||
} | ||||||
V.getInt().toString(Str); | ||||||
|
||||||
llvm::APSInt vInt = V.getInt(); | ||||||
topperc marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
if (llvm::APSInt::compareValues( | ||||||
vInt, llvm::APSInt::getUnsigned( | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This whole bit here is equivilent to: |
||||||
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; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
vInt.toString(Str, 16); | ||||||
Str.erase(Str.begin() + cutSize, Str.end() - cutSize); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This here doesn't really seem right. We're just erasing blindly in the middle, despite not knowing that we have enough room. I think what we REALLY want is to decide to keep the first N characters, and the last N characters (and still do the ...). Additionally, I think instead of doing the whole to-string mechanism here (and since we're doing it in hex it is easy to do so), we could just do a numeric-trim of hte front/back instead and join them afterwards. THAT SAID: I'm not sold on doing this as a hex-print, I think we can keep it decimal. We could have a new function in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like the idea of keeping the decimals. I think it avoids the weirdness happening in the enum test, which I think might have been caused by some characters getting cut in half. Working on it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi just wanted to run something by you before I make further changes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't really know how this is supposed to work. We need to know what to display without printing the value to a string at all, because THAT is what's breaking our neck. The simplest solution would be to just check the value (or even There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I had no problem with the "around 20 digits" on each side. My suggestion was to have the actual printing in
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? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool, that is basically what I had in mind. I'm extending toString and there is a Pos variable as you have there counting how many digits were already inserted and we can get the number of remaing using value.logBase2/log2(Radix) +1 that actually gives the exact count. Then the division will be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @tbaederr I think the last comment from @erichkeane probably made it clearer but basically what we were discussing is creating a separate version of toString (tentatively naming it toStringTruncated) that does not print all of the number, the implementation of that function basically takes the number and does a huge number of divisions to get each digit in the resulting String, the approach suggested is that once we have printed 20 digits we do a division that jumps us to the first 20. I'm hoping I can have something to push in the next couple days time permitting. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That sounds VAGUELY familiar :) Its been a few decades since I've been in a math class.... With the 'pow', you probably need SOME sort of guard to make sure you don't exceed the number we can store. |
||||||
Str.insert(Str.begin() + cutSize, 3, '.'); | ||||||
} else { | ||||||
vInt.toString(Str); | ||||||
} | ||||||
} | ||||||
|
||||||
break; | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -87,12 +87,12 @@ typedef unsigned __int128 uint128_t; | |
static const __uint128_t UINT128_MAX =__uint128_t(__int128_t(-1L)); | ||
static_assert(UINT128_MAX == -1, ""); | ||
static_assert(UINT128_MAX == 1, ""); // both-error {{static assertion failed}} \ | ||
// both-note {{'340282366920938463463374607431768211455 == 1'}} | ||
// both-note {{'FFFFFFFFFFFFFFFFFFFF...FFFFFFFFFFFFFFFFFFFF == 1'}} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is making these print in hex? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test was not fixed yet I was hitting a problem where the division was throwing a Floting point error that I was still looking at. |
||
|
||
static const __int128_t INT128_MAX = UINT128_MAX >> (__int128_t)1; | ||
static_assert(INT128_MAX != 0, ""); | ||
static_assert(INT128_MAX == 0, ""); // both-error {{failed}} \ | ||
// both-note {{evaluates to '170141183460469231731687303715884105727 == 0'}} | ||
// both-note {{evaluates to '7FFFFFFFFFFFFFFFFFFF...FFFFFFFFFFFFFFFFFFFF == 0'}} | ||
static const __int128_t INT128_MIN = -INT128_MAX - 1; | ||
|
||
|
||
|
@@ -113,14 +113,14 @@ namespace i128 { | |
static const __uint128_t UINT128_MAX =__uint128_t(__int128_t(-1L)); | ||
static_assert(UINT128_MAX == -1, ""); | ||
static_assert(UINT128_MAX == 1, ""); // both-error {{static assertion failed}} \ | ||
// both-note {{'340282366920938463463374607431768211455 == 1'}} | ||
// both-note {{'FFFFFFFFFFFFFFFFFFFF...FFFFFFFFFFFFFFFFFFFF == 1'}} | ||
|
||
constexpr uint128_t TooMuch = UINT128_MAX * 2; | ||
|
||
static const __int128_t INT128_MAX = UINT128_MAX >> (__int128_t)1; | ||
static_assert(INT128_MAX != 0, ""); | ||
static_assert(INT128_MAX == 0, ""); // both-error {{failed}} \ | ||
// both-note {{evaluates to '170141183460469231731687303715884105727 == 0'}} | ||
// both-note {{evaluates to '7FFFFFFFFFFFFFFFFFFF...FFFFFFFFFFFFFFFFFFFF == 0'}} | ||
|
||
constexpr int128_t TooMuch2 = INT128_MAX * INT128_MAX; // both-error {{must be initialized by a constant expression}} \ | ||
// both-note {{value 28948022309329048855892746252171976962977213799489202546401021394546514198529 is outside the range of representable}} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -196,7 +196,7 @@ enum GH59352 { // expected-warning {{enumeration values exceed range of largest | |
BigVal = 66666666666666666666wb | ||
}; | ||
_Static_assert(BigVal == 66666666666666666666wb); /* expected-error {{static assertion failed due to requirement 'BigVal == 66666666666666666666wb'}} | ||
expected-note {{expression evaluates to '11326434445538011818 == 66666666666666666666'}} | ||
expected-note {{expression evaluates to '11326434445538011818 == 39D2F941E420AAAAA<U+0000><U+0000><U+0000>...<U+0000><U+0000><U+0000>39D2F941E420AAAAA'}} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems VERY wrong here... |
||
*/ | ||
_Static_assert( | ||
_Generic(BigVal, // expected-error {{static assertion failed}} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.