aaron.ballman created this revision.
aaron.ballman added a reviewer: klimek.
aaron.ballman added a subscriber: cfe-commits.
Herald added a subscriber: klimek.

The AST matching code that traverses from types to decls misses a lot of 
possible conversions. This patch adds all of the conversions I could find. 
However, not all of the type->decl conversions can be used from the AST 
matchers yet. For instance, we do not have matcher support for 
ObjCInterfaceDecl. I've added a test case for the one conversion we currently 
support. I feel it's reasonable to have reduced test coverage for the other 
types at this point compared to the difficulty of tracking down why simple 
matchers were failing.

This now allows us to write a matcher like:

varDecl(hasType(namedDecl(hasName("Foo"))))

that matches code like:

typedef int Foo;
Foo f; // matches f

Previously, the hasType(namedDecl()) matcher would only properly match if the 
type queried was a TagType. Now it can support any type which is traversable to 
a decl.

http://reviews.llvm.org/D12736

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

Index: unittests/ASTMatchers/ASTMatchersTest.cpp
===================================================================
--- unittests/ASTMatchers/ASTMatchersTest.cpp
+++ unittests/ASTMatchers/ASTMatchersTest.cpp
@@ -924,6 +924,15 @@
                        varDecl(hasType(namedDecl(hasName("S"))))));
 }
 
+TEST(TypeMatcher, MatchesDeclTypes) {
+  EXPECT_TRUE(matches("typedef int I; void f(I i);",
+                      parmVarDecl(hasType(namedDecl(hasName("I"))))));
+
+  // FIXME: when we support ObjCInterfaceDecl, and TemplateTypeParmDecl, add
+  // testing code here. Explore whether we should add testing code for
+  // UnresolvedUsingType and InjectedClassNameType.
+}
+
 TEST(Matcher, BindMatchedNodes) {
   DeclarationMatcher ClassX = has(recordDecl(hasName("::X")).bind("x"));
 
Index: include/clang/ASTMatchers/ASTMatchersInternal.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchersInternal.h
+++ include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -672,10 +672,22 @@
   /// matcher matches on it.
   bool matchesSpecialized(const QualType &Node, ASTMatchFinder *Finder,
                           BoundNodesTreeBuilder *Builder) const {
-    /// FIXME: Add other ways to convert...
     if (Node.isNull())
       return false;
-    return matchesDecl(Node->getAsTagDecl(), Finder, Builder);
+
+    if (auto *TD = Node->getAsTagDecl())
+      return matchesDecl(TD, Finder, Builder);
+    else if (auto *TT = Node->getAs<TypedefType>())
+      return matchesDecl(TT->getDecl(), Finder, Builder);
+    else if (auto *TTP = Node->getAs<TemplateTypeParmType>())
+      return matchesDecl(TTP->getDecl(), Finder, Builder);
+    else if (auto *OCIT = Node->getAs<ObjCInterfaceType>())
+      return matchesDecl(OCIT->getDecl(), Finder, Builder);
+    else if (auto *UUT = Node->getAs<UnresolvedUsingType>())
+      return matchesDecl(UUT->getDecl(), Finder, Builder);
+    else if (auto *ICNT = Node->getAs<InjectedClassNameType>())
+      return matchesDecl(ICNT->getDecl(), Finder, Builder);
+    return false;
   }
 
   /// \brief Gets the TemplateDecl from a TemplateSpecializationType


Index: unittests/ASTMatchers/ASTMatchersTest.cpp
===================================================================
--- unittests/ASTMatchers/ASTMatchersTest.cpp
+++ unittests/ASTMatchers/ASTMatchersTest.cpp
@@ -924,6 +924,15 @@
                        varDecl(hasType(namedDecl(hasName("S"))))));
 }
 
+TEST(TypeMatcher, MatchesDeclTypes) {
+  EXPECT_TRUE(matches("typedef int I; void f(I i);",
+                      parmVarDecl(hasType(namedDecl(hasName("I"))))));
+
+  // FIXME: when we support ObjCInterfaceDecl, and TemplateTypeParmDecl, add
+  // testing code here. Explore whether we should add testing code for
+  // UnresolvedUsingType and InjectedClassNameType.
+}
+
 TEST(Matcher, BindMatchedNodes) {
   DeclarationMatcher ClassX = has(recordDecl(hasName("::X")).bind("x"));
 
Index: include/clang/ASTMatchers/ASTMatchersInternal.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchersInternal.h
+++ include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -672,10 +672,22 @@
   /// matcher matches on it.
   bool matchesSpecialized(const QualType &Node, ASTMatchFinder *Finder,
                           BoundNodesTreeBuilder *Builder) const {
-    /// FIXME: Add other ways to convert...
     if (Node.isNull())
       return false;
-    return matchesDecl(Node->getAsTagDecl(), Finder, Builder);
+
+    if (auto *TD = Node->getAsTagDecl())
+      return matchesDecl(TD, Finder, Builder);
+    else if (auto *TT = Node->getAs<TypedefType>())
+      return matchesDecl(TT->getDecl(), Finder, Builder);
+    else if (auto *TTP = Node->getAs<TemplateTypeParmType>())
+      return matchesDecl(TTP->getDecl(), Finder, Builder);
+    else if (auto *OCIT = Node->getAs<ObjCInterfaceType>())
+      return matchesDecl(OCIT->getDecl(), Finder, Builder);
+    else if (auto *UUT = Node->getAs<UnresolvedUsingType>())
+      return matchesDecl(UUT->getDecl(), Finder, Builder);
+    else if (auto *ICNT = Node->getAs<InjectedClassNameType>())
+      return matchesDecl(ICNT->getDecl(), Finder, Builder);
+    return false;
   }
 
   /// \brief Gets the TemplateDecl from a TemplateSpecializationType
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to