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 OrderedPenalty; + typedef std::pair 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(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"