Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions clang/docs/ClangFormatStyleOptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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>`
Expand Down
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1124,6 +1124,7 @@ clang-format
- Adds ``RemoveEmptyLinesInUnwrappedLines`` option.
- Adds ``KeepFormFeed`` option and set it to ``true`` for ``GNU`` style.
- Adds ``AllowShortNamespacesOnASingleLine`` option.
- Adds ``VariableTemplates`` option.

libclang
--------
Expand Down
11 changes: 10 additions & 1 deletion clang/include/clang/Format/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Format/Format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Format/FormatToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */ \
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Format/FormatTokenLexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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);
}
}

Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Format/FormatTokenLexer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
19 changes: 15 additions & 4 deletions clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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)
Expand Down
13 changes: 13 additions & 0 deletions clang/unittests/Format/TokenAnnotatorTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {}");
Expand Down
Loading