Author: Owen Pan Date: 2024-10-02T18:10:56-07:00 New Revision: 688bc958bd4167512f0d45e1fd008c9551de1c75
URL: https://github.com/llvm/llvm-project/commit/688bc958bd4167512f0d45e1fd008c9551de1c75 DIFF: https://github.com/llvm/llvm-project/commit/688bc958bd4167512f0d45e1fd008c9551de1c75.diff LOG: [clang-format] Add TemplateNames option to help parse C++ angles (#109916) Closes #109912. Added: Modified: clang/docs/ClangFormatStyleOptions.rst clang/docs/ReleaseNotes.rst clang/include/clang/Format/Format.h clang/lib/Format/Format.cpp clang/lib/Format/FormatToken.h clang/lib/Format/FormatTokenLexer.cpp clang/lib/Format/FormatTokenLexer.h clang/lib/Format/TokenAnnotator.cpp clang/unittests/Format/TokenAnnotatorTest.cpp Removed: ################################################################################ diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index a427d7cd40fcdd..a16edb0989b05c 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -6554,6 +6554,15 @@ the configuration (without a prefix: ``Auto``). let DAGArgOtherID = (other i32:$other1, i32:$other2); let DAGArgBang = (!cast<SomeType>("Some") i32:$src1, i32:$src2) +.. _TemplateNames: + +**TemplateNames** (``List of Strings``) :versionbadge:`clang-format 20` :ref:`¶ <TemplateNames>` + A vector of non-keyword identifiers that should be interpreted as + template names. + + A ``<`` after a template name is annotated as a template opener instead of + a binary operator. + .. _TypeNames: **TypeNames** (``List of Strings``) :versionbadge:`clang-format 17` :ref:`¶ <TypeNames>` diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index bb759cede22ff9..329ba37d6791c3 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -615,6 +615,7 @@ clang-format ------------ - Adds ``BreakBinaryOperations`` option. +- Adds ``TemplateNames`` option. libclang -------- diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index d8b62c7652a0f6..53a9577e0f72e7 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -4974,6 +4974,15 @@ struct FormatStyle { /// \version 3.7 unsigned TabWidth; + /// A vector of non-keyword identifiers that should be interpreted as + /// template names. + /// + /// A ``<`` after a template name is annotated as a template opener instead of + /// a binary operator. + /// + /// \version 20 + std::vector<std::string> TemplateNames; + /// A vector of non-keyword identifiers that should be interpreted as type /// names. /// @@ -5230,6 +5239,7 @@ struct FormatStyle { TableGenBreakingDAGArgOperators == R.TableGenBreakingDAGArgOperators && TableGenBreakInsideDAGArg == R.TableGenBreakInsideDAGArg && + TabWidth == R.TabWidth && TemplateNames == R.TemplateNames && TabWidth == R.TabWidth && TypeNames == R.TypeNames && TypenameMacros == R.TypenameMacros && UseTab == R.UseTab && VerilogBreakBetweenInstancePorts == diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index d2463b892fbb96..5350c66ea5132b 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -1147,6 +1147,7 @@ template <> struct MappingTraits<FormatStyle> { IO.mapOptional("TableGenBreakInsideDAGArg", Style.TableGenBreakInsideDAGArg); IO.mapOptional("TabWidth", Style.TabWidth); + IO.mapOptional("TemplateNames", Style.TemplateNames); IO.mapOptional("TypeNames", Style.TypeNames); IO.mapOptional("TypenameMacros", Style.TypenameMacros); IO.mapOptional("UseTab", Style.UseTab); diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index 03c0cbd60961a2..7d342a7dcca01d 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -179,6 +179,7 @@ namespace format { TYPE(TrailingReturnArrow) \ TYPE(TrailingUnaryOperator) \ TYPE(TypeDeclarationParen) \ + TYPE(TemplateName) \ TYPE(TypeName) \ TYPE(TypenameMacro) \ TYPE(UnaryOperator) \ diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp index 63949b2e26bdc1..2cdf6cd286b280 100644 --- a/clang/lib/Format/FormatTokenLexer.cpp +++ b/clang/lib/Format/FormatTokenLexer.cpp @@ -72,6 +72,8 @@ FormatTokenLexer::FormatTokenLexer( Macros.insert({Identifier, TT_StatementAttributeLikeMacro}); } + for (const auto &TemplateName : Style.TemplateNames) + TemplateNames.insert(&IdentTable.get(TemplateName)); for (const auto &TypeName : Style.TypeNames) TypeNames.insert(&IdentTable.get(TypeName)); } @@ -1368,6 +1370,8 @@ FormatToken *FormatTokenLexer::getNextToken() { FormatTok->setType(TT_MacroBlockBegin); else if (MacroBlockEndRegex.match(Text)) FormatTok->setType(TT_MacroBlockEnd); + else if (TemplateNames.contains(Identifier)) + FormatTok->setFinalizedType(TT_TemplateName); else if (TypeNames.contains(Identifier)) FormatTok->setFinalizedType(TT_TypeName); } diff --git a/clang/lib/Format/FormatTokenLexer.h b/clang/lib/Format/FormatTokenLexer.h index 277cc0a2dfde66..71389d2ade2b73 100644 --- a/clang/lib/Format/FormatTokenLexer.h +++ b/clang/lib/Format/FormatTokenLexer.h @@ -129,7 +129,7 @@ class FormatTokenLexer { llvm::SmallMapVector<IdentifierInfo *, TokenType, 8> Macros; - llvm::SmallPtrSet<IdentifierInfo *, 8> TypeNames; + llvm::SmallPtrSet<IdentifierInfo *, 8> TemplateNames, TypeNames; bool FormattingDisabled; diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index bdaeae4b7593bb..130ae829f026d6 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -149,36 +149,36 @@ class AnnotatingParser { } bool parseAngle() { - if (!CurrentToken || !CurrentToken->Previous) + if (!CurrentToken) + return false; + + auto *Left = CurrentToken->Previous; // The '<'. + if (!Left) return false; - if (NonTemplateLess.count(CurrentToken->Previous) > 0) + + if (NonTemplateLess.count(Left) > 0) return false; - if (const auto &Previous = *CurrentToken->Previous; // The '<'. - Previous.Previous) { - if (Previous.Previous->Tok.isLiteral()) + const auto *BeforeLess = Left->Previous; + + if (BeforeLess) { + if (BeforeLess->Tok.isLiteral()) return false; - if (Previous.Previous->is(tok::r_brace)) + if (BeforeLess->is(tok::r_brace)) return false; - if (Previous.Previous->is(tok::r_paren) && Contexts.size() > 1 && - (!Previous.Previous->MatchingParen || - Previous.Previous->MatchingParen->isNot( - TT_OverloadedOperatorLParen))) { + if (BeforeLess->is(tok::r_paren) && Contexts.size() > 1 && + !(BeforeLess->MatchingParen && + BeforeLess->MatchingParen->is(TT_OverloadedOperatorLParen))) { return false; } - if (Previous.Previous->is(tok::kw_operator) && - CurrentToken->is(tok::l_paren)) { + if (BeforeLess->is(tok::kw_operator) && CurrentToken->is(tok::l_paren)) return false; - } } - FormatToken *Left = CurrentToken->Previous; Left->ParentBracket = Contexts.back().ContextKind; ScopedContextCreator ContextCreator(*this, tok::less, 12); Contexts.back().IsExpression = false; - const auto *BeforeLess = Left->Previous; - // If there's a template keyword before the opening angle bracket, this is a // template parameter, not an argument. if (BeforeLess && BeforeLess->isNot(tok::kw_template)) @@ -229,6 +229,10 @@ class AnnotatingParser { next(); return true; } + if (BeforeLess && BeforeLess->is(TT_TemplateName)) { + next(); + continue; + } if (CurrentToken->is(tok::question) && Style.Language == FormatStyle::LK_Java) { next(); diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index ed139c42207e3f..c8184d6f789504 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -3516,6 +3516,23 @@ TEST_F(TokenAnnotatorTest, SplitPenalty) { EXPECT_SPLIT_PENALTY(Tokens[7], 23u); } +TEST_F(TokenAnnotatorTest, TemplateName) { + constexpr StringRef Code{"return Foo < A || B > (C ^ D);"}; + + auto Tokens = annotate(Code); + ASSERT_EQ(Tokens.size(), 14u) << Tokens; + EXPECT_TOKEN(Tokens[2], tok::less, TT_BinaryOperator); + EXPECT_TOKEN(Tokens[6], tok::greater, TT_BinaryOperator); + + auto Style = getLLVMStyle(); + Style.TemplateNames.push_back("Foo"); + + Tokens = annotate(Code, Style); + EXPECT_TOKEN(Tokens[1], tok::identifier, TT_TemplateName); + EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[6], tok::greater, TT_TemplateCloser); +} + } // namespace } // namespace format } // namespace clang _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits