[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