Skip to content

Commit 1a0d0ae

Browse files
authored
[clang-format] Add VariableTemplates option (#121318)
Closes #120148.
1 parent 508929d commit 1a0d0ae

File tree

9 files changed

+56
-6
lines changed

9 files changed

+56
-6
lines changed

clang/docs/ClangFormatStyleOptions.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6798,6 +6798,15 @@ the configuration (without a prefix: ``Auto``).
67986798

67996799

68006800

6801+
.. _VariableTemplates:
6802+
6803+
**VariableTemplates** (``List of Strings``) :versionbadge:`clang-format 20` :ref:`<VariableTemplates>`
6804+
A vector of non-keyword identifiers that should be interpreted as variable
6805+
template names.
6806+
6807+
A ``)`` after a variable template instantiation is **not** annotated as
6808+
the closing parenthesis of C-style cast operator.
6809+
68016810
.. _VerilogBreakBetweenInstancePorts:
68026811

68036812
**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
@@ -1125,6 +1125,7 @@ clang-format
11251125
- Adds ``RemoveEmptyLinesInUnwrappedLines`` option.
11261126
- Adds ``KeepFormFeed`` option and set it to ``true`` for ``GNU`` style.
11271127
- Adds ``AllowShortNamespacesOnASingleLine`` option.
1128+
- Adds ``VariableTemplates`` option.
11281129
- Adds support for bash globstar in ``.clang-format-ignore``.
11291130

11301131
libclang

clang/include/clang/Format/Format.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5103,6 +5103,15 @@ struct FormatStyle {
51035103
/// \version 3.7
51045104
UseTabStyle UseTab;
51055105

5106+
/// A vector of non-keyword identifiers that should be interpreted as variable
5107+
/// template names.
5108+
///
5109+
/// A ``)`` after a variable template instantiation is **not** annotated as
5110+
/// the closing parenthesis of C-style cast operator.
5111+
///
5112+
/// \version 20
5113+
std::vector<std::string> VariableTemplates;
5114+
51065115
/// For Verilog, put each port on its own line in module instantiations.
51075116
/// \code
51085117
/// true:
@@ -5314,7 +5323,7 @@ struct FormatStyle {
53145323
TableGenBreakInsideDAGArg == R.TableGenBreakInsideDAGArg &&
53155324
TabWidth == R.TabWidth && TemplateNames == R.TemplateNames &&
53165325
TypeNames == R.TypeNames && TypenameMacros == R.TypenameMacros &&
5317-
UseTab == R.UseTab &&
5326+
UseTab == R.UseTab && VariableTemplates == R.VariableTemplates &&
53185327
VerilogBreakBetweenInstancePorts ==
53195328
R.VerilogBreakBetweenInstancePorts &&
53205329
WhitespaceSensitiveMacros == R.WhitespaceSensitiveMacros;

clang/lib/Format/Format.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1166,6 +1166,7 @@ template <> struct MappingTraits<FormatStyle> {
11661166
IO.mapOptional("TypeNames", Style.TypeNames);
11671167
IO.mapOptional("TypenameMacros", Style.TypenameMacros);
11681168
IO.mapOptional("UseTab", Style.UseTab);
1169+
IO.mapOptional("VariableTemplates", Style.VariableTemplates);
11691170
IO.mapOptional("VerilogBreakBetweenInstancePorts",
11701171
Style.VerilogBreakBetweenInstancePorts);
11711172
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)