Skip to content

Commit 834ac2e

Browse files
authored
[clang-format] Allow ternary in all templates (#96801)
Currently, question mark and colon tokens are not allowed between angle brackets, as a template argument, if we are in an expression context. However, expressions can still allowed in non-expression contexts, leading to inconsistent formatting. Removing this check entirely fixes this issue, and, surprisingly, breaks no tests. Fixes #81385
1 parent d0fee98 commit 834ac2e

File tree

2 files changed

+19
-8
lines changed

2 files changed

+19
-8
lines changed

clang/lib/Format/TokenAnnotator.cpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,6 @@ class AnnotatingParser {
176176
Left->ParentBracket = Contexts.back().ContextKind;
177177
ScopedContextCreator ContextCreator(*this, tok::less, 12);
178178

179-
// If this angle is in the context of an expression, we need to be more
180-
// hesitant to detect it as opening template parameters.
181-
bool InExprContext = Contexts.back().IsExpression;
182-
183179
Contexts.back().IsExpression = false;
184180
// If there's a template keyword before the opening angle bracket, this is a
185181
// template parameter, not an argument.
@@ -231,11 +227,8 @@ class AnnotatingParser {
231227
next();
232228
continue;
233229
}
234-
if (CurrentToken->isOneOf(tok::r_paren, tok::r_square, tok::r_brace) ||
235-
(CurrentToken->isOneOf(tok::colon, tok::question) && InExprContext &&
236-
!Style.isCSharp() && !Style.isProto())) {
230+
if (CurrentToken->isOneOf(tok::r_paren, tok::r_square, tok::r_brace))
237231
return false;
238-
}
239232
// If a && or || is found and interpreted as a binary operator, this set
240233
// of angles is likely part of something like "a < b && c > d". If the
241234
// angles are inside an expression, the ||/&& might also be a binary

clang/unittests/Format/TokenAnnotatorTest.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,24 @@ TEST_F(TokenAnnotatorTest, UnderstandsGreaterAfterTemplateCloser) {
567567
EXPECT_TOKEN(Tokens[8], tok::greater, TT_BinaryOperator);
568568
}
569569

570+
TEST_F(TokenAnnotatorTest, UnderstandsTernaryInTemplate) {
571+
// IsExpression = false
572+
auto Tokens = annotate("foo<true ? 1 : 2>();");
573+
ASSERT_EQ(Tokens.size(), 12u) << Tokens;
574+
EXPECT_TOKEN(Tokens[1], tok::less, TT_TemplateOpener);
575+
EXPECT_TOKEN(Tokens[3], tok::question, TT_ConditionalExpr);
576+
EXPECT_TOKEN(Tokens[5], tok::colon, TT_ConditionalExpr);
577+
EXPECT_TOKEN(Tokens[7], tok::greater, TT_TemplateCloser);
578+
579+
// IsExpression = true
580+
Tokens = annotate("return foo<true ? 1 : 2>();");
581+
ASSERT_EQ(Tokens.size(), 13u) << Tokens;
582+
EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener);
583+
EXPECT_TOKEN(Tokens[4], tok::question, TT_ConditionalExpr);
584+
EXPECT_TOKEN(Tokens[6], tok::colon, TT_ConditionalExpr);
585+
EXPECT_TOKEN(Tokens[8], tok::greater, TT_TemplateCloser);
586+
}
587+
570588
TEST_F(TokenAnnotatorTest, UnderstandsNonTemplateAngleBrackets) {
571589
auto Tokens = annotate("return a < b && c > d;");
572590
ASSERT_EQ(Tokens.size(), 10u) << Tokens;

0 commit comments

Comments
 (0)