diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h index 2af4e6e88109..5e3af4a2a34b 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -2039,7 +2039,8 @@ equivalentUnaryOperator(const NodeType &Node) { template <> inline Optional equivalentUnaryOperator(const CXXOperatorCallExpr &Node) { - if (Node.getNumArgs() != 1) + if (Node.getNumArgs() != 1 && Node.getOperator() != OO_PlusPlus && + Node.getOperator() != OO_MinusMinus) return None; switch (Node.getOperator()) { default: diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp index 8a6e94cf5624..9909cec2065c 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -1630,6 +1630,84 @@ void opFree() cxxOperatorCallExpr(forFunction(functionDecl(hasName("opFree"))), hasAnyOperatorName("+", "!"), hasUnaryOperand(s1Expr))))); + + Code = R"cpp( +struct HasIncOperatorsMem +{ + HasIncOperatorsMem& operator++(); + HasIncOperatorsMem operator++(int); +}; +struct HasIncOperatorsFree +{ +}; +HasIncOperatorsFree& operator++(HasIncOperatorsFree&); +HasIncOperatorsFree operator++(HasIncOperatorsFree&, int); + +void prefixIncOperatorMem() +{ + HasIncOperatorsMem s1; + ++s1; +} +void prefixIncOperatorFree() +{ + HasIncOperatorsFree s1; + ++s1; +} +void postfixIncOperatorMem() +{ + HasIncOperatorsMem s1; + s1++; +} +void postfixIncOperatorFree() +{ + HasIncOperatorsFree s1; + s1++; +} + +struct HasOpPlusInt +{ + HasOpPlusInt& operator+(int); +}; +void plusIntOperator() +{ + HasOpPlusInt s1; + s1+1; +} +)cpp"; + + EXPECT_TRUE(matches( + Code, + traverse(TK_IgnoreUnlessSpelledInSource, + cxxOperatorCallExpr( + forFunction(functionDecl(hasName("prefixIncOperatorMem"))), + hasOperatorName("++"), hasUnaryOperand(declRefExpr()))))); + + EXPECT_TRUE(matches( + Code, + traverse(TK_IgnoreUnlessSpelledInSource, + cxxOperatorCallExpr( + forFunction(functionDecl(hasName("prefixIncOperatorFree"))), + hasOperatorName("++"), hasUnaryOperand(declRefExpr()))))); + + EXPECT_TRUE(matches( + Code, + traverse(TK_IgnoreUnlessSpelledInSource, + cxxOperatorCallExpr( + forFunction(functionDecl(hasName("postfixIncOperatorMem"))), + hasOperatorName("++"), hasUnaryOperand(declRefExpr()))))); + + EXPECT_TRUE(matches( + Code, + traverse(TK_IgnoreUnlessSpelledInSource, + cxxOperatorCallExpr( + forFunction(functionDecl(hasName("postfixIncOperatorFree"))), + hasOperatorName("++"), hasUnaryOperand(declRefExpr()))))); + + EXPECT_FALSE(matches( + Code, traverse(TK_IgnoreUnlessSpelledInSource, + cxxOperatorCallExpr( + forFunction(functionDecl(hasName("plusIntOperator"))), + hasOperatorName("+"), hasUnaryOperand(expr()))))); } TEST(Matcher, UnaryOperatorTypes) {