From 85036b258697d6c279d9b8150530ef8d2f6e29b6 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Mon, 27 Oct 2025 21:42:03 -0700 Subject: [PATCH 1/3] [clang-format] Fix a bug in annotating operator functions Fixes #164866 --- clang/lib/Format/TokenAnnotator.cpp | 11 +++++++---- clang/unittests/Format/TokenAnnotatorTest.cpp | 5 +++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 1d0dfd0b9c151..f4ea3948c14c4 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2646,9 +2646,9 @@ class AnnotatingParser { return false; } - bool IsPPKeyword = PreviousNotConst->is(tok::identifier) && - PreviousNotConst->Previous && - PreviousNotConst->Previous->is(tok::hash); + const auto *PrevPrev = PreviousNotConst->Previous; + const bool IsPPKeyword = PreviousNotConst->is(tok::identifier) && + PrevPrev && PrevPrev->is(tok::hash); if (PreviousNotConst->is(TT_TemplateCloser)) { return PreviousNotConst && PreviousNotConst->MatchingParen && @@ -2674,8 +2674,11 @@ class AnnotatingParser { } // *a or &a or &&a. - if (PreviousNotConst->is(TT_PointerOrReference)) + if (PreviousNotConst->is(TT_PointerOrReference) || + (PreviousNotConst->is(tok::coloncolon) && PrevPrev && + PrevPrev->is(TT_PointerOrReference))) { return true; + } // MyClass a; if (PreviousNotConst->isTypeName(LangOpts)) diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index ca99940890984..86e21775ad9ed 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -2344,6 +2344,11 @@ TEST_F(TokenAnnotatorTest, UnderstandsFunctionDeclarationNames) { EXPECT_TOKEN(Tokens[2], tok::identifier, TT_FunctionDeclarationName); EXPECT_TOKEN(Tokens[3], tok::l_paren, TT_FunctionDeclarationLParen); + Tokens = annotate("::foo::bar& ::foo::bar::operator=(::foo::bar& other);"); + ASSERT_EQ(Tokens.size(), 22u) << Tokens; + EXPECT_TOKEN(Tokens[6], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[17], tok::amp, TT_PointerOrReference); + Tokens = annotate("int iso_time(time_t);"); ASSERT_EQ(Tokens.size(), 7u) << Tokens; EXPECT_TOKEN(Tokens[1], tok::identifier, TT_FunctionDeclarationName); From d9058f7cc15d66ab0fb4a51fe682e24bbcca909d Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Mon, 27 Oct 2025 22:38:32 -0700 Subject: [PATCH 2/3] NFC --- clang/lib/Format/TokenAnnotator.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index f4ea3948c14c4..021d8c658eb11 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2646,9 +2646,9 @@ class AnnotatingParser { return false; } - const auto *PrevPrev = PreviousNotConst->Previous; - const bool IsPPKeyword = PreviousNotConst->is(tok::identifier) && - PrevPrev && PrevPrev->is(tok::hash); + bool IsPPKeyword = PreviousNotConst->is(tok::identifier) && + PreviousNotConst->Previous && + PreviousNotConst->Previous->is(tok::hash); if (PreviousNotConst->is(TT_TemplateCloser)) { return PreviousNotConst && PreviousNotConst->MatchingParen && @@ -2675,8 +2675,8 @@ class AnnotatingParser { // *a or &a or &&a. if (PreviousNotConst->is(TT_PointerOrReference) || - (PreviousNotConst->is(tok::coloncolon) && PrevPrev && - PrevPrev->is(TT_PointerOrReference))) { + PreviousNotConst->endsSequence(tok::coloncolon, + TT_PointerOrReference)) { return true; } From 82693f17f6b7e785d36ab1e9a93cc1436871a1ff Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Tue, 28 Oct 2025 19:18:54 -0700 Subject: [PATCH 3/3] NFC: add a test case for the root cause --- clang/unittests/Format/TokenAnnotatorTest.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 86e21775ad9ed..c046142c613b0 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -1119,6 +1119,11 @@ TEST_F(TokenAnnotatorTest, UnderstandsOverloadedOperators) { EXPECT_TOKEN(Tokens[8], tok::amp, TT_PointerOrReference); EXPECT_TOKEN(Tokens[12], tok::amp, TT_PointerOrReference); + Tokens = annotate("::foo::bar& ::foo::bar::operator=(::foo::bar& other);"); + ASSERT_EQ(Tokens.size(), 22u) << Tokens; + EXPECT_TOKEN(Tokens[6], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[17], tok::amp, TT_PointerOrReference); + Tokens = annotate("SomeLoooooooooooooooooType::Awaitable\n" "SomeLoooooooooooooooooType::operator co_await();"); ASSERT_EQ(Tokens.size(), 11u) << Tokens; @@ -2344,11 +2349,6 @@ TEST_F(TokenAnnotatorTest, UnderstandsFunctionDeclarationNames) { EXPECT_TOKEN(Tokens[2], tok::identifier, TT_FunctionDeclarationName); EXPECT_TOKEN(Tokens[3], tok::l_paren, TT_FunctionDeclarationLParen); - Tokens = annotate("::foo::bar& ::foo::bar::operator=(::foo::bar& other);"); - ASSERT_EQ(Tokens.size(), 22u) << Tokens; - EXPECT_TOKEN(Tokens[6], tok::identifier, TT_FunctionDeclarationName); - EXPECT_TOKEN(Tokens[17], tok::amp, TT_PointerOrReference); - Tokens = annotate("int iso_time(time_t);"); ASSERT_EQ(Tokens.size(), 7u) << Tokens; EXPECT_TOKEN(Tokens[1], tok::identifier, TT_FunctionDeclarationName); @@ -3489,6 +3489,10 @@ TEST_F(TokenAnnotatorTest, StartOfName) { ASSERT_EQ(Tokens.size(), 8u) << Tokens; EXPECT_TOKEN(Tokens[2], tok::identifier, TT_Unknown); // Not StartOfName + Tokens = annotate("int* ::foo::bar;"); + ASSERT_EQ(Tokens.size(), 8u) << Tokens; + EXPECT_TOKEN(Tokens[3], tok::identifier, TT_StartOfName); + auto Style = getLLVMStyle(); Style.StatementAttributeLikeMacros.push_back("emit"); Tokens = annotate("emit foo = 0;", Style);