sstwcw created this revision. sstwcw added reviewers: HazardyKnusperkeks, MyDeveloperDay, curdeius, owenpan. Herald added a project: All. sstwcw requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
Fixes https://github.com/llvm/llvm-project/issues/57738 old #define FOO(typeName, realClass) \ { \ #typeName, foo < FooType>(new foo <realClass>(#typeName)) \ } new #define FOO(typeName, realClass) \ { #typeName, foo<FooType>(new foo<realClass>(#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. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D133954 Files: clang/lib/Format/TokenAnnotator.cpp clang/lib/Format/TokenAnnotator.h clang/lib/Format/UnwrappedLineParser.cpp clang/lib/Format/UnwrappedLineParser.h clang/unittests/Format/FormatTest.cpp clang/unittests/Format/TokenAnnotatorTest.cpp
Index: clang/unittests/Format/TokenAnnotatorTest.cpp =================================================================== --- clang/unittests/Format/TokenAnnotatorTest.cpp +++ clang/unittests/Format/TokenAnnotatorTest.cpp @@ -284,6 +284,17 @@ EXPECT_TOKEN(Tokens[13], tok::ampamp, TT_BinaryOperator); } +TEST_F(TokenAnnotatorTest, UnderstandsTemplatesInMacros) { + auto Tokens = + annotate("#define FOO(typeName) \\\n" + " { #typeName, foo<FooType>(new foo<realClass>(#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"); Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -9790,6 +9790,9 @@ verifyFormat("bool x = 5 < a<int>::x;"); verifyFormat("bool x = a < 4 ? a > 2 : false;"); verifyFormat("bool x = f() ? a < 2 : a > 2;"); + verifyFormat("#define FOO(typeName, realClass) " + " \\\n" + " { #typeName, foo<FooType>(new foo<realClass>(#typeName)) }"); verifyGoogleFormat("A<A<int>> a;"); verifyGoogleFormat("A<A<A<int>>> a;"); Index: clang/lib/Format/UnwrappedLineParser.h =================================================================== --- clang/lib/Format/UnwrappedLineParser.h +++ clang/lib/Format/UnwrappedLineParser.h @@ -46,6 +46,8 @@ /// 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 @@ }; 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 Index: clang/lib/Format/UnwrappedLineParser.cpp =================================================================== --- clang/lib/Format/UnwrappedLineParser.cpp +++ clang/lib/Format/UnwrappedLineParser.cpp @@ -116,12 +116,14 @@ 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 @@ Parser.Line = std::make_unique<UnwrappedLine>(); Parser.Line->Level = PreBlockLine->Level; Parser.Line->InPPDirective = PreBlockLine->InPPDirective; + Parser.Line->InMacroBody = PreBlockLine->InMacroBody; } ~ScopedLineState() { @@ -1251,6 +1254,7 @@ 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 Index: clang/lib/Format/TokenAnnotator.h =================================================================== --- clang/lib/Format/TokenAnnotator.h +++ clang/lib/Format/TokenAnnotator.h @@ -40,7 +40,7 @@ : 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 @@ size_t MatchingOpeningBlockLineIndex; size_t MatchingClosingBlockLineIndex; bool InPPDirective; + bool InMacroBody; bool MustBeDeclaration; bool MightBeFunctionDecl; bool IsMultiVariableDeclStmt; Index: clang/lib/Format/TokenAnnotator.cpp =================================================================== --- clang/lib/Format/TokenAnnotator.cpp +++ clang/lib/Format/TokenAnnotator.cpp @@ -1427,7 +1427,7 @@ 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 @@ 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))
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits