Skip to content

Commit 40d12f0

Browse files
committed
[clang-format] Fix a bug in mis-annotating arrows
Fixed #66923.
1 parent 134ae13 commit 40d12f0

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
@@ -2014,8 +2014,7 @@ class AnnotatingParser {
20142014
Style.Language == FormatStyle::LK_Java) {
20152015
Current.setType(TT_LambdaArrow);
20162016
} else if (Current.is(tok::arrow) && AutoFound &&
2017-
(Line.MightBeFunctionDecl || Line.InPPDirective) &&
2018-
Current.NestingLevel == 0 &&
2017+
Line.MightBeFunctionDecl && Current.NestingLevel == 0 &&
20192018
!Current.Previous->isOneOf(tok::kw_operator, tok::identifier)) {
20202019
// not auto operator->() -> xxx;
20212020
Current.setType(TT_TrailingReturnArrow);
@@ -3250,7 +3249,8 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) {
32503249
// This function heuristically determines whether 'Current' starts the name of a
32513250
// function declaration.
32523251
static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current,
3253-
const AnnotatedLine &Line) {
3252+
const AnnotatedLine &Line,
3253+
FormatToken *&ClosingParen) {
32543254
assert(Current.Previous);
32553255

32563256
if (Current.is(TT_FunctionDeclarationName))
@@ -3336,16 +3336,16 @@ static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current,
33363336
// Check whether parameter list can belong to a function declaration.
33373337
if (!Next || Next->isNot(tok::l_paren) || !Next->MatchingParen)
33383338
return false;
3339+
ClosingParen = Next->MatchingParen;
3340+
assert(ClosingParen->is(tok::r_paren));
33393341
// If the lines ends with "{", this is likely a function definition.
33403342
if (Line.Last->is(tok::l_brace))
33413343
return true;
3342-
if (Next->Next == Next->MatchingParen)
3344+
if (Next->Next == ClosingParen)
33433345
return true; // Empty parentheses.
33443346
// If there is an &/&& after the r_paren, this is likely a function.
3345-
if (Next->MatchingParen->Next &&
3346-
Next->MatchingParen->Next->is(TT_PointerOrReference)) {
3347+
if (ClosingParen->Next && ClosingParen->Next->is(TT_PointerOrReference))
33473348
return true;
3348-
}
33493349

33503350
// Check for K&R C function definitions (and C++ function definitions with
33513351
// unnamed parameters), e.g.:
@@ -3362,7 +3362,7 @@ static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current,
33623362
return true;
33633363
}
33643364

3365-
for (const FormatToken *Tok = Next->Next; Tok && Tok != Next->MatchingParen;
3365+
for (const FormatToken *Tok = Next->Next; Tok && Tok != ClosingParen;
33663366
Tok = Tok->Next) {
33673367
if (Tok->is(TT_TypeDeclarationParen))
33683368
return true;
@@ -3434,11 +3434,12 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
34343434
calculateArrayInitializerColumnList(Line);
34353435

34363436
bool LineIsFunctionDeclaration = false;
3437+
FormatToken *ClosingParen = nullptr;
34373438
for (FormatToken *Tok = Current, *AfterLastAttribute = nullptr; Tok;
34383439
Tok = Tok->Next) {
34393440
if (Tok->Previous->EndsCppAttributeGroup)
34403441
AfterLastAttribute = Tok;
3441-
if (isFunctionDeclarationName(Style.isCpp(), *Tok, Line)) {
3442+
if (isFunctionDeclarationName(Style.isCpp(), *Tok, Line, ClosingParen)) {
34423443
LineIsFunctionDeclaration = true;
34433444
Tok->setFinalizedType(TT_FunctionDeclarationName);
34443445
if (AfterLastAttribute &&
@@ -3450,29 +3451,38 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
34503451
}
34513452
}
34523453

3453-
if (Style.isCpp() && !LineIsFunctionDeclaration) {
3454-
// Annotate */&/&& in `operator` function calls as binary operators.
3455-
for (const auto *Tok = Line.First; Tok; Tok = Tok->Next) {
3456-
if (Tok->isNot(tok::kw_operator))
3457-
continue;
3458-
do {
3459-
Tok = Tok->Next;
3460-
} while (Tok && Tok->isNot(TT_OverloadedOperatorLParen));
3461-
if (!Tok)
3462-
break;
3463-
const auto *LeftParen = Tok;
3464-
for (Tok = Tok->Next; Tok && Tok != LeftParen->MatchingParen;
3465-
Tok = Tok->Next) {
3466-
if (Tok->isNot(tok::identifier))
3467-
continue;
3468-
auto *Next = Tok->Next;
3469-
const bool NextIsBinaryOperator =
3470-
Next && Next->isOneOf(tok::star, tok::amp, tok::ampamp) &&
3471-
Next->Next && Next->Next->is(tok::identifier);
3472-
if (!NextIsBinaryOperator)
3454+
if (Style.isCpp()) {
3455+
if (!LineIsFunctionDeclaration) {
3456+
// Annotate */&/&& in `operator` function calls as binary operators.
3457+
for (const auto *Tok = Line.First; Tok; Tok = Tok->Next) {
3458+
if (Tok->isNot(tok::kw_operator))
34733459
continue;
3474-
Next->setType(TT_BinaryOperator);
3475-
Tok = Next;
3460+
do {
3461+
Tok = Tok->Next;
3462+
} while (Tok && Tok->isNot(TT_OverloadedOperatorLParen));
3463+
if (!Tok)
3464+
break;
3465+
const auto *LeftParen = Tok;
3466+
for (Tok = Tok->Next; Tok && Tok != LeftParen->MatchingParen;
3467+
Tok = Tok->Next) {
3468+
if (Tok->isNot(tok::identifier))
3469+
continue;
3470+
auto *Next = Tok->Next;
3471+
const bool NextIsBinaryOperator =
3472+
Next && Next->isOneOf(tok::star, tok::amp, tok::ampamp) &&
3473+
Next->Next && Next->Next->is(tok::identifier);
3474+
if (!NextIsBinaryOperator)
3475+
continue;
3476+
Next->setType(TT_BinaryOperator);
3477+
Tok = Next;
3478+
}
3479+
}
3480+
} else if (ClosingParen) {
3481+
for (auto *Tok = ClosingParen->Next; Tok; Tok = Tok->Next) {
3482+
if (Tok->is(tok::arrow)) {
3483+
Tok->setType(TT_TrailingReturnArrow);
3484+
break;
3485+
}
34763486
}
34773487
}
34783488
}

clang/unittests/Format/TokenAnnotatorTest.cpp

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

1734+
Tokens = annotate("#define P(ptr) auto p = (ptr)->p");
1735+
ASSERT_EQ(Tokens.size(), 15u) << Tokens;
1736+
EXPECT_TOKEN(Tokens[12], tok::arrow, TT_Unknown);
1737+
17341738
// Mixed
17351739
Tokens = annotate("auto f() -> int { auto a = b()->c; }");
17361740
ASSERT_EQ(Tokens.size(), 18u) << Tokens;

0 commit comments

Comments
 (0)