https://github.com/Atousa updated https://github.com/llvm/llvm-project/pull/80939
>From ac75fc2873fc7b8eec6c24ba97f4673e94457c8e Mon Sep 17 00:00:00 2001 From: Atousa Duprat <atous...@gmail.com> Date: Tue, 6 Feb 2024 21:02:05 -0800 Subject: [PATCH 1/8] [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 | 6 +- clang/test/AST/Interp/c.c | 4 +- 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 | 112 ++++++++++---------- 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 ++++++ 14 files changed, 185 insertions(+), 124 deletions(-) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 089bc2094567f7..d9037072c6767f 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; @@ -13852,7 +13853,8 @@ bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { if (Info.checkingForUndefinedBehavior()) Info.Ctx.getDiagnostics().Report(E->getExprLoc(), diag::warn_integer_constant_overflow) - << toString(Value, 10) << E->getType() << E->getSourceRange(); + << toString(Value, 10, Value.isSigned(), false, true, true) + << E->getType() << E->getSourceRange(); if (!HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1), E->getType())) diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c index 9ab271a82aeef9..aa067b0bc74831 100644 --- a/clang/test/AST/Interp/c.c +++ b/clang/test/AST/Interp/c.c @@ -109,9 +109,9 @@ int somefunc(int i) { // pedantic-expected-warning {{left operand of comma operator has no effect}} \ // pedantic-expected-warning {{overflow in expression; result is 131073}} \ // ref-warning {{left operand of comma operator has no effect}} \ - // ref-warning {{overflow in expression; result is 131073}} \ + // ref-warning {{overflow in expression; result is 131'073}} \ // pedantic-ref-warning {{left operand of comma operator has no effect}} \ - // pedantic-ref-warning {{overflow in expression; result is 131073}} + // pedantic-ref-warning {{overflow in expression; result is 131'073}} } diff --git a/clang/test/C/drs/dr0xx.c b/clang/test/C/drs/dr0xx.c index d9c1fbe4ee40ab..c93cfb63d604cf 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 9c8d77518ab55e..1b68b65acca6af 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 cf822f346e8b29..220fc1bed515a1 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 95e64748fb1fbf..09221990ac11d3 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 fc65fd16f8c302..c482b3c571ab4a 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 0e8ad050aa14d8..6049458b93bbd0 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)); } @@ -211,7 +211,7 @@ namespace EvaluationCrashes { namespace GH31643 { void f() { - int a = -(1<<31); // expected-warning {{overflow in expression; result is -2147483648 with type 'int'}} + int a = -(1<<31); // expected-warning {{overflow in expression; result is -2'147'483'648 with type 'int'}} } } @@ -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 6d82e2951c1e65..255142729f8d56 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 aa7dc955fb5feb..a6c098947b0b2a 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 6f2f25548cc84b..dd6d71b93334bb 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 a24368924bc90a..32f5828c92d05c 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 05b1526da95ff7..a186b81bc6797f 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 3b909f8f7d14e2..e3e7e1e7bac65d 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) { >From 4f2509a845f819899c8d9c6e2077c4c3e5db98aa Mon Sep 17 00:00:00 2001 From: Atousa Duprat <atous...@gmail.com> Date: Mon, 12 Feb 2024 12:50:13 -0800 Subject: [PATCH 2/8] Update clang/lib/AST/ExprConstant.cpp Co-authored-by: Timm Baeder <tbae...@redhat.com> --- clang/lib/AST/ExprConstant.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index cb2f372311826a..1ae1c99b31d4b0 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -2774,7 +2774,7 @@ 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, Result.isSigned(), false, true, true) + << toString(Result, 10, Result.isSigned(), /*formatAsCLiteral=*/false, /*upperCase=*/true, /*insertSeparators=*/true) << E->getType() << E->getSourceRange(); return HandleOverflow(Info, E, Value, E->getType()); } >From ba7bb34c90a8b28ac14779283793eea2c3792d6a Mon Sep 17 00:00:00 2001 From: Atousa Duprat <atous...@gmail.com> Date: Mon, 12 Feb 2024 12:50:23 -0800 Subject: [PATCH 3/8] Update llvm/lib/Support/APInt.cpp Co-authored-by: Timm Baeder <tbae...@redhat.com> --- llvm/lib/Support/APInt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp index a186b81bc6797f..1087fa13a9a276 100644 --- a/llvm/lib/Support/APInt.cpp +++ b/llvm/lib/Support/APInt.cpp @@ -2188,7 +2188,7 @@ void APInt::toString(SmallVectorImpl<char> &Str, unsigned Radix, bool Signed, } } - // Number of digits in a group between separators + // Number of digits in a group between separators. int Grouping = 4; if (Radix == 8 || Radix == 10) { Grouping = 3; >From 9632dcb3737216f569374ec6cf1ca1bb7b237c2b Mon Sep 17 00:00:00 2001 From: Atousa Duprat <atous...@gmail.com> Date: Mon, 12 Feb 2024 12:51:29 -0800 Subject: [PATCH 4/8] Update llvm/lib/Support/APInt.cpp Co-authored-by: Timm Baeder <tbae...@redhat.com> --- llvm/lib/Support/APInt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp index 1087fa13a9a276..65f265a667f93b 100644 --- a/llvm/lib/Support/APInt.cpp +++ b/llvm/lib/Support/APInt.cpp @@ -2189,7 +2189,7 @@ void APInt::toString(SmallVectorImpl<char> &Str, unsigned Radix, bool Signed, } // Number of digits in a group between separators. - int Grouping = 4; + unsigned Grouping = (Radix == 8 || Radix == 10) ? 3 : 4; if (Radix == 8 || Radix == 10) { Grouping = 3; } >From 30ed47b6c5ff2d29e24d2d3b8054b75983040252 Mon Sep 17 00:00:00 2001 From: Atousa Duprat <atous...@gmail.com> Date: Tue, 13 Feb 2024 21:19:25 -0800 Subject: [PATCH 5/8] Update printing APInt numbers with separators The new constant interpreter can also emit integer constant overflow warnings. The code was updated to also print these with separators. --- clang/lib/AST/ExprConstant.cpp | 6 ++++-- clang/lib/AST/Interp/Interp.h | 12 +++++++++--- clang/test/AST/Interp/c.c | 2 +- llvm/lib/Support/APInt.cpp | 3 --- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index ce44a8a968cf5a..9ef60f79ea9e6a 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -2778,7 +2778,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, Result.isSigned(), /*formatAsCLiteral=*/false, /*upperCase=*/true, /*insertSeparators=*/true) + << toString(Result, 10, Result.isSigned(), /*formatAsCLiteral=*/false, + /*upperCase=*/true, /*insertSeparators=*/true) << E->getType() << E->getSourceRange(); return HandleOverflow(Info, E, Value, E->getType()); } @@ -13858,7 +13859,8 @@ bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { if (Info.checkingForUndefinedBehavior()) Info.Ctx.getDiagnostics().Report(E->getExprLoc(), diag::warn_integer_constant_overflow) - << toString(Value, 10, Value.isSigned(), false, true, true) + << toString(Value, 10, Value.isSigned(), /*formatAsCLiteral=*/false, + /*upperCase=*/true, /*insertSeparators=*/true) << E->getType() << E->getSourceRange(); if (!HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1), diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index e2fda18e3f44d4..c265171d58215d 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -285,7 +285,9 @@ bool AddSubMulHelper(InterpState &S, CodePtr OpPC, unsigned Bits, const T &LHS, QualType Type = E->getType(); if (S.checkingForUndefinedBehavior()) { SmallString<32> Trunc; - Value.trunc(Result.bitWidth()).toString(Trunc, 10); + Value.trunc(Result.bitWidth()) + .toString(Trunc, 10, Result.isSigned(), /*formatAsCLiteral=*/false, + /*upperCase=*/true, /*insertSeparators=*/true); auto Loc = E->getExprLoc(); S.report(Loc, diag::warn_integer_constant_overflow) << Trunc << Type << E->getSourceRange(); @@ -497,7 +499,9 @@ bool Neg(InterpState &S, CodePtr OpPC) { if (S.checkingForUndefinedBehavior()) { SmallString<32> Trunc; - NegatedValue.trunc(Result.bitWidth()).toString(Trunc, 10); + NegatedValue.trunc(Result.bitWidth()) + .toString(Trunc, 10, Result.isSigned(), /*formatAsCLiteral=*/false, + /*upperCase=*/true, /*insertSeparators=*/true); auto Loc = E->getExprLoc(); S.report(Loc, diag::warn_integer_constant_overflow) << Trunc << Type << E->getSourceRange(); @@ -554,7 +558,9 @@ bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { QualType Type = E->getType(); if (S.checkingForUndefinedBehavior()) { SmallString<32> Trunc; - APResult.trunc(Result.bitWidth()).toString(Trunc, 10); + APResult.trunc(Result.bitWidth()) + .toString(Trunc, 10, Result.isSigned(), /*formatAsCLiteral=*/false, + /*upperCase=*/true, /*insertSeparators=*/true); auto Loc = E->getExprLoc(); S.report(Loc, diag::warn_integer_constant_overflow) << Trunc << Type << E->getSourceRange(); diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c index 532e1c7369e58e..02a031da7e105c 100644 --- a/clang/test/AST/Interp/c.c +++ b/clang/test/AST/Interp/c.c @@ -91,7 +91,7 @@ int chooseexpr[__builtin_choose_expr(1, 1, expr)]; int somefunc(int i) { return (i, 65537) * 65537; // all-warning {{left operand of comma operator has no effect}} \ - // all-warning {{overflow in expression; result is 131'073}} + // all-warning {{overflow in expression; result is 131'073 with type 'int'}} } /// FIXME: The following test is incorrect in the new interpreter. diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp index 65f265a667f93b..9206997924ba3a 100644 --- a/llvm/lib/Support/APInt.cpp +++ b/llvm/lib/Support/APInt.cpp @@ -2190,9 +2190,6 @@ void APInt::toString(SmallVectorImpl<char> &Str, unsigned Radix, bool Signed, // Number of digits in a group between separators. unsigned Grouping = (Radix == 8 || Radix == 10) ? 3 : 4; - if (Radix == 8 || Radix == 10) { - Grouping = 3; - } // First, check for a zero value and just short circuit the logic below. if (isZero()) { >From 5ff2197dee2fdc043697b5cecbeaebe011cf4147 Mon Sep 17 00:00:00 2001 From: Atousa Duprat <atous...@gmail.com> Date: Fri, 1 Mar 2024 13:01:40 -0800 Subject: [PATCH 6/8] [clang][NFC] Update code style conventions --- clang/docs/ReleaseNotes.rst | 3 +++ llvm/include/llvm/ADT/APInt.h | 2 +- llvm/include/llvm/ADT/StringExtras.h | 4 ++-- llvm/lib/Support/APInt.cpp | 13 ++++++------- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 402a2f8687386c..579664238d5dce 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -156,6 +156,9 @@ Improvements to Clang's diagnostics - The ``-Wshorten-64-to-32`` diagnostic is now grouped under ``-Wimplicit-int-conversion`` instead of ``-Wconversion``. Fixes `#69444 <https://github.com/llvm/llvm-project/issues/69444>`_. +- Clang now uses thousand separators when printing large numbers in integer overflow diagnostics. + Fixes `#80939 <https://github.com/llvm/llvm-project/issues/80939>`_. + Improvements to Clang's time-trace ---------------------------------- diff --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h index dd6d71b93334bb..7795e2625f9346 100644 --- a/llvm/include/llvm/ADT/APInt.h +++ b/llvm/include/llvm/ADT/APInt.h @@ -1627,7 +1627,7 @@ class [[nodiscard]] APInt { /// digits. void toString(SmallVectorImpl<char> &Str, unsigned Radix, bool Signed, bool formatAsCLiteral = false, bool UpperCase = true, - bool insertSeparators = false) const; + 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 32f5828c92d05c..9e44b155c09355 100644 --- a/llvm/include/llvm/ADT/StringExtras.h +++ b/llvm/include/llvm/ADT/StringExtras.h @@ -330,9 +330,9 @@ inline std::string itostr(int64_t X) { inline std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral = false, - bool upperCase = true, bool addSeparators = false) { + bool UpperCase = true, bool InsertSeparators = false) { SmallString<40> S; - I.toString(S, Radix, Signed, formatAsCLiteral, upperCase, addSeparators); + I.toString(S, Radix, Signed, formatAsCLiteral, UpperCase, InsertSeparators); return std::string(S); } diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp index 9206997924ba3a..2464db5a48215e 100644 --- a/llvm/lib/Support/APInt.cpp +++ b/llvm/lib/Support/APInt.cpp @@ -2162,7 +2162,7 @@ void APInt::fromString(unsigned numbits, StringRef str, uint8_t radix) { void APInt::toString(SmallVectorImpl<char> &Str, unsigned Radix, bool Signed, bool formatAsCLiteral, bool UpperCase, - bool insertSeparators) const { + bool InsertSeparators) const { assert((Radix == 10 || Radix == 8 || Radix == 16 || Radix == 2 || Radix == 36) && "Radix should be 2, 8, 10, 16, or 36!"); @@ -2229,9 +2229,8 @@ void APInt::toString(SmallVectorImpl<char> &Str, unsigned Radix, bool Signed, int Pos = 0; while (N) { - if (insertSeparators && Pos % Grouping == 0 && Pos > 0) { + if (InsertSeparators && Pos % Grouping == 0 && Pos > 0) *--BufPtr = '\''; - } *--BufPtr = Digits[N % Radix]; N /= Radix; Pos++; @@ -2269,9 +2268,9 @@ void APInt::toString(SmallVectorImpl<char> &Str, unsigned Radix, bool Signed, int Pos = 0; while (Tmp.getBoolValue()) { unsigned Digit = unsigned(Tmp.getRawData()[0]) & MaskAmt; - if (insertSeparators && Pos % Grouping == 0 && Pos > 0) { + if (InsertSeparators && Pos % Grouping == 0 && Pos > 0) Str.push_back('\''); - } + Str.push_back(Digits[Digit]); Tmp.lshrInPlace(ShiftAmt); Pos++; @@ -2282,9 +2281,9 @@ void APInt::toString(SmallVectorImpl<char> &Str, unsigned Radix, bool Signed, uint64_t Digit; udivrem(Tmp, Radix, Tmp, Digit); assert(Digit < Radix && "divide failed"); - if (insertSeparators && Pos % Grouping == 0 && Pos > 0) { + if (InsertSeparators && Pos % Grouping == 0 && Pos > 0) Str.push_back('\''); - } + Str.push_back(Digits[Digit]); Pos++; } >From ec25d26f9dd2da903b261f66031d20731314b12b Mon Sep 17 00:00:00 2001 From: Atousa Duprat <atous...@gmail.com> Date: Fri, 1 Mar 2024 13:01:40 -0800 Subject: [PATCH 7/8] [clang][NFC] Update code style conventions --- llvm/include/llvm/ADT/StringExtras.h | 3 ++- llvm/lib/Support/APInt.cpp | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/llvm/include/llvm/ADT/StringExtras.h b/llvm/include/llvm/ADT/StringExtras.h index 9e44b155c09355..20e6ad1f68f996 100644 --- a/llvm/include/llvm/ADT/StringExtras.h +++ b/llvm/include/llvm/ADT/StringExtras.h @@ -330,7 +330,8 @@ inline std::string itostr(int64_t X) { inline std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral = false, - bool UpperCase = true, bool InsertSeparators = false) { + bool UpperCase = true, + bool InsertSeparators = false) { SmallString<40> S; I.toString(S, Radix, Signed, formatAsCLiteral, UpperCase, InsertSeparators); return std::string(S); diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp index 2464db5a48215e..e686b976523302 100644 --- a/llvm/lib/Support/APInt.cpp +++ b/llvm/lib/Support/APInt.cpp @@ -2229,7 +2229,7 @@ void APInt::toString(SmallVectorImpl<char> &Str, unsigned Radix, bool Signed, int Pos = 0; while (N) { - if (InsertSeparators && Pos % Grouping == 0 && Pos > 0) + if (InsertSeparators && Pos % Grouping == 0 && Pos > 0) *--BufPtr = '\''; *--BufPtr = Digits[N % Radix]; N /= Radix; @@ -2268,7 +2268,7 @@ void APInt::toString(SmallVectorImpl<char> &Str, unsigned Radix, bool Signed, int Pos = 0; while (Tmp.getBoolValue()) { unsigned Digit = unsigned(Tmp.getRawData()[0]) & MaskAmt; - if (InsertSeparators && Pos % Grouping == 0 && Pos > 0) + if (InsertSeparators && Pos % Grouping == 0 && Pos > 0) Str.push_back('\''); Str.push_back(Digits[Digit]); >From a23fdfb00761fcf0f66b6c2d0d4cd4f31ec6dcc7 Mon Sep 17 00:00:00 2001 From: Atousa Duprat <atous...@gmail.com> Date: Mon, 4 Mar 2024 09:41:17 -0800 Subject: [PATCH 8/8] [clang][NFC] Update code style conventions --- clang/docs/ReleaseNotes.rst | 2 +- clang/lib/AST/ExprConstant.cpp | 4 ++-- clang/lib/AST/Interp/Interp.h | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index b85298f47583fa..34d6fead2a8aff 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -176,7 +176,7 @@ Improvements to Clang's diagnostics of ``-Wconversion``. Fixes `#69444 <https://github.com/llvm/llvm-project/issues/69444>`_. - Clang now uses thousand separators when printing large numbers in integer overflow diagnostics. - Fixes `#80939 <https://github.com/llvm/llvm-project/issues/80939>`_. + Fixes #GH80939. - Clang now diagnoses friend declarations with an ``enum`` elaborated-type-specifier in language modes after C++98. diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 312e097509fa7a..4b6ccafbb7f0ed 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -2779,7 +2779,7 @@ static bool CheckedIntArithmetic(EvalInfo &Info, const Expr *E, Info.Ctx.getDiagnostics().Report(E->getExprLoc(), diag::warn_integer_constant_overflow) << toString(Result, 10, Result.isSigned(), /*formatAsCLiteral=*/false, - /*upperCase=*/true, /*insertSeparators=*/true) + /*UpperCase=*/true, /*InsertSeparators=*/true) << E->getType() << E->getSourceRange(); return HandleOverflow(Info, E, Value, E->getType()); } @@ -13913,7 +13913,7 @@ bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { Info.Ctx.getDiagnostics().Report(E->getExprLoc(), diag::warn_integer_constant_overflow) << toString(Value, 10, Value.isSigned(), /*formatAsCLiteral=*/false, - /*upperCase=*/true, /*insertSeparators=*/true) + /*UpperCase=*/true, /*InsertSeparators=*/true) << E->getType() << E->getSourceRange(); if (!HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1), diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index 7e2123e9b68d52..7da536de233935 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -289,7 +289,7 @@ bool AddSubMulHelper(InterpState &S, CodePtr OpPC, unsigned Bits, const T &LHS, SmallString<32> Trunc; Value.trunc(Result.bitWidth()) .toString(Trunc, 10, Result.isSigned(), /*formatAsCLiteral=*/false, - /*upperCase=*/true, /*insertSeparators=*/true); + /*UpperCase=*/true, /*InsertSeparators=*/true); auto Loc = E->getExprLoc(); S.report(Loc, diag::warn_integer_constant_overflow) << Trunc << Type << E->getSourceRange(); @@ -503,7 +503,7 @@ bool Neg(InterpState &S, CodePtr OpPC) { SmallString<32> Trunc; NegatedValue.trunc(Result.bitWidth()) .toString(Trunc, 10, Result.isSigned(), /*formatAsCLiteral=*/false, - /*upperCase=*/true, /*insertSeparators=*/true); + /*UpperCase=*/true, /*InsertSeparators=*/true); auto Loc = E->getExprLoc(); S.report(Loc, diag::warn_integer_constant_overflow) << Trunc << Type << E->getSourceRange(); @@ -567,7 +567,7 @@ bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { SmallString<32> Trunc; APResult.trunc(Result.bitWidth()) .toString(Trunc, 10, Result.isSigned(), /*formatAsCLiteral=*/false, - /*upperCase=*/true, /*insertSeparators=*/true); + /*UpperCase=*/true, /*InsertSeparators=*/true); auto Loc = E->getExprLoc(); S.report(Loc, diag::warn_integer_constant_overflow) << Trunc << Type << E->getSourceRange(); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits