lukasza updated the summary for this revision.
lukasza updated this revision to Diff 72350.
lukasza marked an inline comment as done.
lukasza added a comment.

- Added test where both TemplateSpecializationType and TypedefType are present 
and both should match regardless of code order inside 
HasDeclarationMatcher::matchesSpecialized(const QualType &Node...).  Removed 
significance of order inside this matchesSpecialized method.

- Tweaked test proposed in the previous patchset, so that it matches specific 
decls (rather than any decls)

- Added support for matching hasDeclaration(elaboratedType(...)) + test (in the 
test from the previous patchset).


https://reviews.llvm.org/D24361

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

Index: unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===================================================================
--- unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -2106,5 +2106,56 @@
                                        functionDecl(hasName("bar"))))));
 }
 
+TEST(HasDeclaration, ElaboratedTypeAndTemplateSpecializationType) {
+  std::string input =
+      "namespace Namespace {\n"
+      "template<typename T>\n"
+      "class Template {\n"
+      " public:\n"
+      "  void Method() {}\n"
+      "};\n"
+      "}  // namespace Namespace\n"
+      "template <typename U>\n"
+      "void Function(Namespace::Template<U> param) {\n"
+      "  param.Method();\n"
+      "};\n";
+
+  // Matcher for ::Namespace::Template<T> template decl.
+  auto param_type_decl_matcher = classTemplateDecl(
+      hasName("Template"),
+      hasParent(namespaceDecl(hasName("Namespace"))),
+      has(templateTypeParmDecl(hasName("T"))));
+
+  // hasDeclaration / qualType-flavour.
+  EXPECT_TRUE(matches(input, parmVarDecl(
+      hasName("param"),
+      hasType(qualType(hasDeclaration(decl(param_type_decl_matcher)))))));
+
+  // hasDeclaration / elaboratedType-flavour.
+  EXPECT_TRUE(matches(input, parmVarDecl(
+      hasName("param"),
+      hasType(elaboratedType(hasDeclaration(decl(param_type_decl_matcher)))))));
+}
+
+TEST(HasDeclaration, TypedefTypeAndTemplateSpecializationTypeAreBothHere) {
+  std::string input =
+      "template<typename T>\n"
+      "class Foo {};\n"
+      "using Bar = Foo<int>;\n"
+      "Bar variable;\n";
+
+  // hasDeclaration should match typedefNameDecl.
+  EXPECT_TRUE(matches(input, varDecl(
+      hasName("variable"),
+      hasType(qualType(hasDeclaration(decl(
+          typeAliasDecl(hasName("Bar")))))))));
+
+  // hasDeclaration should match templateSpecializationType
+  EXPECT_TRUE(matches(input, varDecl(
+      hasName("variable"),
+      hasType(qualType(hasDeclaration(decl(
+          classTemplateSpecializationDecl())))))));
+}
+
 } // namespace ast_matchers
 } // namespace clang
Index: include/clang/ASTMatchers/ASTMatchersInternal.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchersInternal.h
+++ include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -744,16 +744,29 @@
     if (Node.isNull())
       return false;
 
-    if (auto *TD = Node->getAsTagDecl())
-      return matchesDecl(TD, Finder, Builder);
-    else if (auto *TT = Node->getAs<TypedefType>())
-      return matchesDecl(TT->getDecl(), Finder, Builder);
     // Do not use getAs<TemplateTypeParmType> instead of the direct dyn_cast.
     // Calling getAs will return the canonical type, but that type does not
     // store a TemplateTypeParmDecl. We *need* the uncanonical type, if it is
     // available, and using dyn_cast ensures that.
-    else if (auto *TTP = dyn_cast<TemplateTypeParmType>(Node.getTypePtr()))
+    if (auto *TTP = dyn_cast<TemplateTypeParmType>(Node.getTypePtr()))
       return matchesDecl(TTP->getDecl(), Finder, Builder);
+
+    // Try if any of desugaring results match
+    // (these are not mutually exclusive).
+    if (auto *TST = Node->getAs<TemplateSpecializationType>()) {
+      if (matchesSpecialized(*TST, Finder, Builder))
+        return true;
+    }
+    if (auto *TT = Node->getAs<TypedefType>()) {
+      if (matchesDecl(TT->getDecl(), Finder, Builder))
+        return true;
+    }
+
+    // Try non-desugarable types.
+    if (auto *TD = Node->getAsTagDecl())
+      return matchesDecl(TD, Finder, Builder);
+    else if (auto *ET = Node->getAs<ElaboratedType>())
+      return matchesSpecialized(*ET, Finder, Builder);
     else if (auto *OCIT = Node->getAs<ObjCInterfaceType>())
       return matchesDecl(OCIT->getDecl(), Finder, Builder);
     else if (auto *UUT = Node->getAs<UnresolvedUsingType>())
@@ -760,9 +773,18 @@
       return matchesDecl(UUT->getDecl(), Finder, Builder);
     else if (auto *ICNT = Node->getAs<InjectedClassNameType>())
       return matchesDecl(ICNT->getDecl(), Finder, Builder);
+
     return false;
   }
 
+  /// \brief Gets the QualType from ElaboratedType
+  /// and returns whether the inner matches on it.
+  bool matchesSpecialized(const ElaboratedType &Node,
+                          ASTMatchFinder *Finder,
+                          BoundNodesTreeBuilder *Builder) const {
+    return matchesSpecialized(Node.getNamedType(), Finder, Builder);
+  }
+
   /// \brief Gets the TemplateDecl from a TemplateSpecializationType
   /// and returns whether the inner matches on it.
   bool matchesSpecialized(const TemplateSpecializationType &Node,
@@ -1007,10 +1029,10 @@
                  TypeLoc, QualType> AdaptativeDefaultToTypes;
 
 /// \brief All types that are supported by HasDeclarationMatcher above.
-typedef TypeList<CallExpr, CXXConstructExpr, DeclRefExpr, EnumType,
-                 InjectedClassNameType, LabelStmt, AddrLabelExpr, MemberExpr,
-                 QualType, RecordType, TagType, TemplateSpecializationType,
-                 TemplateTypeParmType, TypedefType,
+typedef TypeList<CallExpr, CXXConstructExpr, DeclRefExpr, ElaboratedType,
+                 EnumType, InjectedClassNameType, LabelStmt, AddrLabelExpr,
+                 MemberExpr, QualType, RecordType, TagType,
+                 TemplateSpecializationType, TemplateTypeParmType, TypedefType,
                  UnresolvedUsingType> HasDeclarationSupportedTypes;
 
 /// \brief Converts a \c Matcher<T> to a matcher of desired type \c To by
Index: include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchers.h
+++ include/clang/ASTMatchers/ASTMatchers.h
@@ -2454,7 +2454,8 @@
 /// function. e.g. various subtypes of clang::Type and various expressions.
 ///
 /// Usable as: Matcher<CallExpr>, Matcher<CXXConstructExpr>,
-///   Matcher<DeclRefExpr>, Matcher<EnumType>, Matcher<InjectedClassNameType>,
+///   Matcher<DeclRefExpr>, Matcher<ElaboratedType>, Matcher<EnumType>,
+///   Matcher<InjectedClassNameType>,
 ///   Matcher<LabelStmt>, Matcher<AddrLabelExpr>, Matcher<MemberExpr>,
 ///   Matcher<QualType>, Matcher<RecordType>, Matcher<TagType>,
 ///   Matcher<TemplateSpecializationType>, Matcher<TemplateTypeParmType>,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to