Skip to content

Commit

Permalink
[clang-format] Correctly annotate pointer/reference in if statement (
Browse files Browse the repository at this point in the history
  • Loading branch information
owenca authored Sep 21, 2024
1 parent 4fd14b9 commit c28e268
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 21 deletions.
34 changes: 13 additions & 21 deletions clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ class AnnotatingParser {
return false;
}

bool parseParens(bool LookForDecls = false) {
bool parseParens(bool IsIf = false) {
if (!CurrentToken)
return false;
assert(CurrentToken->Previous && "Unknown previous token");
Expand Down Expand Up @@ -468,24 +468,6 @@ class AnnotatingParser {
OpeningParen.Previous && OpeningParen.Previous->is(tok::kw_for);
FormatToken *PossibleObjCForInToken = nullptr;
while (CurrentToken) {
// LookForDecls is set when "if (" has been seen. Check for
// 'identifier' '*' 'identifier' followed by not '=' -- this
// '*' has to be a binary operator but determineStarAmpUsage() will
// categorize it as an unary operator, so set the right type here.
if (LookForDecls && CurrentToken->Next) {
FormatToken *Prev = CurrentToken->getPreviousNonComment();
if (Prev) {
FormatToken *PrevPrev = Prev->getPreviousNonComment();
FormatToken *Next = CurrentToken->Next;
if (PrevPrev && PrevPrev->is(tok::identifier) &&
PrevPrev->isNot(TT_TypeName) && Prev->isPointerOrReference() &&
CurrentToken->is(tok::identifier) && Next->isNot(tok::equal)) {
Prev->setType(TT_BinaryOperator);
LookForDecls = false;
}
}
}

if (CurrentToken->Previous->is(TT_PointerOrReference) &&
CurrentToken->Previous->Previous->isOneOf(tok::l_paren,
tok::coloncolon)) {
Expand Down Expand Up @@ -581,6 +563,15 @@ class AnnotatingParser {
PossibleObjCForInToken = nullptr;
}
}
if (IsIf && CurrentToken->is(tok::semi)) {
for (auto *Tok = OpeningParen.Next;
Tok != CurrentToken &&
!Tok->isOneOf(tok::equal, tok::l_paren, tok::l_brace);
Tok = Tok->Next) {
if (Tok->isPointerOrReference())
Tok->setFinalizedType(TT_PointerOrReference);
}
}
if (MightBeObjCForRangeLoop && CurrentToken->is(Keywords.kw_in)) {
PossibleObjCForInToken = CurrentToken;
PossibleObjCForInToken->setType(TT_ObjCForIn);
Expand Down Expand Up @@ -1307,7 +1298,7 @@ class AnnotatingParser {
// Multi-line string itself is a single annotated token.
if (Tok->is(TT_TableGenMultiLineString))
return true;
switch (Tok->Tok.getKind()) {
switch (bool IsIf = false; Tok->Tok.getKind()) {
case tok::plus:
case tok::minus:
if (!Tok->Previous && Line.MustBeDeclaration)
Expand Down Expand Up @@ -1467,11 +1458,12 @@ class AnnotatingParser {
CurrentToken->isOneOf(tok::kw_constexpr, tok::identifier)) {
next();
}
IsIf = true;
[[fallthrough]];
case tok::kw_while:
if (CurrentToken && CurrentToken->is(tok::l_paren)) {
next();
if (!parseParens(/*LookForDecls=*/true))
if (!parseParens(IsIf))
return false;
}
break;
Expand Down
14 changes: 14 additions & 0 deletions clang/unittests/Format/TokenAnnotatorTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,20 @@ TEST_F(TokenAnnotatorTest, UnderstandsUsesOfStarAndAmp) {
EXPECT_TOKEN(Tokens[7], tok::ampamp, TT_BinaryOperator);
EXPECT_TOKEN(Tokens[10], tok::greater, TT_BinaryOperator);

Tokens = annotate("if (Foo *foo; bar)");
ASSERT_EQ(Tokens.size(), 9u) << Tokens;
EXPECT_TOKEN(Tokens[3], tok::star, TT_PointerOrReference);

Tokens = annotate("if (Foo **foo(); bar)");
ASSERT_EQ(Tokens.size(), 12u) << Tokens;
EXPECT_TOKEN(Tokens[3], tok::star, TT_PointerOrReference);
EXPECT_TOKEN(Tokens[4], tok::star, TT_PointerOrReference);

Tokens = annotate("if (Foo *&foo{a}; bar)");
ASSERT_EQ(Tokens.size(), 13u) << Tokens;
EXPECT_TOKEN(Tokens[3], tok::star, TT_PointerOrReference);
EXPECT_TOKEN(Tokens[4], tok::amp, TT_PointerOrReference);

FormatStyle Style = getLLVMStyle();
Style.TypeNames.push_back("MYI");
Tokens = annotate("if (MYI *p{nullptr})", Style);
Expand Down

0 comments on commit c28e268

Please sign in to comment.