Skip to content

Commit 3c0d4aa

Browse files
authored
[clang-format] Handle static_assert more accurately (#166042)
Used test cases from #165631.
1 parent a9f0594 commit 3c0d4aa

File tree

2 files changed

+41
-6
lines changed

2 files changed

+41
-6
lines changed

clang/lib/Format/TokenAnnotator.cpp

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -358,11 +358,11 @@ class AnnotatingParser {
358358
Contexts.back().IsExpression = false;
359359
} else if (OpeningParen.Previous &&
360360
(OpeningParen.Previous->isOneOf(
361-
tok::kw_static_assert, tok::kw_noexcept, tok::kw_explicit,
362-
tok::kw_while, tok::l_paren, tok::comma, TT_CastRParen,
361+
tok::kw_noexcept, tok::kw_explicit, tok::kw_while,
362+
tok::l_paren, tok::comma, TT_CastRParen,
363363
TT_BinaryOperator) ||
364364
OpeningParen.Previous->isIf())) {
365-
// static_assert, if and while usually contain expressions.
365+
// if and while usually contain expressions.
366366
Contexts.back().IsExpression = true;
367367
} else if (Style.isJavaScript() && OpeningParen.Previous &&
368368
(OpeningParen.Previous->is(Keywords.kw_function) ||
@@ -454,6 +454,11 @@ class AnnotatingParser {
454454
if (StartsObjCSelector)
455455
OpeningParen.setType(TT_ObjCSelector);
456456

457+
const bool IsStaticAssert =
458+
PrevNonComment && PrevNonComment->is(tok::kw_static_assert);
459+
if (IsStaticAssert)
460+
Contexts.back().InStaticAssertFirstArgument = true;
461+
457462
// MightBeFunctionType and ProbablyFunctionType are used for
458463
// function pointer and reference types as well as Objective-C
459464
// block types:
@@ -583,8 +588,12 @@ class AnnotatingParser {
583588
}
584589
// When we discover a 'new', we set CanBeExpression to 'false' in order to
585590
// parse the type correctly. Reset that after a comma.
586-
if (CurrentToken->is(tok::comma))
587-
Contexts.back().CanBeExpression = true;
591+
if (CurrentToken->is(tok::comma)) {
592+
if (IsStaticAssert)
593+
Contexts.back().InStaticAssertFirstArgument = false;
594+
else
595+
Contexts.back().CanBeExpression = true;
596+
}
588597

589598
if (Style.isTableGen()) {
590599
if (CurrentToken->is(tok::comma)) {
@@ -2144,6 +2153,7 @@ class AnnotatingParser {
21442153
bool CaretFound = false;
21452154
bool InCpp11AttributeSpecifier = false;
21462155
bool InCSharpAttributeSpecifier = false;
2156+
bool InStaticAssertFirstArgument = false;
21472157
bool VerilogAssignmentFound = false;
21482158
// Whether the braces may mean concatenation instead of structure or array
21492159
// literal.
@@ -2440,7 +2450,8 @@ class AnnotatingParser {
24402450
} else if (Current.isPointerOrReference()) {
24412451
Current.setType(determineStarAmpUsage(
24422452
Current,
2443-
Contexts.back().CanBeExpression && Contexts.back().IsExpression,
2453+
(Contexts.back().CanBeExpression && Contexts.back().IsExpression) ||
2454+
Contexts.back().InStaticAssertFirstArgument,
24442455
Contexts.back().ContextType == Context::TemplateArgument));
24452456
} else if (Current.isOneOf(tok::minus, tok::plus, tok::caret) ||
24462457
(Style.isVerilog() && Current.is(tok::pipe))) {

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)