diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -5613,6 +5613,40 @@ +
Matches function calls and constructor calls + +Because CallExpr and CXXConstructExpr do not share a common +base class with API accessing arguments etc, AST Matchers for code +which should match both are typically duplicated. This matcher +removes the need for duplication. + +Given code +struct ConstructorTakesInt +{ + ConstructorTakesInt(int i) {} +}; + +void callTakesInt(int i) +{ +} + +void doCall() +{ + callTakesInt(42); +} + +void doConstruct() +{ + ConstructorTakesInt cti(42); +} + +The matcher +invocation(hasArgument(0, integerLiteral(equals(42)))) +matches the expression in both doCall and doConstruct +
Matches if any of the given matchers matches. diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -2829,6 +2829,42 @@ CXXRewrittenBinaryOperator> binaryOperation; +/// Matches function calls and constructor calls +/// +/// Because CallExpr and CXXConstructExpr do not share a common +/// base class with API accessing arguments etc, AST Matchers for code +/// which should match both are typically duplicated. This matcher +/// removes the need for duplication. +/// +/// Given code +/// \code +/// struct ConstructorTakesInt +/// { +/// ConstructorTakesInt(int i) {} +/// }; +/// +/// void callTakesInt(int i) +/// { +/// } +/// +/// void doCall() +/// { +/// callTakesInt(42); +/// } +/// +/// void doConstruct() +/// { +/// ConstructorTakesInt cti(42); +/// } +/// \endcode +/// +/// The matcher +/// \code +/// invocation(hasArgument(0, integerLiteral(equals(42)))) +/// \endcode +/// matches the expression in both doCall and doConstruct +extern const internal::MapAnyOfMatcherinvocation; + /// Matches unary expressions that have a specific type of argument. /// /// Given diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp --- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -924,6 +924,7 @@ const internal::MapAnyOfMatcher binaryOperation; +const internal::MapAnyOfMatcher invocation; const internal::VariadicDynCastAllOfMatcher unaryOperator; const internal::VariadicDynCastAllOfMatcher conditionalOperator; diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -358,6 +358,7 @@ REGISTER_MATCHER(injectedClassNameType); REGISTER_MATCHER(innerType); REGISTER_MATCHER(integerLiteral); + REGISTER_MATCHER(invocation); REGISTER_MATCHER(isAllowedToContainClauseKind); REGISTER_MATCHER(isAnonymous); REGISTER_MATCHER(isAnyCharacter); diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp --- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -863,6 +863,47 @@ mapAnyOf(unaryOperator, cxxOperatorCallExpr) .with(hasAnyOperatorName("+", "!"), forFunction(functionDecl(hasName("opFree"))))))); + + Code = R"cpp( +struct ConstructorTakesInt +{ + ConstructorTakesInt(int i) {} +}; + +void callTakesInt(int i) +{ + +} + +void doCall() +{ + callTakesInt(42); +} + +void doConstruct() +{ + ConstructorTakesInt cti(42); +} +)cpp"; + + EXPECT_TRUE(matches( + Code, traverse(TK_IgnoreUnlessSpelledInSource, + invocation(forFunction(functionDecl(hasName("doCall"))), + hasArgument(0, integerLiteral(equals(42))), + hasAnyArgument(integerLiteral(equals(42))), + forEachArgumentWithParam( + integerLiteral(equals(42)), + parmVarDecl(hasName("i"))))))); + + EXPECT_TRUE(matches( + Code, + traverse( + TK_IgnoreUnlessSpelledInSource, + invocation(forFunction(functionDecl(hasName("doConstruct"))), + hasArgument(0, integerLiteral(equals(42))), + hasAnyArgument(integerLiteral(equals(42))), + forEachArgumentWithParam(integerLiteral(equals(42)), + parmVarDecl(hasName("i"))))))); } TEST_P(ASTMatchersTest, IsDerivedFrom) {