steveire created this revision. steveire added a reviewer: aaron.ballman. steveire requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
This makes them composable with mapAnyOf(). Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D94128 Files: clang/docs/LibASTMatchersReference.html clang/include/clang/ASTMatchers/ASTMatchers.h clang/include/clang/ASTMatchers/ASTMatchersInternal.h clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp =================================================================== --- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -1313,6 +1313,42 @@ traverse(TK_AsIs, hasRHS(hasType(pointsTo(qualType()))))); EXPECT_TRUE(matches("void x() { 1[\"abc\"]; }", OperatorIntPointer)); EXPECT_TRUE(notMatches("void x() { \"abc\"[1]; }", OperatorIntPointer)); + + StringRef Code = R"cpp( +struct HasOpEq +{ + bool operator==(const HasOpEq& other) const + { + return true; + } +}; + +void binop() +{ + HasOpEq s1; + HasOpEq s2; + if (s1 == s2) + return; +} +)cpp"; + auto s1Expr = declRefExpr(to(varDecl(hasName("s1")))); + auto s2Expr = declRefExpr(to(varDecl(hasName("s2")))); + EXPECT_TRUE(matches( + Code, traverse(TK_IgnoreUnlessSpelledInSource, + cxxOperatorCallExpr(hasOperatorName("=="), hasLHS(s1Expr), + hasRHS(s2Expr))))); + EXPECT_TRUE( + matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, + cxxOperatorCallExpr(hasAnyOperatorName("!=", "=="), + hasLHS(s1Expr))))); + EXPECT_TRUE(matches( + Code, traverse(TK_IgnoreUnlessSpelledInSource, + cxxOperatorCallExpr(hasOperatorName("=="), + hasOperands(s1Expr, s2Expr))))); + EXPECT_TRUE( + matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, + cxxOperatorCallExpr(hasOperatorName("=="), + hasEitherOperand(s2Expr))))); } TEST(MatchBinaryOperator, HasEitherOperand) { @@ -1461,6 +1497,32 @@ EXPECT_TRUE(matches("void x() { !false; }", OperatorOnFalse)); EXPECT_TRUE(notMatches("void x() { !true; }", OperatorOnFalse)); + + StringRef Code = R"cpp( +struct HasOpBang +{ + bool operator!() const + { + return false; + } +}; + +void binop() +{ + HasOpBang s1; + if (!s1) + return; +} +)cpp"; + auto s1Expr = declRefExpr(to(varDecl(hasName("s1")))); + EXPECT_TRUE( + matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, + cxxOperatorCallExpr(hasOperatorName("!"), + hasUnaryOperand(s1Expr))))); + EXPECT_TRUE( + matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, + cxxOperatorCallExpr(hasAnyOperatorName("+", "!"), + hasUnaryOperand(s1Expr))))); } TEST(Matcher, UnaryOperatorTypes) { Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp =================================================================== --- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -524,6 +524,158 @@ EXPECT_TRUE(matches( Code, traverse(TK_IgnoreUnlessSpelledInSource, mapAnyOf(callExpr, cxxConstructExpr).bind("call")))); + + Code = R"cpp( +struct HasOpNeq +{ + bool operator!=(const HasOpNeq& other) const + { + return true; + } +}; + +void binop() +{ + int s1; + int s2; + if (s1 != s2) + return; +} + +void opCall() +{ + HasOpNeq s1; + HasOpNeq s2; + if (s1 != s2) + return; +} +)cpp"; + + EXPECT_TRUE(matches( + Code, + traverse(TK_IgnoreUnlessSpelledInSource, + mapAnyOf(binaryOperator, cxxOperatorCallExpr) + .with(hasOperatorName("!="), + forFunction(functionDecl(hasName("binop"))), + hasLHS(declRefExpr(to(varDecl(hasName("s1"))))), + hasRHS(declRefExpr(to(varDecl(hasName("s2"))))))))); + + EXPECT_TRUE(matches( + Code, + traverse(TK_IgnoreUnlessSpelledInSource, + mapAnyOf(binaryOperator, cxxOperatorCallExpr) + .with(hasOperatorName("!="), + forFunction(functionDecl(hasName("opCall"))), + hasLHS(declRefExpr(to(varDecl(hasName("s1"))))), + hasRHS(declRefExpr(to(varDecl(hasName("s2"))))))))); + + EXPECT_TRUE(matches( + Code, traverse(TK_IgnoreUnlessSpelledInSource, + mapAnyOf(binaryOperator, cxxOperatorCallExpr) + .with(hasOperatorName("!="), + forFunction(functionDecl(hasName("binop"))), + hasEitherOperand( + declRefExpr(to(varDecl(hasName("s1"))))), + hasEitherOperand( + declRefExpr(to(varDecl(hasName("s2"))))))))); + + EXPECT_TRUE(matches( + Code, traverse(TK_IgnoreUnlessSpelledInSource, + mapAnyOf(binaryOperator, cxxOperatorCallExpr) + .with(hasOperatorName("!="), + forFunction(functionDecl(hasName("opCall"))), + hasEitherOperand( + declRefExpr(to(varDecl(hasName("s1"))))), + hasEitherOperand( + declRefExpr(to(varDecl(hasName("s2"))))))))); + + EXPECT_TRUE(matches( + Code, + traverse( + TK_IgnoreUnlessSpelledInSource, + mapAnyOf(binaryOperator, cxxOperatorCallExpr) + .with(hasOperatorName("!="), + forFunction(functionDecl(hasName("binop"))), + hasOperands(declRefExpr(to(varDecl(hasName("s1")))), + declRefExpr(to(varDecl(hasName("s2"))))), + hasOperands(declRefExpr(to(varDecl(hasName("s2")))), + declRefExpr(to(varDecl(hasName("s1"))))))))); + + EXPECT_TRUE(matches( + Code, + traverse( + TK_IgnoreUnlessSpelledInSource, + mapAnyOf(binaryOperator, cxxOperatorCallExpr) + .with(hasOperatorName("!="), + forFunction(functionDecl(hasName("opCall"))), + hasOperands(declRefExpr(to(varDecl(hasName("s1")))), + declRefExpr(to(varDecl(hasName("s2"))))), + hasOperands(declRefExpr(to(varDecl(hasName("s2")))), + declRefExpr(to(varDecl(hasName("s1"))))))))); + + EXPECT_TRUE(matches( + Code, traverse(TK_IgnoreUnlessSpelledInSource, + mapAnyOf(binaryOperator, cxxOperatorCallExpr) + .with(hasAnyOperatorName("==", "!="), + forFunction(functionDecl(hasName("binop"))))))); + + EXPECT_TRUE(matches( + Code, traverse(TK_IgnoreUnlessSpelledInSource, + mapAnyOf(binaryOperator, cxxOperatorCallExpr) + .with(hasAnyOperatorName("==", "!="), + forFunction(functionDecl(hasName("opCall"))))))); + + Code = R"cpp( +struct HasOpBang +{ + bool operator!() const + { + return false; + } +}; + +void unop() +{ + int s1; + if (!s1) + return; +} + +void opCall() +{ + HasOpBang s1; + if (!s1) + return; +} +)cpp"; + + EXPECT_TRUE(matches( + Code, traverse(TK_IgnoreUnlessSpelledInSource, + mapAnyOf(unaryOperator, cxxOperatorCallExpr) + .with(hasOperatorName("!"), + forFunction(functionDecl(hasName("unop"))), + hasUnaryOperand( + declRefExpr(to(varDecl(hasName("s1"))))))))); + + EXPECT_TRUE(matches( + Code, traverse(TK_IgnoreUnlessSpelledInSource, + mapAnyOf(unaryOperator, cxxOperatorCallExpr) + .with(hasOperatorName("!"), + forFunction(functionDecl(hasName("opCall"))), + hasUnaryOperand( + declRefExpr(to(varDecl(hasName("s1"))))))))); + + EXPECT_TRUE(matches( + Code, traverse(TK_IgnoreUnlessSpelledInSource, + mapAnyOf(unaryOperator, cxxOperatorCallExpr) + .with(hasAnyOperatorName("+", "!"), + forFunction(functionDecl(hasName("unop"))))))); + + EXPECT_TRUE(matches( + Code, traverse(TK_IgnoreUnlessSpelledInSource, + mapAnyOf(unaryOperator, cxxOperatorCallExpr) + .with(hasAnyOperatorName("+", "!"), + forFunction(functionDecl(hasName("opCall"))))))); } TEST_P(ASTMatchersTest, IsDerivedFrom) { Index: clang/include/clang/ASTMatchers/ASTMatchersInternal.h =================================================================== --- clang/include/clang/ASTMatchers/ASTMatchersInternal.h +++ clang/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -1882,6 +1882,160 @@ } }; +template <typename NodeType> +inline Optional<BinaryOperatorKind> +equivalentBinaryOperator(const NodeType &Node) { + return Node.getOpcode(); +} + +template <> +inline Optional<BinaryOperatorKind> +equivalentBinaryOperator<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) { + if (Node.getNumArgs() != 2) + return None; + switch (Node.getOperator()) { + default: + return None; + case OO_ArrowStar: + return BO_PtrMemI; + case OO_Star: + return BO_Mul; + case OO_Slash: + return BO_Div; + case OO_Percent: + return BO_Rem; + case OO_Plus: + return BO_Add; + case OO_Minus: + return BO_Sub; + case OO_LessLess: + return BO_Shl; + case OO_GreaterGreater: + return BO_Shr; + case OO_Spaceship: + return BO_Cmp; + case OO_Less: + return BO_LT; + case OO_Greater: + return BO_GT; + case OO_LessEqual: + return BO_LE; + case OO_GreaterEqual: + return BO_GE; + case OO_EqualEqual: + return BO_EQ; + case OO_ExclaimEqual: + return BO_NE; + case OO_Amp: + return BO_And; + case OO_Caret: + return BO_Xor; + case OO_Pipe: + return BO_Or; + case OO_AmpAmp: + return BO_LAnd; + case OO_PipePipe: + return BO_LOr; + case OO_Equal: + return BO_Assign; + case OO_StarEqual: + return BO_MulAssign; + case OO_SlashEqual: + return BO_DivAssign; + case OO_PercentEqual: + return BO_RemAssign; + case OO_PlusEqual: + return BO_AddAssign; + case OO_MinusEqual: + return BO_SubAssign; + case OO_LessLessEqual: + return BO_ShlAssign; + case OO_GreaterGreaterEqual: + return BO_ShrAssign; + case OO_AmpEqual: + return BO_AndAssign; + case OO_CaretEqual: + return BO_XorAssign; + case OO_PipeEqual: + return BO_OrAssign; + case OO_Comma: + return BO_Comma; + } +} + +template <typename NodeType> +inline Optional<UnaryOperatorKind> +equivalentUnaryOperator(const NodeType &Node) { + return Node.getOpcode(); +} + +template <> +inline Optional<UnaryOperatorKind> +equivalentUnaryOperator<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) { + if (Node.getNumArgs() != 1) + return None; + switch (Node.getOperator()) { + default: + return None; + case OO_Plus: + return UO_Plus; + case OO_Minus: + return UO_Minus; + case OO_Amp: + return UO_AddrOf; + case OO_Tilde: + return UO_Not; + case OO_Exclaim: + return UO_LNot; + case OO_PlusPlus: { + const auto *FD = Node.getDirectCallee(); + if (!FD) + return None; + return FD->getNumParams() > 0 ? UO_PostInc : UO_PreInc; + } + case OO_MinusMinus: { + const auto *FD = Node.getDirectCallee(); + if (!FD) + return None; + return FD->getNumParams() > 0 ? UO_PostDec : UO_PreDec; + } + case OO_Coawait: + return UO_Coawait; + } +} + +template <typename NodeType> inline const Expr *getLHS(const NodeType &Node) { + return Node.getLHS(); +} +template <> +inline const Expr * +getLHS<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) { + if (!internal::equivalentBinaryOperator(Node)) + return nullptr; + return Node.getArg(0); +} +template <typename NodeType> inline const Expr *getRHS(const NodeType &Node) { + return Node.getRHS(); +} +template <> +inline const Expr * +getRHS<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) { + if (!internal::equivalentBinaryOperator(Node)) + return nullptr; + return Node.getArg(1); +} +template <typename NodeType> +inline const Expr *getSubExpr(const NodeType &Node) { + return Node.getSubExpr(); +} +template <> +inline const Expr * +getSubExpr<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) { + if (!internal::equivalentUnaryOperator(Node)) + return nullptr; + return Node.getArg(0); +} + template <typename Ty> struct HasSizeMatcher { static bool hasSize(const Ty &Node, unsigned int N) { @@ -1936,8 +2090,10 @@ template <typename T, typename ArgT = std::vector<std::string>> class HasAnyOperatorNameMatcher : public SingleNodeMatcherInterface<T> { static_assert(std::is_same<T, BinaryOperator>::value || + std::is_same<T, CXXOperatorCallExpr>::value || std::is_same<T, UnaryOperator>::value, - "Matcher only supports `BinaryOperator` and `UnaryOperator`"); + "Matcher only supports `BinaryOperator`, `UnaryOperator` and " + "`CXXOperatorCallExpr`"); static_assert(std::is_same<ArgT, std::vector<std::string>>::value, "Matcher ArgT must be std::vector<std::string>"); @@ -1946,26 +2102,57 @@ : SingleNodeMatcherInterface<T>(), Names(std::move(Names)) {} bool matchesNode(const T &Node) const override { - StringRef OpName = getOpName(Node); - return llvm::any_of( - Names, [&](const std::string &Name) { return Name == OpName; }); + Optional<StringRef> OptOpName = getOpName(Node); + if (!OptOpName) + return false; + return llvm::any_of(Names, [OpName = *OptOpName](const std::string &Name) { + return Name == OpName; + }); } private: - static StringRef getOpName(const UnaryOperator &Node) { + static Optional<StringRef> getOpName(const UnaryOperator &Node) { return Node.getOpcodeStr(Node.getOpcode()); } - static StringRef getOpName(const BinaryOperator &Node) { + static Optional<StringRef> getOpName(const BinaryOperator &Node) { return Node.getOpcodeStr(); } + static Optional<StringRef> getOpName(const CXXOperatorCallExpr &Node) { + auto optBinaryOpcode = equivalentBinaryOperator(Node); + if (!optBinaryOpcode) { + auto optUnaryOpcode = equivalentUnaryOperator(Node); + if (!optUnaryOpcode) + return None; + return UnaryOperator::getOpcodeStr(*optUnaryOpcode); + } + return BinaryOperator::getOpcodeStr(*optBinaryOpcode); + } const std::vector<std::string> Names; }; -using HasOpNameMatcher = - PolymorphicMatcherWithParam1<HasAnyOperatorNameMatcher, - std::vector<std::string>, - void(TypeList<BinaryOperator, UnaryOperator>)>; +template <typename NodeType> +inline bool nodeHasOperatorName(const NodeType &Node, const std::string &Name) { + return Name == Node.getOpcodeStr(Node.getOpcode()); +} +template <> +inline bool +nodeHasOperatorName<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node, + const std::string &Name) { + auto optBinaryOpcode = equivalentBinaryOperator(Node); + if (!optBinaryOpcode) { + auto optUnaryOpcode = equivalentUnaryOperator(Node); + if (!optUnaryOpcode) { + return false; + } + return Name == UnaryOperator::getOpcodeStr(*optUnaryOpcode); + } + return Name == BinaryOperator::getOpcodeStr(*optBinaryOpcode); +} + +using HasOpNameMatcher = PolymorphicMatcherWithParam1< + HasAnyOperatorNameMatcher, std::vector<std::string>, + void(TypeList<BinaryOperator, CXXOperatorCallExpr, UnaryOperator>)>; HasOpNameMatcher hasAnyOperatorNameFunc(ArrayRef<const StringRef *> NameRefs); Index: clang/include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- clang/include/clang/ASTMatchers/ASTMatchers.h +++ clang/include/clang/ASTMatchers/ASTMatchers.h @@ -5201,9 +5201,10 @@ /// \endcode AST_POLYMORPHIC_MATCHER_P(hasOperatorName, AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, + CXXOperatorCallExpr, UnaryOperator), std::string, Name) { - return Name == Node.getOpcodeStr(Node.getOpcode()); + return internal::nodeHasOperatorName(Node, Name); } /// Matches operator expressions (binary or unary) that have any of the @@ -5215,7 +5216,8 @@ extern const internal::VariadicFunction< internal::PolymorphicMatcherWithParam1< internal::HasAnyOperatorNameMatcher, std::vector<std::string>, - AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, UnaryOperator)>, + AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, CXXOperatorCallExpr, + UnaryOperator)>, StringRef, internal::hasAnyOperatorNameFunc> hasAnyOperatorName; @@ -5267,9 +5269,10 @@ /// \endcode AST_POLYMORPHIC_MATCHER_P(hasLHS, AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, + CXXOperatorCallExpr, ArraySubscriptExpr), internal::Matcher<Expr>, InnerMatcher) { - const Expr *LeftHandSide = Node.getLHS(); + const Expr *LeftHandSide = internal::getLHS(Node); return (LeftHandSide != nullptr && InnerMatcher.matches(*LeftHandSide, Finder, Builder)); } @@ -5282,18 +5285,23 @@ /// \endcode AST_POLYMORPHIC_MATCHER_P(hasRHS, AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, + CXXOperatorCallExpr, ArraySubscriptExpr), internal::Matcher<Expr>, InnerMatcher) { - const Expr *RightHandSide = Node.getRHS(); + const Expr *RightHandSide = internal::getRHS(Node); return (RightHandSide != nullptr && InnerMatcher.matches(*RightHandSide, Finder, Builder)); } /// Matches if either the left hand side or the right hand side of a /// binary operator matches. -inline internal::Matcher<BinaryOperator> hasEitherOperand( - const internal::Matcher<Expr> &InnerMatcher) { - return anyOf(hasLHS(InnerMatcher), hasRHS(InnerMatcher)); +AST_POLYMORPHIC_MATCHER_P(hasEitherOperand, + AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, + CXXOperatorCallExpr), + internal::Matcher<Expr>, InnerMatcher) { + return internal::VariadicDynCastAllOfMatcher<Stmt, NodeType>()( + anyOf(hasLHS(InnerMatcher), hasRHS(InnerMatcher))) + .matches(Node, Finder, Builder); } /// Matches if both matchers match with opposite sides of the binary operator. @@ -5306,11 +5314,15 @@ /// 1 + 1 // No match /// 2 + 2 // No match /// \endcode -inline internal::Matcher<BinaryOperator> -hasOperands(const internal::Matcher<Expr> &Matcher1, - const internal::Matcher<Expr> &Matcher2) { - return anyOf(allOf(hasLHS(Matcher1), hasRHS(Matcher2)), - allOf(hasLHS(Matcher2), hasRHS(Matcher1))); +AST_POLYMORPHIC_MATCHER_P2(hasOperands, + AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, + CXXOperatorCallExpr), + internal::Matcher<Expr>, Matcher1, + internal::Matcher<Expr>, Matcher2) { + return internal::VariadicDynCastAllOfMatcher<Stmt, NodeType>()( + anyOf(allOf(hasLHS(Matcher1), hasRHS(Matcher2)), + allOf(hasLHS(Matcher2), hasRHS(Matcher1)))) + .matches(Node, Finder, Builder); } /// Matches if the operand of a unary operator matches. @@ -5320,9 +5332,11 @@ /// \code /// !true /// \endcode -AST_MATCHER_P(UnaryOperator, hasUnaryOperand, - internal::Matcher<Expr>, InnerMatcher) { - const Expr * const Operand = Node.getSubExpr(); +AST_POLYMORPHIC_MATCHER_P(hasUnaryOperand, + AST_POLYMORPHIC_SUPPORTED_TYPES(UnaryOperator, + CXXOperatorCallExpr), + internal::Matcher<Expr>, InnerMatcher) { + const Expr *const Operand = internal::getSubExpr(Node); return (Operand != nullptr && InnerMatcher.matches(*Operand, Finder, Builder)); } Index: clang/docs/LibASTMatchersReference.html =================================================================== --- clang/docs/LibASTMatchersReference.html +++ clang/docs/LibASTMatchersReference.html @@ -3232,6 +3232,16 @@ </pre></td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>></td><td class="name" onclick="toggle('hasAnyOperatorName1')"><a name="hasAnyOperatorName1Anchor">hasAnyOperatorName</a></td><td>StringRef, ..., StringRef</td></tr> +<tr><td colspan="4" class="doc" id="hasAnyOperatorName1"><pre>Matches operator expressions (binary or unary) that have any of the +specified names. + + hasAnyOperatorName("+", "-") + Is equivalent to + anyOf(hasOperatorName("+"), hasOperatorName("-")) +</pre></td></tr> + + <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>></td><td class="name" onclick="toggle('hasAnyOverloadedOperatorName0')"><a name="hasAnyOverloadedOperatorName0Anchor">hasAnyOverloadedOperatorName</a></td><td>StringRef, ..., StringRef</td></tr> <tr><td colspan="4" class="doc" id="hasAnyOverloadedOperatorName0"><pre>Matches overloaded operator names. @@ -3244,6 +3254,15 @@ </pre></td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>></td><td class="name" onclick="toggle('hasOperatorName1')"><a name="hasOperatorName1Anchor">hasOperatorName</a></td><td>std::string Name</td></tr> +<tr><td colspan="4" class="doc" id="hasOperatorName1"><pre>Matches the operator Name of operator expressions (binary or +unary). + +Example matches a || b (matcher = binaryOperator(hasOperatorName("||"))) + !(a || b) +</pre></td></tr> + + <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>></td><td class="name" onclick="toggle('hasOverloadedOperatorName1')"><a name="hasOverloadedOperatorName1Anchor">hasOverloadedOperatorName</a></td><td>StringRef Name</td></tr> <tr><td colspan="4" class="doc" id="hasOverloadedOperatorName1"><pre>Matches overloaded operator names. @@ -5152,8 +5171,8 @@ </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1UnaryOperator.html">UnaryOperator</a>></td><td class="name" onclick="toggle('hasAnyOperatorName1')"><a name="hasAnyOperatorName1Anchor">hasAnyOperatorName</a></td><td>StringRef, ..., StringRef</td></tr> -<tr><td colspan="4" class="doc" id="hasAnyOperatorName1"><pre>Matches operator expressions (binary or unary) that have any of the +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1UnaryOperator.html">UnaryOperator</a>></td><td class="name" onclick="toggle('hasAnyOperatorName2')"><a name="hasAnyOperatorName2Anchor">hasAnyOperatorName</a></td><td>StringRef, ..., StringRef</td></tr> +<tr><td colspan="4" class="doc" id="hasAnyOperatorName2"><pre>Matches operator expressions (binary or unary) that have any of the specified names. hasAnyOperatorName("+", "-") @@ -5162,8 +5181,8 @@ </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1UnaryOperator.html">UnaryOperator</a>></td><td class="name" onclick="toggle('hasOperatorName1')"><a name="hasOperatorName1Anchor">hasOperatorName</a></td><td>std::string Name</td></tr> -<tr><td colspan="4" class="doc" id="hasOperatorName1"><pre>Matches the operator Name of operator expressions (binary or +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1UnaryOperator.html">UnaryOperator</a>></td><td class="name" onclick="toggle('hasOperatorName2')"><a name="hasOperatorName2Anchor">hasOperatorName</a></td><td>std::string Name</td></tr> +<tr><td colspan="4" class="doc" id="hasOperatorName2"><pre>Matches the operator Name of operator expressions (binary or unary). Example matches a || b (matcher = binaryOperator(hasOperatorName("||"))) @@ -5689,16 +5708,16 @@ </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ArraySubscriptExpr.html">ArraySubscriptExpr</a>></td><td class="name" onclick="toggle('hasLHS1')"><a name="hasLHS1Anchor">hasLHS</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="hasLHS1"><pre>Matches the left hand side of binary operator expressions. +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ArraySubscriptExpr.html">ArraySubscriptExpr</a>></td><td class="name" onclick="toggle('hasLHS2')"><a name="hasLHS2Anchor">hasLHS</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasLHS2"><pre>Matches the left hand side of binary operator expressions. Example matches a (matcher = binaryOperator(hasLHS())) a || b </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ArraySubscriptExpr.html">ArraySubscriptExpr</a>></td><td class="name" onclick="toggle('hasRHS1')"><a name="hasRHS1Anchor">hasRHS</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="hasRHS1"><pre>Matches the right hand side of binary operator expressions. +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ArraySubscriptExpr.html">ArraySubscriptExpr</a>></td><td class="name" onclick="toggle('hasRHS2')"><a name="hasRHS2Anchor">hasRHS</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasRHS2"><pre>Matches the right hand side of binary operator expressions. Example matches b (matcher = binaryOperator(hasRHS())) a || b @@ -5749,7 +5768,7 @@ </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>></td><td class="name" onclick="toggle('hasEitherOperand0')"><a name="hasEitherOperand0Anchor">hasEitherOperand</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>></td><td class="name" onclick="toggle('hasEitherOperand0')"><a name="hasEitherOperand0Anchor">hasEitherOperand</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr> <tr><td colspan="4" class="doc" id="hasEitherOperand0"><pre>Matches if either the left hand side or the right hand side of a binary operator matches. </pre></td></tr> @@ -5763,7 +5782,7 @@ </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>></td><td class="name" onclick="toggle('hasOperands0')"><a name="hasOperands0Anchor">hasOperands</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> Matcher1, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> Matcher2</td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>></td><td class="name" onclick="toggle('hasOperands0')"><a name="hasOperands0Anchor">hasOperands</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> Matcher1, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> Matcher2</td></tr> <tr><td colspan="4" class="doc" id="hasOperands0"><pre>Matches if both matchers match with opposite sides of the binary operator. Example matcher = binaryOperator(hasOperands(integerLiteral(equals(1), @@ -6276,6 +6295,49 @@ </pre></td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>></td><td class="name" onclick="toggle('hasEitherOperand1')"><a name="hasEitherOperand1Anchor">hasEitherOperand</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasEitherOperand1"><pre>Matches if either the left hand side or the right hand side of a +binary operator matches. +</pre></td></tr> + + +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>></td><td class="name" onclick="toggle('hasLHS1')"><a name="hasLHS1Anchor">hasLHS</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasLHS1"><pre>Matches the left hand side of binary operator expressions. + +Example matches a (matcher = binaryOperator(hasLHS())) + a || b +</pre></td></tr> + + +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>></td><td class="name" onclick="toggle('hasOperands1')"><a name="hasOperands1Anchor">hasOperands</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> Matcher1, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> Matcher2</td></tr> +<tr><td colspan="4" class="doc" id="hasOperands1"><pre>Matches if both matchers match with opposite sides of the binary operator. + +Example matcher = binaryOperator(hasOperands(integerLiteral(equals(1), + integerLiteral(equals(2))) + 1 + 2 // Match + 2 + 1 // Match + 1 + 1 // No match + 2 + 2 // No match +</pre></td></tr> + + +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>></td><td class="name" onclick="toggle('hasRHS1')"><a name="hasRHS1Anchor">hasRHS</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasRHS1"><pre>Matches the right hand side of binary operator expressions. + +Example matches b (matcher = binaryOperator(hasRHS())) + a || b +</pre></td></tr> + + +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>></td><td class="name" onclick="toggle('hasUnaryOperand1')"><a name="hasUnaryOperand1Anchor">hasUnaryOperand</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasUnaryOperand1"><pre>Matches if the operand of a unary operator matches. + +Example matches true (matcher = hasUnaryOperand( + cxxBoolLiteral(equals(true)))) + !true +</pre></td></tr> + + <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>></td><td class="name" onclick="toggle('hasAnyBase0')"><a name="hasAnyBase0Anchor">hasAnyBase</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>> BaseSpecMatcher</td></tr> <tr><td colspan="4" class="doc" id="hasAnyBase0"><pre>Matches C++ classes that have a direct or indirect base matching BaseSpecMatcher.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits