Nuullll created this revision. Nuullll added reviewers: djasper, HazardyKnusperkeks, curdeius, MyDeveloperDay. Nuullll added a project: clang-format. Nuullll requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
https://llvm.org/PR50568 When an overloaded operator is called, its argument must be an expression. Before: void f() { a.operator()(a *a); } After: void f() { a.operator()(a * a); } Signed-off-by: Yilong Guo <yilong....@intel.com> Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D103678 Files: 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 @@ -8761,6 +8761,11 @@ "operator()() && {}"); verifyGoogleFormat("template <typename T>\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) { Index: clang/lib/Format/TokenAnnotator.cpp =================================================================== --- clang/lib/Format/TokenAnnotator.cpp +++ 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,
Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -8761,6 +8761,11 @@ "operator()() && {}"); verifyGoogleFormat("template <typename T>\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) { Index: clang/lib/Format/TokenAnnotator.cpp =================================================================== --- clang/lib/Format/TokenAnnotator.cpp +++ 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,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits