Skip to content

Commit ebbfbd0

Browse files
[clang-format] Improve annotating templates
The static_assert hinted to be an expression and when the || was hit the fate was doomed. As far as I see we can never be sure if it's an expression or a template, but we can improve the situation for common cases.
1 parent 4cb73cd commit ebbfbd0

File tree

2 files changed

+38
-4
lines changed

2 files changed

+38
-4
lines changed

clang/lib/Format/TokenAnnotator.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,14 +150,14 @@ class AnnotatingParser {
150150
if (!CurrentToken)
151151
return false;
152152

153-
auto *Left = CurrentToken->Previous; // The '<'.
153+
auto *const Left = CurrentToken->Previous; // The '<'.
154154
if (!Left)
155155
return false;
156156

157157
if (NonTemplateLess.count(Left) > 0)
158158
return false;
159159

160-
const auto *BeforeLess = Left->Previous;
160+
const auto *const BeforeLess = Left->Previous;
161161

162162
if (BeforeLess) {
163163
if (BeforeLess->Tok.isLiteral())
@@ -206,8 +206,18 @@ class AnnotatingParser {
206206
(!Next || Next->isNoneOf(tok::l_paren, tok::l_brace))) {
207207
return false;
208208
}
209-
if (!MaybeAngles)
210-
return false;
209+
if (!MaybeAngles) {
210+
const bool IsCommonCppTemplate =
211+
(BeforeLess && BeforeLess->is(tok::identifier) &&
212+
(BeforeLess->TokenText.ends_with("_t") ||
213+
BeforeLess->TokenText.ends_with("_v"))) ||
214+
(Next &&
215+
Next->startsSequence(tok::coloncolon, tok::identifier) &&
216+
(Next->Next->TokenText == "type" ||
217+
Next->Next->TokenText == "value"));
218+
if (!IsCommonCppTemplate)
219+
return false;
220+
}
211221
}
212222
Left->MatchingParen = CurrentToken;
213223
CurrentToken->MatchingParen = Left;

clang/unittests/Format/TokenAnnotatorTest.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,30 @@ TEST_F(TokenAnnotatorTest, UnderstandsTemplateTemplateParameters) {
799799
EXPECT_TOKEN(Tokens[23], tok::identifier, TT_ClassHeadName);
800800
}
801801

802+
TEST_F(TokenAnnotatorTest, UnderstandsCommonCppTemplates) {
803+
auto Tokens =
804+
annotate("static_assert(std::conditional_t<A || B, C, D>::value);");
805+
ASSERT_EQ(Tokens.size(), 19u) << Tokens;
806+
EXPECT_TOKEN(Tokens[5], tok::less, TT_TemplateOpener);
807+
EXPECT_TOKEN(Tokens[13], tok::greater, TT_TemplateCloser);
808+
809+
Tokens =
810+
annotate("static_assert(std::conditional<A || B, C, D>::type::value);");
811+
ASSERT_EQ(Tokens.size(), 21u) << Tokens;
812+
EXPECT_TOKEN(Tokens[5], tok::less, TT_TemplateOpener);
813+
EXPECT_TOKEN(Tokens[13], tok::greater, TT_TemplateCloser);
814+
815+
Tokens = annotate("static_assert(fancy_v<A || B>);");
816+
ASSERT_EQ(Tokens.size(), 11u) << Tokens;
817+
EXPECT_TOKEN(Tokens[3], tok::less, TT_TemplateOpener);
818+
EXPECT_TOKEN(Tokens[7], tok::greater, TT_TemplateCloser);
819+
820+
Tokens = annotate("static_assert(fancy<A || B>::value);");
821+
ASSERT_EQ(Tokens.size(), 13u) << Tokens;
822+
EXPECT_TOKEN(Tokens[3], tok::less, TT_TemplateOpener);
823+
EXPECT_TOKEN(Tokens[7], tok::greater, TT_TemplateCloser);
824+
}
825+
802826
TEST_F(TokenAnnotatorTest, UnderstandsWhitespaceSensitiveMacros) {
803827
FormatStyle Style = getLLVMStyle();
804828
Style.WhitespaceSensitiveMacros.push_back("FOO");

0 commit comments

Comments
 (0)