[PATCH] Support in hasDeclaration for types with getDecl()

Edwin Vane edwin.vane at intel.com
Sun Feb 17 08:03:52 PST 2013


Hi klimek, gribozavr,

Using a new metafunction for detecting the presence of the member
'getDecl' in a type T, added support to hasDeclaration for any such type
T. This allows hasDecl() to be replaced and enables several other
subclasses of clang::Type to use hasDeclaration.

Updated unittests.

http://llvm-reviews.chandlerc.com/D417

Files:
  include/clang/ASTMatchers/ASTMatchers.h
  include/clang/ASTMatchers/ASTMatchersInternal.h
  unittests/ASTMatchers/ASTMatchersTest.cpp

Index: include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchers.h
+++ include/clang/ASTMatchers/ASTMatchers.h
@@ -52,6 +52,9 @@
 #include "llvm/Support/Regex.h"
 #include <iterator>
 
+#include "clang/Basic/LangOptions.h"
+#include "llvm/Support/raw_ostream.h"
+
 namespace clang {
 namespace ast_matchers {
 
@@ -1562,7 +1565,8 @@
 /// matcher.
 ///
 /// Usable as: Matcher<QualType>, Matcher<CallExpr>, Matcher<CXXConstructExpr>,
-///   Matcher<MemberExpr>
+///   Matcher<MemberExpr>, Matcher<T> where T has the getDecl() member (e.g.
+///   various subclasses of clang::Type).
 inline internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher,
                                      internal::Matcher<Decl> >
     hasDeclaration(const internal::Matcher<Decl> &InnerMatcher) {
@@ -2846,13 +2850,6 @@
 ///   matches "typedef int X"
 AST_TYPE_MATCHER(TypedefType, typedefType);
 
-/// \brief Matches \c TypedefTypes referring to a specific
-/// \c TypedefNameDecl.
-AST_MATCHER_P(TypedefType, hasDecl,
-              internal::Matcher<TypedefNameDecl>, InnerMatcher) {
-  return InnerMatcher.matches(*Node.getDecl(), Finder, Builder);
-}
-
 /// \brief Matches nested name specifiers.
 ///
 /// Given
@@ -2927,6 +2924,7 @@
                        internal::Matcher<NestedNameSpecifier>, InnerMatcher,
                        0) {
   NestedNameSpecifier *NextNode = Node.getPrefix();
+  LangOptions opts;
   if (NextNode == NULL)
     return false;
   return InnerMatcher.matches(*NextNode, Finder, Builder);
Index: include/clang/ASTMatchers/ASTMatchersInternal.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchersInternal.h
+++ include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -353,6 +353,18 @@
   return Matcher<T>(Implementation);
 }
 
+/// \brief Metafunction to determine if type T has a member called getDecl.
+template <typename T> struct has_getDecl {
+  typedef char yes[1];
+  typedef char no[2];
+
+  template <typename TestType>
+  static yes &test(char[sizeof(&TestType::getDecl)]);
+  template <typename> static no &test(...);
+
+  static bool const value = sizeof(test<T>(0)) == sizeof(yes);
+};
+
 /// \brief Matches declarations for QualType and CallExpr.
 ///
 /// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but
@@ -373,6 +385,15 @@
   }
 
 private:
+  /// \brief If getDecl exists as a member of U, returns whether the inner
+  /// matcher matches Node.getDecl().
+  template <typename U>
+  bool matchesSpecialized(
+      const U &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
+      typename llvm::enable_if<has_getDecl<U>, int>::type = 0) const {
+    return matchesDecl(Node.getDecl(), Finder, Builder);
+  }
+
   /// \brief Extracts the CXXRecordDecl or EnumDecl of a QualType and returns
   /// whether the inner matcher matches on it.
   bool matchesSpecialized(const QualType &Node, ASTMatchFinder *Finder,
Index: unittests/ASTMatchers/ASTMatchersTest.cpp
===================================================================
--- unittests/ASTMatchers/ASTMatchersTest.cpp
+++ unittests/ASTMatchers/ASTMatchersTest.cpp
@@ -816,6 +816,10 @@
   EXPECT_TRUE(matches("enum X {}; void y(X *x) { x; }",
                       expr(hasType(pointsTo(
                           qualType(hasDeclaration(enumDecl(hasName("X")))))))));
+
+  EXPECT_TRUE(matches("typedef int X; X a;",
+                      varDecl(hasName("a"),
+                              hasType(typedefType(hasDeclaration(decl()))))));
 }
 
 TEST(HasType, TakesQualTypeMatcherAndMatchesExpr) {
@@ -3350,10 +3354,6 @@
 TEST(TypeMatching, MatchesTypedefTypes) {
   EXPECT_TRUE(matches("typedef int X; X a;", varDecl(hasName("a"),
                                                      hasType(typedefType()))));
-
-  EXPECT_TRUE(matches("typedef int X; X a;",
-                      varDecl(hasName("a"),
-                              hasType(typedefType(hasDecl(decl()))))));
 }
 
 TEST(NNS, MatchesNestedNameSpecifiers) {
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D417.1.patch
Type: text/x-patch
Size: 4118 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130217/ac2c7a7e/attachment.bin>


More information about the cfe-commits mailing list