diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -47,14 +47,17 @@ bool CXXOperatorCallExpr::isInfixBinaryOp() const { // An infix binary operator is any operator with two arguments other than - // operator() and operator[]. Note that none of these operators can have - // default arguments, so it suffices to check the number of argument - // expressions. + // operator()/operator[], and operator++/operator--. Note that none of these + // operators can have default arguments, so it suffices to check the number of + // argument expressions. if (getNumArgs() != 2) return false; switch (getOperator()) { - case OO_Call: case OO_Subscript: + case OO_Call: + case OO_Subscript: + case OO_PlusPlus: + case OO_MinusMinus: return false; default: return true; diff --git a/clang/unittests/Tooling/CMakeLists.txt b/clang/unittests/Tooling/CMakeLists.txt --- a/clang/unittests/Tooling/CMakeLists.txt +++ b/clang/unittests/Tooling/CMakeLists.txt @@ -61,6 +61,7 @@ RewriterTest.cpp SourceCodeBuildersTest.cpp SourceCodeTest.cpp + CXXOperatorCallExprTest.cpp StencilTest.cpp ToolingTest.cpp TransformerTest.cpp diff --git a/clang/unittests/Tooling/CXXOperatorCallExprTest.cpp b/clang/unittests/Tooling/CXXOperatorCallExprTest.cpp new file mode 100644 --- /dev/null +++ b/clang/unittests/Tooling/CXXOperatorCallExprTest.cpp @@ -0,0 +1,78 @@ + +//===- unittests/Tooling/CXXOperatorCallExprTest.cpp ----------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Unit tests for the predicates in CXXOperatorCallExpr. +// +//===----------------------------------------------------------------------===// + +#include "TestVisitor.h" +#include "gtest/gtest.h" + +namespace clang { +namespace { + +TEST(CXXOperatorPredicatesTest, InfixBinaryOp) { + const std::string Code = R"cpp( + struct X{ + friend X operator+(X, X); + }; + void test(X x){ + x + x; + } + )cpp"; + + struct Visitor : TestVisitor { + bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { + EXPECT_TRUE(E->isInfixBinaryOp()); + return true; + } + } visitor; + visitor.runOver(Code); +} + +TEST(CXXOperatorPredicatesTest, CallLikeOp) { + const std::string Code = R"cpp( + struct X{ + int operator[](int idx); + }; + void test(X x){ + x[1]; + } + )cpp"; + struct Visitor : TestVisitor { + bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { + EXPECT_FALSE(E->isInfixBinaryOp()); + return true; + } + } visitor; + + visitor.runOver(Code); +} + +TEST(CXXOperatorPredicatesTest, PostfixUnaryOp) { + const std::string Code = R"cpp( + struct X{ + X operator++(int); + }; + void test(X x){ + x++; + } + )cpp"; + + struct Visitor : TestVisitor { + bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { + EXPECT_FALSE(E->isInfixBinaryOp()); + return true; + } + } visitor; + + visitor.runOver(Code); +} +} // namespace +} // namespace clang