Skip to content
38 changes: 35 additions & 3 deletions clang/lib/Format/ContinuationIndenter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,37 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
return !Tok.Previous->isOneOf(TT_CastRParen, tok::kw_for, tok::kw_while,
tok::kw_switch);
};
auto IsFunctionCallParen = [](const FormatToken &Tok) {
return Tok.is(tok::l_paren) && Tok.ParameterCount > 0 && Tok.Previous &&
Tok.Previous->is(tok::identifier);
};
const auto IsInTemplateString = [this](const FormatToken &Tok) {
if (!Style.isJavaScript())
return false;
for (const auto *Prev = &Tok; Prev; Prev = Prev->Previous) {
if (Prev->is(TT_TemplateString) && Prev->opensScope())
return true;
if (Prev->is(TT_TemplateString) && Prev->closesScope())
break;
}
return false;
};
// Identifies simple (no expression) one-argument function calls.
const auto IsSimpleFunction = [&](const FormatToken &Tok) {
if (!Tok.FakeLParens.empty() && Tok.FakeLParens.back() > prec::Unknown)
return false;
const auto *Previous = Tok.Previous;
if (!Previous || (!Previous->isOneOf(TT_FunctionDeclarationLParen,
TT_LambdaDefinitionLParen) &&
!IsFunctionCallParen(*Previous))) {
return true;
}
if (IsOpeningBracket(Tok) || IsInTemplateString(Tok))
return true;
const auto *Next = Tok.Next;
return !Next || Next->isMemberAccess() ||
Next->is(TT_FunctionDeclarationLParen) || IsFunctionCallParen(*Next);
};
if ((Style.AlignAfterOpenBracket == FormatStyle::BAS_AlwaysBreak ||
Style.AlignAfterOpenBracket == FormatStyle::BAS_BlockIndent) &&
IsOpeningBracket(Previous) && State.Column > getNewLineColumn(State) &&
Expand All @@ -813,10 +844,10 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
// caaaaaaaaaaaall(
// caaaaaaaaaaaall(
// caaaaaaaaaaaaaaaaaaaaaaall(aaaaaaaaaaaaaa, aaaaaaaaa))));
Current.FakeLParens.size() > 0 &&
Current.FakeLParens.back() > prec::Unknown) {
!IsSimpleFunction(Current)) {
CurrentState.NoLineBreak = true;
}

if (Previous.is(TT_TemplateString) && Previous.opensScope())
CurrentState.NoLineBreak = true;

Expand All @@ -831,7 +862,8 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
Previous.isNot(TT_TableGenDAGArgOpenerToBreak) &&
!(Current.MacroParent && Previous.MacroParent) &&
(Current.isNot(TT_LineComment) ||
Previous.isOneOf(BK_BracedInit, TT_VerilogMultiLineListLParen))) {
Previous.isOneOf(BK_BracedInit, TT_VerilogMultiLineListLParen)) &&
!IsInTemplateString(Current)) {
CurrentState.Indent = State.Column + Spaces;
CurrentState.IsAligned = true;
}
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 @@ -102,6 +102,7 @@ namespace format {
TYPE(JsTypeColon) \
TYPE(JsTypeOperator) \
TYPE(JsTypeOptionalQuestion) \
TYPE(LambdaDefinitionLParen) \
TYPE(LambdaLBrace) \
TYPE(LambdaLSquare) \
TYPE(LeadingJavaAnnotation) \
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ static bool canBeObjCSelectorComponent(const FormatToken &Tok) {

/// With `Left` being '(', check if we're at either `[...](` or
/// `[...]<...>(`, where the [ opens a lambda capture list.
// FIXME: this doesn't cover attributes/constraints before the l_paren.
static bool isLambdaParameterList(const FormatToken *Left) {
// Skip <...> if present.
if (Left->Previous && Left->Previous->is(tok::greater) &&
Expand Down Expand Up @@ -365,6 +366,7 @@ class AnnotatingParser {
Contexts.back().IsExpression = false;
} else if (isLambdaParameterList(&OpeningParen)) {
// This is a parameter list of a lambda expression.
OpeningParen.setType(TT_LambdaDefinitionLParen);
Contexts.back().IsExpression = false;
} else if (OpeningParen.is(TT_RequiresExpressionLParen)) {
Contexts.back().IsExpression = false;
Expand Down Expand Up @@ -6205,6 +6207,12 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
return !(Previous && (Previous->is(tok::kw_for) || Previous->isIf()));
}

if (Left.isOneOf(tok::r_paren, TT_TrailingAnnotation) &&
Right.is(TT_TrailingAnnotation) &&
Style.AlignAfterOpenBracket == FormatStyle::BAS_BlockIndent) {
return false;
}

// Allow breaking after a trailing annotation, e.g. after a method
// declaration.
if (Left.is(TT_TrailingAnnotation)) {
Expand Down
25 changes: 25 additions & 0 deletions clang/unittests/Format/FormatTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9338,6 +9338,31 @@ TEST_F(FormatTest, AlignsAfterOpenBracket) {
" aaaaaaaaaaaaaaaa\n"
");",
Style);
verifyFormat("bool aaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
" const bool &aaaaaaaaa, const void *aaaaaaaaaa\n"
") const {\n"
" return true;\n"
"}",
Style);
verifyFormat("bool aaaaaaaaaaaaaaaaaaaaaaaa(\n"
" const bool &aaaaaaaaaa, const void *aaaaaaaaaa\n"
") const;",
Style);
verifyFormat("void aaaaaaaaa(\n"
" int aaaaaa, int bbbbbb, int cccccc, int dddddddddd\n"
") const noexcept -> std::vector<of_very_long_type>;",
Style);
verifyFormat(
"x = aaaaaaaaaaaaaaa(\n"
" \"a aaaaaaa aaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaa aaaaaaaaaaaaa\"\n"
");",
Style);
Style.ColumnLimit = 60;
verifyFormat("auto lambda =\n"
" [&b](\n"
" auto aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
" ) {};",
Style);
}

TEST_F(FormatTest, ParenthesesAndOperandAlignment) {
Expand Down
32 changes: 32 additions & 0 deletions clang/unittests/Format/TokenAnnotatorTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1665,38 +1665,45 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) {
auto Tokens = annotate("[]() constexpr {}");
ASSERT_EQ(Tokens.size(), 8u) << Tokens;
EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare);
EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_LambdaDefinitionLParen);
EXPECT_TOKEN(Tokens[5], tok::l_brace, TT_LambdaLBrace);

Tokens = annotate("[]() consteval {}");
ASSERT_EQ(Tokens.size(), 8u) << Tokens;
EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare);
EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_LambdaDefinitionLParen);
EXPECT_TOKEN(Tokens[5], tok::l_brace, TT_LambdaLBrace);

Tokens = annotate("[]() mutable {}");
ASSERT_EQ(Tokens.size(), 8u) << Tokens;
EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare);
EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_LambdaDefinitionLParen);
EXPECT_TOKEN(Tokens[5], tok::l_brace, TT_LambdaLBrace);

Tokens = annotate("[]() static {}");
ASSERT_EQ(Tokens.size(), 8u) << Tokens;
EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare);
EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_LambdaDefinitionLParen);
EXPECT_TOKEN(Tokens[5], tok::l_brace, TT_LambdaLBrace);

Tokens = annotate("[]() -> auto {}");
ASSERT_EQ(Tokens.size(), 9u) << Tokens;
EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare);
EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_LambdaDefinitionLParen);
EXPECT_TOKEN(Tokens[4], tok::arrow, TT_TrailingReturnArrow);
EXPECT_TOKEN(Tokens[6], tok::l_brace, TT_LambdaLBrace);

Tokens = annotate("[]() -> auto & {}");
ASSERT_EQ(Tokens.size(), 10u) << Tokens;
EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare);
EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_LambdaDefinitionLParen);
EXPECT_TOKEN(Tokens[4], tok::arrow, TT_TrailingReturnArrow);
EXPECT_TOKEN(Tokens[7], tok::l_brace, TT_LambdaLBrace);

Tokens = annotate("[]() -> auto * {}");
ASSERT_EQ(Tokens.size(), 10u) << Tokens;
EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare);
EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_LambdaDefinitionLParen);
EXPECT_TOKEN(Tokens[4], tok::arrow, TT_TrailingReturnArrow);
EXPECT_TOKEN(Tokens[7], tok::l_brace, TT_LambdaLBrace);

Expand Down Expand Up @@ -1725,13 +1732,15 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) {
Tokens = annotate("foo([&](u32 bar) __attribute__((attr)) -> void {});");
ASSERT_EQ(Tokens.size(), 22u) << Tokens;
EXPECT_TOKEN(Tokens[2], tok::l_square, TT_LambdaLSquare);
EXPECT_TOKEN(Tokens[5], tok::l_paren, TT_LambdaDefinitionLParen);
EXPECT_TOKEN(Tokens[15], tok::arrow, TT_TrailingReturnArrow);
EXPECT_TOKEN(Tokens[17], tok::l_brace, TT_LambdaLBrace);

Tokens = annotate("[] <typename T> () {}");
ASSERT_EQ(Tokens.size(), 11u) << Tokens;
EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare);
EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener);
EXPECT_TOKEN(Tokens[6], tok::l_paren, TT_LambdaDefinitionLParen);
EXPECT_TOKEN(Tokens[8], tok::l_brace, TT_LambdaLBrace);

Tokens = annotate("[] <typename T> {}");
Expand All @@ -1744,6 +1753,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) {
ASSERT_EQ(Tokens.size(), 12u) << Tokens;
EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare);
EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener);
EXPECT_TOKEN(Tokens[7], tok::l_paren, TT_LambdaDefinitionLParen);
EXPECT_TOKEN(Tokens[9], tok::l_brace, TT_LambdaLBrace);

Tokens = annotate("[] <typename... T> {}");
Expand All @@ -1756,6 +1766,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) {
ASSERT_EQ(Tokens.size(), 12u) << Tokens;
EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare);
EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener);
EXPECT_TOKEN(Tokens[7], tok::l_paren, TT_LambdaDefinitionLParen);
EXPECT_TOKEN(Tokens[9], tok::l_brace, TT_LambdaLBrace);

Tokens = annotate("[] <int... T> {}");
Expand All @@ -1768,6 +1779,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) {
ASSERT_EQ(Tokens.size(), 12u) << Tokens;
EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare);
EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener);
EXPECT_TOKEN(Tokens[7], tok::l_paren, TT_LambdaDefinitionLParen);
EXPECT_TOKEN(Tokens[9], tok::l_brace, TT_LambdaLBrace);

Tokens = annotate("[] <Foo... T> {}");
Expand All @@ -1781,6 +1793,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) {
ASSERT_EQ(Tokens.size(), 18u) << Tokens;
EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare);
EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener);
EXPECT_TOKEN(Tokens[6], tok::l_paren, TT_LambdaDefinitionLParen);
EXPECT_TOKEN(Tokens[10], tok::kw_requires, TT_RequiresClause);
EXPECT_TRUE(Tokens[14]->ClosesRequiresClause);
EXPECT_TOKEN(Tokens[15], tok::l_brace, TT_LambdaLBrace);
Expand All @@ -1789,6 +1802,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) {
ASSERT_EQ(Tokens.size(), 19u) << Tokens;
EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare);
EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener);
EXPECT_TOKEN(Tokens[6], tok::l_paren, TT_LambdaDefinitionLParen);
EXPECT_TOKEN(Tokens[8], tok::ampamp, TT_PointerOrReference);
EXPECT_TOKEN(Tokens[11], tok::kw_requires, TT_RequiresClause);
EXPECT_TRUE(Tokens[15]->ClosesRequiresClause);
Expand All @@ -1798,6 +1812,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) {
ASSERT_EQ(Tokens.size(), 23u) << Tokens;
EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare);
EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener);
EXPECT_TOKEN(Tokens[6], tok::l_paren, TT_LambdaDefinitionLParen);
EXPECT_TOKEN(Tokens[10], tok::kw_requires, TT_RequiresClause);
EXPECT_TRUE(Tokens[19]->ClosesRequiresClause);
EXPECT_TOKEN(Tokens[20], tok::l_brace, TT_LambdaLBrace);
Expand All @@ -1806,6 +1821,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) {
ASSERT_EQ(Tokens.size(), 20u) << Tokens;
EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare);
EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener);
EXPECT_TOKEN(Tokens[6], tok::l_paren, TT_LambdaDefinitionLParen);
EXPECT_TOKEN(Tokens[10], tok::arrow, TT_TrailingReturnArrow);
EXPECT_TOKEN(Tokens[12], tok::kw_requires, TT_RequiresClause);
EXPECT_TRUE(Tokens[16]->ClosesRequiresClause);
Expand All @@ -1817,6 +1833,8 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) {
EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener);
EXPECT_TOKEN(Tokens[6], tok::kw_requires, TT_RequiresClause);
EXPECT_TRUE(Tokens[10]->ClosesRequiresClause);
// FIXME:
// EXPECT_TOKEN(Tokens[11], tok::l_paren, TT_LambdaDefinitionLParen);
EXPECT_TOKEN(Tokens[15], tok::l_brace, TT_LambdaLBrace);

Tokens = annotate("[] <typename T> requires Bar<T> (T &&t) {}");
Expand All @@ -1825,6 +1843,8 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) {
EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener);
EXPECT_TOKEN(Tokens[6], tok::kw_requires, TT_RequiresClause);
EXPECT_TRUE(Tokens[10]->ClosesRequiresClause);
// FIXME:
// EXPECT_TOKEN(Tokens[11], tok::l_paren, TT_LambdaDefinitionLParen);
EXPECT_TOKEN(Tokens[13], tok::ampamp, TT_PointerOrReference);
EXPECT_TOKEN(Tokens[16], tok::l_brace, TT_LambdaLBrace);

Expand All @@ -1834,6 +1854,8 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) {
EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener);
EXPECT_TOKEN(Tokens[6], tok::kw_requires, TT_RequiresClause);
EXPECT_TRUE(Tokens[15]->ClosesRequiresClause);
// FIXME:
// EXPECT_TOKEN(Tokens[16], tok::l_paren, TT_LambdaDefinitionLParen);
EXPECT_TOKEN(Tokens[20], tok::l_brace, TT_LambdaLBrace);

Tokens = annotate("[] <typename T> requires true (T&& t) {}");
Expand All @@ -1842,6 +1864,8 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) {
EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener);
EXPECT_TOKEN(Tokens[6], tok::kw_requires, TT_RequiresClause);
EXPECT_TRUE(Tokens[7]->ClosesRequiresClause);
// FIXME:
// EXPECT_TOKEN(Tokens[8], tok::l_paren, TT_LambdaDefinitionLParen);
EXPECT_TOKEN(Tokens[10], tok::ampamp, TT_PointerOrReference);
EXPECT_TOKEN(Tokens[13], tok::l_brace, TT_LambdaLBrace);

Expand Down Expand Up @@ -1876,6 +1900,8 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) {
EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener);
EXPECT_TOKEN(Tokens[6], tok::kw_requires, TT_RequiresClause);
EXPECT_TRUE(Tokens[10]->ClosesRequiresClause);
// FIXME:
// EXPECT_TOKEN(Tokens[11], tok::l_paren, TT_LambdaDefinitionLParen);
EXPECT_TOKEN(Tokens[15], tok::kw_requires, TT_RequiresClause);
EXPECT_TRUE(Tokens[19]->ClosesRequiresClause);
EXPECT_TOKEN(Tokens[20], tok::l_brace, TT_LambdaLBrace);
Expand All @@ -1885,20 +1911,23 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) {
EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare);
EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener);
EXPECT_TOKEN(Tokens[7], tok::greater, TT_TemplateCloser);
EXPECT_TOKEN(Tokens[8], tok::l_paren, TT_LambdaDefinitionLParen);
EXPECT_TOKEN(Tokens[12], tok::l_brace, TT_LambdaLBrace);

Tokens = annotate("[] <int I = 0> (T t) {}");
ASSERT_EQ(Tokens.size(), 15u) << Tokens;
EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare);
EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener);
EXPECT_TOKEN(Tokens[7], tok::greater, TT_TemplateCloser);
EXPECT_TOKEN(Tokens[8], tok::l_paren, TT_LambdaDefinitionLParen);
EXPECT_TOKEN(Tokens[12], tok::l_brace, TT_LambdaLBrace);

Tokens = annotate("[] <bool b = false> (T t) {}");
ASSERT_EQ(Tokens.size(), 15u) << Tokens;
EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare);
EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener);
EXPECT_TOKEN(Tokens[7], tok::greater, TT_TemplateCloser);
EXPECT_TOKEN(Tokens[8], tok::l_paren, TT_LambdaDefinitionLParen);
EXPECT_TOKEN(Tokens[12], tok::l_brace, TT_LambdaLBrace);

Tokens = annotate("[] <bool b = true && false> (T&& t) {}");
Expand All @@ -1907,6 +1936,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) {
EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener);
EXPECT_TOKEN(Tokens[7], tok::ampamp, TT_BinaryOperator);
EXPECT_TOKEN(Tokens[9], tok::greater, TT_TemplateCloser);
EXPECT_TOKEN(Tokens[10], tok::l_paren, TT_LambdaDefinitionLParen);
EXPECT_TOKEN(Tokens[12], tok::ampamp, TT_PointerOrReference);
EXPECT_TOKEN(Tokens[15], tok::l_brace, TT_LambdaLBrace);

Expand All @@ -1916,6 +1946,8 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) {
EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener);
EXPECT_TOKEN(Tokens[7], tok::greater, TT_TemplateCloser);
EXPECT_TOKEN(Tokens[8], tok::kw_requires, TT_RequiresClause);
// FIXME:
// EXPECT_TOKEN(Tokens[13], tok::l_paren, TT_LambdaDefinitionLParen);
EXPECT_TOKEN(Tokens[17], tok::l_brace, TT_LambdaLBrace);
}

Expand Down