Browse Source

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
Jacob Bandes-Storch 8 years ago
parent
commit
bfca5df301
3 changed files with 38 additions and 12 deletions
  1. 11 9
      lib/Format/WhitespaceManager.cpp
  2. 3 3
      lib/Format/WhitespaceManager.h
  3. 24 0
      unittests/Format/FormatTest.cpp

+ 11 - 9
lib/Format/WhitespaceManager.cpp

@@ -603,8 +603,9 @@ void WhitespaceManager::generateChanges() {
     if (C.CreateReplacement) {
     if (C.CreateReplacement) {
       std::string ReplacementText = C.PreviousLinePostfix;
       std::string ReplacementText = C.PreviousLinePostfix;
       if (C.ContinuesPPDirective)
       if (C.ContinuesPPDirective)
-        appendNewlineText(ReplacementText, C.NewlinesBefore,
-                          C.PreviousEndOfTokenColumn, C.EscapedNewlineColumn);
+        appendEscapedNewlineText(ReplacementText, C.NewlinesBefore,
+                                 C.PreviousEndOfTokenColumn,
+                                 C.EscapedNewlineColumn);
       else
       else
         appendNewlineText(ReplacementText, C.NewlinesBefore);
         appendNewlineText(ReplacementText, C.NewlinesBefore);
       appendIndentText(ReplacementText, C.Tok->IndentLevel,
       appendIndentText(ReplacementText, C.Tok->IndentLevel,
@@ -640,16 +641,17 @@ void WhitespaceManager::appendNewlineText(std::string &Text,
     Text.append(UseCRLF ? "\r\n" : "\n");
     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) {
   if (Newlines > 0) {
-    unsigned Offset =
-        std::min<int>(EscapedNewlineColumn - 2, PreviousEndOfTokenColumn);
+    unsigned Spaces =
+        std::max<int>(1, EscapedNewlineColumn - PreviousEndOfTokenColumn - 1);
     for (unsigned i = 0; i < Newlines; ++i) {
     for (unsigned i = 0; i < Newlines; ++i) {
-      Text.append(EscapedNewlineColumn - Offset - 1, ' ');
+      Text.append(Spaces, ' ');
       Text.append(UseCRLF ? "\\\r\n" : "\\\n");
       Text.append(UseCRLF ? "\\\r\n" : "\\\n");
-      Offset = 0;
+      Spaces = std::max<int>(0, EscapedNewlineColumn - 1);
     }
     }
   }
   }
 }
 }

+ 3 - 3
lib/Format/WhitespaceManager.h

@@ -195,9 +195,9 @@ private:
   /// \brief Stores \p Text as the replacement for the whitespace in \p Range.
   /// \brief Stores \p Text as the replacement for the whitespace in \p Range.
   void storeReplacement(SourceRange Range, StringRef Text);
   void storeReplacement(SourceRange Range, StringRef Text);
   void appendNewlineText(std::string &Text, unsigned Newlines);
   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,
   void appendIndentText(std::string &Text, unsigned IndentLevel,
                         unsigned Spaces, unsigned WhitespaceStartColumn);
                         unsigned Spaces, unsigned WhitespaceStartColumn);
 
 

+ 24 - 0
unittests/Format/FormatTest.cpp

@@ -2309,6 +2309,30 @@ TEST_F(FormatTest, EscapedNewlines) {
   EXPECT_EQ("template <class T> f();", format("\\\ntemplate <class T> f();"));
   EXPECT_EQ("template <class T> f();", format("\\\ntemplate <class T> f();"));
   EXPECT_EQ("/* \\  \\  \\\n */", format("\\\n/* \\  \\  \\\n */"));
   EXPECT_EQ("/* \\  \\  \\\n */", format("\\\n/* \\  \\  \\\n */"));
   EXPECT_EQ("<a\n\\\\\n>", format("<a\n\\\\\n>"));
   EXPECT_EQ("<a\n\\\\\n>", format("<a\n\\\\\n>"));
+
+  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) {
 TEST_F(FormatTest, CalculateSpaceOnConsecutiveLinesInMacro) {