krasimir created this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
krasimir added a reviewer: mprobst.

Revision a75f8d98d7ac9e557b238a229a9a2647c71feed1 
<https://reviews.llvm.org/rGa75f8d98d7ac9e557b238a229a9a2647c71feed1> fixed 
spacing for operators,
but caused the const and non-const versions to diverge:

  // With Style.PointerAlignment = FormatStyle::PAS_Left:
  
  struct A {
    operator char*() { return ""; }
    operator const char *() const { return ""; }
  };

The code was checking if the type specifier was directly preceded by `operator`.
However there could be comments and `const/volatile` in between.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D72911

Files:
  clang/lib/Format/TokenAnnotator.cpp
  clang/unittests/Format/FormatTest.cpp


Index: clang/unittests/Format/FormatTest.cpp
===================================================================
--- clang/unittests/Format/FormatTest.cpp
+++ clang/unittests/Format/FormatTest.cpp
@@ -15007,6 +15007,9 @@
   Style.PointerAlignment = FormatStyle::PAS_Left;
   verifyFormat("Foo::operator*();", Style);
   verifyFormat("Foo::operator void*();", Style);
+  verifyFormat("Foo::operator/*comment*/ void*();", Style);
+  verifyFormat("Foo::operator/*a*/ const /*b*/ void*();", Style);
+  verifyFormat("Foo::operator/*a*/ volatile /*b*/ void*();", Style);
   verifyFormat("Foo::operator()(void*);", Style);
   verifyFormat("Foo::operator*(void*);", Style);
   verifyFormat("Foo::operator*();", Style);
Index: clang/lib/Format/TokenAnnotator.cpp
===================================================================
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -2706,12 +2706,26 @@
   if (Right.is(tok::star) && Left.is(tok::l_paren))
     return false;
   if (Right.isOneOf(tok::star, tok::amp, tok::ampamp) &&
-      (Left.is(tok::identifier) || Left.isSimpleTypeSpecifier()) &&
-      Left.Previous && Left.Previous->is(tok::kw_operator))
-    // Space between the type and the *
-    // operator void*(), operator char*(), operator Foo*() dependant
-    // on PointerAlignment style.
-    return (Style.PointerAlignment != FormatStyle::PAS_Left);
+      (Left.is(tok::identifier) || Left.isSimpleTypeSpecifier())) {
+    // Space between the type and the * in:
+    //   operator void*()
+    //   operator void*()
+    //   operator char*()
+    //   operator /*comment*/ const char*()
+    //   operator volatile /*comment*/ char*()
+    //   operator Foo*()
+    // dependant on PointerAlignment style.
+
+    // Here, Left points to the type specifier. Skip back over const and
+    // volatile, looking for `operator`.
+    FormatToken *Before = Left.getPreviousNonComment();
+    while (Before && Before->isOneOf(tok::kw_const, tok::kw_volatile)) {
+      Before = Before->getPreviousNonComment();
+    }
+    if (Before && Before->is(tok::kw_operator)) {
+      return (Style.PointerAlignment != FormatStyle::PAS_Left);
+    }
+  }
   const auto SpaceRequiredForArrayInitializerLSquare =
       [](const FormatToken &LSquareTok, const FormatStyle &Style) {
         return Style.SpacesInContainerLiterals ||


Index: clang/unittests/Format/FormatTest.cpp
===================================================================
--- clang/unittests/Format/FormatTest.cpp
+++ clang/unittests/Format/FormatTest.cpp
@@ -15007,6 +15007,9 @@
   Style.PointerAlignment = FormatStyle::PAS_Left;
   verifyFormat("Foo::operator*();", Style);
   verifyFormat("Foo::operator void*();", Style);
+  verifyFormat("Foo::operator/*comment*/ void*();", Style);
+  verifyFormat("Foo::operator/*a*/ const /*b*/ void*();", Style);
+  verifyFormat("Foo::operator/*a*/ volatile /*b*/ void*();", Style);
   verifyFormat("Foo::operator()(void*);", Style);
   verifyFormat("Foo::operator*(void*);", Style);
   verifyFormat("Foo::operator*();", Style);
Index: clang/lib/Format/TokenAnnotator.cpp
===================================================================
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -2706,12 +2706,26 @@
   if (Right.is(tok::star) && Left.is(tok::l_paren))
     return false;
   if (Right.isOneOf(tok::star, tok::amp, tok::ampamp) &&
-      (Left.is(tok::identifier) || Left.isSimpleTypeSpecifier()) &&
-      Left.Previous && Left.Previous->is(tok::kw_operator))
-    // Space between the type and the *
-    // operator void*(), operator char*(), operator Foo*() dependant
-    // on PointerAlignment style.
-    return (Style.PointerAlignment != FormatStyle::PAS_Left);
+      (Left.is(tok::identifier) || Left.isSimpleTypeSpecifier())) {
+    // Space between the type and the * in:
+    //   operator void*()
+    //   operator void*()
+    //   operator char*()
+    //   operator /*comment*/ const char*()
+    //   operator volatile /*comment*/ char*()
+    //   operator Foo*()
+    // dependant on PointerAlignment style.
+
+    // Here, Left points to the type specifier. Skip back over const and
+    // volatile, looking for `operator`.
+    FormatToken *Before = Left.getPreviousNonComment();
+    while (Before && Before->isOneOf(tok::kw_const, tok::kw_volatile)) {
+      Before = Before->getPreviousNonComment();
+    }
+    if (Before && Before->is(tok::kw_operator)) {
+      return (Style.PointerAlignment != FormatStyle::PAS_Left);
+    }
+  }
   const auto SpaceRequiredForArrayInitializerLSquare =
       [](const FormatToken &LSquareTok, const FormatStyle &Style) {
         return Style.SpacesInContainerLiterals ||
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to