add isAtPosition narrowing matcher for parmVarDecl

Differential Revision: https://reviews.llvm.org/D80603
This commit is contained in:
Vy Nguyen 2020-05-28 00:33:13 -04:00
parent eca41919d2
commit 51401a676c
4 changed files with 85 additions and 0 deletions

View File

@ -4671,6 +4671,23 @@ cxxRecordDecl(hasName("::X"), isTemplateInstantiation())
Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;
</pre></td></tr>
<tr><td>Matcher&lt;clang::ParmVarDecl&gt;</td><td class="name" onclick="toggle('isAtPosition0')"><a name="isAtPosition0Anchor">isAtPosition</a></td><td>unsigned N</td></tr>
<tr><td colspan="4" class="doc" id="isAtPosition0"><pre>Matches the ParmVarDecl nodes that are at the N'th position in the parameter
list. The parameter list could be that of either a block, function, or
objc-method.
Given
void f(int a, int b, int c) {
}
``parmVarDecl(isAtPosition(0))`` matches ``int a``.
``parmVarDecl(isAtPosition(1))`` matches ``int b``.
</pre></td></tr>
<!--END_NARROWING_MATCHERS -->
</table>

View File

@ -4257,6 +4257,34 @@ AST_POLYMORPHIC_MATCHER_P2(forEachArgumentWithParam,
return Matched;
}
/// Matches the ParmVarDecl nodes that are at the N'th position in the parameter
/// list. The parameter list could be that of either a block, function, or
/// objc-method.
///
///
/// Given
///
/// \code
/// void f(int a, int b, int c) {
/// }
/// \endcode
///
/// ``parmVarDecl(isAtPosition(0))`` matches ``int a``.
///
/// ``parmVarDecl(isAtPosition(1))`` matches ``int b``.
AST_MATCHER_P(clang::ParmVarDecl, isAtPosition, unsigned, N) {
const clang::DeclContext *Context = Node.getParentFunctionOrMethod();
if (const auto *Decl = dyn_cast_or_null<FunctionDecl>(Context))
return N < Decl->param_size() && Decl->getParamDecl(N) == &Node;
if (const auto *Decl = dyn_cast_or_null<BlockDecl>(Context))
return N < Decl->param_size() && Decl->getParamDecl(N) == &Node;
if (const auto *Decl = dyn_cast_or_null<ObjCMethodDecl>(Context))
return N < Decl->param_size() && Decl->getParamDecl(N) == &Node;
return false;
}
/// Matches any parameter of a function or an ObjC method declaration or a
/// block.
///

View File

@ -219,6 +219,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(floatLiteral);
REGISTER_MATCHER(forEach);
REGISTER_MATCHER(forEachArgumentWithParam);
REGISTER_MATCHER(isAtPosition);
REGISTER_MATCHER(forEachConstructorInitializer);
REGISTER_MATCHER(forEachDescendant);
REGISTER_MATCHER(forEachOverridden);

View File

@ -2643,6 +2643,45 @@ TEST(HasDefaultArgument, Basic) {
parmVarDecl(hasDefaultArgument())));
}
TEST(IsAtPosition, Basic) {
EXPECT_TRUE(matches("void x(int a, int b) {}", parmVarDecl(isAtPosition(1))));
EXPECT_TRUE(matches("void x(int a, int b) {}", parmVarDecl(isAtPosition(0))));
EXPECT_TRUE(matches("void x(int a, int b) {}", parmVarDecl(isAtPosition(1))));
EXPECT_TRUE(notMatches("void x(int val) {}", parmVarDecl(isAtPosition(1))));
}
TEST(IsAtPosition, FunctionDecl) {
EXPECT_TRUE(matches("void x(int a);", parmVarDecl(isAtPosition(0))));
EXPECT_TRUE(matches("void x(int a, int b);", parmVarDecl(isAtPosition(0))));
EXPECT_TRUE(matches("void x(int a, int b);", parmVarDecl(isAtPosition(1))));
EXPECT_TRUE(notMatches("void x(int val);", parmVarDecl(isAtPosition(1))));
}
TEST(IsAtPosition, Lambda) {
EXPECT_TRUE(
matches("void x() { [](int a) {}; }", parmVarDecl(isAtPosition(0))));
EXPECT_TRUE(matches("void x() { [](int a, int b) {}; }",
parmVarDecl(isAtPosition(0))));
EXPECT_TRUE(matches("void x() { [](int a, int b) {}; }",
parmVarDecl(isAtPosition(1))));
EXPECT_TRUE(
notMatches("void x() { [](int val) {}; }", parmVarDecl(isAtPosition(1))));
}
TEST(IsAtPosition, BlockDecl) {
EXPECT_TRUE(matchesObjC(
"void func() { void (^my_block)(int arg) = ^void(int arg) {}; } ",
parmVarDecl(isAtPosition(0))));
EXPECT_TRUE(matchesObjC("void func() { void (^my_block)(int x, int y) = "
"^void(int x, int y) {}; } ",
parmVarDecl(isAtPosition(1))));
EXPECT_TRUE(notMatchesObjC(
"void func() { void (^my_block)(int arg) = ^void(int arg) {}; } ",
parmVarDecl(isAtPosition(1))));
}
TEST(IsArray, Basic) {
EXPECT_TRUE(matches("struct MyClass {}; MyClass *p1 = new MyClass[10];",
cxxNewExpr(isArray())));