Skip to content

Commit c83d64f

Browse files
authored
[clang-format] Fix a bug in mis-annotating arrows (#67780)
Fixed #66923.
1 parent 75441a6 commit c83d64f

File tree

2 files changed

+45
-31
lines changed

2 files changed

+45
-31
lines changed

clang/lib/Format/TokenAnnotator.cpp

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2016,8 +2016,7 @@ class AnnotatingParser {
20162016
Style.Language == FormatStyle::LK_Java) {
20172017
Current.setType(TT_LambdaArrow);
20182018
} else if (Current.is(tok::arrow) && AutoFound &&
2019-
(Line.MightBeFunctionDecl || Line.InPPDirective) &&
2020-
Current.NestingLevel == 0 &&
2019+
Line.MightBeFunctionDecl && Current.NestingLevel == 0 &&
20212020
!Current.Previous->isOneOf(tok::kw_operator, tok::identifier)) {
20222021
// not auto operator->() -> xxx;
20232022
Current.setType(TT_TrailingReturnArrow);
@@ -3252,7 +3251,8 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) {
32523251
// This function heuristically determines whether 'Current' starts the name of a
32533252
// function declaration.
32543253
static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current,
3255-
const AnnotatedLine &Line) {
3254+
const AnnotatedLine &Line,
3255+
FormatToken *&ClosingParen) {
32563256
assert(Current.Previous);
32573257

32583258
if (Current.is(TT_FunctionDeclarationName))
@@ -3344,16 +3344,16 @@ static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current,
33443344
// Check whether parameter list can belong to a function declaration.
33453345
if (!Next || Next->isNot(tok::l_paren) || !Next->MatchingParen)
33463346
return false;
3347+
ClosingParen = Next->MatchingParen;
3348+
assert(ClosingParen->is(tok::r_paren));
33473349
// If the lines ends with "{", this is likely a function definition.
33483350
if (Line.Last->is(tok::l_brace))
33493351
return true;
3350-
if (Next->Next == Next->MatchingParen)
3352+
if (Next->Next == ClosingParen)
33513353
return true; // Empty parentheses.
33523354
// If there is an &/&& after the r_paren, this is likely a function.
3353-
if (Next->MatchingParen->Next &&
3354-
Next->MatchingParen->Next->is(TT_PointerOrReference)) {
3355+
if (ClosingParen->Next && ClosingParen->Next->is(TT_PointerOrReference))
33553356
return true;
3356-
}
33573357

33583358
// Check for K&R C function definitions (and C++ function definitions with
33593359
// unnamed parameters), e.g.:
@@ -3370,7 +3370,7 @@ static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current,
33703370
return true;
33713371
}
33723372

3373-
for (const FormatToken *Tok = Next->Next; Tok && Tok != Next->MatchingParen;
3373+
for (const FormatToken *Tok = Next->Next; Tok && Tok != ClosingParen;
33743374
Tok = Tok->Next) {
33753375
if (Tok->is(TT_TypeDeclarationParen))
33763376
return true;
@@ -3442,11 +3442,12 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
34423442
calculateArrayInitializerColumnList(Line);
34433443

34443444
bool LineIsFunctionDeclaration = false;
3445+
FormatToken *ClosingParen = nullptr;
34453446
for (FormatToken *Tok = Current, *AfterLastAttribute = nullptr; Tok;
34463447
Tok = Tok->Next) {
34473448
if (Tok->Previous->EndsCppAttributeGroup)
34483449
AfterLastAttribute = Tok;
3449-
if (isFunctionDeclarationName(Style.isCpp(), *Tok, Line)) {
3450+
if (isFunctionDeclarationName(Style.isCpp(), *Tok, Line, ClosingParen)) {
34503451
LineIsFunctionDeclaration = true;
34513452
Tok->setFinalizedType(TT_FunctionDeclarationName);
34523453
if (AfterLastAttribute &&
@@ -3458,29 +3459,38 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
34583459
}
34593460
}
34603461

3461-
if (Style.isCpp() && !LineIsFunctionDeclaration) {
3462-
// Annotate */&/&& in `operator` function calls as binary operators.
3463-
for (const auto *Tok = Line.First; Tok; Tok = Tok->Next) {
3464-
if (Tok->isNot(tok::kw_operator))
3465-
continue;
3466-
do {
3467-
Tok = Tok->Next;
3468-
} while (Tok && Tok->isNot(TT_OverloadedOperatorLParen));
3469-
if (!Tok)
3470-
break;
3471-
const auto *LeftParen = Tok;
3472-
for (Tok = Tok->Next; Tok && Tok != LeftParen->MatchingParen;
3473-
Tok = Tok->Next) {
3474-
if (Tok->isNot(tok::identifier))
3475-
continue;
3476-
auto *Next = Tok->Next;
3477-
const bool NextIsBinaryOperator =
3478-
Next && Next->isOneOf(tok::star, tok::amp, tok::ampamp) &&
3479-
Next->Next && Next->Next->is(tok::identifier);
3480-
if (!NextIsBinaryOperator)
3462+
if (Style.isCpp()) {
3463+
if (!LineIsFunctionDeclaration) {
3464+
// Annotate */&/&& in `operator` function calls as binary operators.
3465+
for (const auto *Tok = Line.First; Tok; Tok = Tok->Next) {
3466+
if (Tok->isNot(tok::kw_operator))
34813467
continue;
3482-
Next->setType(TT_BinaryOperator);
3483-
Tok = Next;
3468+
do {
3469+
Tok = Tok->Next;
3470+
} while (Tok && Tok->isNot(TT_OverloadedOperatorLParen));
3471+
if (!Tok)
3472+
break;
3473+
const auto *LeftParen = Tok;
3474+
for (Tok = Tok->Next; Tok && Tok != LeftParen->MatchingParen;
3475+
Tok = Tok->Next) {
3476+
if (Tok->isNot(tok::identifier))
3477+
continue;
3478+
auto *Next = Tok->Next;
3479+
const bool NextIsBinaryOperator =
3480+
Next && Next->isOneOf(tok::star, tok::amp, tok::ampamp) &&
3481+
Next->Next && Next->Next->is(tok::identifier);
3482+
if (!NextIsBinaryOperator)
3483+
continue;
3484+
Next->setType(TT_BinaryOperator);
3485+
Tok = Next;
3486+
}
3487+
}
3488+
} else if (ClosingParen) {
3489+
for (auto *Tok = ClosingParen->Next; Tok; Tok = Tok->Next) {
3490+
if (Tok->is(tok::arrow)) {
3491+
Tok->setType(TT_TrailingReturnArrow);
3492+
break;
3493+
}
34843494
}
34853495
}
34863496
}

clang/unittests/Format/TokenAnnotatorTest.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1759,6 +1759,10 @@ TEST_F(TokenAnnotatorTest, UnderstandsTrailingReturnArrow) {
17591759
ASSERT_EQ(Tokens.size(), 16u) << Tokens;
17601760
EXPECT_TOKEN(Tokens[11], tok::arrow, TT_Unknown);
17611761

1762+
Tokens = annotate("#define P(ptr) auto p = (ptr)->p");
1763+
ASSERT_EQ(Tokens.size(), 15u) << Tokens;
1764+
EXPECT_TOKEN(Tokens[12], tok::arrow, TT_Unknown);
1765+
17621766
// Mixed
17631767
Tokens = annotate("auto f() -> int { auto a = b()->c; }");
17641768
ASSERT_EQ(Tokens.size(), 18u) << Tokens;

0 commit comments

Comments
 (0)