Author: Jino Park Date: 2022-01-20T08:59:04+01:00 New Revision: 560eb2277bb5aea0982ce5f90321788cda3fe4b3
URL: https://github.com/llvm/llvm-project/commit/560eb2277bb5aea0982ce5f90321788cda3fe4b3 DIFF: https://github.com/llvm/llvm-project/commit/560eb2277bb5aea0982ce5f90321788cda3fe4b3.diff LOG: [clang-format] Fix bug in parsing `operator<` with template Fixes 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 `< <>` as `<< >`, 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 Reviewed By: MyDeveloperDay, curdeius Differential Revision: https://reviews.llvm.org/D117398 Added: Modified: clang/lib/Format/FormatTokenLexer.cpp clang/lib/Format/TokenAnnotator.cpp clang/unittests/Format/FormatTest.cpp Removed: ################################################################################ diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp index 7736a7042f862..04629fec1bcaf 100644 --- a/clang/lib/Format/FormatTokenLexer.cpp +++ b/clang/lib/Format/FormatTokenLexer.cpp @@ -429,11 +429,18 @@ bool FormatTokenLexer::tryMergeLessLess() { if (Tokens.size() < 3) return false; + auto First = Tokens.end() - 3; bool FourthTokenIsLess = false; - if (Tokens.size() > 3) - FourthTokenIsLess = (Tokens.end() - 4)[0]->is(tok::less); - auto First = Tokens.end() - 3; + if (Tokens.size() > 3) { + auto Fourth = (Tokens.end() - 4)[0]; + FourthTokenIsLess = Fourth->is(tok::less); + + // Do not remove a whitespace between the two "<" e.g. "operator< <>". + if (First[2]->is(tok::greater) && Fourth->is(tok::kw_operator)) + return false; + } + if (First[2]->is(tok::less) || First[1]->isNot(tok::less) || First[0]->isNot(tok::less) || FourthTokenIsLess) return false; diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 7948dd105ee8b..71f29e8c010e5 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -3346,6 +3346,9 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, if (Right.is(tok::l_brace) && Right.is(BK_BracedInit) && !Left.opensScope() && Style.SpaceBeforeCpp11BracedList) return true; + if (Left.is(tok::less) && Left.is(TT_OverloadedOperator) && + Right.is(TT_TemplateOpener)) + return true; } else if (Style.Language == FormatStyle::LK_Proto || Style.Language == FormatStyle::LK_TextProto) { if (Right.is(tok::period) && diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index b8645b8896d2a..6bd417388fc7d 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -9463,6 +9463,10 @@ TEST_F(FormatTest, UnderstandsOverloadedOperators) { verifyFormat("operator SomeType<int>();"); verifyFormat("operator SomeType<int, int>();"); verifyFormat("operator SomeType<SomeType<int>>();"); + verifyFormat("operator< <>();"); + verifyFormat("operator<< <>();"); + verifyFormat("< <>"); + verifyFormat("void *operator new(std::size_t size);"); verifyFormat("void *operator new[](std::size_t size);"); verifyFormat("void operator delete(void *ptr);"); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits