Add an AST matcher, isFinal(), for testing whether a method or class declaration are marked final.

llvm-svn: 243107
This commit is contained in:
Aaron Ballman 2015-07-24 12:35:41 +00:00
parent c9bc0b1e14
commit 41143bb573
4 changed files with 62 additions and 0 deletions

View File

@ -1488,6 +1488,25 @@ methodDecl(isConst()) matches A::foo() but not A::bar()
</pre></td></tr>
<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('isFinal0')"><a name="isFinal0Anchor">isFinal</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isFinal0"><pre>Matches if the given method declaration is final.
Given:
struct A {
virtual void foo();
virtual void bar();
};
struct B : A {
void foo() final;
void bar();
};
methodDecl(isFinal()) matches B::foo() but not B::bar(), A::foo(), or A::bar()
</pre></td></tr>
<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('isOverride0')"><a name="isOverride0Anchor">isOverride</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isOverride0"><pre>Matches if the given method declaration overrides another method.
@ -1573,6 +1592,18 @@ isSameOrDerivedFrom(hasName(...)).
</pre></td></tr>
<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('isFinal1')"><a name="isFinal1Anchor">isFinal</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isFinal1"><pre>Matches if the given class declaration is final.
Given:
struct A {};
struct B final : A {};
recordDecl(isFinal()) matches B but not A.
</pre></td></tr>
<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('isTemplateInstantiation2')"><a name="isTemplateInstantiation2Anchor">isTemplateInstantiation</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isTemplateInstantiation2"><pre>Matches template instantiations of function, class, or static
member variable template instantiations.

View File

@ -3147,6 +3147,27 @@ AST_MATCHER(CXXMethodDecl, isVirtual) {
return Node.isVirtual();
}
/// \brief Matches if the given method or class declaration is final.
///
/// Given:
/// \code
/// class A final {};
///
/// struct B {
/// virtual void f();
/// };
///
/// struct C : B {
/// void f() final;
/// };
/// \endcode
/// matches A and C::f, but not B, C, or B::f
AST_POLYMORPHIC_MATCHER(isFinal,
AST_POLYMORPHIC_SUPPORTED_TYPES(CXXRecordDecl,
CXXMethodDecl)) {
return Node.hasAttr<FinalAttr>();
}
/// \brief Matches if the given method declaration is pure.
///
/// Given

View File

@ -249,6 +249,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(isExplicitTemplateSpecialization);
REGISTER_MATCHER(isExpr);
REGISTER_MATCHER(isExternC);
REGISTER_MATCHER(isFinal);
REGISTER_MATCHER(isImplicit);
REGISTER_MATCHER(isExpansionInFileMatching);
REGISTER_MATCHER(isExpansionInMainFile);

View File

@ -1784,6 +1784,15 @@ TEST(Matcher, MatchesAccessSpecDecls) {
EXPECT_TRUE(notMatches("class C { int i; };", accessSpecDecl()));
}
TEST(Matcher, MatchesFinal) {
EXPECT_TRUE(matches("class X final {};", recordDecl(isFinal())));
EXPECT_TRUE(matches("class X { virtual void f() final; };",
methodDecl(isFinal())));
EXPECT_TRUE(notMatches("class X {};", recordDecl(isFinal())));
EXPECT_TRUE(notMatches("class X { virtual void f(); };",
methodDecl(isFinal())));
}
TEST(Matcher, MatchesVirtualMethod) {
EXPECT_TRUE(matches("class X { virtual int f(); };",
methodDecl(isVirtual(), hasName("::X::f"))));