Author: Marek Kurdej Date: 2022-02-09T22:39:59+01:00 New Revision: a7b5e5b413bd1654e8e96b9c7842c7c1ab0db58a
URL: https://github.com/llvm/llvm-project/commit/a7b5e5b413bd1654e8e96b9c7842c7c1ab0db58a DIFF: https://github.com/llvm/llvm-project/commit/a7b5e5b413bd1654e8e96b9c7842c7c1ab0db58a.diff LOG: [clang-format] Fix formatting of macro definitions with a leading comment. Fixes https://github.com/llvm/llvm-project/issues/43206. Reviewed By: HazardyKnusperkeks Differential Revision: https://reviews.llvm.org/D118924 Added: Modified: clang/lib/Format/UnwrappedLineParser.cpp clang/unittests/Format/FormatTest.cpp Removed: ################################################################################ diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 97a2cf367e80..0686aeb253ad 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -3551,6 +3551,8 @@ void UnwrappedLineParser::distributeComments( void UnwrappedLineParser::readToken(int LevelDifference) { SmallVector<FormatToken *, 1> Comments; + bool PreviousWasComment = false; + bool FirstNonCommentOnLine = false; do { FormatTok = Tokens->getNextToken(); assert(FormatTok); @@ -3567,8 +3569,26 @@ void UnwrappedLineParser::readToken(int LevelDifference) { FormatTok->MustBreakBefore = true; } + auto IsFirstNonCommentOnLine = [](bool FirstNonCommentOnLine, + const FormatToken &Tok, + bool PreviousWasComment) { + auto IsFirstOnLine = [](const FormatToken &Tok) { + return Tok.HasUnescapedNewline || Tok.IsFirst; + }; + + // Consider preprocessor directives preceded by block comments as first + // on line. + if (PreviousWasComment) + return FirstNonCommentOnLine || IsFirstOnLine(Tok); + return IsFirstOnLine(Tok); + }; + + FirstNonCommentOnLine = IsFirstNonCommentOnLine( + FirstNonCommentOnLine, *FormatTok, PreviousWasComment); + PreviousWasComment = FormatTok->Tok.is(tok::comment); + while (!Line->InPPDirective && FormatTok->Tok.is(tok::hash) && - (FormatTok->HasUnescapedNewline || FormatTok->IsFirst)) { + FirstNonCommentOnLine) { distributeComments(Comments, FormatTok); Comments.clear(); // If there is an unfinished unwrapped line, we flush the preprocessor @@ -3587,6 +3607,9 @@ void UnwrappedLineParser::readToken(int LevelDifference) { Line->Level += PPBranchLevel; flushComments(isOnNewLine(*FormatTok)); parsePPDirective(); + PreviousWasComment = FormatTok->Tok.is(tok::comment); + FirstNonCommentOnLine = IsFirstNonCommentOnLine( + FirstNonCommentOnLine, *FormatTok, PreviousWasComment); } if (!PPStack.empty() && (PPStack.back().Kind == PP_Unreachable) && diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 6f76a0c62edf..c7516427c2f4 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -1797,6 +1797,17 @@ TEST_F(FormatTest, FormatShortBracedStatements) { TEST_F(FormatTest, UnderstandsMacros) { verifyFormat("#define A (parentheses)"); + verifyFormat("/* comment */ #define A (parentheses)"); + verifyFormat("/* comment */ /* another comment */ #define A (parentheses)"); + // Even the partial code should never be merged. + EXPECT_EQ("/* comment */ #define A (parentheses)\n" + "#", + format("/* comment */ #define A (parentheses)\n" + "#")); + verifyFormat("/* comment */ #define A (parentheses)\n" + "#\n"); + verifyFormat("/* comment */ #define A (parentheses)\n" + "#define B (parentheses)"); verifyFormat("#define true ((int)1)"); verifyFormat("#define and(x)"); verifyFormat("#define if(x) x"); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits