[clang] 3c0d4aa - [clang-format] Handle static_assert more accurately (#166042)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Nov 2 22:35:54 PST 2025
Author: owenca
Date: 2025-11-02T22:35:50-08:00
New Revision: 3c0d4aa60156b05c5ca71a78b5f384820814f604
URL: https://github.com/llvm/llvm-project/commit/3c0d4aa60156b05c5ca71a78b5f384820814f604
DIFF: https://github.com/llvm/llvm-project/commit/3c0d4aa60156b05c5ca71a78b5f384820814f604.diff
LOG: [clang-format] Handle static_assert more accurately (#166042)
Used test cases from #165631.
Added:
Modified:
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/TokenAnnotatorTest.cpp
Removed:
################################################################################
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 8e227da2a79ab..cb41756c56bf7 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -358,11 +358,11 @@ class AnnotatingParser {
Contexts.back().IsExpression = false;
} else if (OpeningParen.Previous &&
(OpeningParen.Previous->isOneOf(
- tok::kw_static_assert, tok::kw_noexcept, tok::kw_explicit,
- tok::kw_while, tok::l_paren, tok::comma, TT_CastRParen,
+ tok::kw_noexcept, tok::kw_explicit, tok::kw_while,
+ tok::l_paren, tok::comma, TT_CastRParen,
TT_BinaryOperator) ||
OpeningParen.Previous->isIf())) {
- // static_assert, if and while usually contain expressions.
+ // if and while usually contain expressions.
Contexts.back().IsExpression = true;
} else if (Style.isJavaScript() && OpeningParen.Previous &&
(OpeningParen.Previous->is(Keywords.kw_function) ||
@@ -454,6 +454,11 @@ class AnnotatingParser {
if (StartsObjCSelector)
OpeningParen.setType(TT_ObjCSelector);
+ const bool IsStaticAssert =
+ PrevNonComment && PrevNonComment->is(tok::kw_static_assert);
+ if (IsStaticAssert)
+ Contexts.back().InStaticAssertFirstArgument = true;
+
// MightBeFunctionType and ProbablyFunctionType are used for
// function pointer and reference types as well as Objective-C
// block types:
@@ -583,8 +588,12 @@ class AnnotatingParser {
}
// When we discover a 'new', we set CanBeExpression to 'false' in order to
// parse the type correctly. Reset that after a comma.
- if (CurrentToken->is(tok::comma))
- Contexts.back().CanBeExpression = true;
+ if (CurrentToken->is(tok::comma)) {
+ if (IsStaticAssert)
+ Contexts.back().InStaticAssertFirstArgument = false;
+ else
+ Contexts.back().CanBeExpression = true;
+ }
if (Style.isTableGen()) {
if (CurrentToken->is(tok::comma)) {
@@ -2144,6 +2153,7 @@ class AnnotatingParser {
bool CaretFound = false;
bool InCpp11AttributeSpecifier = false;
bool InCSharpAttributeSpecifier = false;
+ bool InStaticAssertFirstArgument = false;
bool VerilogAssignmentFound = false;
// Whether the braces may mean concatenation instead of structure or array
// literal.
@@ -2440,7 +2450,8 @@ class AnnotatingParser {
} else if (Current.isPointerOrReference()) {
Current.setType(determineStarAmpUsage(
Current,
- Contexts.back().CanBeExpression && Contexts.back().IsExpression,
+ (Contexts.back().CanBeExpression && Contexts.back().IsExpression) ||
+ Contexts.back().InStaticAssertFirstArgument,
Contexts.back().ContextType == Context::TemplateArgument));
} else if (Current.isOneOf(tok::minus, tok::plus, tok::caret) ||
(Style.isVerilog() && Current.is(tok::pipe))) {
diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp
index 6c05feaeb13e0..815c79e68dac9 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -799,6 +799,30 @@ TEST_F(TokenAnnotatorTest, UnderstandsTemplateTemplateParameters) {
EXPECT_TOKEN(Tokens[23], tok::identifier, TT_ClassHeadName);
}
+TEST_F(TokenAnnotatorTest, UnderstandsCommonCppTemplates) {
+ auto Tokens =
+ annotate("static_assert(std::conditional_t<A || B, C, D>::value);");
+ ASSERT_EQ(Tokens.size(), 19u) << Tokens;
+ EXPECT_TOKEN(Tokens[5], tok::less, TT_TemplateOpener);
+ EXPECT_TOKEN(Tokens[13], tok::greater, TT_TemplateCloser);
+
+ Tokens =
+ annotate("static_assert(std::conditional<A || B, C, D>::type::value);");
+ ASSERT_EQ(Tokens.size(), 21u) << Tokens;
+ EXPECT_TOKEN(Tokens[5], tok::less, TT_TemplateOpener);
+ EXPECT_TOKEN(Tokens[13], tok::greater, TT_TemplateCloser);
+
+ Tokens = annotate("static_assert(fancy_v<A || B>);");
+ ASSERT_EQ(Tokens.size(), 11u) << Tokens;
+ EXPECT_TOKEN(Tokens[3], tok::less, TT_TemplateOpener);
+ EXPECT_TOKEN(Tokens[7], tok::greater, TT_TemplateCloser);
+
+ Tokens = annotate("static_assert(fancy<A || B>::value);");
+ ASSERT_EQ(Tokens.size(), 13u) << Tokens;
+ EXPECT_TOKEN(Tokens[3], tok::less, TT_TemplateOpener);
+ EXPECT_TOKEN(Tokens[7], tok::greater, TT_TemplateCloser);
+}
+
TEST_F(TokenAnnotatorTest, UnderstandsWhitespaceSensitiveMacros) {
FormatStyle Style = getLLVMStyle();
Style.WhitespaceSensitiveMacros.push_back("FOO");
More information about the cfe-commits
mailing list