[PATCH] D94129: [ASTMatchers] Add binaryOperation matcher
This revision was landed with ongoing or failed builds. This revision was automatically updated to reflect the committed changes. Closed by commit rGe810e95e4bb9: [ASTMatchers] Add binaryOperation matcher (authored by stephenkelly). Changed prior to commit: https://reviews.llvm.org/D94129?vs=316749=317172#toc Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D94129/new/ https://reviews.llvm.org/D94129 Files: clang/docs/LibASTMatchersReference.html clang/docs/tools/dump_ast_matchers.py clang/include/clang/ASTMatchers/ASTMatchers.h clang/lib/ASTMatchers/ASTMatchersInternal.cpp clang/lib/ASTMatchers/Dynamic/Marshallers.h clang/lib/ASTMatchers/Dynamic/Registry.cpp clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp === --- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -470,6 +470,10 @@ return; } + if (GetParam().hasDelayedTemplateParsing()) { +return; + } + StringRef Code = R"cpp( void F() { if (true) {} @@ -556,6 +560,15 @@ if (s1 != s2) return; } + +template +void templ() +{ +T s1; +T s2; +if (s1 != s2) +return; +} )cpp"; EXPECT_TRUE(matches( @@ -669,6 +682,38 @@ .with(hasAnyOperatorName("==", "!="), forFunction(functionDecl(hasName("opFree"))); + EXPECT_TRUE(matches( + Code, traverse(TK_IgnoreUnlessSpelledInSource, + binaryOperation( + hasOperatorName("!="), + forFunction(functionDecl(hasName("binop"))), + hasLHS(declRefExpr(to(varDecl(hasName("s1"), + hasRHS(declRefExpr(to(varDecl(hasName("s2"); + + EXPECT_TRUE(matches( + Code, traverse(TK_IgnoreUnlessSpelledInSource, + binaryOperation( + hasOperatorName("!="), + forFunction(functionDecl(hasName("opMem"))), + hasLHS(declRefExpr(to(varDecl(hasName("s1"), + hasRHS(declRefExpr(to(varDecl(hasName("s2"); + + EXPECT_TRUE(matches( + Code, traverse(TK_IgnoreUnlessSpelledInSource, + binaryOperation( + hasOperatorName("!="), + forFunction(functionDecl(hasName("opFree"))), + hasLHS(declRefExpr(to(varDecl(hasName("s1"), + hasRHS(declRefExpr(to(varDecl(hasName("s2"); + + EXPECT_TRUE(matches( + Code, traverse(TK_IgnoreUnlessSpelledInSource, + binaryOperation( + hasOperatorName("!="), + forFunction(functionDecl(hasName("templ"))), + hasLHS(declRefExpr(to(varDecl(hasName("s1"), + hasRHS(declRefExpr(to(varDecl(hasName("s2"); + Code = R"cpp( struct HasOpBangMem { Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp === --- clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -143,6 +143,7 @@ REGISTER_MATCHER(autoreleasePoolStmt) REGISTER_MATCHER(binaryConditionalOperator); REGISTER_MATCHER(binaryOperator); + REGISTER_MATCHER(binaryOperation); REGISTER_MATCHER(blockDecl); REGISTER_MATCHER(blockExpr); REGISTER_MATCHER(blockPointerType); Index: clang/lib/ASTMatchers/Dynamic/Marshallers.h === --- clang/lib/ASTMatchers/Dynamic/Marshallers.h +++ clang/lib/ASTMatchers/Dynamic/Marshallers.h @@ -925,6 +925,50 @@ const StringRef MatcherName; }; +template +class MapAnyOfMatcherDescriptor : public MatcherDescriptor { + std::vector Funcs; + +public: + MapAnyOfMatcherDescriptor(StringRef MatcherName) + : Funcs{DynCastAllOfMatcherDescriptor( +ast_matchers::internal::VariadicDynCastAllOfMatcher{}, +MatcherName)...} {} + + VariantMatcher create(SourceRange NameRange, ArrayRef Args, +Diagnostics *Error) const override { +std::vector InnerArgs; + +for (auto const : Funcs) { + InnerArgs.push_back(F.create(NameRange, Args, Error)); + if (!Error->errors().empty()) +return {}; +} +return VariantMatcher::SingleMatcher( +ast_matchers::internal::BindableMatcher( +VariantMatcher::VariadicOperatorMatcher( +ast_matchers::internal::DynTypedMatcher::VO_AnyOf, +std::move(InnerArgs)) +.getTypedMatcher())); + } + + bool isVariadic() const override { return true; } + unsigned getNumArgs() const override { return 0; } + + void
[PATCH] D94129: [ASTMatchers] Add binaryOperation matcher
aaron.ballman accepted this revision. aaron.ballman added a comment. This revision is now accepted and ready to land. LGTM aside from some minor NFC improvements. Comment at: clang/lib/ASTMatchers/Dynamic/Marshallers.h:957 + + void getArgKinds(ASTNodeKind ThisKind, unsigned ArgNo, + std::vector ) const override { Comment at: clang/lib/ASTMatchers/Dynamic/Marshallers.h:964-968 +for (auto const : Funcs) { + if (F.isConvertibleTo(Kind, Specificity, LeastDerivedKind)) +return true; +} +return false; Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D94129/new/ https://reviews.llvm.org/D94129 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D94129: [ASTMatchers] Add binaryOperation matcher
steveire updated this revision to Diff 316749. steveire added a comment. Update Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D94129/new/ https://reviews.llvm.org/D94129 Files: clang/docs/LibASTMatchersReference.html clang/docs/tools/dump_ast_matchers.py clang/include/clang/ASTMatchers/ASTMatchers.h clang/lib/ASTMatchers/ASTMatchersInternal.cpp clang/lib/ASTMatchers/Dynamic/Marshallers.h clang/lib/ASTMatchers/Dynamic/Registry.cpp clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp === --- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -470,6 +470,10 @@ return; } + if (GetParam().hasDelayedTemplateParsing()) { +return; + } + StringRef Code = R"cpp( void F() { if (true) {} @@ -541,6 +545,15 @@ if (s1 != s2) return; } + +template +void templ() +{ +T s1; +T s2; +if (s1 != s2) +return; +} )cpp"; EXPECT_TRUE(matches( @@ -617,6 +630,30 @@ .with(hasAnyOperatorName("==", "!="), forFunction(functionDecl(hasName("opCall"))); + EXPECT_TRUE(matches( + Code, traverse(TK_IgnoreUnlessSpelledInSource, + binaryOperation( + hasOperatorName("!="), + forFunction(functionDecl(hasName("binop"))), + hasLHS(declRefExpr(to(varDecl(hasName("s1"), + hasRHS(declRefExpr(to(varDecl(hasName("s2"); + + EXPECT_TRUE(matches( + Code, traverse(TK_IgnoreUnlessSpelledInSource, + binaryOperation( + hasOperatorName("!="), + forFunction(functionDecl(hasName("opCall"))), + hasLHS(declRefExpr(to(varDecl(hasName("s1"), + hasRHS(declRefExpr(to(varDecl(hasName("s2"); + + EXPECT_TRUE(matches( + Code, traverse(TK_IgnoreUnlessSpelledInSource, + binaryOperation( + hasOperatorName("!="), + forFunction(functionDecl(hasName("templ"))), + hasLHS(declRefExpr(to(varDecl(hasName("s1"), + hasRHS(declRefExpr(to(varDecl(hasName("s2"); + Code = R"cpp( struct HasOpBang { Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp === --- clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -143,6 +143,7 @@ REGISTER_MATCHER(autoreleasePoolStmt) REGISTER_MATCHER(binaryConditionalOperator); REGISTER_MATCHER(binaryOperator); + REGISTER_MATCHER(binaryOperation); REGISTER_MATCHER(blockDecl); REGISTER_MATCHER(blockExpr); REGISTER_MATCHER(blockPointerType); Index: clang/lib/ASTMatchers/Dynamic/Marshallers.h === --- clang/lib/ASTMatchers/Dynamic/Marshallers.h +++ clang/lib/ASTMatchers/Dynamic/Marshallers.h @@ -925,6 +925,50 @@ const StringRef MatcherName; }; +template +class MapAnyOfMatcherDescriptor : public MatcherDescriptor { + std::vector Funcs; + +public: + MapAnyOfMatcherDescriptor(StringRef MatcherName) + : Funcs{DynCastAllOfMatcherDescriptor( +ast_matchers::internal::VariadicDynCastAllOfMatcher{}, +MatcherName)...} {} + + VariantMatcher create(SourceRange NameRange, ArrayRef Args, +Diagnostics *Error) const override { +std::vector InnerArgs; + +for (auto const : Funcs) { + InnerArgs.push_back(F.create(NameRange, Args, Error)); +} +return VariantMatcher::SingleMatcher( +ast_matchers::internal::BindableMatcher( +VariantMatcher::VariadicOperatorMatcher( +ast_matchers::internal::DynTypedMatcher::VO_AnyOf, +std::move(InnerArgs)) +.getTypedMatcher())); + } + + bool isVariadic() const override { return true; } + unsigned getNumArgs() const override { return 0; } + + void getArgKinds(ASTNodeKind ThisKind, unsigned ArgNo, + std::vector ) const override { +Kinds.push_back(ThisKind); + } + + bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity, + ASTNodeKind *LeastDerivedKind) const override { +for (auto const : Funcs) { + if (F.isConvertibleTo(Kind, Specificity, LeastDerivedKind)) +return true; +} +return false; + } +}; + /// Helper functions to select the appropriate marshaller functions. /// They detect the number of arguments, arguments types and return type. @@ -1029,6 +1073,14 @@ MinCount, MaxCount, Func.Op, MatcherName); } +template +std::unique_ptr
[PATCH] D94129: [ASTMatchers] Add binaryOperation matcher
aaron.ballman added inline comments. Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:2739 +/// Matches nodes which can be used with binary operators +/// Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:2785 +internal::BindableMatcher +binaryOperation(InnerMatcherType &&... Matchers) { + return mapAnyOf(binaryOperator, cxxOperatorCallExpr).with(Matchers...); Missing changes to Registry.cpp to expose this to clang-query? Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D94129/new/ https://reviews.llvm.org/D94129 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D94129: [ASTMatchers] Add binaryOperation matcher
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 is a simple utility which allows matching on binaryOperator and cxxOperatorCallExpr. It can also be extended to support cxxRewrittenBinaryOperator. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D94129 Files: clang/docs/LibASTMatchersReference.html clang/docs/tools/dump_ast_matchers.py clang/include/clang/ASTMatchers/ASTMatchers.h clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp === --- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -478,6 +478,10 @@ return; } + if (GetParam().hasDelayedTemplateParsing()) { +return; + } + StringRef Code = R"cpp( void F() { if (true) {} @@ -549,6 +553,15 @@ if (s1 != s2) return; } + +template +void templ() +{ +T s1; +T s2; +if (s1 != s2) +return; +} )cpp"; EXPECT_TRUE(matches( @@ -625,6 +638,30 @@ .with(hasAnyOperatorName("==", "!="), forFunction(functionDecl(hasName("opCall"))); + EXPECT_TRUE(matches( + Code, traverse(TK_IgnoreUnlessSpelledInSource, + binaryOperation( + hasOperatorName("!="), + forFunction(functionDecl(hasName("binop"))), + hasLHS(declRefExpr(to(varDecl(hasName("s1"), + hasRHS(declRefExpr(to(varDecl(hasName("s2"); + + EXPECT_TRUE(matches( + Code, traverse(TK_IgnoreUnlessSpelledInSource, + binaryOperation( + hasOperatorName("!="), + forFunction(functionDecl(hasName("opCall"))), + hasLHS(declRefExpr(to(varDecl(hasName("s1"), + hasRHS(declRefExpr(to(varDecl(hasName("s2"); + + EXPECT_TRUE(matches( + Code, traverse(TK_IgnoreUnlessSpelledInSource, + binaryOperation( + hasOperatorName("!="), + forFunction(functionDecl(hasName("templ"))), + hasLHS(declRefExpr(to(varDecl(hasName("s1"), + hasRHS(declRefExpr(to(varDecl(hasName("s2"); + Code = R"cpp( struct HasOpBang { Index: clang/include/clang/ASTMatchers/ASTMatchers.h === --- clang/include/clang/ASTMatchers/ASTMatchers.h +++ clang/include/clang/ASTMatchers/ASTMatchers.h @@ -1973,6 +1973,8 @@ /// ostream int b = 1, c = 1; /// o << b << c; /// \endcode +/// See also the binaryOperation() matcher for more-general matching of binary +/// uses of this AST node. extern const internal::VariadicDynCastAllOfMatcher cxxOperatorCallExpr; @@ -2395,6 +2397,7 @@ /// \code /// !(a || b) /// \endcode +/// See also the binaryOperation() matcher for more-general matching. extern const internal::VariadicDynCastAllOfMatcher binaryOperator; @@ -2733,6 +2736,56 @@ NodeMatcher...); } +/// Matches nodes which can be used with binary operators +/// +/// The code +/// \code +/// var1 != var2; +/// \endcode +/// might be represented in the clang AST as a binaryOperator or a +/// cxxOperatorCallExpr, depending on +/// +/// * whether the types of var1 and var2 are fundamental (binaryOperator) or at +/// least one is a class type (cxxOperatorCallExpr) +/// * whether the code appears in a template declaration, if at least one of the +/// vars is a dependent-type (binaryOperator) +/// +/// This matcher elides details in places where the matchers for the nodes are +/// compatible. +/// +/// Given +/// \code +/// binaryOperation( +/// hasOperatorName("!="), +/// hasLHS(expr().bind("lhs")), +/// hasRHS(expr().bind("rhs")) +/// ) +/// \endcode +/// matches each use of "!=" in: +/// \code +/// struct S{ +/// bool operator!=(const S&) const; +/// }; +/// +/// void foo() +/// { +/// 1 != 2; +/// S() != S(); +/// } +/// +/// template +/// void templ() +/// { +/// 1 != 2; +/// T() != S(); +/// } +/// \endcode +template +internal::BindableMatcher +binaryOperation(InnerMatcherType &&... Matchers) { + return mapAnyOf(binaryOperator, cxxOperatorCallExpr).with(Matchers...); +} + /// Matches unary expressions that have a specific type of argument. /// /// Given Index: clang/docs/tools/dump_ast_matchers.py === --- clang/docs/tools/dump_ast_matchers.py +++ clang/docs/tools/dump_ast_matchers.py @@ -126,6 +126,9 @@ args = "nodeMatcherFunction..." docs_result_type =