https://github.com/VachanVY updated 
https://github.com/llvm/llvm-project/pull/211785

>From f2f3a679bb89cdab7070e607507c1e70ca8c456c Mon Sep 17 00:00:00 2001
From: Vachan V Y <[email protected]>
Date: Mon, 27 Jul 2026 22:37:27 +0530
Subject: [PATCH] [Clang] Add thousands-separator to large integers; change the
 diagnostics engine

---
 clang/include/clang/AST/OptionalDiagnostic.h  |  5 ++--
 clang/include/clang/Basic/Diagnostic.h        | 26 ++++++++++++++-----
 .../include/clang/Basic/DiagnosticASTKinds.td |  2 +-
 clang/lib/AST/ByteCode/Interp.h               | 24 +++++++----------
 clang/lib/AST/ByteCode/InterpHelpers.h        |  4 +--
 clang/lib/AST/ExprConstant.cpp                | 10 +++----
 clang/lib/Basic/Diagnostic.cpp                | 21 +++++++++++++--
 clang/lib/Sema/SemaDecl.cpp                   |  5 ++--
 clang/lib/Sema/SemaExprCXX.cpp                |  4 +--
 clang/lib/Sema/SemaType.cpp                   |  4 +--
 10 files changed, 61 insertions(+), 44 deletions(-)

diff --git a/clang/include/clang/AST/OptionalDiagnostic.h 
b/clang/include/clang/AST/OptionalDiagnostic.h
index c9a2d19f4ebce..b21955bf0088b 100644
--- a/clang/include/clang/AST/OptionalDiagnostic.h
+++ b/clang/include/clang/AST/OptionalDiagnostic.h
@@ -39,9 +39,8 @@ class OptionalDiagnostic {
 
   OptionalDiagnostic &operator<<(const llvm::APSInt &I) {
     if (Diag) {
-      SmallVector<char, 32> Buffer;
-      I.toString(Buffer);
-      *Diag << StringRef(Buffer.data(), Buffer.size());
+      std::string Str = formatDiagnosticInteger(I, I.isSigned());
+      *Diag << StringRef(Str);
     }
     return *this;
   }
diff --git a/clang/include/clang/Basic/Diagnostic.h 
b/clang/include/clang/Basic/Diagnostic.h
index 66e79e3b4300b..82285d2bac1aa 100644
--- a/clang/include/clang/Basic/Diagnostic.h
+++ b/clang/include/clang/Basic/Diagnostic.h
@@ -1402,19 +1402,33 @@ inline const StreamingDiagnostic &operator<<(const 
StreamingDiagnostic &DB,
   return DB;
 }
 
+inline constexpr uint64_t DiagnosticIntegerSeparatorThreshold = 100'000;
+
+inline std::string formatDiagnosticInteger(const llvm::APInt &Val,
+                                           bool Signed) {
+  bool Small = false;
+  if (Signed) {
+    if (Val.getSignificantBits() <= 64) {
+      int64_t S = Val.getSExtValue();
+      uint64_t Magnitude = S < 0 ? -static_cast<uint64_t>(S) : uint64_t(S);
+      Small = Magnitude < DiagnosticIntegerSeparatorThreshold;
+    }
+  } else if (Val.getActiveBits() <= 64) {
+    Small = Val.getZExtValue() < DiagnosticIntegerSeparatorThreshold;
+  }
+  return toString(Val, /*Radix=*/10, Signed, /*formatAsCLiteral=*/false,
+                  /*UpperCase=*/true, /*InsertSeparators=*/!Small);
+}
+
 inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                              const llvm::APSInt &Int) {
-  DB.AddString(toString(Int, /*Radix=*/10, Int.isSigned(),
-                        /*formatAsCLiteral=*/false,
-                        /*UpperCase=*/true, /*InsertSeparators=*/true));
+  DB.AddString(formatDiagnosticInteger(Int, Int.isSigned()));
   return DB;
 }
 
 inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                              const llvm::APInt &Int) {
-  DB.AddString(toString(Int, /*Radix=*/10, /*Signed=*/false,
-                        /*formatAsCLiteral=*/false,
-                        /*UpperCase=*/true, /*InsertSeparators=*/true));
+  DB.AddString(formatDiagnosticInteger(Int, /*Signed=*/false));
   return DB;
 }
 
diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td 
b/clang/include/clang/Basic/DiagnosticASTKinds.td
index f86f0157b2b1f..658750d25251a 100644
--- a/clang/include/clang/Basic/DiagnosticASTKinds.td
+++ b/clang/include/clang/Basic/DiagnosticASTKinds.td
@@ -355,7 +355,7 @@ def note_constexpr_new_negative : Note<
 def note_constexpr_new_too_large : Note<
   "cannot allocate array; evaluated array bound %0 is too large">;
 def note_constexpr_new_exceeds_limits : Note<
-  "cannot allocate array; evaluated array bound %0 exceeds the limit (%1); "
+  "cannot allocate array; evaluated array bound %0 exceeds the limit of %1; "
   "use '-fconstexpr-steps' to increase this limit">;
 def note_constexpr_new_too_small : Note<
   "cannot allocate array; evaluated array bound %0 is too small to hold "
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 405f4a29ec982..cc57ddb61d1e5 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -356,12 +356,10 @@ bool AddSubMulHelper(InterpState &S, CodePtr OpPC, 
unsigned Bits, const T &LHS,
   if (S.checkingForUndefinedBehavior()) {
     const Expr *E = S.Current->getExpr(OpPC);
     QualType Type = E->getType();
-    SmallString<32> Trunc;
-    Value.trunc(Result.bitWidth())
-        .toString(Trunc, 10, Result.isSigned(), /*formatAsCLiteral=*/false,
-                  /*UpperCase=*/true, /*InsertSeparators=*/true);
     S.report(E->getExprLoc(), diag::warn_integer_constant_overflow)
-        << Trunc << Type << E->getSourceRange();
+        << formatDiagnosticInteger(Value.trunc(Result.bitWidth()),
+                                   Result.isSigned())
+        << Type << E->getSourceRange();
   }
 
   if (!handleOverflow(S, OpPC, Value)) {
@@ -867,12 +865,10 @@ bool Neg(InterpState &S, CodePtr OpPC) {
     if (S.checkingForUndefinedBehavior()) {
       const Expr *E = S.Current->getExpr(OpPC);
       QualType Type = E->getType();
-      SmallString<32> Trunc;
-      NegatedValue.trunc(Result.bitWidth())
-          .toString(Trunc, 10, Result.isSigned(), /*formatAsCLiteral=*/false,
-                    /*UpperCase=*/true, /*InsertSeparators=*/true);
       S.report(E->getExprLoc(), diag::warn_integer_constant_overflow)
-          << Trunc << Type << E->getSourceRange();
+          << formatDiagnosticInteger(NegatedValue.trunc(Result.bitWidth()),
+                                     Result.isSigned())
+          << Type << E->getSourceRange();
       return true;
     }
 
@@ -956,12 +952,10 @@ bool IncDecHelper(InterpState &S, CodePtr OpPC, const 
Pointer &Ptr,
   if (S.checkingForUndefinedBehavior()) {
     const Expr *E = S.Current->getExpr(OpPC);
     QualType Type = E->getType();
-    SmallString<32> Trunc;
-    APResult.trunc(Result.bitWidth())
-        .toString(Trunc, 10, Result.isSigned(), /*formatAsCLiteral=*/false,
-                  /*UpperCase=*/true, /*InsertSeparators=*/true);
     S.report(E->getExprLoc(), diag::warn_integer_constant_overflow)
-        << Trunc << Type << E->getSourceRange();
+        << formatDiagnosticInteger(APResult.trunc(Result.bitWidth()),
+                                   Result.isSigned())
+        << Type << E->getSourceRange();
     return true;
   }
   return handleOverflow(S, OpPC, APResult);
diff --git a/clang/lib/AST/ByteCode/InterpHelpers.h 
b/clang/lib/AST/ByteCode/InterpHelpers.h
index 4d908d1e44546..00136add4433f 100644
--- a/clang/lib/AST/ByteCode/InterpHelpers.h
+++ b/clang/lib/AST/ByteCode/InterpHelpers.h
@@ -145,10 +145,10 @@ bool CheckArraySize(InterpState &S, CodePtr OpPC, SizeT 
*NumElements,
 
       if (NumElements->isSigned() && NumElements->isNegative()) {
         S.FFDiag(Loc, diag::note_constexpr_new_negative)
-            << NumElements->toDiagnosticString(S.getASTContext());
+            << NumElements->toAPSInt();
       } else {
         S.FFDiag(Loc, diag::note_constexpr_new_too_large)
-            << NumElements->toDiagnosticString(S.getASTContext());
+            << NumElements->toAPSInt();
       }
     }
     return false;
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 574dd8b04e779..f07f7d4c1e70c 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -2819,9 +2819,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)
-          << E->getType() << E->getSourceRange();
+          << formatDiagnosticInteger(Result, Result.isSigned()) << E->getType()
+          << E->getSourceRange();
     return HandleOverflow(Info, E, Value, E->getType());
   }
   return true;
@@ -19857,9 +19856,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(), 
/*formatAsCLiteral=*/false,
-                        /*UpperCase=*/true, /*InsertSeparators=*/true)
-            << E->getType() << E->getSourceRange();
+            << formatDiagnosticInteger(Value, Value.isSigned()) << E->getType()
+            << E->getSourceRange();
 
       if (!HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1),
                           E->getType()))
diff --git a/clang/lib/Basic/Diagnostic.cpp b/clang/lib/Basic/Diagnostic.cpp
index 4c63e54964ed6..7e7f261a4a5d7 100644
--- a/clang/lib/Basic/Diagnostic.cpp
+++ b/clang/lib/Basic/Diagnostic.cpp
@@ -22,6 +22,7 @@
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/Specifiers.h"
 #include "clang/Basic/TokenKinds.h"
+#include "llvm/ADT/APInt.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringExtras.h"
@@ -895,6 +896,22 @@ static void HandleIntegerHumanModifier(int64_t ValNo,
   Out << ValNo;
 }
 
+static void HandleIntegerDefaultModifier(int64_t Val,
+                                         SmallVectorImpl<char> &OutStr) {
+  std::string Str = formatDiagnosticInteger(
+      llvm::APInt(64, static_cast<uint64_t>(Val), /*isSigned=*/true),
+      /*Signed=*/true);
+  OutStr.append(Str.begin(), Str.end());
+}
+
+static void
+HandleUnsignedIntegerDefaultModifier(uint64_t Val,
+                                     SmallVectorImpl<char> &OutStr) {
+  std::string Str =
+      formatDiagnosticInteger(llvm::APInt(64, Val), /*Signed=*/false);
+  OutStr.append(Str.begin(), Str.end());
+}
+
 /// PluralNumber - Parse an unsigned integer and advance Start.
 static unsigned PluralNumber(const char *&Start, const char *End) {
   // Programming 101: Parse a decimal number :-)
@@ -1279,7 +1296,7 @@ void Diagnostic::FormatDiagnostic(const char *DiagStr, 
const char *DiagEnd,
         HandleIntegerHumanModifier(Val, OutStr);
       } else {
         assert(ModifierLen == 0 && "Unknown integer modifier");
-        llvm::raw_svector_ostream(OutStr) << Val;
+        HandleIntegerDefaultModifier(Val, OutStr);
       }
       break;
     }
@@ -1299,7 +1316,7 @@ void Diagnostic::FormatDiagnostic(const char *DiagStr, 
const char *DiagEnd,
         HandleIntegerHumanModifier(Val, OutStr);
       } else {
         assert(ModifierLen == 0 && "Unknown integer modifier");
-        llvm::raw_svector_ostream(OutStr) << Val;
+        HandleUnsignedIntegerDefaultModifier(Val, OutStr);
       }
       break;
     }
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index c5920f03ed6e1..40491bf996bed 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -6860,9 +6860,8 @@ bool Sema::tryToFixVariablyModifiedVarType(TypeSourceInfo 
*&TInfo,
   if (SizeIsNegative)
     Diag(Loc, diag::err_typecheck_negative_array_size);
   else if (Oversized.getBoolValue())
-    Diag(Loc, diag::err_array_too_large) << toString(
-        Oversized, 10, Oversized.isSigned(), /*formatAsCLiteral=*/false,
-        /*UpperCase=*/false, /*InsertSeparators=*/true);
+    Diag(Loc, diag::err_array_too_large)
+        << formatDiagnosticInteger(Oversized, Oversized.isSigned());
   else if (FailedFoldDiagID)
     Diag(Loc, FailedFoldDiagID);
   return false;
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 538604aa2e64b..7a9e8d1a51b18 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -2415,9 +2415,7 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool 
UseGlobal,
         if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context))
           return ExprError(
               Diag((*ArraySize)->getBeginLoc(), diag::err_array_too_large)
-              << toString(*Value, 10, Value->isSigned(),
-                          /*formatAsCLiteral=*/false, /*UpperCase=*/false,
-                          /*InsertSeparators=*/true)
+              << formatDiagnosticInteger(*Value, Value->isSigned())
               << (*ArraySize)->getSourceRange());
       }
 
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 5161db6ac1a99..595b238a5fbcd 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -2307,9 +2307,7 @@ QualType Sema::BuildArrayType(QualType T, 
ArraySizeModifier ASM,
               : ConstVal.getActiveBits();
       if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) {
         Diag(ArraySize->getBeginLoc(), diag::err_array_too_large)
-            << toString(ConstVal, 10, ConstVal.isSigned(),
-                        /*formatAsCLiteral=*/false, /*UpperCase=*/false,
-                        /*InsertSeparators=*/true)
+            << formatDiagnosticInteger(ConstVal, ConstVal.isSigned())
             << ArraySize->getSourceRange();
         return QualType();
       }

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to