Skip to content

Commit 8f61998

Browse files
committed
[clang-format] Add VariableTemplate option
Closes #120148.
1 parent 141c544 commit 8f61998

File tree

9 files changed

+60
-10
lines changed

9 files changed

+60
-10
lines changed

clang/docs/ClangFormatStyleOptions.rst

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6725,8 +6725,8 @@ the configuration (without a prefix: ``Auto``).
67256725
.. _TemplateNames:
67266726

67276727
**TemplateNames** (``List of Strings``) :versionbadge:`clang-format 20` :ref:`<TemplateNames>`
6728-
A vector of non-keyword identifiers that should be interpreted as
6729-
template names.
6728+
A vector of non-keyword identifiers that should be interpreted as template
6729+
names.
67306730

67316731
A ``<`` after a template name is annotated as a template opener instead of
67326732
a binary operator.
@@ -6793,6 +6793,15 @@ the configuration (without a prefix: ``Auto``).
67936793

67946794

67956795

6796+
.. _VariableTemplates:
6797+
6798+
**VariableTemplates** (``List of Strings``) :versionbadge:`clang-format 20` :ref:`<VariableTemplates>`
6799+
A vector of non-keyword identifiers that should be interpreted as variable
6800+
template names.
6801+
6802+
A ``)`` after a non-variable template instantiation may be annotated as
6803+
the closing parenthesis of the C-style cast operator.
6804+
67966805
.. _VerilogBreakBetweenInstancePorts:
67976806

67986807
**VerilogBreakBetweenInstancePorts** (``Boolean``) :versionbadge:`clang-format 17` :ref:`<VerilogBreakBetweenInstancePorts>`

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,6 +1118,7 @@ clang-format
11181118
``Never``, and ``true`` to ``Always``.
11191119
- Adds ``RemoveEmptyLinesInUnwrappedLines`` option.
11201120
- Adds ``KeepFormFeed`` option and set it to ``true`` for ``GNU`` style.
1121+
- Adds ``VariableTemplates`` option.
11211122

11221123
libclang
11231124
--------

clang/include/clang/Format/Format.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5038,8 +5038,8 @@ struct FormatStyle {
50385038
/// \version 3.7
50395039
unsigned TabWidth;
50405040

5041-
/// A vector of non-keyword identifiers that should be interpreted as
5042-
/// template names.
5041+
/// A vector of non-keyword identifiers that should be interpreted as template
5042+
/// names.
50435043
///
50445044
/// A ``<`` after a template name is annotated as a template opener instead of
50455045
/// a binary operator.
@@ -5099,6 +5099,15 @@ struct FormatStyle {
50995099
/// \version 3.7
51005100
UseTabStyle UseTab;
51015101

5102+
/// A vector of non-keyword identifiers that should be interpreted as variable
5103+
/// template names.
5104+
///
5105+
/// A ``)`` after a non-variable template instantiation may be annotated as
5106+
/// the closing parenthesis of the C-style cast operator.
5107+
///
5108+
/// \version 20
5109+
std::vector<std::string> VariableTemplates;
5110+
51025111
/// For Verilog, put each port on its own line in module instantiations.
51035112
/// \code
51045113
/// true:
@@ -5308,7 +5317,7 @@ struct FormatStyle {
53085317
TableGenBreakInsideDAGArg == R.TableGenBreakInsideDAGArg &&
53095318
TabWidth == R.TabWidth && TemplateNames == R.TemplateNames &&
53105319
TypeNames == R.TypeNames && TypenameMacros == R.TypenameMacros &&
5311-
UseTab == R.UseTab &&
5320+
UseTab == R.UseTab && VariableTemplates == R.VariableTemplates &&
53125321
VerilogBreakBetweenInstancePorts ==
53135322
R.VerilogBreakBetweenInstancePorts &&
53145323
WhitespaceSensitiveMacros == R.WhitespaceSensitiveMacros;

clang/lib/Format/Format.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,6 +1164,7 @@ template <> struct MappingTraits<FormatStyle> {
11641164
IO.mapOptional("TypeNames", Style.TypeNames);
11651165
IO.mapOptional("TypenameMacros", Style.TypenameMacros);
11661166
IO.mapOptional("UseTab", Style.UseTab);
1167+
IO.mapOptional("VariableTemplates", Style.VariableTemplates);
11671168
IO.mapOptional("VerilogBreakBetweenInstancePorts",
11681169
Style.VerilogBreakBetweenInstancePorts);
11691170
IO.mapOptional("WhitespaceSensitiveMacros",

clang/lib/Format/FormatToken.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ namespace format {
186186
TYPE(UnionLBrace) \
187187
TYPE(UnionRBrace) \
188188
TYPE(UntouchableMacroFunc) \
189+
TYPE(VariableTemplate) \
189190
/* Like in 'assign x = 0, y = 1;' . */ \
190191
TYPE(VerilogAssignComma) \
191192
/* like in begin : block */ \

clang/lib/Format/FormatTokenLexer.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ FormatTokenLexer::FormatTokenLexer(
7676
TemplateNames.insert(&IdentTable.get(TemplateName));
7777
for (const auto &TypeName : Style.TypeNames)
7878
TypeNames.insert(&IdentTable.get(TypeName));
79+
for (const auto &VariableTemplate : Style.VariableTemplates)
80+
VariableTemplates.insert(&IdentTable.get(VariableTemplate));
7981
}
8082

8183
ArrayRef<FormatToken *> FormatTokenLexer::lex() {
@@ -1382,6 +1384,8 @@ FormatToken *FormatTokenLexer::getNextToken() {
13821384
FormatTok->setFinalizedType(TT_TemplateName);
13831385
else if (TypeNames.contains(Identifier))
13841386
FormatTok->setFinalizedType(TT_TypeName);
1387+
else if (VariableTemplates.contains(Identifier))
1388+
FormatTok->setFinalizedType(TT_VariableTemplate);
13851389
}
13861390
}
13871391

clang/lib/Format/FormatTokenLexer.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,8 @@ class FormatTokenLexer {
129129

130130
llvm::SmallMapVector<IdentifierInfo *, TokenType, 8> Macros;
131131

132-
llvm::SmallPtrSet<IdentifierInfo *, 8> TemplateNames, TypeNames;
132+
llvm::SmallPtrSet<IdentifierInfo *, 8> TemplateNames, TypeNames,
133+
VariableTemplates;
133134

134135
bool FormattingDisabled;
135136

clang/lib/Format/TokenAnnotator.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2792,6 +2792,16 @@ class AnnotatingParser {
27922792
return true;
27932793
}
27942794

2795+
auto IsNonVariableTemplate = [](const FormatToken &Tok) {
2796+
if (Tok.isNot(TT_TemplateCloser))
2797+
return false;
2798+
const auto *Less = Tok.MatchingParen;
2799+
if (!Less)
2800+
return false;
2801+
const auto *BeforeLess = Less->getPreviousNonComment();
2802+
return BeforeLess && BeforeLess->isNot(TT_VariableTemplate);
2803+
};
2804+
27952805
// Heuristically try to determine whether the parentheses contain a type.
27962806
auto IsQualifiedPointerOrReference = [](const FormatToken *T,
27972807
const LangOptions &LangOpts) {
@@ -2825,10 +2835,11 @@ class AnnotatingParser {
28252835
}
28262836
return T && T->is(TT_PointerOrReference);
28272837
};
2828-
bool ParensAreType =
2829-
BeforeRParen->isOneOf(TT_TemplateCloser, TT_TypeDeclarationParen) ||
2830-
BeforeRParen->isTypeName(LangOpts) ||
2831-
IsQualifiedPointerOrReference(BeforeRParen, LangOpts);
2838+
2839+
bool ParensAreType = IsNonVariableTemplate(*BeforeRParen) ||
2840+
BeforeRParen->is(TT_TypeDeclarationParen) ||
2841+
BeforeRParen->isTypeName(LangOpts) ||
2842+
IsQualifiedPointerOrReference(BeforeRParen, LangOpts);
28322843
bool ParensCouldEndDecl =
28332844
AfterRParen->isOneOf(tok::equal, tok::semi, tok::l_brace, tok::greater);
28342845
if (ParensAreType && !ParensCouldEndDecl)

clang/unittests/Format/TokenAnnotatorTest.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3615,6 +3615,19 @@ TEST_F(TokenAnnotatorTest, TemplateInstantiation) {
36153615
EXPECT_TOKEN(Tokens[18], tok::greater, TT_TemplateCloser);
36163616
}
36173617

3618+
TEST_F(TokenAnnotatorTest, VariableTemplate) {
3619+
auto Style = getLLVMStyle();
3620+
Style.VariableTemplates.push_back("a");
3621+
3622+
auto Tokens = annotate("auto t3 = (a<int>) + b;", Style);
3623+
ASSERT_EQ(Tokens.size(), 13u) << Tokens;
3624+
EXPECT_TOKEN(Tokens[4], tok::identifier, TT_VariableTemplate);
3625+
EXPECT_TOKEN(Tokens[5], tok::less, TT_TemplateOpener);
3626+
EXPECT_TOKEN(Tokens[7], tok::greater, TT_TemplateCloser);
3627+
EXPECT_TOKEN(Tokens[8], tok::r_paren, TT_Unknown); // Not TT_CastRParen
3628+
EXPECT_TOKEN(Tokens[9], tok::plus, TT_BinaryOperator);
3629+
}
3630+
36183631
TEST_F(TokenAnnotatorTest, SwitchInMacroArgument) {
36193632
auto Tokens = annotate("FOOBAR(switch);\n"
36203633
"void f() {}");

0 commit comments

Comments
 (0)