forked from OSchip/llvm-project
[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
This commit is contained in:
parent
8eae99dfe5
commit
560eb2277b
|
@ -429,11 +429,18 @@ bool FormatTokenLexer::tryMergeLessLess() {
|
|||
if (Tokens.size() < 3)
|
||||
return false;
|
||||
|
||||
bool FourthTokenIsLess = false;
|
||||
if (Tokens.size() > 3)
|
||||
FourthTokenIsLess = (Tokens.end() - 4)[0]->is(tok::less);
|
||||
|
||||
auto First = Tokens.end() - 3;
|
||||
bool FourthTokenIsLess = false;
|
||||
|
||||
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;
|
||||
|
|
|
@ -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) &&
|
||||
|
|
|
@ -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);");
|
||||
|
|
Loading…
Reference in New Issue