https://github.com/yashaggarwal85d updated 
https://github.com/llvm/llvm-project/pull/236087

>From 260c694189bd573b98ebccbb3f3c957327b00210 Mon Sep 17 00:00:00 2001
From: Yash Aggarwal <[email protected]>
Date: Tue, 27 Oct 2026 10:37:51 +0000
Subject: [PATCH 1/2] [clang-format] Use 64-bit penalties in the optimizing
 line formatter

---
 clang/lib/Format/UnwrappedLineFormatter.cpp | 12 +++++++-----
 clang/unittests/Format/FormatTest.cpp       |  9 +++++++++
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp 
b/clang/lib/Format/UnwrappedLineFormatter.cpp
index d1f68877ef0339..bb44d134f3edf4 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -1425,7 +1425,7 @@ class OptimizingLineFormatter : public LineFormatter {
   /// In case of equal penalties, we want to prefer states that were inserted
   /// first. During state generation we make sure that we insert states first
   /// that break the line as late as possible.
-  typedef std::pair<unsigned, unsigned> OrderedPenalty;
+  typedef std::pair<uint64_t, unsigned> OrderedPenalty;
 
   /// An edge in the solution space from \c Previous->State to \c State,
   /// inserting a newline dependent on the \c NewLine.
@@ -1468,7 +1468,7 @@ class OptimizingLineFormatter : public LineFormatter {
     Queue.push(QueueItem(OrderedPenalty(0, Count), RootNode));
     ++Count;
 
-    unsigned Penalty = 0;
+    uint64_t Penalty = 0;
 
     // While not empty, take first element and follow edges.
     while (!Queue.empty()) {
@@ -1517,14 +1517,14 @@ class OptimizingLineFormatter : public LineFormatter {
                << "Total number of analyzed states: " << Count << "\n");
     LLVM_DEBUG(llvm::dbgs() << "---\n");
 
-    return Penalty;
+    return std::min<uint64_t>(Penalty, UINT_MAX);
   }
 
   /// Add the following state to the analysis queue \c Queue.
   ///
   /// Assume the current state is \p PreviousNode and has been reached with a
   /// penalty of \p Penalty. Insert a line break if \p NewLine is \c true.
-  void addNextStateToQueue(unsigned Penalty, StateNode *PreviousNode,
+  void addNextStateToQueue(uint64_t Penalty, StateNode *PreviousNode,
                            bool NewLine, unsigned *Count, QueueType *Queue) {
     if (NewLine && !Indenter->canBreak(PreviousNode->State))
       return;
@@ -1533,9 +1533,11 @@ class OptimizingLineFormatter : public LineFormatter {
 
     StateNode *Node = new (Allocator.Allocate())
         StateNode(PreviousNode->State, NewLine, PreviousNode);
-    if (!formatChildren(Node->State, NewLine, /*DryRun=*/true, Penalty))
+    unsigned ChildrenPenalty = 0;
+    if (!formatChildren(Node->State, NewLine, /*DryRun=*/true, 
ChildrenPenalty))
       return;
 
+    Penalty += ChildrenPenalty;
     Penalty += Indenter->addTokenToState(Node->State, NewLine, true);
 
     Queue->push(QueueItem(OrderedPenalty(Penalty, *Count), Node));
diff --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index f38287757ffba1..df971a4c513845 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -20440,6 +20440,15 @@ TEST_F(FormatTest, BreakPenaltyScopeResolution) {
                Style);
 }
 
+TEST_F(FormatTest, PenaltyDoesNotOverflow) {
+  // The total penalty of this line is above 2^32.
+  std::string Code = "int t[] = {\n";
+  for (int I = 0; I < 81; ++I)
+    Code += "    0x" + std::string(100, '0') + ",\n";
+  Code += "};";
+  verifyFormat(Code);
+}
+
 TEST_F(FormatTest, WorksFor8bitEncodings) {
   // FIXME: unstable test case
   EXPECT_EQ("\"\xce\xe4\xed\xe0\xe6\xe4\xfb \xe2 \"\n"

>From 0f365b4d1f80bb319fc2101a0351c80f15505676 Mon Sep 17 00:00:00 2001
From: Yash Aggarwal <[email protected]>
Date: Sat, 31 Oct 2026 06:32:42 +0000
Subject: [PATCH 2/2] Keep penalties 64-bit through UnwrappedLineFormatter and
 simplify the test

---
 clang/lib/Format/Format.cpp                 |  5 ++--
 clang/lib/Format/UnwrappedLineFormatter.cpp | 28 ++++++++++-----------
 clang/lib/Format/UnwrappedLineFormatter.h   |  4 +--
 clang/unittests/Format/FormatTest.cpp       | 14 ++++++-----
 4 files changed, 26 insertions(+), 25 deletions(-)

diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index d83ca4a558b7f8..9b34a9d74e7d5b 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -3032,7 +3032,7 @@ class Formatter : public TokenAnalyzer {
     ContinuationIndenter Indenter(Style, Tokens.getKeywords(),
                                   Env.getSourceManager(), Whitespaces, 
Encoding,
                                   BinPackInconclusiveFunctions);
-    unsigned Penalty =
+    uint64_t Penalty =
         UnwrappedLineFormatter(&Indenter, &Whitespaces, Style,
                                Tokens.getKeywords(), Env.getSourceManager(),
                                Status)
@@ -3045,7 +3045,8 @@ class Formatter : public TokenAnalyzer {
     for (const auto &R : Whitespaces.generateReplacements())
       if (Result.add(R))
         return std::make_pair(Result, 0);
-    return std::make_pair(Result, Penalty);
+    return std::make_pair(
+        Result, static_cast<unsigned>(std::min<uint64_t>(Penalty, UINT_MAX)));
   }
 
 private:
diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp 
b/clang/lib/Format/UnwrappedLineFormatter.cpp
index bb44d134f3edf4..f478e7d3d6a112 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -1243,7 +1243,7 @@ class LineFormatter {
   /// Formats an \c AnnotatedLine and returns the penalty.
   ///
   /// If \p DryRun is \c false, directly applies the changes.
-  virtual unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
+  virtual uint64_t formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
                               unsigned FirstStartColumn, bool DryRun) = 0;
 
 protected:
@@ -1268,7 +1268,7 @@ class LineFormatter {
   /// \c UnwrappedLineFormatter, where we only have two options for each token:
   /// break or don't break.
   bool formatChildren(LineState &State, bool NewLine, bool DryRun,
-                      unsigned &Penalty) {
+                      uint64_t &Penalty) {
     const FormatToken *LBrace = State.NextToken->getPreviousNonComment();
     bool HasLBrace = LBrace && LBrace->is(tok::l_brace) && 
LBrace->is(BK_Block);
     FormatToken &Previous = *State.NextToken->Previous;
@@ -1348,7 +1348,7 @@ class NoColumnLimitLineFormatter : public LineFormatter {
 
   /// Formats the line, simply keeping all of the input's line breaking
   /// decisions.
-  unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
+  uint64_t formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
                       unsigned FirstStartColumn, bool DryRun) override {
     assert(!DryRun);
     LineState State = Indenter->getInitialState(FirstIndent, FirstStartColumn,
@@ -1357,7 +1357,7 @@ class NoColumnLimitLineFormatter : public LineFormatter {
       bool Newline =
           Indenter->mustBreak(State) ||
           (Indenter->canBreak(State) && State.NextToken->NewlinesBefore > 0);
-      unsigned Penalty = 0;
+      uint64_t Penalty = 0;
       formatChildren(State, Newline, /*DryRun=*/false, Penalty);
       Indenter->addTokenToState(State, Newline, /*DryRun=*/false);
     }
@@ -1374,9 +1374,9 @@ class NoLineBreakFormatter : public LineFormatter {
       : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
 
   /// Puts all tokens into a single line.
-  unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
+  uint64_t formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
                       unsigned FirstStartColumn, bool DryRun) override {
-    unsigned Penalty = 0;
+    uint64_t Penalty = 0;
     LineState State =
         Indenter->getInitialState(FirstIndent, FirstStartColumn, &Line, 
DryRun);
     while (State.NextToken) {
@@ -1399,7 +1399,7 @@ class OptimizingLineFormatter : public LineFormatter {
 
   /// Formats the line by finding the best line breaks with line lengths
   /// below the column limit.
-  unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
+  uint64_t formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
                       unsigned FirstStartColumn, bool DryRun) override {
     LineState State =
         Indenter->getInitialState(FirstIndent, FirstStartColumn, &Line, 
DryRun);
@@ -1454,7 +1454,7 @@ class OptimizingLineFormatter : public LineFormatter {
   /// to a state where all tokens are placed. Returns the penalty.
   ///
   /// If \p DryRun is \c false, directly applies the changes.
-  unsigned analyzeSolutionSpace(LineState &InitialState, bool DryRun) {
+  uint64_t analyzeSolutionSpace(LineState &InitialState, bool DryRun) {
     std::set<LineState *, CompareLineStatePointers> Seen;
 
     // Increasing count of \c StateNode items we have created. This is used to
@@ -1517,7 +1517,7 @@ class OptimizingLineFormatter : public LineFormatter {
                << "Total number of analyzed states: " << Count << "\n");
     LLVM_DEBUG(llvm::dbgs() << "---\n");
 
-    return std::min<uint64_t>(Penalty, UINT_MAX);
+    return Penalty;
   }
 
   /// Add the following state to the analysis queue \c Queue.
@@ -1533,11 +1533,9 @@ class OptimizingLineFormatter : public LineFormatter {
 
     StateNode *Node = new (Allocator.Allocate())
         StateNode(PreviousNode->State, NewLine, PreviousNode);
-    unsigned ChildrenPenalty = 0;
-    if (!formatChildren(Node->State, NewLine, /*DryRun=*/true, 
ChildrenPenalty))
+    if (!formatChildren(Node->State, NewLine, /*DryRun=*/true, Penalty))
       return;
 
-    Penalty += ChildrenPenalty;
     Penalty += Indenter->addTokenToState(Node->State, NewLine, true);
 
     Queue->push(QueueItem(OrderedPenalty(Penalty, *Count), Node));
@@ -1554,7 +1552,7 @@ class OptimizingLineFormatter : public LineFormatter {
       Best = Best->Previous;
     }
     for (const auto &Node : llvm::reverse(Path)) {
-      unsigned Penalty = 0;
+      uint64_t Penalty = 0;
       formatChildren(State, Node->NewLine, /*DryRun=*/false, Penalty);
       Penalty += Indenter->addTokenToState(State, Node->NewLine, false);
 
@@ -1574,7 +1572,7 @@ class OptimizingLineFormatter : public LineFormatter {
 
 } // anonymous namespace
 
-unsigned UnwrappedLineFormatter::format(
+uint64_t UnwrappedLineFormatter::format(
     const SmallVectorImpl<AnnotatedLine *> &Lines, bool DryRun,
     int AdditionalIndent, bool FixBadIndentation, unsigned FirstStartColumn,
     unsigned NextStartColumn, unsigned LastStartColumn) {
@@ -1588,7 +1586,7 @@ unsigned UnwrappedLineFormatter::format(
     return CacheIt->second;
 
   assert(!Lines.empty());
-  unsigned Penalty = 0;
+  uint64_t Penalty = 0;
   LevelIndentTracker IndentTracker(Style, Keywords, Lines[0]->Level,
                                    AdditionalIndent);
   const AnnotatedLine *PrevPrevLine = nullptr;
diff --git a/clang/lib/Format/UnwrappedLineFormatter.h 
b/clang/lib/Format/UnwrappedLineFormatter.h
index a33a4f98df2560..1761ef53c47513 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.h
+++ b/clang/lib/Format/UnwrappedLineFormatter.h
@@ -35,7 +35,7 @@ class UnwrappedLineFormatter {
         Keywords(Keywords), SourceMgr(SourceMgr), Status(Status) {}
 
   /// Format the current block and return the penalty.
-  unsigned format(const SmallVectorImpl<AnnotatedLine *> &Lines,
+  uint64_t format(const SmallVectorImpl<AnnotatedLine *> &Lines,
                   bool DryRun = false, int AdditionalIndent = 0,
                   bool FixBadIndentation = false, unsigned FirstStartColumn = 
0,
                   unsigned NextStartColumn = 0, unsigned LastStartColumn = 0);
@@ -57,7 +57,7 @@ class UnwrappedLineFormatter {
   // starting from a specific additional offset. Improves performance if there
   // are many nested blocks.
   std::map<std::pair<const SmallVectorImpl<AnnotatedLine *> *, unsigned>,
-           unsigned>
+           uint64_t>
       PenaltyCache;
 
   ContinuationIndenter *Indenter;
diff --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index df971a4c513845..2be65b0d7301a7 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -20441,12 +20441,14 @@ TEST_F(FormatTest, BreakPenaltyScopeResolution) {
 }
 
 TEST_F(FormatTest, PenaltyDoesNotOverflow) {
-  // The total penalty of this line is above 2^32.
-  std::string Code = "int t[] = {\n";
-  for (int I = 0; I < 81; ++I)
-    Code += "    0x" + std::string(100, '0') + ",\n";
-  Code += "};";
-  verifyFormat(Code);
+  // Indenting the rows more would make the total penalty go past 2^32.
+  auto Style = getLLVMStyleWithColumns(20);
+  Style.PenaltyExcessCharacter = 200'000'000;
+  verifyFormat("int t[] = {\n"
+               "    11111111111111111111,\n"
+               "    11111111111111111111,\n"
+               "};",
+               Style);
 }
 
 TEST_F(FormatTest, WorksFor8bitEncodings) {

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

Reply via email to