diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -229,7 +229,19 @@ } if (Left->is(TT_OverloadedOperatorLParen)) { - Contexts.back().IsExpression = false; + // Find the previous kw_operator token. + FormatToken *Prev = Left; + while (!Prev->is(tok::kw_operator)) { + Prev = Prev->Previous; + assert(Prev && "Expect a kw_operator prior to the OperatorLParen!"); + } + + // If faced with "a.operator*(argument)" or "a->operator*(argument)", + // i.e. the operator is called as a member function, + // then the argument must be an expression. + bool OperatorCalledAsMemberFunction = + Prev->Previous && Prev->Previous->isOneOf(tok::period, tok::arrow); + Contexts.back().IsExpression = OperatorCalledAsMemberFunction; } else if (Style.Language == FormatStyle::LK_JavaScript && (Line.startsWith(Keywords.kw_type, tok::identifier) || Line.startsWith(tok::kw_export, Keywords.kw_type, diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -8274,6 +8274,16 @@ verifyFormat("using A::operator+;"); verifyFormat("inline A operator^(const A &lhs, const A &rhs) {}\n" "int i;"); + + // Calling an operator as a member function. + verifyFormat("void f() { a.operator*(); }"); + verifyFormat("void f() { a.operator*(b & b); }"); + verifyFormat("void f() { a->operator&(a * b); }"); + verifyFormat("void f() { NS::a.operator+(*b * *b); }"); + // TODO: Calling an operator as a non-member function is hard to distinguish. + // https://llvm.org/PR50629 + // verifyFormat("void f() { operator*(a & a); }"); + // verifyFormat("void f() { operator&(a, b * b); }"); } TEST_F(FormatTest, UnderstandsFunctionRefQualification) { @@ -8766,6 +8776,13 @@ "operator()() && {}"); verifyGoogleFormat("template \n" "auto x() & -> int {}"); + + // Should be binary operators when used as an argument expression (overloaded + // operator invoked as a member function). + verifyFormat("void f() { a.operator()(a * a); }"); + verifyFormat("void f() { a->operator()(a & a); }"); + verifyFormat("void f() { a.operator()(*a & *a); }"); + verifyFormat("void f() { a->operator()(*a * *a); }"); } TEST_F(FormatTest, UnderstandsAttributes) {