owenpan created this revision. Herald added projects: All, clang, clang-format. Herald added a subscriber: cfe-commits. Herald added reviewers: rymiel, HazardyKnusperkeks, MyDeveloperDay. owenpan requested review of this revision.
If the first token of an annotated line is finalized, reuse its `NewlinesBefore` value to avoid potential overlapping whitespace replacements before preprocessor branching directives. Fixes https://github.com/llvm/llvm-project/issues/62892. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D151954 Files: clang/lib/Format/UnwrappedLineFormatter.cpp clang/unittests/Format/FormatTest.cpp Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -12856,6 +12856,22 @@ " 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" Index: clang/lib/Format/UnwrappedLineFormatter.cpp =================================================================== --- clang/lib/Format/UnwrappedLineFormatter.cpp +++ clang/lib/Format/UnwrappedLineFormatter.cpp @@ -1418,19 +1418,12 @@ return Penalty; } -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; - } +static auto newlinesBeforeLine(const AnnotatedLine &Line, + const AnnotatedLine *PreviousLine, + const AnnotatedLine *PrevPrevLine, + const SmallVectorImpl<AnnotatedLine *> &Lines, + const FormatToken &RootToken, + const FormatStyle &Style) { unsigned Newlines = std::min(RootToken.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1); // Remove empty lines before "}" where applicable. @@ -1510,6 +1503,27 @@ } } + 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, 1u); + unsigned TokenIndent = Newlines ? NewlineIndent : 0; + Whitespaces->replaceWhitespace(RootToken, Newlines, TokenIndent, + TokenIndent); + return; + } + + const auto Newlines = + RootToken.Finalized ? RootToken.NewlinesBefore + : newlinesBeforeLine(Line, PreviousLine, PrevPrevLine, + Lines, RootToken, Style); if (Newlines) Indent = NewlineIndent;
Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -12856,6 +12856,22 @@ " 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" Index: clang/lib/Format/UnwrappedLineFormatter.cpp =================================================================== --- clang/lib/Format/UnwrappedLineFormatter.cpp +++ clang/lib/Format/UnwrappedLineFormatter.cpp @@ -1418,19 +1418,12 @@ return Penalty; } -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; - } +static auto newlinesBeforeLine(const AnnotatedLine &Line, + const AnnotatedLine *PreviousLine, + const AnnotatedLine *PrevPrevLine, + const SmallVectorImpl<AnnotatedLine *> &Lines, + const FormatToken &RootToken, + const FormatStyle &Style) { unsigned Newlines = std::min(RootToken.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1); // Remove empty lines before "}" where applicable. @@ -1510,6 +1503,27 @@ } } + 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, 1u); + unsigned TokenIndent = Newlines ? NewlineIndent : 0; + Whitespaces->replaceWhitespace(RootToken, Newlines, TokenIndent, + TokenIndent); + return; + } + + const auto Newlines = + RootToken.Finalized ? RootToken.NewlinesBefore + : newlinesBeforeLine(Line, PreviousLine, PrevPrevLine, + Lines, RootToken, Style); if (Newlines) Indent = NewlineIndent;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits