From: sstwcw Date: Fri, 16 Sep 2022 13:18:21 +0000 (+0000) Subject: [clang-format] Fix template arguments in macros X-Git-Tag: upstream/17.0.6~33363 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e5964223d99a119e4077e3ed1f1322fa2b8cc703;p=platform%2Fupstream%2Fllvm.git [clang-format] Fix template arguments in macros Fixes https://github.com/llvm/llvm-project/issues/57738 old ``` #define FOO(typeName, realClass) \ { \ #typeName, foo < FooType>(new foo (#typeName)) \ } ``` new ``` #define FOO(typeName, realClass) \ { #typeName, foo(new foo(#typeName)) } ``` Previously, when an UnwrappedLine began with a hash in a macro definition, the program incorrectly assumed the line was a preprocessor directive. It should be stringification. The rule in spaceRequiredBefore was added in 8b5297117b. Its purpose is to add a space in an include directive. It also added a space to a template opener when the line began with a stringification hash. So we changed it. Reviewed By: HazardyKnusperkeks, owenpan Differential Revision: https://reviews.llvm.org/D133954 --- diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index d7c2e66..d18adc3 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -1427,7 +1427,7 @@ public: if (!CurrentToken) return LT_Invalid; NonTemplateLess.clear(); - if (CurrentToken->is(tok::hash)) { + if (!Line.InMacroBody && CurrentToken->is(tok::hash)) { // We were not yet allowed to use C++17 optional when this was being // written. So we used LT_Invalid to mark that the line is not a // preprocessor directive. @@ -4241,7 +4241,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, return false; } if (Right.is(tok::less) && Left.isNot(tok::l_paren) && - Line.startsWith(tok::hash)) { + Line.Type == LT_ImportStatement) { return true; } if (Right.is(TT_TrailingUnaryOperator)) diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h index 028ff6d..b6f086d 100644 --- a/clang/lib/Format/TokenAnnotator.h +++ b/clang/lib/Format/TokenAnnotator.h @@ -40,7 +40,7 @@ public: : First(Line.Tokens.front().Tok), Level(Line.Level), MatchingOpeningBlockLineIndex(Line.MatchingOpeningBlockLineIndex), MatchingClosingBlockLineIndex(Line.MatchingClosingBlockLineIndex), - InPPDirective(Line.InPPDirective), + InPPDirective(Line.InPPDirective), InMacroBody(Line.InMacroBody), MustBeDeclaration(Line.MustBeDeclaration), MightBeFunctionDecl(false), IsMultiVariableDeclStmt(false), Affected(false), LeadingEmptyLinesAffected(false), ChildrenAffected(false), @@ -130,6 +130,7 @@ public: size_t MatchingOpeningBlockLineIndex; size_t MatchingClosingBlockLineIndex; bool InPPDirective; + bool InMacroBody; bool MustBeDeclaration; bool MightBeFunctionDecl; bool IsMultiVariableDeclStmt; diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index fce50d6..4fd4fd4 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -116,12 +116,14 @@ public: TokenSource = this; Line.Level = 0; Line.InPPDirective = true; + // InMacroBody gets set after the `#define x` part. } ~ScopedMacroState() override { TokenSource = PreviousTokenSource; ResetToken = Token; Line.InPPDirective = false; + Line.InMacroBody = false; Line.Level = PreviousLineLevel; } @@ -196,6 +198,7 @@ public: Parser.Line = std::make_unique(); Parser.Line->Level = PreBlockLine->Level; Parser.Line->InPPDirective = PreBlockLine->InPPDirective; + Parser.Line->InMacroBody = PreBlockLine->InMacroBody; } ~ScopedLineState() { @@ -1253,6 +1256,7 @@ void UnwrappedLineParser::parsePPDefine() { Line->Level += PPBranchLevel + 1; addUnwrappedLine(); ++Line->Level; + Line->InMacroBody = true; // Errors during a preprocessor directive can only affect the layout of the // preprocessor directive, and thus we ignore them. An alternative approach diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h index 7d6c84e..ce51d17 100644 --- a/clang/lib/Format/UnwrappedLineParser.h +++ b/clang/lib/Format/UnwrappedLineParser.h @@ -46,6 +46,8 @@ struct UnwrappedLine { /// Whether this \c UnwrappedLine is part of a preprocessor directive. bool InPPDirective; + /// Whether it is part of a macro body. + bool InMacroBody; bool MustBeDeclaration; @@ -353,8 +355,8 @@ struct UnwrappedLineNode { }; inline UnwrappedLine::UnwrappedLine() - : Level(0), InPPDirective(false), MustBeDeclaration(false), - MatchingOpeningBlockLineIndex(kInvalidIndex) {} + : Level(0), InPPDirective(false), InMacroBody(false), + MustBeDeclaration(false), MatchingOpeningBlockLineIndex(kInvalidIndex) {} } // end namespace format } // end namespace clang diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 8d9ccfd..828948e 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -9864,6 +9864,10 @@ TEST_F(FormatTest, UnderstandsTemplateParameters) { verifyFormat("Constructor(A... a) : a_(X{std::forward(a)}...) {}"); verifyFormat("< < < < < < < < < < < < < < < < < < < < < < < < < < < < < <"); verifyFormat("some_templated_type"); + + verifyFormat("#define FOO(typeName, realClass) \\\n" + " { #typeName, foo(new foo(#typeName)) }", + getLLVMStyleWithColumns(60)); } TEST_F(FormatTest, UnderstandsShiftOperators) { diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index a92d44b..1fe8bec 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -284,6 +284,17 @@ TEST_F(TokenAnnotatorTest, UnderstandsVariableTemplates) { EXPECT_TOKEN(Tokens[13], tok::ampamp, TT_BinaryOperator); } +TEST_F(TokenAnnotatorTest, UnderstandsTemplatesInMacros) { + auto Tokens = + annotate("#define FOO(typeName) \\\n" + " { #typeName, foo(new foo(#typeName)) }"); + ASSERT_EQ(Tokens.size(), 27u) << Tokens; + EXPECT_TOKEN(Tokens[11], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[13], tok::greater, TT_TemplateCloser); + EXPECT_TOKEN(Tokens[17], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[19], tok::greater, TT_TemplateCloser); +} + TEST_F(TokenAnnotatorTest, UnderstandsWhitespaceSensitiveMacros) { FormatStyle Style = getLLVMStyle(); Style.WhitespaceSensitiveMacros.push_back("FOO");