AST Matchers: introduce functionTemplate(), classTemplate() and

isExplicitTemplateSpecialization() matchers which do what their name says.

llvm-svn: 162115
This commit is contained in:
Dmitri Gribenko 2012-08-17 18:42:47 +00:00
parent 34bc34ecae
commit d394c8a83e
3 changed files with 138 additions and 0 deletions

View File

@ -164,6 +164,14 @@ const internal::VariadicDynCastAllOfMatcher<
Decl,
CXXRecordDecl> record;
/// \brief Matches C++ class template declarations.
///
/// Example matches Z
/// template<class T> class Z {};
const internal::VariadicDynCastAllOfMatcher<
Decl,
ClassTemplateDecl> classTemplate;
/// \brief Matches C++ class template specializations.
///
/// Given
@ -385,6 +393,13 @@ const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> field;
/// void f();
const internal::VariadicDynCastAllOfMatcher<Decl, FunctionDecl> function;
/// \brief Matches C++ function template declarations.
///
/// Example matches f
/// template<class T> void f(T t) {}
const internal::VariadicDynCastAllOfMatcher<
Decl,
FunctionTemplateDecl> functionTemplate;
/// \brief Matches statements.
///
@ -1941,6 +1956,21 @@ isTemplateInstantiation() {
internal::IsTemplateInstantiationMatcher>();
}
/// \brief Matches explicit template specializations of function, class, or
/// static member variable template instantiations.
///
/// Given
/// template<typename T> void A(T t) { }
/// template<> void A(int N) { }
/// function(isExplicitSpecialization())
/// matches the specialization A<int>().
inline internal::PolymorphicMatcherWithParam0<
internal::IsExplicitTemplateSpecializationMatcher>
isExplicitTemplateSpecialization() {
return internal::PolymorphicMatcherWithParam0<
internal::IsExplicitTemplateSpecializationMatcher>();
}
} // end namespace ast_matchers
} // end namespace clang

View File

@ -858,6 +858,23 @@ class IsTemplateInstantiationMatcher : public MatcherInterface<T> {
}
};
/// \brief Matches on explicit template specializations for FunctionDecl,
/// VarDecl or CXXRecordDecl nodes.
template <typename T>
class IsExplicitTemplateSpecializationMatcher : public MatcherInterface<T> {
TOOLING_COMPILE_ASSERT((llvm::is_base_of<FunctionDecl, T>::value) ||
(llvm::is_base_of<VarDecl, T>::value) ||
(llvm::is_base_of<CXXRecordDecl, T>::value),
requires_getTemplateSpecializationKind_method);
public:
virtual bool matches(const T& Node,
ASTMatchFinder* Finder,
BoundNodesTreeBuilder* Builder) const {
return (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization);
}
};
class IsArrowMatcher : public SingleNodeMatcherInterface<MemberExpr> {
public:
virtual bool matchesNode(const MemberExpr &Node) const {

View File

@ -292,6 +292,32 @@ TEST(DeclarationMatcher, ClassIsDerived) {
record(isDerivedFrom(record(hasName("X")).bind("test")))));
}
TEST(ClassTemplate, DoesNotMatchClass) {
DeclarationMatcher ClassX = classTemplate(hasName("X"));
EXPECT_TRUE(notMatches("class X;", ClassX));
EXPECT_TRUE(notMatches("class X {};", ClassX));
}
TEST(ClassTemplate, MatchesClassTemplate) {
DeclarationMatcher ClassX = classTemplate(hasName("X"));
EXPECT_TRUE(matches("template<typename T> class X {};", ClassX));
EXPECT_TRUE(matches("class Z { template<class T> class X {}; };", ClassX));
}
TEST(ClassTemplate, DoesNotMatchClassTemplateExplicitSpecialization) {
EXPECT_TRUE(notMatches("template<typename T> class X { };"
"template<> class X<int> { int a; };",
classTemplate(hasName("X"),
hasDescendant(field(hasName("a"))))));
}
TEST(ClassTemplate, DoesNotMatchClassTemplatePartialSpecialization) {
EXPECT_TRUE(notMatches("template<typename T, typename U> class X { };"
"template<typename T> class X<T, int> { int a; };",
classTemplate(hasName("X"),
hasDescendant(field(hasName("a"))))));
}
TEST(AllOf, AllOverloadsWork) {
const char Program[] =
"struct T { }; int f(int, T*); void g(int x) { T t; f(x, &t); }";
@ -1017,6 +1043,27 @@ TEST(Function, MatchesFunctionDeclarations) {
CallFunctionF));
}
TEST(FunctionTemplate, MatchesFunctionTemplateDeclarations) {
EXPECT_TRUE(
matches("template <typename T> void f(T t) {}",
functionTemplate(hasName("f"))));
}
TEST(FunctionTemplate, DoesNotMatchFunctionDeclarations) {
EXPECT_TRUE(
notMatches("void f(double d); void f(int t) {}",
functionTemplate(hasName("f"))));
}
TEST(FunctionTemplate, DoesNotMatchFunctionTemplateSpecializations) {
EXPECT_TRUE(
notMatches("void g(); template <typename T> void f(T t) {}"
"template <> void f(int t) { g(); }",
functionTemplate(hasName("f"),
hasDescendant(declarationReference(
to(function(hasName("g"))))))));
}
TEST(Matcher, Argument) {
StatementMatcher CallArgumentY = expression(call(
hasArgument(0, declarationReference(to(variable(hasName("y")))))));
@ -2565,5 +2612,49 @@ TEST(IsTemplateInstantiation, DoesNotMatchNonTemplate) {
record(isTemplateInstantiation())));
}
TEST(IsExplicitTemplateSpecialization,
DoesNotMatchPrimaryTemplate) {
EXPECT_TRUE(notMatches(
"template <typename T> class X {};",
record(isExplicitTemplateSpecialization())));
EXPECT_TRUE(notMatches(
"template <typename T> void f(T t);",
function(isExplicitTemplateSpecialization())));
}
TEST(IsExplicitTemplateSpecialization,
DoesNotMatchExplicitTemplateInstantiations) {
EXPECT_TRUE(notMatches(
"template <typename T> class X {};"
"template class X<int>; extern template class X<long>;",
record(isExplicitTemplateSpecialization())));
EXPECT_TRUE(notMatches(
"template <typename T> void f(T t) {}"
"template void f(int t); extern template void f(long t);",
function(isExplicitTemplateSpecialization())));
}
TEST(IsExplicitTemplateSpecialization,
DoesNotMatchImplicitTemplateInstantiations) {
EXPECT_TRUE(notMatches(
"template <typename T> class X {}; X<int> x;",
record(isExplicitTemplateSpecialization())));
EXPECT_TRUE(notMatches(
"template <typename T> void f(T t); void g() { f(10); }",
function(isExplicitTemplateSpecialization())));
}
TEST(IsExplicitTemplateSpecialization,
MatchesExplicitTemplateSpecializations) {
EXPECT_TRUE(matches(
"template <typename T> class X {};"
"template<> class X<int> {};",
record(isExplicitTemplateSpecialization())));
EXPECT_TRUE(matches(
"template <typename T> void f(T t) {}"
"template<> void f(int t) {}",
function(isExplicitTemplateSpecialization())));
}
} // end namespace ast_matchers
} // end namespace clang