]> granicus.if.org Git - clang/commitdiff
[ASTMatcher] Add handling for DeducedType to HasDeclarationMatcher
authorFlorian Gross <fgross@noexcept.net>
Fri, 4 Aug 2017 18:59:19 +0000 (18:59 +0000)
committerFlorian Gross <fgross@noexcept.net>
Fri, 4 Aug 2017 18:59:19 +0000 (18:59 +0000)
HasDeclarationMatcher did not handle DeducedType, it always returned false for deduced types.

So with code like this:
struct X{};
auto x = X{};

This did no longer match:
varDecl(hasType(recordDecl(hasName("X"))))

Because HasDeclarationMatcher didn't resolve the DeducedType of x.

Differential Revision: https://reviews.llvm.org/D36308

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@310095 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/ASTMatchers/ASTMatchersInternal.h
unittests/ASTMatchers/ASTMatchersNodeTest.cpp

index 2a85ac6c99a37bd993000f3b8f1a50de3ec468ac..cd59bbcaeb494c0cfe43a8be20c4eaee7b5f4ecc 100644 (file)
@@ -741,24 +741,34 @@ private:
   /// matcher matches on it.
   bool matchesSpecialized(const Type &Node, ASTMatchFinder *Finder,
                           BoundNodesTreeBuilder *Builder) const {
+
+    // DeducedType does not have declarations of its own, so\r
+    // match the deduced type instead.
+    const Type *EffectiveType = &Node;
+    if (const auto *S = dyn_cast<DeducedType>(&Node)) {
+      EffectiveType = S->getDeducedType().getTypePtrOrNull();
+      if (!EffectiveType)
+        return false;
+    }
+
     // First, for any types that have a declaration, extract the declaration and
     // match on it.
-    if (const auto *S = dyn_cast<TagType>(&Node)) {
+    if (const auto *S = dyn_cast<TagType>(EffectiveType)) {
       return matchesDecl(S->getDecl(), Finder, Builder);
     }
-    if (const auto *S = dyn_cast<InjectedClassNameType>(&Node)) {
+    if (const auto *S = dyn_cast<InjectedClassNameType>(EffectiveType)) {
       return matchesDecl(S->getDecl(), Finder, Builder);
     }
-    if (const auto *S = dyn_cast<TemplateTypeParmType>(&Node)) {
+    if (const auto *S = dyn_cast<TemplateTypeParmType>(EffectiveType)) {
       return matchesDecl(S->getDecl(), Finder, Builder);
     }
-    if (const auto *S = dyn_cast<TypedefType>(&Node)) {
+    if (const auto *S = dyn_cast<TypedefType>(EffectiveType)) {
       return matchesDecl(S->getDecl(), Finder, Builder);
     }
-    if (const auto *S = dyn_cast<UnresolvedUsingType>(&Node)) {
+    if (const auto *S = dyn_cast<UnresolvedUsingType>(EffectiveType)) {
       return matchesDecl(S->getDecl(), Finder, Builder);
     }
-    if (const auto *S = dyn_cast<ObjCObjectType>(&Node)) {
+    if (const auto *S = dyn_cast<ObjCObjectType>(EffectiveType)) {
       return matchesDecl(S->getInterface(), Finder, Builder);
     }
 
@@ -770,14 +780,14 @@ private:
     //   template<typename T> struct X { T t; } class A {}; X<A> a;
     // The following matcher will match, which otherwise would not:
     //   fieldDecl(hasType(pointerType())).
-    if (const auto *S = dyn_cast<SubstTemplateTypeParmType>(&Node)) {
+    if (const auto *S = dyn_cast<SubstTemplateTypeParmType>(EffectiveType)) {
       return matchesSpecialized(S->getReplacementType(), Finder, Builder);
     }
 
     // For template specialization types, we want to match the template
     // declaration, as long as the type is still dependent, and otherwise the
     // declaration of the instantiated tag type.
-    if (const auto *S = dyn_cast<TemplateSpecializationType>(&Node)) {
+    if (const auto *S = dyn_cast<TemplateSpecializationType>(EffectiveType)) {
       if (!S->isTypeAlias() && S->isSugared()) {
         // If the template is non-dependent, we want to match the instantiated
         // tag type.
@@ -796,7 +806,7 @@ private:
     // FIXME: We desugar elaborated types. This makes the assumption that users
     // do never want to match on whether a type is elaborated - there are
     // arguments for both sides; for now, continue desugaring.
-    if (const auto *S = dyn_cast<ElaboratedType>(&Node)) {
+    if (const auto *S = dyn_cast<ElaboratedType>(EffectiveType)) {
       return matchesSpecialized(S->desugar(), Finder, Builder);
     }
     return false;
index 58c26eafd7e0d1225c3ef815e262eb73a037b4f9..712c3854c483f386852f4894c4f08b62a9bb9e1c 100644 (file)
@@ -1184,6 +1184,10 @@ TEST(TypeMatching, MatchesAutoTypes) {
   EXPECT_TRUE(matches("int v[] = { 2, 3 }; void f() { for (int i : v) {} }",
                       autoType()));
 
+  EXPECT_TRUE(matches("auto i = 2;", varDecl(hasType(isInteger()))));
+  EXPECT_TRUE(matches("struct X{}; auto x = X{};",
+                      varDecl(hasType(recordDecl(hasName("X"))))));
+
   // FIXME: Matching against the type-as-written can't work here, because the
   //        type as written was not deduced.
   //EXPECT_TRUE(matches("auto a = 1;",