[ASTMatchers] Add invocation matcher

Differential Revision: https://reviews.llvm.org/D94865
This commit is contained in:
Stephen Kelly 2021-01-16 14:26:32 +00:00
parent 6f0df3cddb
commit 3c79734f29
5 changed files with 113 additions and 0 deletions

View File

@ -5613,6 +5613,40 @@ matches each use of "!=" in:
</pre></td></tr>
<tr><td>Matcher&lt;*&gt;</td><td class="name" onclick="toggle('invocation0')"><a name="invocation0Anchor">invocation</a></td><td>Matcher&lt;*&gt;...Matcher&lt;*&gt;</td></tr>
<tr><td colspan="4" class="doc" id="invocation0"><pre>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
</pre></td></tr>
<tr><td>Matcher&lt;*&gt;</td><td class="name" onclick="toggle('eachOf0')"><a name="eachOf0Anchor">eachOf</a></td><td>Matcher&lt;*&gt;, ..., Matcher&lt;*&gt;</td></tr>
<tr><td colspan="4" class="doc" id="eachOf0"><pre>Matches if any of the given matchers matches.

View File

@ -2829,6 +2829,42 @@ extern const internal::MapAnyOfMatcher<BinaryOperator, CXXOperatorCallExpr,
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::MapAnyOfMatcher<CallExpr, CXXConstructExpr> invocation;
/// Matches unary expressions that have a specific type of argument.
///
/// Given

View File

@ -924,6 +924,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, BinaryOperator>
const internal::MapAnyOfMatcher<BinaryOperator, CXXOperatorCallExpr,
CXXRewrittenBinaryOperator>
binaryOperation;
const internal::MapAnyOfMatcher<CallExpr, CXXConstructExpr> invocation;
const internal::VariadicDynCastAllOfMatcher<Stmt, UnaryOperator> unaryOperator;
const internal::VariadicDynCastAllOfMatcher<Stmt, ConditionalOperator>
conditionalOperator;

View File

@ -358,6 +358,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(injectedClassNameType);
REGISTER_MATCHER(innerType);
REGISTER_MATCHER(integerLiteral);
REGISTER_MATCHER(invocation);
REGISTER_MATCHER(isAllowedToContainClauseKind);
REGISTER_MATCHER(isAnonymous);
REGISTER_MATCHER(isAnyCharacter);

View File

@ -863,6 +863,47 @@ void opFree()
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) {