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
