[clang] [llvm] [clang] Use separator for large numeric values in overflow diagnostic (PR #80939)

Atousa Duprat via cfe-commits cfe-commits at lists.llvm.org
Fri Mar 1 13:04:25 PST 2024


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 <atousa.p at gmail.com>
Date: Tue, 6 Feb 2024 21:02:05 -0800
Subject: [PATCH 1/6] [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 at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   uint64_t overflow = 4608 * 1024 * 1024,
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
            overflow2 = (uint64_t)(4608 * 1024 * 1024),
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
            overflow3 = (uint64_t)(4608 * 1024 * 1024 * i),
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
            overflow4 =  (1ULL * ((4608) * ((1024) * (1024))) + 2ULL),
-// expected-warning at +1 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +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 at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   overflow += overflow2 = overflow3 = (uint64_t)(4608 * 1024 * 1024);
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +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 at +1 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 2{{overflow in expression; result is 536'870'912 with type 'int'}}
   overflow = 4608 * 1024 * 1024 ?  4608 * 1024 * 1024 : 0;
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   overflow =  0 ? 0 : 4608 * 1024 * 1024;
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   if (4608 * 1024 * 1024)
     return 0;
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   if ((uint64_t)(4608 * 1024 * 1024))
     return 1;
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   if ((uint64_t)(4608 * 1024 * 1024))
     return 2;
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   if ((uint64_t)(4608 * 1024 * 1024 * i))
     return 3;
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   if ((1ULL * ((4608) * ((1024) * (1024))) + 2ULL))
     return 4;
 
-// expected-warning at +1 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +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 at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   case 4608 * 1024 * 1024:
     return 6;
-// expected-warning at +1 {{overflow in expression; result is 537919488 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 537'919'488 with type 'int'}}
   case (uint64_t)(4609 * 1024 * 1024):
     return 7;
 // expected-error at +1 {{expression is not an integer constant expression}}
   case ((uint64_t)(4608 * 1024 * 1024 * i)):
     return 8;
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   case ((1ULL * ((4608) * ((1024) * (1024))) + 2ULL)):
     return 9;
-// expected-warning at +2 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +2 2{{overflow in expression; result is 536'870'912 with type 'int'}}
 // expected-warning at +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 at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   while (4608 * 1024 * 1024);
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   while ((uint64_t)(4608 * 1024 * 1024));
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   while ((uint64_t)(4608 * 1024 * 1024));
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   while ((uint64_t)(4608 * 1024 * 1024 * i));
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   while ((1ULL * ((4608) * ((1024) * (1024))) + 2ULL));
 
-// expected-warning at +1 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +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 at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   do { } while (4608 * 1024 * 1024);
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   do { } while ((uint64_t)(4608 * 1024 * 1024));
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   do { } while ((uint64_t)(4608 * 1024 * 1024));
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   do { } while ((uint64_t)(4608 * 1024 * 1024 * i));
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   do { } while ((1ULL * ((4608) * ((1024) * (1024))) + 2ULL));
 
-// expected-warning at +1 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +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 at +3 {{overflow in expression; result is 536870912 with type 'int'}}
-// expected-warning at +3 {{overflow in expression; result is 536870912 with type 'int'}}
-// expected-warning at +3 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +3 {{overflow in expression; result is 536'870'912 with type 'int'}}
+// expected-warning at +3 {{overflow in expression; result is 536'870'912 with type 'int'}}
+// expected-warning at +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 at +3 {{overflow in expression; result is 536870912 with type 'int'}}
-// expected-warning at +3 2{{overflow in expression; result is 536870912 with type 'int'}}
-// expected-warning at +3 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +3 {{overflow in expression; result is 536'870'912 with type 'int'}}
+// expected-warning at +3 2{{overflow in expression; result is 536'870'912 with type 'int'}}
+// expected-warning at +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 at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   _Complex long long x = 4608 * 1024 * 1024;
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   (__real__ x) = 4608 * 1024 * 1024;
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   (__imag__ x) = 4608 * 1024 * 1024;
 
-// expected-warning at +4 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +4 {{overflow in expression; result is 536'870'912 with type 'int'}}
 // expected-warning at +3 {{array index 536870912 is past the end of the array (that has type 'uint64_t[10]' (aka 'unsigned long long[10]'))}}
 // expected-note at +1 {{array 'a' declared here}}
   uint64_t a[10];
   a[4608 * 1024 * 1024] = 1i;
 
-// expected-warning at +2 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +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 at +1 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 2{{overflow in expression; result is 536'870'912 with type 'int'}}
   (void)((i ? (4608 * 1024 * 1024) : (4608 * 1024 * 1024)) + 1);
 
-// expected-warning at +1 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +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 at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   (void)f0(4608 * 1024 * 1024);
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   uint64_t x = f0(4608 * 1024 * 1024);
 
-// expected-warning at +2 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +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 at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +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 at -2 {{overflow in expression; result is -2147483647 with type 'int'}}
+    // expected-warning at -2 {{overflow in expression; result is -2'147'483'647 with type 'int'}}
 #else
     // expected-error at -4 {{case value is not a constant expression}} \
     // expected-note at -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 at -2 {{overflow in expression; result is -1375982336 with type 'int'}}
+    // expected-warning at -2 {{overflow in expression; result is -1'375'982'336 with type 'int'}}
 #else
     // expected-error at -4 {{case value is not a constant expression}} \
     // expected-note at -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 at -2 {{not an integral constant expression}}
 // expected-note at -3 {{value 28958703552 is outside the range of representable values}}
 #else 
-// expected-warning at -5 {{overflow in expression; result is -1106067520 with type 'int'}}
+// expected-warning at -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 at -2 {{enumerator value is not a constant expression}}
 // expected-note at -3 {{value 28958703552 is outside the range of representable values}}
 #else
-// expected-warning at -5 {{overflow in expression; result is -1106067520 with type 'int'}}
+// expected-warning at -5 {{overflow in expression; result is -1'106'067'520 with type 'int'}}
 // expected-warning at -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 at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   uint64_t overflow = 4608 * 1024 * 1024,
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
            overflow2 = (uint64_t)(4608 * 1024 * 1024),
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
            overflow3 = (uint64_t)(4608 * 1024 * 1024 * i),
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
            overflow4 =  (1ULL * ((4608) * ((1024) * (1024))) + 2ULL),
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
            overflow5 = static_cast<uint64_t>(4608 * 1024 * 1024),
-// expected-warning at +1 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +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 at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   overflow += overflow2 = overflow3 = (uint64_t)(4608 * 1024 * 1024);
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   overflow += overflow2 = overflow3 = 4608 * 1024 * 1024;
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +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 at +1 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 2{{overflow in expression; result is 536'870'912 with type 'int'}}
   overflow = 4608 * 1024 * 1024 ?  4608 * 1024 * 1024 : 0;
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   overflow =  0 ? 0 : 4608 * 1024 * 1024;
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   if (4608 * 1024 * 1024)
     return 0;
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   if ((uint64_t)(4608 * 1024 * 1024))
     return 1;
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   if (static_cast<uint64_t>(4608 * 1024 * 1024))
     return 1;
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   if ((uint64_t)(4608 * 1024 * 1024))
     return 2;
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   if ((uint64_t)(4608 * 1024 * 1024 * i))
     return 3;
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   if ((1ULL * ((4608) * ((1024) * (1024))) + 2ULL))
     return 4;
 
-// expected-warning at +1 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +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 at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   case 4608 * 1024 * 1024:
     return 6;
-// expected-warning at +1 {{overflow in expression; result is 537919488 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 537'919'488 with type 'int'}}
   case (uint64_t)(4609 * 1024 * 1024):
     return 7;
-// expected-warning at +1 {{overflow in expression; result is 537919488 with type 'int'}}
+// expected-warning at +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 at +1 {{expression is not an integral constant expression}}
   case ((uint64_t)(4608 * 1024 * 1024 * i)):
     return 8;
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   case ((1ULL * ((4608) * ((1024) * (1024))) + 2ULL)):
     return 9;
-// expected-warning at +2 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +2 2{{overflow in expression; result is 536'870'912 with type 'int'}}
 // expected-warning at +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 at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   while (4608 * 1024 * 1024);
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   while ((uint64_t)(4608 * 1024 * 1024));
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   while (static_cast<uint64_t>(4608 * 1024 * 1024));
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   while ((uint64_t)(4608 * 1024 * 1024));
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   while ((uint64_t)(4608 * 1024 * 1024 * i));
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   while ((1ULL * ((4608) * ((1024) * (1024))) + 2ULL));
 
-// expected-warning at +1 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +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 at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   do { } while (4608 * 1024 * 1024);
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   do { } while ((uint64_t)(4608 * 1024 * 1024));
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   do { } while (static_cast<uint64_t>(4608 * 1024 * 1024));
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   do { } while ((uint64_t)(4608 * 1024 * 1024));
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   do { } while ((uint64_t)(4608 * 1024 * 1024 * i));
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   do { } while ((1ULL * ((4608) * ((1024) * (1024))) + 2ULL));
 
-// expected-warning at +1 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +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 at +3 {{overflow in expression; result is 536870912 with type 'int'}}
-// expected-warning at +3 {{overflow in expression; result is 536870912 with type 'int'}}
-// expected-warning at +3 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +3 {{overflow in expression; result is 536'870'912 with type 'int'}}
+// expected-warning at +3 {{overflow in expression; result is 536'870'912 with type 'int'}}
+// expected-warning at +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 at +3 {{overflow in expression; result is 536870912 with type 'int'}}
-// expected-warning at +3 2{{overflow in expression; result is 536870912 with type 'int'}}
-// expected-warning at +3 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +3 {{overflow in expression; result is 536'870'912 with type 'int'}}
+// expected-warning at +3 2{{overflow in expression; result is 536'870'912 with type 'int'}}
+// expected-warning at +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 at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   _Complex long long x = 4608 * 1024 * 1024;
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   (__real__ x) = 4608 * 1024 * 1024;
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   (__imag__ x) = 4608 * 1024 * 1024;
 
-// expected-warning at +2 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +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 at -4 {{array 'a' declared here}}
 #endif
 
-// expected-warning at +1 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +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 at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   (void)f0(4608 * 1024 * 1024);
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   uint64_t x = f0(4608 * 1024 * 1024);
 
-// expected-warning at +2 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +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 at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +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 at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   (void)[self add:0 with:4608 * 1024 * 1024];
 
-// expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning at +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 <atousa.p at gmail.com>
Date: Mon, 12 Feb 2024 12:50:13 -0800
Subject: [PATCH 2/6] Update clang/lib/AST/ExprConstant.cpp

Co-authored-by: Timm Baeder <tbaeder at 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 <atousa.p at gmail.com>
Date: Mon, 12 Feb 2024 12:50:23 -0800
Subject: [PATCH 3/6] Update llvm/lib/Support/APInt.cpp

Co-authored-by: Timm Baeder <tbaeder at 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 <atousa.p at gmail.com>
Date: Mon, 12 Feb 2024 12:51:29 -0800
Subject: [PATCH 4/6] Update llvm/lib/Support/APInt.cpp

Co-authored-by: Timm Baeder <tbaeder at 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 <atousa.p at gmail.com>
Date: Tue, 13 Feb 2024 21:19:25 -0800
Subject: [PATCH 5/6] 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 <atousa.p at gmail.com>
Date: Fri, 1 Mar 2024 13:01:40 -0800
Subject: [PATCH 6/6] [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++;
     }



More information about the cfe-commits mailing list