From: Jacob Bandes-Storch Date: Thu, 10 Aug 2017 00:15:31 +0000 (+0000) Subject: clang-format: Fix bug with ENAS_DontAlign and empty lines X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bfca5df30168f318bab4dec75ac070d6f2ee5369;p=clang clang-format: Fix bug with ENAS_DontAlign and empty lines This fixes a bug in `ENAS_DontAlign` (introduced in D32733) where blank lines had an EscapedNewlineColumn of 0, causing a subtraction to overflow when converted back to unsigned and leading to runaway memory allocation. Differential Revision: https://reviews.llvm.org/D36019 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@310539 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Format/WhitespaceManager.cpp b/lib/Format/WhitespaceManager.cpp index 4b4fd13145..e41a0767f5 100644 --- a/lib/Format/WhitespaceManager.cpp +++ b/lib/Format/WhitespaceManager.cpp @@ -603,8 +603,9 @@ void WhitespaceManager::generateChanges() { if (C.CreateReplacement) { std::string ReplacementText = C.PreviousLinePostfix; if (C.ContinuesPPDirective) - appendNewlineText(ReplacementText, C.NewlinesBefore, - C.PreviousEndOfTokenColumn, C.EscapedNewlineColumn); + appendEscapedNewlineText(ReplacementText, C.NewlinesBefore, + C.PreviousEndOfTokenColumn, + C.EscapedNewlineColumn); else appendNewlineText(ReplacementText, C.NewlinesBefore); appendIndentText(ReplacementText, C.Tok->IndentLevel, @@ -640,16 +641,17 @@ void WhitespaceManager::appendNewlineText(std::string &Text, Text.append(UseCRLF ? "\r\n" : "\n"); } -void WhitespaceManager::appendNewlineText(std::string &Text, unsigned Newlines, - unsigned PreviousEndOfTokenColumn, - unsigned EscapedNewlineColumn) { +void WhitespaceManager::appendEscapedNewlineText(std::string &Text, + unsigned Newlines, + unsigned PreviousEndOfTokenColumn, + unsigned EscapedNewlineColumn) { if (Newlines > 0) { - unsigned Offset = - std::min(EscapedNewlineColumn - 2, PreviousEndOfTokenColumn); + unsigned Spaces = + std::max(1, EscapedNewlineColumn - PreviousEndOfTokenColumn - 1); for (unsigned i = 0; i < Newlines; ++i) { - Text.append(EscapedNewlineColumn - Offset - 1, ' '); + Text.append(Spaces, ' '); Text.append(UseCRLF ? "\\\r\n" : "\\\n"); - Offset = 0; + Spaces = std::max(0, EscapedNewlineColumn - 1); } } } diff --git a/lib/Format/WhitespaceManager.h b/lib/Format/WhitespaceManager.h index 50df59d096..548bb18c58 100644 --- a/lib/Format/WhitespaceManager.h +++ b/lib/Format/WhitespaceManager.h @@ -195,9 +195,9 @@ private: /// \brief Stores \p Text as the replacement for the whitespace in \p Range. void storeReplacement(SourceRange Range, StringRef Text); void appendNewlineText(std::string &Text, unsigned Newlines); - void appendNewlineText(std::string &Text, unsigned Newlines, - unsigned PreviousEndOfTokenColumn, - unsigned EscapedNewlineColumn); + void appendEscapedNewlineText(std::string &Text, unsigned Newlines, + unsigned PreviousEndOfTokenColumn, + unsigned EscapedNewlineColumn); void appendIndentText(std::string &Text, unsigned IndentLevel, unsigned Spaces, unsigned WhitespaceStartColumn); diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index 4577a67fd1..dcc96b259a 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -2309,6 +2309,30 @@ TEST_F(FormatTest, EscapedNewlines) { EXPECT_EQ("template f();", format("\\\ntemplate f();")); EXPECT_EQ("/* \\ \\ \\\n */", format("\\\n/* \\ \\ \\\n */")); EXPECT_EQ("", format("")); + + FormatStyle DontAlign = getLLVMStyle(); + DontAlign.AlignEscapedNewlines = FormatStyle::ENAS_DontAlign; + DontAlign.MaxEmptyLinesToKeep = 3; + // FIXME: can't use verifyFormat here because the newline before + // "public:" is not inserted the first time it's reformatted + EXPECT_EQ("#define A \\\n" + " class Foo { \\\n" + " void bar(); \\\n" + "\\\n" + "\\\n" + "\\\n" + " public: \\\n" + " void baz(); \\\n" + " };", + format("#define A \\\n" + " class Foo { \\\n" + " void bar(); \\\n" + "\\\n" + "\\\n" + "\\\n" + " public: \\\n" + " void baz(); \\\n" + " };", DontAlign)); } TEST_F(FormatTest, CalculateSpaceOnConsecutiveLinesInMacro) {