[cfe-commits] r162115 - in /cfe/trunk: include/clang/ASTMatchers/ASTMatchers.h include/clang/ASTMatchers/ASTMatchersInternal.h unittests/ASTMatchers/ASTMatchersTest.cpp
Dmitri Gribenko
gribozavr at gmail.com
Fri Aug 17 11:42:47 PDT 2012
Author: gribozavr
Date: Fri Aug 17 13:42:47 2012
New Revision: 162115
URL: http://llvm.org/viewvc/llvm-project?rev=162115&view=rev
Log:
AST Matchers: introduce functionTemplate(), classTemplate() and
isExplicitTemplateSpecialization() matchers which do what their name says.
Modified:
cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h
cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=162115&r1=162114&r2=162115&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Fri Aug 17 13:42:47 2012
@@ -164,6 +164,14 @@
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 @@
/// 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 @@
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
Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h?rev=162115&r1=162114&r2=162115&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h Fri Aug 17 13:42:47 2012
@@ -858,6 +858,23 @@
}
};
+/// \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 {
Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp?rev=162115&r1=162114&r2=162115&view=diff
==============================================================================
--- cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp Fri Aug 17 13:42:47 2012
@@ -292,6 +292,32 @@
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 @@
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 @@
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
More information about the cfe-commits
mailing list