[clang] b0d3ea1 - [ASTMatchers] Added hasDirectBase Matcher
Nathan James via cfe-commits
cfe-commits at lists.llvm.org
Tue Jul 7 08:05:21 PDT 2020
Author: Nathan James
Date: 2020-07-07T16:05:11+01:00
New Revision: b0d3ea171bd56b3b079be9213935925e1499df15
URL: https://github.com/llvm/llvm-project/commit/b0d3ea171bd56b3b079be9213935925e1499df15
DIFF: https://github.com/llvm/llvm-project/commit/b0d3ea171bd56b3b079be9213935925e1499df15.diff
LOG: [ASTMatchers] Added hasDirectBase Matcher
Adds a matcher called `hasDirectBase` for matching the `CXXBaseSpecifier` of a class that directly derives from another class.
Reviewed By: aaron.ballman
Differential Revision: https://reviews.llvm.org/D81552
Added:
Modified:
clang/docs/LibASTMatchersReference.html
clang/include/clang/ASTMatchers/ASTMatchers.h
clang/lib/ASTMatchers/Dynamic/Registry.cpp
clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
Removed:
################################################################################
diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html
index 9c04322f0ae6..2256cbf71869 100644
--- a/clang/docs/LibASTMatchersReference.html
+++ b/clang/docs/LibASTMatchersReference.html
@@ -5658,7 +5658,7 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasAnyBase0"><pre>Matches C++ classes that have a direct or indirect base matching BaseSpecMatcher.
Example:
-matcher hasAnyBase(hasType(cxxRecordDecl(hasName("SpecialBase")))))
+matcher hasAnyBase(hasType(cxxRecordDecl(hasName("SpecialBase"))))
class Foo;
class Bar : Foo {};
class Baz : Bar {};
@@ -5670,6 +5670,20 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
</pre></td></tr>
+<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>></td><td class="name" onclick="toggle('hasDirectBase0')"><a name="hasDirectBase0Anchor">hasDirectBase</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>> BaseSpecMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasDirectBase0"><pre>Matches C++ classes that have a direct base matching BaseSpecMatcher.
+
+Example:
+matcher hasDirectBase(hasType(cxxRecordDecl(hasName("SpecialBase"))))
+ class Foo;
+ class Bar : Foo {};
+ class Baz : Bar {};
+ class SpecialBase;
+ class Proxy : SpecialBase {}; // matches Proxy
+ class IndirectlyDerived : Proxy {}; // doesn't match
+</pre></td></tr>
+
+
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>></td><td class="name" onclick="toggle('hasMethod0')"><a name="hasMethod0Anchor">hasMethod</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasMethod0"><pre>Matches the first method of a class or struct that satisfies InnerMatcher.
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index 153b51753085..f16fb876cdd3 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -2862,7 +2862,7 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
/// BaseSpecMatcher.
///
/// Example:
-/// matcher hasAnyBase(hasType(cxxRecordDecl(hasName("SpecialBase")))))
+/// matcher hasAnyBase(hasType(cxxRecordDecl(hasName("SpecialBase"))))
/// \code
/// class Foo;
/// class Bar : Foo {};
@@ -2878,6 +2878,26 @@ AST_MATCHER_P(CXXRecordDecl, hasAnyBase, internal::Matcher<CXXBaseSpecifier>,
return internal::matchesAnyBase(Node, BaseSpecMatcher, Finder, Builder);
}
+/// Matches C++ classes that have a direct base matching \p BaseSpecMatcher.
+///
+/// Example:
+/// matcher hasDirectBase(hasType(cxxRecordDecl(hasName("SpecialBase"))))
+/// \code
+/// class Foo;
+/// class Bar : Foo {};
+/// class Baz : Bar {};
+/// class SpecialBase;
+/// class Proxy : SpecialBase {}; // matches Proxy
+/// class IndirectlyDerived : Proxy {}; // doesn't match
+/// \endcode
+AST_MATCHER_P(CXXRecordDecl, hasDirectBase, internal::Matcher<CXXBaseSpecifier>,
+ BaseSpecMatcher) {
+ return Node.hasDefinition() &&
+ llvm::any_of(Node.bases(), [&](const CXXBaseSpecifier &Base) {
+ return BaseSpecMatcher.matches(Base, Finder, Builder);
+ });
+}
+
/// Similar to \c isDerivedFrom(), but also matches classes that directly
/// match \c Base.
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
index f01c68a518d9..a0a65092a92b 100644
--- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -278,6 +278,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasDefinition);
REGISTER_MATCHER(hasDescendant);
REGISTER_MATCHER(hasDestinationType);
+ REGISTER_MATCHER(hasDirectBase);
REGISTER_MATCHER(hasDynamicExceptionSpec);
REGISTER_MATCHER(hasEitherOperand);
REGISTER_MATCHER(hasElementType);
diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
index fa7f75b58b4e..aeb4fd098d22 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -3125,5 +3125,44 @@ TEST(IsVirtual, NoVirtualBase) {
cxxRecordDecl(hasAnyBase(isVirtual()))));
}
+TEST(BaseSpecifier, hasDirectBase) {
+ EXPECT_TRUE(matches(
+ R"cc(
+ class Base {};
+ class Derived : Base{};
+ )cc",
+ cxxRecordDecl(hasName("Derived"),
+ hasDirectBase(hasType(cxxRecordDecl(hasName("Base")))))));
+
+ StringRef MultiDerived = R"cc(
+ class Base {};
+ class Base2 {};
+ class Derived : Base, Base2{};
+ )cc";
+
+ EXPECT_TRUE(matches(
+ MultiDerived,
+ cxxRecordDecl(hasName("Derived"),
+ hasDirectBase(hasType(cxxRecordDecl(hasName("Base")))))));
+ EXPECT_TRUE(matches(
+ MultiDerived,
+ cxxRecordDecl(hasName("Derived"),
+ hasDirectBase(hasType(cxxRecordDecl(hasName("Base2")))))));
+
+ StringRef Indirect = R"cc(
+ class Base {};
+ class Intermediate : Base {};
+ class Derived : Intermediate{};
+ )cc";
+
+ EXPECT_TRUE(
+ matches(Indirect, cxxRecordDecl(hasName("Derived"),
+ hasDirectBase(hasType(cxxRecordDecl(
+ hasName("Intermediate")))))));
+ EXPECT_TRUE(notMatches(
+ Indirect,
+ cxxRecordDecl(hasName("Derived"),
+ hasDirectBase(hasType(cxxRecordDecl(hasName("Base")))))));
+}
} // namespace ast_matchers
} // namespace clang
More information about the cfe-commits
mailing list