[clang] [clang-format] Fix a bug in annotating operator function declarations (PR #165351)

via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 28 19:20:06 PDT 2025


https://github.com/owenca updated https://github.com/llvm/llvm-project/pull/165351

>From 85036b258697d6c279d9b8150530ef8d2f6e29b6 Mon Sep 17 00:00:00 2001
From: Owen Pan <owenpiano at gmail.com>
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 <owenpiano at gmail.com>
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 <owenpiano at gmail.com>
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);



More information about the cfe-commits mailing list