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); + } + + // 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 @@ -8761,6 +8761,11 @@ "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); }"); } TEST_F(FormatTest, UnderstandsAttributes) {