forked from OSchip/llvm-project
[ASTMatchers] Add matchers for decomposition decls
Differential Revision: https://reviews.llvm.org/D95739
This commit is contained in:
parent
c722575633
commit
467a045601
|
@ -591,6 +591,15 @@ accessSpecDecl()
|
|||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('bindingDecl0')"><a name="bindingDecl0Anchor">bindingDecl</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BindingDecl.html">BindingDecl</a>>...</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="bindingDecl0"><pre>Matches binding declarations
|
||||
Example matches foo and bar
|
||||
(matcher = bindingDecl()
|
||||
|
||||
auto [foo, bar] = std::make_pair{42, 42};
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('blockDecl0')"><a name="blockDecl0Anchor">blockDecl</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html">BlockDecl</a>>...</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="blockDecl0"><pre>Matches block declarations.
|
||||
|
||||
|
@ -6011,6 +6020,24 @@ Example matches b (matcher = binaryOperator(hasRHS()))
|
|||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BindingDecl.html">BindingDecl</a>></td><td class="name" onclick="toggle('forDecomposition0')"><a name="forDecomposition0Anchor">forDecomposition</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>> InnerMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="forDecomposition0"><pre>Matches the DecompositionDecl the binding belongs to.
|
||||
|
||||
For example, in:
|
||||
void foo()
|
||||
{
|
||||
int arr[3];
|
||||
auto &[f, s, t] = arr;
|
||||
|
||||
f = 42;
|
||||
}
|
||||
The matcher:
|
||||
bindingDecl(hasName("f"),
|
||||
forDecomposition(decompositionDecl())
|
||||
matches 'f' in 'auto &[f, s, t]'.
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html">BlockDecl</a>></td><td class="name" onclick="toggle('hasAnyParameter2')"><a name="hasAnyParameter2Anchor">hasAnyParameter</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>> InnerMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasAnyParameter2"><pre>Matches any parameter of a function or an ObjC method declaration or a
|
||||
block.
|
||||
|
@ -7090,6 +7117,40 @@ Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl
|
|||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DecompositionDecl.html">DecompositionDecl</a>></td><td class="name" onclick="toggle('hasAnyBinding0')"><a name="hasAnyBinding0Anchor">hasAnyBinding</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BindingDecl.html">BindingDecl</a>> InnerMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasAnyBinding0"><pre>Matches any binding of a DecompositionDecl.
|
||||
|
||||
For example, in:
|
||||
void foo()
|
||||
{
|
||||
int arr[3];
|
||||
auto &[f, s, t] = arr;
|
||||
|
||||
f = 42;
|
||||
}
|
||||
The matcher:
|
||||
decompositionDecl(hasAnyBinding(bindingDecl(hasName("f").bind("fBinding"))))
|
||||
matches the decomposition decl with 'f' bound to "fBinding".
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DecompositionDecl.html">DecompositionDecl</a>></td><td class="name" onclick="toggle('hasBinding0')"><a name="hasBinding0Anchor">hasBinding</a></td><td>unsigned N, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BindingDecl.html">BindingDecl</a>> InnerMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasBinding0"><pre>Matches the Nth binding of a DecompositionDecl.
|
||||
|
||||
For example, in:
|
||||
void foo()
|
||||
{
|
||||
int arr[3];
|
||||
auto &[f, s, t] = arr;
|
||||
|
||||
f = 42;
|
||||
}
|
||||
The matcher:
|
||||
decompositionDecl(hasBinding(0, bindingDecl(hasName("f").bind("fBinding"))))
|
||||
matches the decomposition decl with 'f' bound to "fBinding".
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DoStmt.html">DoStmt</a>></td><td class="name" onclick="toggle('hasBody0')"><a name="hasBody0Anchor">hasBody</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>> InnerMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasBody0"><pre></pre></td></tr>
|
||||
|
||||
|
|
|
@ -347,6 +347,16 @@ extern const internal::VariadicAllOfMatcher<Decl> decl;
|
|||
extern const internal::VariadicDynCastAllOfMatcher<Decl, DecompositionDecl>
|
||||
decompositionDecl;
|
||||
|
||||
/// Matches binding declarations
|
||||
/// Example matches \c foo and \c bar
|
||||
/// (matcher = bindingDecl()
|
||||
///
|
||||
/// \code
|
||||
/// auto [foo, bar] = std::make_pair{42, 42};
|
||||
/// \endcode
|
||||
extern const internal::VariadicDynCastAllOfMatcher<Decl, BindingDecl>
|
||||
bindingDecl;
|
||||
|
||||
/// Matches a declaration of a linkage specification.
|
||||
///
|
||||
/// Given
|
||||
|
@ -7379,6 +7389,80 @@ AST_MATCHER(Expr, nullPointerConstant) {
|
|||
Expr::NPC_ValueDependentIsNull);
|
||||
}
|
||||
|
||||
/// Matches the DecompositionDecl the binding belongs to.
|
||||
///
|
||||
/// For example, in:
|
||||
/// \code
|
||||
/// void foo()
|
||||
/// {
|
||||
/// int arr[3];
|
||||
/// auto &[f, s, t] = arr;
|
||||
///
|
||||
/// f = 42;
|
||||
/// }
|
||||
/// \endcode
|
||||
/// The matcher:
|
||||
/// \code
|
||||
/// bindingDecl(hasName("f"),
|
||||
/// forDecomposition(decompositionDecl())
|
||||
/// \endcode
|
||||
/// matches 'f' in 'auto &[f, s, t]'.
|
||||
AST_MATCHER_P(BindingDecl, forDecomposition, internal::Matcher<ValueDecl>,
|
||||
InnerMatcher) {
|
||||
if (const ValueDecl *VD = Node.getDecomposedDecl())
|
||||
return InnerMatcher.matches(*VD, Finder, Builder);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Matches the Nth binding of a DecompositionDecl.
|
||||
///
|
||||
/// For example, in:
|
||||
/// \code
|
||||
/// void foo()
|
||||
/// {
|
||||
/// int arr[3];
|
||||
/// auto &[f, s, t] = arr;
|
||||
///
|
||||
/// f = 42;
|
||||
/// }
|
||||
/// \endcode
|
||||
/// The matcher:
|
||||
/// \code
|
||||
/// decompositionDecl(hasBinding(0,
|
||||
/// bindingDecl(hasName("f").bind("fBinding"))))
|
||||
/// \endcode
|
||||
/// matches the decomposition decl with 'f' bound to "fBinding".
|
||||
AST_MATCHER_P2(DecompositionDecl, hasBinding, unsigned, N,
|
||||
internal::Matcher<BindingDecl>, InnerMatcher) {
|
||||
if (Node.bindings().size() <= N)
|
||||
return false;
|
||||
return InnerMatcher.matches(*Node.bindings()[N], Finder, Builder);
|
||||
}
|
||||
|
||||
/// Matches any binding of a DecompositionDecl.
|
||||
///
|
||||
/// For example, in:
|
||||
/// \code
|
||||
/// void foo()
|
||||
/// {
|
||||
/// int arr[3];
|
||||
/// auto &[f, s, t] = arr;
|
||||
///
|
||||
/// f = 42;
|
||||
/// }
|
||||
/// \endcode
|
||||
/// The matcher:
|
||||
/// \code
|
||||
/// decompositionDecl(hasAnyBinding(bindingDecl(hasName("f").bind("fBinding"))))
|
||||
/// \endcode
|
||||
/// matches the decomposition decl with 'f' bound to "fBinding".
|
||||
AST_MATCHER_P(DecompositionDecl, hasAnyBinding, internal::Matcher<BindingDecl>,
|
||||
InnerMatcher) {
|
||||
return llvm::any_of(Node.bindings(), [&](const auto *Binding) {
|
||||
return InnerMatcher.matches(*Binding, Finder, Builder);
|
||||
});
|
||||
}
|
||||
|
||||
/// Matches declaration of the function the statement belongs to
|
||||
///
|
||||
/// Given:
|
||||
|
|
|
@ -144,6 +144,7 @@ RegistryMaps::RegistryMaps() {
|
|||
REGISTER_MATCHER(binaryConditionalOperator);
|
||||
REGISTER_MATCHER(binaryOperator);
|
||||
REGISTER_MATCHER(binaryOperation);
|
||||
REGISTER_MATCHER(bindingDecl);
|
||||
REGISTER_MATCHER(blockDecl);
|
||||
REGISTER_MATCHER(blockExpr);
|
||||
REGISTER_MATCHER(blockPointerType);
|
||||
|
@ -226,6 +227,7 @@ RegistryMaps::RegistryMaps() {
|
|||
REGISTER_MATCHER(exprWithCleanups);
|
||||
REGISTER_MATCHER(fieldDecl);
|
||||
REGISTER_MATCHER(floatLiteral);
|
||||
REGISTER_MATCHER(forDecomposition);
|
||||
REGISTER_MATCHER(forEach);
|
||||
REGISTER_MATCHER(forEachArgumentWithParam);
|
||||
REGISTER_MATCHER(forEachArgumentWithParamType);
|
||||
|
@ -248,6 +250,7 @@ RegistryMaps::RegistryMaps() {
|
|||
REGISTER_MATCHER(hasAncestor);
|
||||
REGISTER_MATCHER(hasAnyArgument);
|
||||
REGISTER_MATCHER(hasAnyBase);
|
||||
REGISTER_MATCHER(hasAnyBinding);
|
||||
REGISTER_MATCHER(hasAnyClause);
|
||||
REGISTER_MATCHER(hasAnyConstructorInitializer);
|
||||
REGISTER_MATCHER(hasAnyDeclaration);
|
||||
|
@ -266,6 +269,7 @@ RegistryMaps::RegistryMaps() {
|
|||
REGISTER_MATCHER(hasAttr);
|
||||
REGISTER_MATCHER(hasAutomaticStorageDuration);
|
||||
REGISTER_MATCHER(hasBase);
|
||||
REGISTER_MATCHER(hasBinding);
|
||||
REGISTER_MATCHER(hasBitWidth);
|
||||
REGISTER_MATCHER(hasBody);
|
||||
REGISTER_MATCHER(hasCanonicalType);
|
||||
|
|
|
@ -2129,6 +2129,37 @@ TEST(ASTMatchersTestObjC, ObjCExceptionStmts) {
|
|||
EXPECT_TRUE(matchesObjC(ObjCString, objcFinallyStmt()));
|
||||
}
|
||||
|
||||
TEST(ASTMatchersTest, DecompositionDecl) {
|
||||
StringRef Code = R"cpp(
|
||||
void foo()
|
||||
{
|
||||
int arr[3];
|
||||
auto &[f, s, t] = arr;
|
||||
|
||||
f = 42;
|
||||
}
|
||||
)cpp";
|
||||
EXPECT_TRUE(matchesConditionally(
|
||||
Code, decompositionDecl(hasBinding(0, bindingDecl(hasName("f")))), true,
|
||||
{"-std=c++17"}));
|
||||
EXPECT_FALSE(matchesConditionally(
|
||||
Code, decompositionDecl(hasBinding(42, bindingDecl(hasName("f")))), true,
|
||||
{"-std=c++17"}));
|
||||
EXPECT_FALSE(matchesConditionally(
|
||||
Code, decompositionDecl(hasBinding(0, bindingDecl(hasName("s")))), true,
|
||||
{"-std=c++17"}));
|
||||
EXPECT_TRUE(matchesConditionally(
|
||||
Code, decompositionDecl(hasBinding(1, bindingDecl(hasName("s")))), true,
|
||||
{"-std=c++17"}));
|
||||
|
||||
EXPECT_TRUE(matchesConditionally(
|
||||
Code,
|
||||
bindingDecl(decl().bind("self"), hasName("f"),
|
||||
forDecomposition(decompositionDecl(
|
||||
hasAnyBinding(bindingDecl(equalsBoundNode("self")))))),
|
||||
true, {"-std=c++17"}));
|
||||
}
|
||||
|
||||
TEST(ASTMatchersTestObjC, ObjCAutoreleasePoolStmt) {
|
||||
StringRef ObjCString = "void f() {"
|
||||
"@autoreleasepool {"
|
||||
|
|
Loading…
Reference in New Issue