[PATCH] D87527: [ASTMatchers] Fix `hasBody` for the descendants of `FunctionDecl`
Balogh, Ádám via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 11 10:02:29 PDT 2020
baloghadamsoftware created this revision.
baloghadamsoftware added reviewers: klimek, sbenza.
baloghadamsoftware added a project: clang.
Herald added subscribers: martong, gamesh411, Szelethus, dkrupp, rnkovacs.
baloghadamsoftware requested review of this revision.
//AST Matcher// `hasBody` is a polymorphic matcher that behaves differently for loop statements and function declarations. The main difference is the for functions declarations it does not only call `FunctionDecl::getBody()` but first checks whether the declaration in question is that specific declaration which has the body by calling `FunctionDecl::doesThisDeclarationHaveABody()`. This is achieved by specialization of the template `GetBodyMatcher`. Unfortunately template specializations do not catch the descendants of the class for which the template is specialized. Therefore it does not work correcly for the descendants of `FunctionDecl`, such as `CXXMethodDecl`, `CXXConstructorDecl`, `CXXDestructorDecl` etc. This patch fixes this issue by using a template metaprogram.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D87527
Files:
clang/include/clang/ASTMatchers/ASTMatchersInternal.h
clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===================================================================
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -1454,10 +1454,30 @@
doStmt(hasBody(compoundStmt()))));
EXPECT_TRUE(matches("void f() { int p[2]; for (auto x : p) {} }",
cxxForRangeStmt(hasBody(compoundStmt()))));
+}
+
+TEST(HasBody, FindsBodyOfFunctions) {
EXPECT_TRUE(matches("void f() {}", functionDecl(hasBody(compoundStmt()))));
EXPECT_TRUE(notMatches("void f();", functionDecl(hasBody(compoundStmt()))));
- EXPECT_TRUE(matches("void f(); void f() {}",
- functionDecl(hasBody(compoundStmt()))));
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ "void f(); void f() {}",
+ functionDecl(hasBody(compoundStmt())).bind("func"),
+ std::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("func", 1)));
+}
+
+TEST(HasBody, FindsBodyOfFunctionChildren) {
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ "class C { void f(); }; void C::f() {}",
+ cxxMethodDecl(hasBody(compoundStmt())).bind("met"),
+ std::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("met", 1)));
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ "class C { C(); }; C::C() {}",
+ cxxConstructorDecl(hasBody(compoundStmt())).bind("ctr"),
+ std::make_unique<VerifyIdIsBoundTo<CXXConstructorDecl>>("ctr", 1)));
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ "class C { ~C(); }; C::~C() {}",
+ cxxDestructorDecl(hasBody(compoundStmt())).bind("dtr"),
+ std::make_unique<VerifyIdIsBoundTo<CXXDestructorDecl>>("dtr", 1)));
}
TEST(HasAnySubstatement, MatchesForTopLevelCompoundStatement) {
Index: clang/include/clang/ASTMatchers/ASTMatchersInternal.h
===================================================================
--- clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -1835,18 +1835,18 @@
DynTypedNode Node;
};
+template <typename Ty, typename Enable = void> struct GetBodyMatcher {
+ static const Stmt *get(const Ty &Node) { return Node.getBody(); }
+};
+
template <typename Ty>
-struct GetBodyMatcher {
+struct GetBodyMatcher<Ty, typename std::enable_if<
+ std::is_base_of<FunctionDecl, Ty>::value>::type> {
static const Stmt *get(const Ty &Node) {
- return Node.getBody();
+ return Node.doesThisDeclarationHaveABody() ? Node.getBody() : nullptr;
}
};
-template <>
-inline const Stmt *GetBodyMatcher<FunctionDecl>::get(const FunctionDecl &Node) {
- return Node.doesThisDeclarationHaveABody() ? Node.getBody() : nullptr;
-}
-
template <typename Ty>
struct HasSizeMatcher {
static bool hasSize(const Ty &Node, unsigned int N) {
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D87527.291260.patch
Type: text/x-patch
Size: 2834 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20200911/70f5bcf7/attachment-0001.bin>
More information about the cfe-commits
mailing list