r244036 - Add AST matchers for narrowing constructors that are default, copy, or move constructors, as well as functionality to determine whether a ctor initializer is a base initializer.
Aaron Ballman
aaron at aaronballman.com
Wed Aug 5 05:11:30 PDT 2015
Author: aaronballman
Date: Wed Aug 5 07:11:30 2015
New Revision: 244036
URL: http://llvm.org/viewvc/llvm-project?rev=244036&view=rev
Log:
Add AST matchers for narrowing constructors that are default, copy, or move constructors, as well as functionality to determine whether a ctor initializer is a base initializer.
Modified:
cfe/trunk/docs/LibASTMatchersReference.html
cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
Modified: cfe/trunk/docs/LibASTMatchersReference.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LibASTMatchersReference.html?rev=244036&r1=244035&r2=244036&view=diff
==============================================================================
--- cfe/trunk/docs/LibASTMatchersReference.html (original)
+++ cfe/trunk/docs/LibASTMatchersReference.html Wed Aug 5 07:11:30 2015
@@ -1460,6 +1460,58 @@ Example matches f(0, 0) (matcher = callE
</pre></td></tr>
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html">CXXConstructorDecl</a>></td><td class="name" onclick="toggle('isCopyConstructor1')"><a name="isCopyConstructor1Anchor">isCopyConstructor</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isCopyConstructor1"><pre>Matches constructor declarations that are copy constructors.
+
+Example matches #2, but not #1 or #3 (matcher = constructorDecl(isCopyConstructor())
+ struct S {
+ S(); // #1
+ S(const S &); // #2
+ S(S &&); // #3
+ };
+</pre></td></tr>
+
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html">CXXConstructorDecl</a>></td><td class="name" onclick="toggle('isDefaultConstructor1')"><a name="isDefaultConstructor1Anchor">isDefaultConstructor</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isDefaultConstructor1"><pre>Matches constructor declarations that are default constructors.
+
+Example matches #1, but not #2 or #3 (matcher = constructorDecl(isDefaultConstructor())
+ struct S {
+ S(); // #1
+ S(const S &); // #2
+ S(S &&); // #3
+ };
+</pre></td></tr>
+
+
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html">CXXConstructorDecl</a>></td><td class="name" onclick="toggle('isMoveConstructor1')"><a name="isMoveConstructor1Anchor">isMoveConstructor</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isMoveConstructor1"><pre>Matches constructor declarations that are move constructors.
+
+Example matches #3, but not #1 or #2 (matcher = constructorDecl(isMoveConstructor())
+ struct S {
+ S(); // #1
+ S(const S &); // #2
+ S(S &&); // #3
+ };
+</pre></td></tr>
+
+
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>></td><td class="name" onclick="toggle('isBaseInitializer0')"><a name="isBaseInitializer0Anchor">isBaseInitializer</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isBaseInitializer0"><pre>Matches a constructor initializer if it is initializing a base, as opposed to a member.
+
+Given
+ struct B {};
+ struct D : B {
+ int I;
+ D(int i) : I(i) {}
+ };
+ struct E : B {
+ E() : B() {}
+ };
+constructorDecl(hasAnyConstructorInitializer(isBaseInitializer()))
+ will match E(), but not match D(int).
+</pre></td></tr>
+
+
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>></td><td class="name" onclick="toggle('isWritten0')"><a name="isWritten0Anchor">isWritten</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isWritten0"><pre>Matches a constructor initializer if it is explicitly written in
code (as opposed to implicitly added by the compiler).
Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=244036&r1=244035&r2=244036&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Wed Aug 5 07:11:30 2015
@@ -2632,6 +2632,26 @@ AST_MATCHER(CXXCtorInitializer, isWritte
return Node.isWritten();
}
+/// \brief Matches a constructor initializer if it is initializing a base, as
+/// opposed to a member.
+///
+/// Given
+/// \code
+/// struct B {};
+/// struct D : B {
+/// int I;
+/// D(int i) : I(i) {}
+/// };
+/// struct E : B {
+/// E() : B() {}
+/// };
+/// \endcode
+/// constructorDecl(hasAnyConstructorInitializer(isBaseInitializer()))
+/// will match E(), but not match D(int).
+AST_MATCHER(CXXCtorInitializer, isBaseInitializer) {
+ return Node.isBaseInitializer();
+}
+
/// \brief Matches any argument of a call expression or a constructor call
/// expression.
///
@@ -4104,6 +4124,51 @@ AST_MATCHER_P(CXXConstructorDecl, forEac
return Matched;
}
+/// \brief Matches constructor declarations that are copy constructors.
+///
+/// Given
+/// \code
+/// struct S {
+/// S(); // #1
+/// S(const S &); // #2
+/// S(S &&); // #3
+/// };
+/// \endcode
+/// constructorDecl(isCopyConstructor()) will match #2, but not #1 or #3.
+AST_MATCHER(CXXConstructorDecl, isCopyConstructor) {
+ return Node.isCopyConstructor();
+}
+
+/// \brief Matches constructor declarations that are move constructors.
+///
+/// Given
+/// \code
+/// struct S {
+/// S(); // #1
+/// S(const S &); // #2
+/// S(S &&); // #3
+/// };
+/// \endcode
+/// constructorDecl(isMoveConstructor()) will match #3, but not #1 or #2.
+AST_MATCHER(CXXConstructorDecl, isMoveConstructor) {
+ return Node.isMoveConstructor();
+}
+
+/// \brief Matches constructor declarations that are default constructors.
+///
+/// Given
+/// \code
+/// struct S {
+/// S(); // #1
+/// S(const S &); // #2
+/// S(S &&); // #3
+/// };
+/// \endcode
+/// constructorDecl(isDefaultConstructor()) will match #1, but not #2 or #3.
+AST_MATCHER(CXXConstructorDecl, isDefaultConstructor) {
+ return Node.isDefaultConstructor();
+}
+
/// \brief If the given case statement does not use the GNU case range
/// extension, matches the constant given in the statement.
///
Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp?rev=244036&r1=244035&r2=244036&view=diff
==============================================================================
--- cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp (original)
+++ cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp Wed Aug 5 07:11:30 2015
@@ -240,9 +240,12 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(innerType);
REGISTER_MATCHER(integerLiteral);
REGISTER_MATCHER(isArrow);
+ REGISTER_MATCHER(isBaseInitializer);
REGISTER_MATCHER(isCatchAll);
REGISTER_MATCHER(isConst);
REGISTER_MATCHER(isConstQualified);
+ REGISTER_MATCHER(isCopyConstructor);
+ REGISTER_MATCHER(isDefaultConstructor);
REGISTER_MATCHER(isDefinition);
REGISTER_MATCHER(isDeleted);
REGISTER_MATCHER(isExceptionVariable);
@@ -259,6 +262,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(isIntegral);
REGISTER_MATCHER(isInTemplateInstantiation);
REGISTER_MATCHER(isListInitialization);
+ REGISTER_MATCHER(isMoveConstructor);
REGISTER_MATCHER(isOverride);
REGISTER_MATCHER(isPrivate);
REGISTER_MATCHER(isProtected);
Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp?rev=244036&r1=244035&r2=244036&view=diff
==============================================================================
--- cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp Wed Aug 5 07:11:30 2015
@@ -1992,6 +1992,29 @@ TEST(ConstructorDeclaration, IsImplicit)
methodDecl(isImplicit(), hasName("operator="))));
}
+TEST(ConstructorDeclaration, Kinds) {
+ EXPECT_TRUE(matches("struct S { S(); };",
+ constructorDecl(isDefaultConstructor())));
+ EXPECT_TRUE(notMatches("struct S { S(); };",
+ constructorDecl(isCopyConstructor())));
+ EXPECT_TRUE(notMatches("struct S { S(); };",
+ constructorDecl(isMoveConstructor())));
+
+ EXPECT_TRUE(notMatches("struct S { S(const S&); };",
+ constructorDecl(isDefaultConstructor())));
+ EXPECT_TRUE(matches("struct S { S(const S&); };",
+ constructorDecl(isCopyConstructor())));
+ EXPECT_TRUE(notMatches("struct S { S(const S&); };",
+ constructorDecl(isMoveConstructor())));
+
+ EXPECT_TRUE(notMatches("struct S { S(S&&); };",
+ constructorDecl(isDefaultConstructor())));
+ EXPECT_TRUE(notMatches("struct S { S(S&&); };",
+ constructorDecl(isCopyConstructor())));
+ EXPECT_TRUE(matches("struct S { S(S&&); };",
+ constructorDecl(isMoveConstructor())));
+}
+
TEST(DestructorDeclaration, MatchesVirtualDestructor) {
EXPECT_TRUE(matches("class Foo { virtual ~Foo(); };",
destructorDecl(ofClass(hasName("Foo")))));
@@ -2058,6 +2081,24 @@ TEST(HasAnyConstructorInitializer, IsWri
allOf(forField(hasName("bar_")), unless(isWritten()))))));
}
+TEST(HasAnyConstructorInitializer, IsBaseInitializer) {
+ static const char Code[] =
+ "struct B {};"
+ "struct D : B {"
+ " int I;"
+ " D(int i) : I(i) {}"
+ "};"
+ "struct E : B {"
+ " E() : B() {}"
+ "};";
+ EXPECT_TRUE(matches(Code, constructorDecl(allOf(
+ hasAnyConstructorInitializer(allOf(isBaseInitializer(), isWritten())),
+ hasName("E")))));
+ EXPECT_TRUE(notMatches(Code, constructorDecl(allOf(
+ hasAnyConstructorInitializer(allOf(isBaseInitializer(), isWritten())),
+ hasName("D")))));
+}
+
TEST(Matcher, NewExpression) {
StatementMatcher New = newExpr();
More information about the cfe-commits
mailing list