[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
This commit is contained in:
Paul Kirth 2023-06-08 21:58:42 +00:00
parent c0ad1b4597
commit b6a718016c
8 changed files with 33 additions and 68 deletions

View File

@ -3555,11 +3555,6 @@ the configuration (without a prefix: ``Auto``).
false: false:
import {VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying,} from "some/module.js" 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:
**KeepEmptyLinesAtTheStartOfBlocks** (``Boolean``) :versionbadge:`clang-format 3.7` :ref:`¶ <KeepEmptyLinesAtTheStartOfBlocks>` **KeepEmptyLinesAtTheStartOfBlocks** (``Boolean``) :versionbadge:`clang-format 3.7` :ref:`¶ <KeepEmptyLinesAtTheStartOfBlocks>`

View File

@ -707,7 +707,6 @@ clang-format
- Fix all known issues associated with ``LambdaBodyIndentation: OuterScope``. - Fix all known issues associated with ``LambdaBodyIndentation: OuterScope``.
- Add ``BracedInitializerIndentWidth`` which can be used to configure - Add ``BracedInitializerIndentWidth`` which can be used to configure
the indentation level of the contents of braced init lists. the indentation level of the contents of braced init lists.
- Add ``KeepEmptyLinesAtEOF`` to keep empty lines at end of file.
libclang libclang
-------- --------

View File

@ -2675,10 +2675,6 @@ struct FormatStyle {
bool JavaScriptWrapImports; bool JavaScriptWrapImports;
// clang-format on // 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. /// If true, the empty line at the start of blocks is kept.
/// \code /// \code
/// true: false: /// true: false:
@ -4368,7 +4364,6 @@ struct FormatStyle {
JavaImportGroups == R.JavaImportGroups && JavaImportGroups == R.JavaImportGroups &&
JavaScriptQuotes == R.JavaScriptQuotes && JavaScriptQuotes == R.JavaScriptQuotes &&
JavaScriptWrapImports == R.JavaScriptWrapImports && JavaScriptWrapImports == R.JavaScriptWrapImports &&
KeepEmptyLinesAtEOF == R.KeepEmptyLinesAtEOF &&
KeepEmptyLinesAtTheStartOfBlocks == KeepEmptyLinesAtTheStartOfBlocks ==
R.KeepEmptyLinesAtTheStartOfBlocks && R.KeepEmptyLinesAtTheStartOfBlocks &&
Language == R.Language && Language == R.Language &&

View File

@ -942,7 +942,6 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports); IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports);
IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks", IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",
Style.KeepEmptyLinesAtTheStartOfBlocks); Style.KeepEmptyLinesAtTheStartOfBlocks);
IO.mapOptional("KeepEmptyLinesAtEOF", Style.KeepEmptyLinesAtEOF);
IO.mapOptional("LambdaBodyIndentation", Style.LambdaBodyIndentation); IO.mapOptional("LambdaBodyIndentation", Style.LambdaBodyIndentation);
IO.mapOptional("LineEnding", Style.LineEnding); IO.mapOptional("LineEnding", Style.LineEnding);
IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin); IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin);
@ -1411,7 +1410,6 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
/*Hex=*/0, /*HexMinDigits=*/0}; /*Hex=*/0, /*HexMinDigits=*/0};
LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave; LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
LLVMStyle.JavaScriptWrapImports = true; LLVMStyle.JavaScriptWrapImports = true;
LLVMStyle.KeepEmptyLinesAtEOF = false;
LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true; LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true;
LLVMStyle.LambdaBodyIndentation = FormatStyle::LBI_Signature; LLVMStyle.LambdaBodyIndentation = FormatStyle::LBI_Signature;
LLVMStyle.LineEnding = FormatStyle::LE_DeriveLF; LLVMStyle.LineEnding = FormatStyle::LE_DeriveLF;

View File

@ -1418,12 +1418,19 @@ unsigned UnwrappedLineFormatter::format(
return Penalty; return Penalty;
} }
static auto newlinesBeforeLine(const AnnotatedLine &Line, void UnwrappedLineFormatter::formatFirstToken(
const AnnotatedLine *PreviousLine, const AnnotatedLine &Line, const AnnotatedLine *PreviousLine,
const AnnotatedLine *PrevPrevLine, const AnnotatedLine *PrevPrevLine,
const SmallVectorImpl<AnnotatedLine *> &Lines, const SmallVectorImpl<AnnotatedLine *> &Lines, unsigned Indent,
const FormatStyle &Style) { unsigned NewlineIndent) {
const auto &RootToken = *Line.First; 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 = unsigned Newlines =
std::min(RootToken.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1); std::min(RootToken.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1);
// Remove empty lines before "}" where applicable. // 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) if (Newlines)
Indent = NewlineIndent; Indent = NewlineIndent;

View File

@ -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

View File

@ -167,7 +167,6 @@ TEST(ConfigParseTest, ParsesConfigurationBools) {
CHECK_PARSE_BOOL(IndentWrappedFunctionNames); CHECK_PARSE_BOOL(IndentWrappedFunctionNames);
CHECK_PARSE_BOOL(InsertBraces); CHECK_PARSE_BOOL(InsertBraces);
CHECK_PARSE_BOOL(InsertNewlineAtEOF); CHECK_PARSE_BOOL(InsertNewlineAtEOF);
CHECK_PARSE_BOOL(KeepEmptyLinesAtEOF);
CHECK_PARSE_BOOL(KeepEmptyLinesAtTheStartOfBlocks); CHECK_PARSE_BOOL(KeepEmptyLinesAtTheStartOfBlocks);
CHECK_PARSE_BOOL(ObjCSpaceAfterProperty); CHECK_PARSE_BOOL(ObjCSpaceAfterProperty);
CHECK_PARSE_BOOL(ObjCSpaceBeforeProtocolList); CHECK_PARSE_BOOL(ObjCSpaceBeforeProtocolList);

View File

@ -12856,22 +12856,6 @@ TEST_F(FormatTest, FormatsAfterAccessModifiers) {
" void f() {}\n" " void f() {}\n"
"};\n", "};\n",
Style); 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; Style.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Always;
verifyFormat("struct foo {\n" verifyFormat("struct foo {\n"
@ -25744,15 +25728,6 @@ TEST_F(FormatTest, InsertNewlineAtEOF) {
verifyFormat("int i;\n", "int i;", Style); 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) { TEST_F(FormatTest, SpaceAfterUDL) {
verifyFormat("auto c = (4s).count();"); verifyFormat("auto c = (4s).count();");
verifyFormat("auto x = 5s .count() == 5;"); 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
} // namespace test } // namespace test
} // namespace format } // namespace format