[PATCH] D117398: [clang-format] Fix bug in parsing `operator<` with template

Jino Park via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Sat Jan 15 08:12:02 PST 2022


pjessesco created this revision.
pjessesco requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

https://github.com/llvm/llvm-project/issues/44601

This patch handles a bug when parsing a below example code :

  template <class> class S;
  
  template <class T> bool operator<(S<T> const &x, S<T> const &y) {
    return x.i < y.i;
  }
  
  template <class T> class S {
    int i = 42;
    friend bool operator<<>(S const &, S const &);
  };
  
  int main() { return S<int>{} < S<int>{}; }

which parse `<<>` to `<< >`, not `< <>` in terms of tokens as discussed in discord.

1. Add a condition in `tryMergeLessLess()` considering `operator` keyword and `>`
2. Force to leave a whitespace between `tok::less` and a template opener
3. Add unit test


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D117398

Files:
  clang/lib/Format/FormatTokenLexer.cpp
  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
@@ -9275,6 +9275,7 @@
   verifyFormat("operator SomeType<int>();");
   verifyFormat("operator SomeType<int, int>();");
   verifyFormat("operator SomeType<SomeType<int>>();");
+  verifyFormat("operator< <>();");
   verifyFormat("void *operator new(std::size_t size);");
   verifyFormat("void *operator new[](std::size_t size);");
   verifyFormat("void operator delete(void *ptr);");
Index: clang/lib/Format/TokenAnnotator.cpp
===================================================================
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -3345,6 +3345,8 @@
     if (Right.is(tok::l_brace) && Right.is(BK_BracedInit) &&
         !Left.opensScope() && Style.SpaceBeforeCpp11BracedList)
       return true;
+    if (Left.is(tok::less) && Right.is(TT_TemplateOpener))
+      return true;
   } else if (Style.Language == FormatStyle::LK_Proto ||
              Style.Language == FormatStyle::LK_TextProto) {
     if (Right.is(tok::period) &&
Index: clang/lib/Format/FormatTokenLexer.cpp
===================================================================
--- clang/lib/Format/FormatTokenLexer.cpp
+++ clang/lib/Format/FormatTokenLexer.cpp
@@ -429,9 +429,10 @@
   if (Tokens.size() < 3)
     return false;
 
+  auto Forth = (Tokens.end() - 4)[0];
   bool FourthTokenIsLess = false;
   if (Tokens.size() > 3)
-    FourthTokenIsLess = (Tokens.end() - 4)[0]->is(tok::less);
+    FourthTokenIsLess = Forth->is(tok::less);
 
   auto First = Tokens.end() - 3;
   if (First[2]->is(tok::less) || First[1]->isNot(tok::less) ||
@@ -443,6 +444,10 @@
       First[1]->WhitespaceRange.getEnd())
     return false;
 
+  // Do not remove a whitespace between the two "<" e.g. "operator<<>".
+  if (First[2]->is(tok::greater) && Forth->is(tok::kw_operator))
+    return false;
+
   First[0]->Tok.setKind(tok::lessless);
   First[0]->TokenText = "<<";
   First[0]->ColumnWidth += 1;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D117398.400286.patch
Type: text/x-patch
Size: 2094 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20220115/9cd1f22e/attachment.bin>


More information about the cfe-commits mailing list