forked from OSchip/llvm-project
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.
llvm-svn: 244036
This commit is contained in:
parent
3c9cb4b3d3
commit
1ca258e6a8
|
@ -1460,6 +1460,58 @@ Example matches f(0, 0) (matcher = callExpr(argumentCountIs(2)))
|
|||
</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).
|
||||
|
|
|
@ -2632,6 +2632,26 @@ AST_MATCHER(CXXCtorInitializer, isWritten) {
|
|||
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, forEachConstructorInitializer,
|
|||
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.
|
||||
///
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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, IsWritten) {
|
|||
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();
|
||||
|
||||
|
|
Loading…
Reference in New Issue