https://github.com/Atousa updated https://github.com/llvm/llvm-project/pull/80939
>From a73812395e80ef79ce19378cae2aed58ad5b0532 Mon Sep 17 00:00:00 2001 From: Atousa Duprat <atous...@gmail.com> Date: Tue, 6 Feb 2024 21:02:05 -0800 Subject: [PATCH] [clang] Use separator for large numeric values in overflow diagnostic Add functionality to APInt::toString() that allows it to insert separators between groups of digits, using the C++ litteral separator ' between groups. Fixes issue #58228 --- clang/lib/AST/ExprConstant.cpp | 3 +- clang/test/C/drs/dr0xx.c | 2 +- clang/test/C/drs/dr2xx.c | 2 +- clang/test/Sema/integer-overflow.c | 100 +++++++++--------- clang/test/Sema/switch-1.c | 6 +- clang/test/SemaCXX/enum.cpp | 4 +- clang/test/SemaCXX/integer-overflow.cpp | 110 ++++++++++---------- clang/test/SemaObjC/integer-overflow.m | 4 +- clang/test/SemaObjC/objc-literal-nsnumber.m | 2 +- llvm/include/llvm/ADT/APInt.h | 3 +- llvm/include/llvm/ADT/StringExtras.h | 5 +- llvm/lib/Support/APInt.cpp | 24 ++++- llvm/unittests/ADT/APIntTest.cpp | 35 +++++++ 13 files changed, 180 insertions(+), 120 deletions(-) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 089bc2094567f..a46887d6cf1be 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -2774,7 +2774,8 @@ static bool CheckedIntArithmetic(EvalInfo &Info, const Expr *E, if (Info.checkingForUndefinedBehavior()) Info.Ctx.getDiagnostics().Report(E->getExprLoc(), diag::warn_integer_constant_overflow) - << toString(Result, 10) << E->getType() << E->getSourceRange(); + << toString(Result, 10, Result.isSigned(), false, true, true) + << E->getType() << E->getSourceRange(); return HandleOverflow(Info, E, Value, E->getType()); } return true; diff --git a/clang/test/C/drs/dr0xx.c b/clang/test/C/drs/dr0xx.c index d9c1fbe4ee40a..c93cfb63d604c 100644 --- a/clang/test/C/drs/dr0xx.c +++ b/clang/test/C/drs/dr0xx.c @@ -214,7 +214,7 @@ _Static_assert(__builtin_types_compatible_p(struct S { int a; }, union U { int a */ void dr031(int i) { switch (i) { - case __INT_MAX__ + 1: break; /* expected-warning {{overflow in expression; result is -2147483648 with type 'int'}} */ + case __INT_MAX__ + 1: break; /* expected-warning {{overflow in expression; result is -2'147'483'648 with type 'int'}} */ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wswitch" /* Silence the targets which issue: diff --git a/clang/test/C/drs/dr2xx.c b/clang/test/C/drs/dr2xx.c index 9c8d77518ab55..1b68b65acca6a 100644 --- a/clang/test/C/drs/dr2xx.c +++ b/clang/test/C/drs/dr2xx.c @@ -277,7 +277,7 @@ void dr258(void) { void dr261(void) { /* This is still an integer constant expression despite the overflow. */ enum e1 { - ex1 = __INT_MAX__ + 1 /* expected-warning {{overflow in expression; result is -2147483648 with type 'int'}} */ + ex1 = __INT_MAX__ + 1 /* expected-warning {{overflow in expression; result is -2'147'483'648 with type 'int'}} */ }; /* This is not an integer constant expression, because of the comma operator, diff --git a/clang/test/Sema/integer-overflow.c b/clang/test/Sema/integer-overflow.c index cf822f346e8b2..220fc1bed515a 100644 --- a/clang/test/Sema/integer-overflow.c +++ b/clang/test/Sema/integer-overflow.c @@ -11,169 +11,169 @@ uint64_t f0(uint64_t); uint64_t f1(uint64_t, uint32_t); uint64_t f2(uint64_t, ...); -static const uint64_t overflow = 1 * 4608 * 1024 * 1024; // expected-warning {{overflow in expression; result is 536870912 with type 'int'}} +static const uint64_t overflow = 1 * 4608 * 1024 * 1024; // expected-warning {{overflow in expression; result is 536'870'912 with type 'int'}} uint64_t check_integer_overflows(int i) { -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} uint64_t overflow = 4608 * 1024 * 1024, -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} overflow2 = (uint64_t)(4608 * 1024 * 1024), -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} overflow3 = (uint64_t)(4608 * 1024 * 1024 * i), -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} overflow4 = (1ULL * ((4608) * ((1024) * (1024))) + 2ULL), -// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 2{{overflow in expression; result is 536'870'912 with type 'int'}} multi_overflow = (uint64_t)((uint64_t)(4608 * 1024 * 1024) * (uint64_t)(4608 * 1024 * 1024)); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} overflow += overflow2 = overflow3 = (uint64_t)(4608 * 1024 * 1024); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} overflow += overflow2 = overflow3 = 4608 * 1024 * 1024; uint64_t not_overflow = 4608 * 1024 * 1024ULL; uint64_t not_overflow2 = (1ULL * ((uint64_t)(4608) * (1024 * 1024)) + 2ULL); -// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 2{{overflow in expression; result is 536'870'912 with type 'int'}} overflow = 4608 * 1024 * 1024 ? 4608 * 1024 * 1024 : 0; -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} overflow = 0 ? 0 : 4608 * 1024 * 1024; -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} if (4608 * 1024 * 1024) return 0; -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} if ((uint64_t)(4608 * 1024 * 1024)) return 1; -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} if ((uint64_t)(4608 * 1024 * 1024)) return 2; -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} if ((uint64_t)(4608 * 1024 * 1024 * i)) return 3; -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} if ((1ULL * ((4608) * ((1024) * (1024))) + 2ULL)) return 4; -// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 2{{overflow in expression; result is 536'870'912 with type 'int'}} if ((uint64_t)((uint64_t)(4608 * 1024 * 1024) * (uint64_t)(4608 * 1024 * 1024))) return 5; switch (i) { -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} case 4608 * 1024 * 1024: return 6; -// expected-warning@+1 {{overflow in expression; result is 537919488 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 537'919'488 with type 'int'}} case (uint64_t)(4609 * 1024 * 1024): return 7; // expected-error@+1 {{expression is not an integer constant expression}} case ((uint64_t)(4608 * 1024 * 1024 * i)): return 8; -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} case ((1ULL * ((4608) * ((1024) * (1024))) + 2ULL)): return 9; -// expected-warning@+2 2{{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+2 2{{overflow in expression; result is 536'870'912 with type 'int'}} // expected-warning@+1 {{overflow converting case value to switch condition type (288230376151711744 to 0)}} case ((uint64_t)((uint64_t)(4608 * 1024 * 1024) * (uint64_t)(4608 * 1024 * 1024))): return 10; } -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} while (4608 * 1024 * 1024); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} while ((uint64_t)(4608 * 1024 * 1024)); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} while ((uint64_t)(4608 * 1024 * 1024)); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} while ((uint64_t)(4608 * 1024 * 1024 * i)); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} while ((1ULL * ((4608) * ((1024) * (1024))) + 2ULL)); -// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 2{{overflow in expression; result is 536'870'912 with type 'int'}} while ((uint64_t)((uint64_t)(4608 * 1024 * 1024) * (uint64_t)(4608 * 1024 * 1024))); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} do { } while (4608 * 1024 * 1024); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} do { } while ((uint64_t)(4608 * 1024 * 1024)); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} do { } while ((uint64_t)(4608 * 1024 * 1024)); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} do { } while ((uint64_t)(4608 * 1024 * 1024 * i)); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} do { } while ((1ULL * ((4608) * ((1024) * (1024))) + 2ULL)); -// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 2{{overflow in expression; result is 536'870'912 with type 'int'}} do { } while ((uint64_t)((uint64_t)(4608 * 1024 * 1024) * (uint64_t)(4608 * 1024 * 1024))); -// expected-warning@+3 {{overflow in expression; result is 536870912 with type 'int'}} -// expected-warning@+3 {{overflow in expression; result is 536870912 with type 'int'}} -// expected-warning@+3 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+3 {{overflow in expression; result is 536'870'912 with type 'int'}} +// expected-warning@+3 {{overflow in expression; result is 536'870'912 with type 'int'}} +// expected-warning@+3 {{overflow in expression; result is 536'870'912 with type 'int'}} for (uint64_t i = 4608 * 1024 * 1024; (uint64_t)(4608 * 1024 * 1024); i += (uint64_t)(4608 * 1024 * 1024 * i)); -// expected-warning@+3 {{overflow in expression; result is 536870912 with type 'int'}} -// expected-warning@+3 2{{overflow in expression; result is 536870912 with type 'int'}} -// expected-warning@+3 2{{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+3 {{overflow in expression; result is 536'870'912 with type 'int'}} +// expected-warning@+3 2{{overflow in expression; result is 536'870'912 with type 'int'}} +// expected-warning@+3 2{{overflow in expression; result is 536'870'912 with type 'int'}} for (uint64_t i = (1ULL * ((4608) * ((1024) * (1024))) + 2ULL); ((uint64_t)((uint64_t)(4608 * 1024 * 1024) * (uint64_t)(4608 * 1024 * 1024))); i = ((4608 * 1024 * 1024) + ((uint64_t)(4608 * 1024 * 1024)))); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} _Complex long long x = 4608 * 1024 * 1024; -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} (__real__ x) = 4608 * 1024 * 1024; -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} (__imag__ x) = 4608 * 1024 * 1024; -// expected-warning@+4 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+4 {{overflow in expression; result is 536'870'912 with type 'int'}} // expected-warning@+3 {{array index 536870912 is past the end of the array (that has type 'uint64_t[10]' (aka 'unsigned long long[10]'))}} // expected-note@+1 {{array 'a' declared here}} uint64_t a[10]; a[4608 * 1024 * 1024] = 1i; -// expected-warning@+2 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+2 {{overflow in expression; result is 536'870'912 with type 'int'}} uint64_t *b; uint64_t b2 = b[4608 * 1024 * 1024] + 1; -// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 2{{overflow in expression; result is 536'870'912 with type 'int'}} (void)((i ? (4608 * 1024 * 1024) : (4608 * 1024 * 1024)) + 1); -// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 2{{overflow in expression; result is 536'870'912 with type 'int'}} return ((4608 * 1024 * 1024) + ((uint64_t)(4608 * 1024 * 1024))); } void check_integer_overflows_in_function_calls(void) { -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} (void)f0(4608 * 1024 * 1024); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} uint64_t x = f0(4608 * 1024 * 1024); -// expected-warning@+2 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+2 {{overflow in expression; result is 536'870'912 with type 'int'}} uint64_t (*f0_ptr)(uint64_t) = &f0; (void)(*f0_ptr)(4608 * 1024 * 1024); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} (void)f2(0, f0(4608 * 1024 * 1024)); } void check_integer_overflows_in_array_size(void) { - int arr[4608 * 1024 * 1024]; // expected-warning {{overflow in expression; result is 536870912 with type 'int'}} + int arr[4608 * 1024 * 1024]; // expected-warning {{overflow in expression; result is 536'870'912 with type 'int'}} } struct s { diff --git a/clang/test/Sema/switch-1.c b/clang/test/Sema/switch-1.c index 95e64748fb1fb..09221990ac11d 100644 --- a/clang/test/Sema/switch-1.c +++ b/clang/test/Sema/switch-1.c @@ -7,7 +7,7 @@ int f(int i) { switch (i) { case 2147483647 + 2: #if (__cplusplus <= 199711L) // C or C++03 or earlier modes - // expected-warning@-2 {{overflow in expression; result is -2147483647 with type 'int'}} + // expected-warning@-2 {{overflow in expression; result is -2'147'483'647 with type 'int'}} #else // expected-error@-4 {{case value is not a constant expression}} \ // expected-note@-4 {{value 2147483649 is outside the range of representable values of type 'int'}} @@ -23,7 +23,7 @@ int f(int i) { return 2; case (123456 *789012) + 1: #if (__cplusplus <= 199711L) - // expected-warning@-2 {{overflow in expression; result is -1375982336 with type 'int'}} + // expected-warning@-2 {{overflow in expression; result is -1'375'982'336 with type 'int'}} #else // expected-error@-4 {{case value is not a constant expression}} \ // expected-note@-4 {{value 97408265472 is outside the range of representable values of type 'int'}} @@ -47,7 +47,7 @@ int f(int i) { case 2147483647: return 0; } - return (i, 65537) * 65537; // expected-warning {{overflow in expression; result is 131073 with type 'int'}} \ + return (i, 65537) * 65537; // expected-warning {{overflow in expression; result is 131'073 with type 'int'}} \ // expected-warning {{left operand of comma operator has no effect}} } diff --git a/clang/test/SemaCXX/enum.cpp b/clang/test/SemaCXX/enum.cpp index fc65fd16f8c30..c482b3c571ab4 100644 --- a/clang/test/SemaCXX/enum.cpp +++ b/clang/test/SemaCXX/enum.cpp @@ -103,7 +103,7 @@ enum { overflow = 123456 * 234567 }; // expected-warning@-2 {{not an integral constant expression}} // expected-note@-3 {{value 28958703552 is outside the range of representable values}} #else -// expected-warning@-5 {{overflow in expression; result is -1106067520 with type 'int'}} +// expected-warning@-5 {{overflow in expression; result is -1'106'067'520 with type 'int'}} #endif // FIXME: This is not consistent with the above case. @@ -112,7 +112,7 @@ enum NoFold : int { overflow2 = 123456 * 234567 }; // expected-error@-2 {{enumerator value is not a constant expression}} // expected-note@-3 {{value 28958703552 is outside the range of representable values}} #else -// expected-warning@-5 {{overflow in expression; result is -1106067520 with type 'int'}} +// expected-warning@-5 {{overflow in expression; result is -1'106'067'520 with type 'int'}} // expected-warning@-6 {{extension}} #endif diff --git a/clang/test/SemaCXX/integer-overflow.cpp b/clang/test/SemaCXX/integer-overflow.cpp index 0e8ad050aa14d..a6c747c2d48c8 100644 --- a/clang/test/SemaCXX/integer-overflow.cpp +++ b/clang/test/SemaCXX/integer-overflow.cpp @@ -13,157 +13,157 @@ uint64_t f0(uint64_t); uint64_t f1(uint64_t, uint32_t); uint64_t f2(uint64_t, ...); -static const uint64_t overflow = 1 * 4608 * 1024 * 1024; // expected-warning {{overflow in expression; result is 536870912 with type 'int'}} +static const uint64_t overflow = 1 * 4608 * 1024 * 1024; // expected-warning {{overflow in expression; result is 536'870'912 with type 'int'}} uint64_t check_integer_overflows(int i) { //expected-note 0+{{declared here}} -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} uint64_t overflow = 4608 * 1024 * 1024, -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} overflow2 = (uint64_t)(4608 * 1024 * 1024), -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} overflow3 = (uint64_t)(4608 * 1024 * 1024 * i), -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} overflow4 = (1ULL * ((4608) * ((1024) * (1024))) + 2ULL), -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} overflow5 = static_cast<uint64_t>(4608 * 1024 * 1024), -// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 2{{overflow in expression; result is 536'870'912 with type 'int'}} multi_overflow = (uint64_t)((uint64_t)(4608 * 1024 * 1024) * (uint64_t)(4608 * 1024 * 1024)); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} overflow += overflow2 = overflow3 = (uint64_t)(4608 * 1024 * 1024); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} overflow += overflow2 = overflow3 = 4608 * 1024 * 1024; -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} overflow += overflow2 = overflow3 = static_cast<uint64_t>(4608 * 1024 * 1024); uint64_t not_overflow = 4608 * 1024 * 1024ULL; uint64_t not_overflow2 = (1ULL * ((uint64_t)(4608) * (1024 * 1024)) + 2ULL); -// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 2{{overflow in expression; result is 536'870'912 with type 'int'}} overflow = 4608 * 1024 * 1024 ? 4608 * 1024 * 1024 : 0; -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} overflow = 0 ? 0 : 4608 * 1024 * 1024; -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} if (4608 * 1024 * 1024) return 0; -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} if ((uint64_t)(4608 * 1024 * 1024)) return 1; -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} if (static_cast<uint64_t>(4608 * 1024 * 1024)) return 1; -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} if ((uint64_t)(4608 * 1024 * 1024)) return 2; -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} if ((uint64_t)(4608 * 1024 * 1024 * i)) return 3; -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} if ((1ULL * ((4608) * ((1024) * (1024))) + 2ULL)) return 4; -// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 2{{overflow in expression; result is 536'870'912 with type 'int'}} if ((uint64_t)((uint64_t)(4608 * 1024 * 1024) * (uint64_t)(4608 * 1024 * 1024))) return 5; #if __cplusplus < 201103L switch (i) { -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} case 4608 * 1024 * 1024: return 6; -// expected-warning@+1 {{overflow in expression; result is 537919488 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 537'919'488 with type 'int'}} case (uint64_t)(4609 * 1024 * 1024): return 7; -// expected-warning@+1 {{overflow in expression; result is 537919488 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 537'919'488 with type 'int'}} case 1 + static_cast<uint64_t>(4609 * 1024 * 1024): return 7; // expected-error@+1 {{expression is not an integral constant expression}} case ((uint64_t)(4608 * 1024 * 1024 * i)): return 8; -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} case ((1ULL * ((4608) * ((1024) * (1024))) + 2ULL)): return 9; -// expected-warning@+2 2{{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+2 2{{overflow in expression; result is 536'870'912 with type 'int'}} // expected-warning@+1 {{overflow converting case value to switch condition type (288230376151711744 to 0)}} case ((uint64_t)((uint64_t)(4608 * 1024 * 1024) * (uint64_t)(4608 * 1024 * 1024))): return 10; } #endif -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} while (4608 * 1024 * 1024); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} while ((uint64_t)(4608 * 1024 * 1024)); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} while (static_cast<uint64_t>(4608 * 1024 * 1024)); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} while ((uint64_t)(4608 * 1024 * 1024)); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} while ((uint64_t)(4608 * 1024 * 1024 * i)); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} while ((1ULL * ((4608) * ((1024) * (1024))) + 2ULL)); -// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 2{{overflow in expression; result is 536'870'912 with type 'int'}} while ((uint64_t)((uint64_t)(4608 * 1024 * 1024) * (uint64_t)(4608 * 1024 * 1024))); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} do { } while (4608 * 1024 * 1024); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} do { } while ((uint64_t)(4608 * 1024 * 1024)); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} do { } while (static_cast<uint64_t>(4608 * 1024 * 1024)); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} do { } while ((uint64_t)(4608 * 1024 * 1024)); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} do { } while ((uint64_t)(4608 * 1024 * 1024 * i)); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} do { } while ((1ULL * ((4608) * ((1024) * (1024))) + 2ULL)); -// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 2{{overflow in expression; result is 536'870'912 with type 'int'}} do { } while ((uint64_t)((uint64_t)(4608 * 1024 * 1024) * (uint64_t)(4608 * 1024 * 1024))); -// expected-warning@+3 {{overflow in expression; result is 536870912 with type 'int'}} -// expected-warning@+3 {{overflow in expression; result is 536870912 with type 'int'}} -// expected-warning@+3 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+3 {{overflow in expression; result is 536'870'912 with type 'int'}} +// expected-warning@+3 {{overflow in expression; result is 536'870'912 with type 'int'}} +// expected-warning@+3 {{overflow in expression; result is 536'870'912 with type 'int'}} for (uint64_t i = 4608 * 1024 * 1024; (uint64_t)(4608 * 1024 * 1024); i += (uint64_t)(4608 * 1024 * 1024 * i)); -// expected-warning@+3 {{overflow in expression; result is 536870912 with type 'int'}} -// expected-warning@+3 2{{overflow in expression; result is 536870912 with type 'int'}} -// expected-warning@+3 2{{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+3 {{overflow in expression; result is 536'870'912 with type 'int'}} +// expected-warning@+3 2{{overflow in expression; result is 536'870'912 with type 'int'}} +// expected-warning@+3 2{{overflow in expression; result is 536'870'912 with type 'int'}} for (uint64_t i = (1ULL * ((4608) * ((1024) * (1024))) + 2ULL); ((uint64_t)((uint64_t)(4608 * 1024 * 1024) * (uint64_t)(4608 * 1024 * 1024))); i = ((4608 * 1024 * 1024) + ((uint64_t)(4608 * 1024 * 1024)))); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} _Complex long long x = 4608 * 1024 * 1024; -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} (__real__ x) = 4608 * 1024 * 1024; -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} (__imag__ x) = 4608 * 1024 * 1024; -// expected-warning@+2 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+2 {{overflow in expression; result is 536'870'912 with type 'int'}} uint64_t a[10]; a[4608 * 1024 * 1024] = 1; #if __cplusplus < 201103L @@ -171,22 +171,22 @@ uint64_t check_integer_overflows(int i) { //expected-note 0+{{declared here}} // expected-note@-4 {{array 'a' declared here}} #endif -// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 2{{overflow in expression; result is 536'870'912 with type 'int'}} return ((4608 * 1024 * 1024) + ((uint64_t)(4608 * 1024 * 1024))); } void check_integer_overflows_in_function_calls() { -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} (void)f0(4608 * 1024 * 1024); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} uint64_t x = f0(4608 * 1024 * 1024); -// expected-warning@+2 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+2 {{overflow in expression; result is 536'870'912 with type 'int'}} uint64_t (*f0_ptr)(uint64_t) = &f0; (void)(*f0_ptr)(4608 * 1024 * 1024); -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} (void)f2(0, f0(4608 * 1024 * 1024)); } @@ -237,8 +237,8 @@ u_ptr<bool> Wrap(int64_t x) { int64_t Pass(int64_t x) { return x; } int m() { - int64_t x = Pass(30 * 24 * 60 * 59 * 1000); // expected-warning {{overflow in expression; result is -1746167296 with type 'int'}} - auto r = Wrap(Pass(30 * 24 * 60 * 59 * 1000)); // expected-warning {{overflow in expression; result is -1746167296 with type 'int'}} + int64_t x = Pass(30 * 24 * 60 * 59 * 1000); // expected-warning {{overflow in expression; result is -1'746'167'296 with type 'int'}} + auto r = Wrap(Pass(30 * 24 * 60 * 59 * 1000)); // expected-warning {{overflow in expression; result is -1'746'167'296 with type 'int'}} return 0; } } diff --git a/clang/test/SemaObjC/integer-overflow.m b/clang/test/SemaObjC/integer-overflow.m index 6d82e2951c1e6..255142729f8d5 100644 --- a/clang/test/SemaObjC/integer-overflow.m +++ b/clang/test/SemaObjC/integer-overflow.m @@ -9,10 +9,10 @@ - (int)add:(int)a with:(int)b { } - (void)testIntegerOverflows { -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} (void)[self add:0 with:4608 * 1024 * 1024]; -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} +// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}} (void)[self add:0 with:[self add:4608 * 1024 * 1024 with:0]]; } @end diff --git a/clang/test/SemaObjC/objc-literal-nsnumber.m b/clang/test/SemaObjC/objc-literal-nsnumber.m index aa7dc955fb5fe..a6c098947b0b2 100644 --- a/clang/test/SemaObjC/objc-literal-nsnumber.m +++ b/clang/test/SemaObjC/objc-literal-nsnumber.m @@ -64,7 +64,7 @@ int main(void) { @-five; // expected-error{{@- must be followed by a number to form an NSNumber object}} @+five; // expected-error{{@+ must be followed by a number to form an NSNumber object}} NSNumber *av = @(1391126400000); - NSNumber *bv = @(1391126400 * 1000); // expected-warning {{overflow in expression; result is -443003904 with type 'int'}} + NSNumber *bv = @(1391126400 * 1000); // expected-warning {{overflow in expression; result is -443'003'904 with type 'int'}} NSNumber *cv = @(big * thousand); } diff --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h index 6f2f25548cc84..dd6d71b93334b 100644 --- a/llvm/include/llvm/ADT/APInt.h +++ b/llvm/include/llvm/ADT/APInt.h @@ -1626,7 +1626,8 @@ class [[nodiscard]] APInt { /// SmallString. If Radix > 10, UpperCase determine the case of letter /// digits. void toString(SmallVectorImpl<char> &Str, unsigned Radix, bool Signed, - bool formatAsCLiteral = false, bool UpperCase = true) const; + bool formatAsCLiteral = false, bool UpperCase = true, + bool insertSeparators = false) const; /// Considers the APInt to be unsigned and converts it into a string in the /// radix given. The radix can be 2, 8, 10 16, or 36. diff --git a/llvm/include/llvm/ADT/StringExtras.h b/llvm/include/llvm/ADT/StringExtras.h index a24368924bc90..32f5828c92d05 100644 --- a/llvm/include/llvm/ADT/StringExtras.h +++ b/llvm/include/llvm/ADT/StringExtras.h @@ -329,9 +329,10 @@ inline std::string itostr(int64_t X) { } inline std::string toString(const APInt &I, unsigned Radix, bool Signed, - bool formatAsCLiteral = false) { + bool formatAsCLiteral = false, + bool upperCase = true, bool addSeparators = false) { SmallString<40> S; - I.toString(S, Radix, Signed, formatAsCLiteral); + I.toString(S, Radix, Signed, formatAsCLiteral, upperCase, addSeparators); return std::string(S); } diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp index 05b1526da95ff..a186b81bc6797 100644 --- a/llvm/lib/Support/APInt.cpp +++ b/llvm/lib/Support/APInt.cpp @@ -2161,7 +2161,8 @@ void APInt::fromString(unsigned numbits, StringRef str, uint8_t radix) { } void APInt::toString(SmallVectorImpl<char> &Str, unsigned Radix, bool Signed, - bool formatAsCLiteral, bool UpperCase) const { + bool formatAsCLiteral, bool UpperCase, + bool insertSeparators) const { assert((Radix == 10 || Radix == 8 || Radix == 16 || Radix == 2 || Radix == 36) && "Radix should be 2, 8, 10, 16, or 36!"); @@ -2187,6 +2188,12 @@ void APInt::toString(SmallVectorImpl<char> &Str, unsigned Radix, bool Signed, } } + // Number of digits in a group between separators + int Grouping = 4; + if (Radix == 8 || Radix == 10) { + Grouping = 3; + } + // First, check for a zero value and just short circuit the logic below. if (isZero()) { while (*Prefix) { @@ -2223,9 +2230,14 @@ void APInt::toString(SmallVectorImpl<char> &Str, unsigned Radix, bool Signed, ++Prefix; }; + int Pos = 0; while (N) { + if (insertSeparators && Pos % Grouping == 0 && Pos > 0) { + *--BufPtr = '\''; + } *--BufPtr = Digits[N % Radix]; N /= Radix; + Pos++; } Str.append(BufPtr, std::end(Buffer)); return; @@ -2257,17 +2269,27 @@ void APInt::toString(SmallVectorImpl<char> &Str, unsigned Radix, bool Signed, unsigned ShiftAmt = (Radix == 16 ? 4 : (Radix == 8 ? 3 : 1)); unsigned MaskAmt = Radix - 1; + int Pos = 0; while (Tmp.getBoolValue()) { unsigned Digit = unsigned(Tmp.getRawData()[0]) & MaskAmt; + if (insertSeparators && Pos % Grouping == 0 && Pos > 0) { + Str.push_back('\''); + } Str.push_back(Digits[Digit]); Tmp.lshrInPlace(ShiftAmt); + Pos++; } } else { + int Pos = 0; while (Tmp.getBoolValue()) { uint64_t Digit; udivrem(Tmp, Radix, Tmp, Digit); assert(Digit < Radix && "divide failed"); + if (insertSeparators && Pos % Grouping == 0 && Pos > 0) { + Str.push_back('\''); + } Str.push_back(Digits[Digit]); + Pos++; } } diff --git a/llvm/unittests/ADT/APIntTest.cpp b/llvm/unittests/ADT/APIntTest.cpp index 3b909f8f7d14e..e3e7e1e7bac65 100644 --- a/llvm/unittests/ADT/APIntTest.cpp +++ b/llvm/unittests/ADT/APIntTest.cpp @@ -1379,6 +1379,23 @@ TEST(APIntTest, toString) { EXPECT_EQ(std::string(S), "0"); S.clear(); + // with separators + APInt(64, 140).toString(S, 2, false, true, false, true); + EXPECT_EQ(std::string(S), "0b1000'1100"); + S.clear(); + APInt(64, 1024).toString(S, 8, false, true, false, true); + EXPECT_EQ(std::string(S), "02'000"); + S.clear(); + APInt(64, 1000000).toString(S, 10, false, true, false, true); + EXPECT_EQ(std::string(S), "1'000'000"); + S.clear(); + APInt(64, 1000000).toString(S, 16, false, true, true, true); + EXPECT_EQ(std::string(S), "0xF'4240"); + S.clear(); + APInt(64, 1'000'000'000).toString(S, 36, false, false, false, true); + EXPECT_EQ(std::string(S), "gj'dgxs"); + S.clear(); + isSigned = false; APInt(8, 255, isSigned).toString(S, 2, isSigned, true); EXPECT_EQ(std::string(S), "0b11111111"); @@ -1415,6 +1432,24 @@ TEST(APIntTest, toString) { APInt(8, 255, isSigned).toString(S, 36, isSigned, false); EXPECT_EQ(std::string(S), "-1"); S.clear(); + + // negative with separators + APInt(64, -140, isSigned).toString(S, 2, isSigned, true, false, true); + EXPECT_EQ(std::string(S), "-0b1000'1100"); + S.clear(); + APInt(64, -1024, isSigned).toString(S, 8, isSigned, true, false, true); + EXPECT_EQ(std::string(S), "-02'000"); + S.clear(); + APInt(64, -1000000, isSigned).toString(S, 10, isSigned, true, false, true); + EXPECT_EQ(std::string(S), "-1'000'000"); + S.clear(); + APInt(64, -1000000, isSigned).toString(S, 16, isSigned, true, true, true); + EXPECT_EQ(std::string(S), "-0xF'4240"); + S.clear(); + APInt(64, -1'000'000'000, isSigned) + .toString(S, 36, isSigned, false, false, true); + EXPECT_EQ(std::string(S), "-gj'dgxs"); + S.clear(); } TEST(APIntTest, Log2) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits