Author: Owen Pan Date: 2025-01-01T18:24:56-08:00 New Revision: 1a0d0ae234544dc4978f1e12730408cb83f6b923
URL: https://github.com/llvm/llvm-project/commit/1a0d0ae234544dc4978f1e12730408cb83f6b923 DIFF: https://github.com/llvm/llvm-project/commit/1a0d0ae234544dc4978f1e12730408cb83f6b923.diff LOG: [clang-format] Add `VariableTemplates` option (#121318) Closes #120148. 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 c175436a2817a9..d9b3f666df03c0 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -6798,6 +6798,15 @@ the configuration (without a prefix: ``Auto``). +.. _VariableTemplates: + +**VariableTemplates** (``List of Strings``) :versionbadge:`clang-format 20` :ref:`¶ <VariableTemplates>` + A vector of non-keyword identifiers that should be interpreted as variable + template names. + + A ``)`` after a variable template instantiation is **not** annotated as + the closing parenthesis of C-style cast operator. + .. _VerilogBreakBetweenInstancePorts: **VerilogBreakBetweenInstancePorts** (``Boolean``) :versionbadge:`clang-format 17` :ref:`¶ <VerilogBreakBetweenInstancePorts>` diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 662c575bad3e8b..e0aef1af2135cd 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -1125,6 +1125,7 @@ clang-format - Adds ``RemoveEmptyLinesInUnwrappedLines`` option. - Adds ``KeepFormFeed`` option and set it to ``true`` for ``GNU`` style. - Adds ``AllowShortNamespacesOnASingleLine`` option. +- Adds ``VariableTemplates`` option. - Adds support for bash globstar in ``.clang-format-ignore``. libclang diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index eefaabf9392fd7..bb34f2d33ac15e 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -5103,6 +5103,15 @@ struct FormatStyle { /// \version 3.7 UseTabStyle UseTab; + /// A vector of non-keyword identifiers that should be interpreted as variable + /// template names. + /// + /// A ``)`` after a variable template instantiation is **not** annotated as + /// the closing parenthesis of C-style cast operator. + /// + /// \version 20 + std::vector<std::string> VariableTemplates; + /// For Verilog, put each port on its own line in module instantiations. /// \code /// true: @@ -5314,7 +5323,7 @@ struct FormatStyle { TableGenBreakInsideDAGArg == R.TableGenBreakInsideDAGArg && TabWidth == R.TabWidth && TemplateNames == R.TemplateNames && TypeNames == R.TypeNames && TypenameMacros == R.TypenameMacros && - UseTab == R.UseTab && + UseTab == R.UseTab && VariableTemplates == R.VariableTemplates && VerilogBreakBetweenInstancePorts == R.VerilogBreakBetweenInstancePorts && WhitespaceSensitiveMacros == R.WhitespaceSensitiveMacros; diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 8f44e9f00212cf..a5657f2d910f68 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -1166,6 +1166,7 @@ template <> struct MappingTraits<FormatStyle> { IO.mapOptional("TypeNames", Style.TypeNames); IO.mapOptional("TypenameMacros", Style.TypenameMacros); IO.mapOptional("UseTab", Style.UseTab); + IO.mapOptional("VariableTemplates", Style.VariableTemplates); IO.mapOptional("VerilogBreakBetweenInstancePorts", Style.VerilogBreakBetweenInstancePorts); IO.mapOptional("WhitespaceSensitiveMacros", diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index f6bb860a1fea31..8917049cefb865 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -186,6 +186,7 @@ namespace format { TYPE(UnionLBrace) \ TYPE(UnionRBrace) \ TYPE(UntouchableMacroFunc) \ + TYPE(VariableTemplate) \ /* Like in 'assign x = 0, y = 1;' . */ \ TYPE(VerilogAssignComma) \ /* like in begin : block */ \ diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp index 7a264bddcdfe19..0f8d4940d4369a 100644 --- a/clang/lib/Format/FormatTokenLexer.cpp +++ b/clang/lib/Format/FormatTokenLexer.cpp @@ -76,6 +76,8 @@ FormatTokenLexer::FormatTokenLexer( TemplateNames.insert(&IdentTable.get(TemplateName)); for (const auto &TypeName : Style.TypeNames) TypeNames.insert(&IdentTable.get(TypeName)); + for (const auto &VariableTemplate : Style.VariableTemplates) + VariableTemplates.insert(&IdentTable.get(VariableTemplate)); } ArrayRef<FormatToken *> FormatTokenLexer::lex() { @@ -1382,6 +1384,8 @@ FormatToken *FormatTokenLexer::getNextToken() { FormatTok->setFinalizedType(TT_TemplateName); else if (TypeNames.contains(Identifier)) FormatTok->setFinalizedType(TT_TypeName); + else if (VariableTemplates.contains(Identifier)) + FormatTok->setFinalizedType(TT_VariableTemplate); } } diff --git a/clang/lib/Format/FormatTokenLexer.h b/clang/lib/Format/FormatTokenLexer.h index 71389d2ade2b73..61474a3f9ada8c 100644 --- a/clang/lib/Format/FormatTokenLexer.h +++ b/clang/lib/Format/FormatTokenLexer.h @@ -129,7 +129,8 @@ class FormatTokenLexer { llvm::SmallMapVector<IdentifierInfo *, TokenType, 8> Macros; - llvm::SmallPtrSet<IdentifierInfo *, 8> TemplateNames, TypeNames; + llvm::SmallPtrSet<IdentifierInfo *, 8> TemplateNames, TypeNames, + VariableTemplates; bool FormattingDisabled; diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index f2cfa7f49f62f9..b0f570966a63f3 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2792,6 +2792,16 @@ class AnnotatingParser { return true; } + auto IsNonVariableTemplate = [](const FormatToken &Tok) { + if (Tok.isNot(TT_TemplateCloser)) + return false; + const auto *Less = Tok.MatchingParen; + if (!Less) + return false; + const auto *BeforeLess = Less->getPreviousNonComment(); + return BeforeLess && BeforeLess->isNot(TT_VariableTemplate); + }; + // Heuristically try to determine whether the parentheses contain a type. auto IsQualifiedPointerOrReference = [](const FormatToken *T, const LangOptions &LangOpts) { @@ -2825,10 +2835,11 @@ class AnnotatingParser { } return T && T->is(TT_PointerOrReference); }; - bool ParensAreType = - BeforeRParen->isOneOf(TT_TemplateCloser, TT_TypeDeclarationParen) || - BeforeRParen->isTypeName(LangOpts) || - IsQualifiedPointerOrReference(BeforeRParen, LangOpts); + + bool ParensAreType = IsNonVariableTemplate(*BeforeRParen) || + BeforeRParen->is(TT_TypeDeclarationParen) || + BeforeRParen->isTypeName(LangOpts) || + IsQualifiedPointerOrReference(BeforeRParen, LangOpts); bool ParensCouldEndDecl = AfterRParen->isOneOf(tok::equal, tok::semi, tok::l_brace, tok::greater); if (ParensAreType && !ParensCouldEndDecl) diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index b2fb5227993c3f..d61b9adf4f58c6 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -3615,6 +3615,19 @@ TEST_F(TokenAnnotatorTest, TemplateInstantiation) { EXPECT_TOKEN(Tokens[18], tok::greater, TT_TemplateCloser); } +TEST_F(TokenAnnotatorTest, VariableTemplate) { + auto Style = getLLVMStyle(); + Style.VariableTemplates.push_back("a"); + + auto Tokens = annotate("auto t3 = (a<int>) + b;", Style); + ASSERT_EQ(Tokens.size(), 13u) << Tokens; + EXPECT_TOKEN(Tokens[4], tok::identifier, TT_VariableTemplate); + EXPECT_TOKEN(Tokens[5], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[7], tok::greater, TT_TemplateCloser); + EXPECT_TOKEN(Tokens[8], tok::r_paren, TT_Unknown); // Not TT_CastRParen + EXPECT_TOKEN(Tokens[9], tok::plus, TT_BinaryOperator); +} + TEST_F(TokenAnnotatorTest, SwitchInMacroArgument) { auto Tokens = annotate("FOOBAR(switch);\n" "void f() {}"); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits