[clang] b6a7180 - [clang-format] Add test case for issue 63170

Paul Kirth via cfe-commits cfe-commits at lists.llvm.org
Fri Jun 9 13:10:29 PDT 2023


Author: Paul Kirth
Date: 2023-06-09T20:10:19Z
New Revision: b6a718016c0fd7a0d883214ba19d88b6f96e3ae1

URL: https://github.com/llvm/llvm-project/commit/b6a718016c0fd7a0d883214ba19d88b6f96e3ae1
DIFF: https://github.com/llvm/llvm-project/commit/b6a718016c0fd7a0d883214ba19d88b6f96e3ae1.diff

LOG: [clang-format] Add test case for issue 63170

After https://reviews.llvm.org/D151954 we've noticed some issues w/
clang-format behavior, as outlined in
https://github.com/llvm/llvm-project/issues/63170.

Valid C/C++ files, that were previously accepted, are now rejected by
clang-format, emitting the message:

"The new replacement overlaps with an existing replacement."

This reverts commit 4b9764959dc4b8783e18747c1742ab164e4bc4ee and
d2627cf88d2553a4c2e850430bdb908a4b7d2e52, which depends on it.

Reviewed By: phosek

Differential Revision: https://reviews.llvm.org/D152473

Added: 
    clang/test/Format/overlapping-lines.cpp

Modified: 
    clang/docs/ClangFormatStyleOptions.rst
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Format/Format.h
    clang/lib/Format/Format.cpp
    clang/lib/Format/UnwrappedLineFormatter.cpp
    clang/unittests/Format/ConfigParseTest.cpp
    clang/unittests/Format/FormatTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index fa552d65e208a..8f23a4aa27a92 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -3555,11 +3555,6 @@ the configuration (without a prefix: ``Auto``).
      false:
      import {VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying,} from "some/module.js"
 
-.. _KeepEmptyLinesAtEOF:
-
-**KeepEmptyLinesAtEOF** (``Boolean``) :versionbadge:`clang-format 17` :ref:`¶ <KeepEmptyLinesAtEOF>`
-  Keep empty lines (up to ``MaxEmptyLinesToKeep``) at end of file.
-
 .. _KeepEmptyLinesAtTheStartOfBlocks:
 
 **KeepEmptyLinesAtTheStartOfBlocks** (``Boolean``) :versionbadge:`clang-format 3.7` :ref:`¶ <KeepEmptyLinesAtTheStartOfBlocks>`

diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index acd8c4d622a89..58e1039c4f133 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -707,7 +707,6 @@ clang-format
 - Fix all known issues associated with ``LambdaBodyIndentation: OuterScope``.
 - Add ``BracedInitializerIndentWidth`` which can be used to configure
   the indentation level of the contents of braced init lists.
-- Add ``KeepEmptyLinesAtEOF`` to keep empty lines at end of file.
 
 libclang
 --------

diff  --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 74b3e15918184..6a9d435174cdd 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -2675,10 +2675,6 @@ struct FormatStyle {
   bool JavaScriptWrapImports;
   // clang-format on
 
-  /// Keep empty lines (up to ``MaxEmptyLinesToKeep``) at end of file.
-  /// \version 17
-  bool KeepEmptyLinesAtEOF;
-
   /// If true, the empty line at the start of blocks is kept.
   /// \code
   ///    true:                                  false:
@@ -4368,7 +4364,6 @@ struct FormatStyle {
            JavaImportGroups == R.JavaImportGroups &&
            JavaScriptQuotes == R.JavaScriptQuotes &&
            JavaScriptWrapImports == R.JavaScriptWrapImports &&
-           KeepEmptyLinesAtEOF == R.KeepEmptyLinesAtEOF &&
            KeepEmptyLinesAtTheStartOfBlocks ==
                R.KeepEmptyLinesAtTheStartOfBlocks &&
            Language == R.Language &&

diff  --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 5fee5e6c261a9..6e2b6a662e7e1 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -942,7 +942,6 @@ template <> struct MappingTraits<FormatStyle> {
     IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports);
     IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",
                    Style.KeepEmptyLinesAtTheStartOfBlocks);
-    IO.mapOptional("KeepEmptyLinesAtEOF", Style.KeepEmptyLinesAtEOF);
     IO.mapOptional("LambdaBodyIndentation", Style.LambdaBodyIndentation);
     IO.mapOptional("LineEnding", Style.LineEnding);
     IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin);
@@ -1411,7 +1410,6 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
       /*Hex=*/0,     /*HexMinDigits=*/0};
   LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
   LLVMStyle.JavaScriptWrapImports = true;
-  LLVMStyle.KeepEmptyLinesAtEOF = false;
   LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true;
   LLVMStyle.LambdaBodyIndentation = FormatStyle::LBI_Signature;
   LLVMStyle.LineEnding = FormatStyle::LE_DeriveLF;

diff  --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp
index f229742b19d97..33be74dfe1b9f 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -1418,12 +1418,19 @@ unsigned UnwrappedLineFormatter::format(
   return Penalty;
 }
 
-static auto newlinesBeforeLine(const AnnotatedLine &Line,
-                               const AnnotatedLine *PreviousLine,
-                               const AnnotatedLine *PrevPrevLine,
-                               const SmallVectorImpl<AnnotatedLine *> &Lines,
-                               const FormatStyle &Style) {
-  const auto &RootToken = *Line.First;
+void UnwrappedLineFormatter::formatFirstToken(
+    const AnnotatedLine &Line, const AnnotatedLine *PreviousLine,
+    const AnnotatedLine *PrevPrevLine,
+    const SmallVectorImpl<AnnotatedLine *> &Lines, unsigned Indent,
+    unsigned NewlineIndent) {
+  FormatToken &RootToken = *Line.First;
+  if (RootToken.is(tok::eof)) {
+    unsigned Newlines = std::min(RootToken.NewlinesBefore, 1u);
+    unsigned TokenIndent = Newlines ? NewlineIndent : 0;
+    Whitespaces->replaceWhitespace(RootToken, Newlines, TokenIndent,
+                                   TokenIndent);
+    return;
+  }
   unsigned Newlines =
       std::min(RootToken.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1);
   // Remove empty lines before "}" where applicable.
@@ -1503,29 +1510,6 @@ static auto newlinesBeforeLine(const AnnotatedLine &Line,
     }
   }
 
-  return Newlines;
-}
-
-void UnwrappedLineFormatter::formatFirstToken(
-    const AnnotatedLine &Line, const AnnotatedLine *PreviousLine,
-    const AnnotatedLine *PrevPrevLine,
-    const SmallVectorImpl<AnnotatedLine *> &Lines, unsigned Indent,
-    unsigned NewlineIndent) {
-  FormatToken &RootToken = *Line.First;
-  if (RootToken.is(tok::eof)) {
-    unsigned Newlines =
-        std::min(RootToken.NewlinesBefore,
-                 Style.KeepEmptyLinesAtEOF ? Style.MaxEmptyLinesToKeep + 1 : 1);
-    unsigned TokenIndent = Newlines ? NewlineIndent : 0;
-    Whitespaces->replaceWhitespace(RootToken, Newlines, TokenIndent,
-                                   TokenIndent);
-    return;
-  }
-
-  const auto Newlines =
-      RootToken.Finalized
-          ? RootToken.NewlinesBefore
-          : newlinesBeforeLine(Line, PreviousLine, PrevPrevLine, Lines, Style);
   if (Newlines)
     Indent = NewlineIndent;
 

diff  --git a/clang/test/Format/overlapping-lines.cpp b/clang/test/Format/overlapping-lines.cpp
new file mode 100644
index 0000000000000..1a8b4785a506b
--- /dev/null
+++ b/clang/test/Format/overlapping-lines.cpp
@@ -0,0 +1,8 @@
+// RUN: grep -Ev "// *[A-Z-]+:" %s | clang-format --style=Google 2>&1 | FileCheck %s 
+// CHECK-NOT: The new replacement overlaps with an existing replacement.
+
+#ifdef 
+    
+
+#else 
+#endif 

diff  --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp
index 6c720ec22054c..169c93d1143eb 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -167,7 +167,6 @@ TEST(ConfigParseTest, ParsesConfigurationBools) {
   CHECK_PARSE_BOOL(IndentWrappedFunctionNames);
   CHECK_PARSE_BOOL(InsertBraces);
   CHECK_PARSE_BOOL(InsertNewlineAtEOF);
-  CHECK_PARSE_BOOL(KeepEmptyLinesAtEOF);
   CHECK_PARSE_BOOL(KeepEmptyLinesAtTheStartOfBlocks);
   CHECK_PARSE_BOOL(ObjCSpaceAfterProperty);
   CHECK_PARSE_BOOL(ObjCSpaceBeforeProtocolList);

diff  --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index adc1eda41a91a..fa53cbd262def 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -12856,22 +12856,6 @@ TEST_F(FormatTest, FormatsAfterAccessModifiers) {
                "  void f() {}\n"
                "};\n",
                Style);
-  verifyFormat("struct foo {\n"
-               "#ifdef FOO\n"
-               "#else\n"
-               "private:\n"
-               "\n"
-               "#endif\n"
-               "};",
-               "struct foo {\n"
-               "#ifdef FOO\n"
-               "#else\n"
-               "private:\n"
-               "\n"
-               "\n"
-               "#endif\n"
-               "};",
-               Style);
 
   Style.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Always;
   verifyFormat("struct foo {\n"
@@ -25744,15 +25728,6 @@ TEST_F(FormatTest, InsertNewlineAtEOF) {
   verifyFormat("int i;\n", "int i;", Style);
 }
 
-TEST_F(FormatTest, KeepEmptyLinesAtEOF) {
-  FormatStyle Style = getLLVMStyle();
-  Style.KeepEmptyLinesAtEOF = true;
-
-  const StringRef Code{"int i;\n\n"};
-  verifyFormat(Code, Code, Style);
-  verifyFormat(Code, "int i;\n\n\n", Style);
-}
-
 TEST_F(FormatTest, SpaceAfterUDL) {
   verifyFormat("auto c = (4s).count();");
   verifyFormat("auto x = 5s .count() == 5;");
@@ -25765,6 +25740,18 @@ TEST_F(FormatTest, InterfaceAsClassMemberName) {
                "}");
 }
 
+TEST_F(FormatTest, PreprocessorOverlappingRegions) {
+  verifyFormat("#ifdef\n\n"
+               "#else\n"
+               "#endif\n",
+               "#ifdef \n"
+               "    \n"
+               "\n"
+               "#else \n"
+               "#endif \n",
+               getGoogleStyle());
+}
+
 } // namespace
 } // namespace test
 } // namespace format


        


More information about the cfe-commits mailing list