From 4feac28e0e4bbbcd7d503171b3867cb33fc4cca7 Mon Sep 17 00:00:00 2001 From: Manuel Klimek Date: Wed, 6 Feb 2013 20:36:22 +0000 Subject: [PATCH] Cleanup of ASTMatcher macros and adding support for overloaded matchers. This is in preparation for adding other overloaded matchers. This change alone is a net win in LOC. I went through all matchers and looked whether we could now encode them as macro, or simplify them with the matcher atoms that were not available before. llvm-svn: 174540 --- clang/docs/LibASTMatchersReference.html | 36 +++--- clang/docs/tools/dump_ast_matchers.py | 3 +- clang/include/clang/ASTMatchers/ASTMatchers.h | 84 ++++++++------ .../clang/ASTMatchers/ASTMatchersInternal.h | 107 ----------------- .../include/clang/ASTMatchers/ASTMatchersMacros.h | 128 +++++++++++++++------ 5 files changed, 164 insertions(+), 194 deletions(-) diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index 672c12d..3027083 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -361,6 +361,14 @@ Example matches 'a', L'a' +Matcher<Stmt>compoundLiteralExprMatcher<CompoundLiteralExpr>... +
Matches compound (i.e. non-scalar) literals
+
+Example match: {1}, (1, 2)
+  int array[4] = {1}; vector int myvec = (vector int)(1, 2);
+
+ + Matcher<Stmt>compoundStmtMatcher<CompoundStmt>...
Matches compound statements.
 
@@ -1291,8 +1299,8 @@ Example matches a << b
 
-Matcher<CXXRecordDecl>isExplicitTemplateSpecialization -
Matches explicit template specializations of function, class, or
+Matcher<CXXRecordDecl>isExplicitTemplateSpecialization
+
Matches explicit template specializations of function, class, or
 static member variable template instantiations.
 
 Given
@@ -1311,8 +1319,8 @@ isSameOrDerivedFrom(hasName(...)).
 
-Matcher<CXXRecordDecl>isTemplateInstantiation -
Matches template instantiations of function, class, or static
+Matcher<CXXRecordDecl>isTemplateInstantiation
+
Matches template instantiations of function, class, or static
 member variable template instantiations.
 
 Given
@@ -1401,8 +1409,8 @@ Usable as: Matcher<FunctionDecl>isDefinition
-
Matches if a declaration has a body attached.
+Matcher<FunctionDecl>isDefinition
+
Matches if a declaration has a body attached.
 
 Example matches A, va, fa
   class A {};
@@ -1416,8 +1424,8 @@ Usable as: Matcher<FunctionDecl>isExplicitTemplateSpecialization
-
Matches explicit template specializations of function, class, or
+Matcher<FunctionDecl>isExplicitTemplateSpecialization
+
Matches explicit template specializations of function, class, or
 static member variable template instantiations.
 
 Given
@@ -1442,8 +1450,8 @@ functionDecl(isExternC())
 
-Matcher<FunctionDecl>isTemplateInstantiation -
Matches template instantiations of function, class, or static
+Matcher<FunctionDecl>isTemplateInstantiation
+
Matches template instantiations of function, class, or static
 member variable template instantiations.
 
 Given
@@ -1573,8 +1581,8 @@ matches "a(int)", "b(long)", but not "c(double)".
 
-Matcher<TagDecl>isDefinition -
Matches if a declaration has a body attached.
+Matcher<TagDecl>isDefinition
+
Matches if a declaration has a body attached.
 
 Example matches A, va, fa
   class A {};
@@ -2569,7 +2577,7 @@ Usable as: Matcher<NestedNameSpecifierLoc>hasPrefixMatcher<NestedNameSpecifierLoc>  InnerMatcher
+Matcher<NestedNameSpecifierLoc>hasPrefixMatcher<NestedNameSpecifierLoc> InnerMatcher
 
Matches on the prefix of a NestedNameSpecifierLoc.
 
 Given
@@ -2599,7 +2607,7 @@ nestedNameSpecifierLoc(specifiesTypeLoc(loc(type(
 
-Matcher<NestedNameSpecifier>hasPrefixMatcher<NestedNameSpecifier> InnerMatcher +Matcher<NestedNameSpecifier>hasPrefixMatcher<NestedNameSpecifier> InnerMatcher
Matches on the prefix of a NestedNameSpecifier.
 
 Given
diff --git a/clang/docs/tools/dump_ast_matchers.py b/clang/docs/tools/dump_ast_matchers.py
index cd7ab0b..4ed6822 100644
--- a/clang/docs/tools/dump_ast_matchers.py
+++ b/clang/docs/tools/dump_ast_matchers.py
@@ -175,13 +175,14 @@ def act_on_decl(declaration, comment, allowed_types):
                       comment)
       return
 
-    m = re.match(r"""^\s*AST_(POLYMORPHIC_)?MATCHER(_P)?(.?)\(
+    m = re.match(r"""^\s*AST_(POLYMORPHIC_)?MATCHER(_P)?(.?)(?:_OVERLOAD)?\(
                        (?:\s*([^\s,]+)\s*,)?
                           \s*([^\s,]+)\s*
                        (?:,\s*([^\s,]+)\s*
                           ,\s*([^\s,]+)\s*)?
                        (?:,\s*([^\s,]+)\s*
                           ,\s*([^\s,]+)\s*)?
+                       (?:,\s*\d+\s*)?
                       \)\s*{\s*$""", declaration, flags=re.X)
     if m:
       p, n, result, name = m.groups()[1:5]
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index 61a0ab2..15c9565 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -1234,7 +1234,7 @@ AST_MATCHER_P(UnaryExprOrTypeTraitExpr, ofKind, UnaryExprOrTypeTrait, Kind) {
 /// alignof.
 inline internal::Matcher alignOfExpr(
     const internal::Matcher &InnerMatcher) {
-  return internal::Matcher(unaryExprOrTypeTraitExpr(allOf(
+  return stmt(unaryExprOrTypeTraitExpr(allOf(
       ofKind(UETT_AlignOf), InnerMatcher)));
 }
 
@@ -1242,8 +1242,8 @@ inline internal::Matcher alignOfExpr(
 /// sizeof.
 inline internal::Matcher sizeOfExpr(
     const internal::Matcher &InnerMatcher) {
-  return internal::Matcher(unaryExprOrTypeTraitExpr(allOf(
-      ofKind(UETT_SizeOf), InnerMatcher)));
+  return stmt(unaryExprOrTypeTraitExpr(
+      allOf(ofKind(UETT_SizeOf), InnerMatcher)));
 }
 
 /// \brief Matches NamedDecl nodes that have the specified name.
@@ -1599,7 +1599,7 @@ AST_MATCHER_P(CallExpr, callee, internal::Matcher,
 /// \endcode
 inline internal::Matcher callee(
     const internal::Matcher &InnerMatcher) {
-  return internal::Matcher(hasDeclaration(InnerMatcher));
+  return callExpr(hasDeclaration(InnerMatcher));
 }
 
 /// \brief Matches if the expression's or declaration's type matches a type
@@ -1637,11 +1637,10 @@ AST_POLYMORPHIC_MATCHER_P(hasType, internal::Matcher,
 ///
 /// Usable as: Matcher, Matcher
 inline internal::PolymorphicMatcherWithParam1<
-  internal::matcher_hasTypeMatcher,
+  internal::matcher_hasType0Matcher,
   internal::Matcher >
 hasType(const internal::Matcher &InnerMatcher) {
-  return hasType(internal::Matcher(
-    hasDeclaration(InnerMatcher)));
+  return hasType(qualType(hasDeclaration(InnerMatcher)));
 }
 
 /// \brief Matches if the matched type is represented by the given string.
@@ -1676,8 +1675,7 @@ AST_MATCHER_P(
 /// \brief Overloaded to match the pointee type's declaration.
 inline internal::Matcher pointsTo(
     const internal::Matcher &InnerMatcher) {
-  return pointsTo(internal::Matcher(
-    hasDeclaration(InnerMatcher)));
+  return pointsTo(qualType(hasDeclaration(InnerMatcher)));
 }
 
 /// \brief Matches if the matched type is a reference type and the referenced
@@ -1701,8 +1699,7 @@ AST_MATCHER_P(QualType, references, internal::Matcher,
 /// \brief Overloaded to match the referenced type's declaration.
 inline internal::Matcher references(
     const internal::Matcher &InnerMatcher) {
-  return references(internal::Matcher(
-    hasDeclaration(InnerMatcher)));
+  return references(qualType(hasDeclaration(InnerMatcher)));
 }
 
 AST_MATCHER_P(CXXMemberCallExpr, onImplicitObjectArgument,
@@ -2348,10 +2345,13 @@ AST_MATCHER_P(ConditionalOperator, hasFalseExpression,
 /// \endcode
 ///
 /// Usable as: Matcher, Matcher, Matcher
-inline internal::PolymorphicMatcherWithParam0
-isDefinition() {
-  return internal::PolymorphicMatcherWithParam0<
-    internal::IsDefinitionMatcher>();
+AST_POLYMORPHIC_MATCHER(isDefinition) {
+  TOOLING_COMPILE_ASSERT(
+      (llvm::is_base_of::value) ||
+      (llvm::is_base_of::value) ||
+      (llvm::is_base_of::value),
+      is_definition_requires_isThisDeclarationADefinition_method);
+  return Node.isThisDeclarationADefinition();
 }
 
 /// \brief Matches the class declaration that the given method declaration
@@ -2393,8 +2393,8 @@ AST_MATCHER_P(CXXMethodDecl, ofClass,
 /// \endcode
 /// memberExpr(isArrow())
 ///   matches this->x, x, y.x, a, this->b
-inline internal::Matcher isArrow() {
-  return makeMatcher(new internal::IsArrowMatcher());
+AST_MATCHER(MemberExpr, isArrow) {
+  return Node.isArrow();
 }
 
 /// \brief Matches QualType nodes that are of integer type.
@@ -2426,8 +2426,8 @@ AST_MATCHER(QualType, isInteger) {
 ///   matches "void b(int const)", "void c(const int)" and
 ///   "void e(int const) {}". It does not match d as there
 ///   is no top-level const on the parameter type "const int *".
-inline internal::Matcher isConstQualified() {
-  return makeMatcher(new internal::IsConstQualifiedMatcher());
+AST_MATCHER(QualType, isConstQualified) {
+  return Node.isConstQualified();
 }
 
 /// \brief Matches a member expression where the member is matched by a
@@ -2523,11 +2523,14 @@ AST_MATCHER_P(UsingShadowDecl, hasTargetDecl,
 ///   does not match, as X is an explicit template specialization.
 ///
 /// Usable as: Matcher, Matcher, Matcher
-inline internal::PolymorphicMatcherWithParam0<
-  internal::IsTemplateInstantiationMatcher>
-isTemplateInstantiation() {
-  return internal::PolymorphicMatcherWithParam0<
-    internal::IsTemplateInstantiationMatcher>();
+AST_POLYMORPHIC_MATCHER(isTemplateInstantiation) {
+  TOOLING_COMPILE_ASSERT((llvm::is_base_of::value) ||
+                         (llvm::is_base_of::value) ||
+                         (llvm::is_base_of::value),
+                         requires_getTemplateSpecializationKind_method);
+  return (Node.getTemplateSpecializationKind() == TSK_ImplicitInstantiation ||
+          Node.getTemplateSpecializationKind() ==
+          TSK_ExplicitInstantiationDefinition);
 }
 
 /// \brief Matches explicit template specializations of function, class, or
@@ -2542,11 +2545,12 @@ isTemplateInstantiation() {
 ///   matches the specialization A().
 ///
 /// Usable as: Matcher, Matcher, Matcher
-inline internal::PolymorphicMatcherWithParam0<
-  internal::IsExplicitTemplateSpecializationMatcher>
-isExplicitTemplateSpecialization() {
-  return internal::PolymorphicMatcherWithParam0<
-    internal::IsExplicitTemplateSpecializationMatcher>();
+AST_POLYMORPHIC_MATCHER(isExplicitTemplateSpecialization) {
+  TOOLING_COMPILE_ASSERT((llvm::is_base_of::value) ||
+                         (llvm::is_base_of::value) ||
+                         (llvm::is_base_of::value),
+                         requires_getTemplateSpecializationKind_method);
+  return (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization);
 }
 
 /// \brief Matches \c TypeLocs for which the given inner
@@ -2897,10 +2901,13 @@ AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc,
 /// \endcode
 /// nestedNameSpecifier(hasPrefix(specifiesType(asString("struct A")))) and
 ///   matches "A::"
-inline internal::Matcher hasPrefix(
-    const internal::Matcher &InnerMatcher) {
-  return internal::makeMatcher(
-    new internal::NestedNameSpecifierPrefixMatcher(InnerMatcher));
+AST_MATCHER_P_OVERLOAD(NestedNameSpecifier, hasPrefix,
+                       internal::Matcher, InnerMatcher,
+                       0) {
+  NestedNameSpecifier *NextNode = Node.getPrefix();
+  if (NextNode == NULL)
+    return false;
+  return InnerMatcher.matches(*NextNode, Finder, Builder);
 }
 
 /// \brief Matches on the prefix of a \c NestedNameSpecifierLoc.
@@ -2912,10 +2919,13 @@ inline internal::Matcher hasPrefix(
 /// \endcode
 /// nestedNameSpecifierLoc(hasPrefix(loc(specifiesType(asString("struct A")))))
 ///   matches "A::"
-inline internal::Matcher hasPrefix(
-    const internal::Matcher &InnerMatcher) {
-  return internal::makeMatcher(
-    new internal::NestedNameSpecifierLocPrefixMatcher(InnerMatcher));
+AST_MATCHER_P_OVERLOAD(NestedNameSpecifierLoc, hasPrefix,
+                       internal::Matcher, InnerMatcher,
+                       1) {
+  NestedNameSpecifierLoc NextNode = Node.getPrefix();
+  if (!NextNode)
+    return false;
+  return InnerMatcher.matches(NextNode, Finder, Builder);
 }
 
 /// \brief Matches nested name specifiers that specify a namespace matching the
diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
index a6661f5..b41a74c 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -1028,69 +1028,6 @@ private:
   const ValueT ExpectedValue;
 };
 
-template 
-class IsDefinitionMatcher : public SingleNodeMatcherInterface {
-  TOOLING_COMPILE_ASSERT(
-    (llvm::is_base_of::value) ||
-    (llvm::is_base_of::value) ||
-    (llvm::is_base_of::value),
-    is_definition_requires_isThisDeclarationADefinition_method);
-public:
-  virtual bool matchesNode(const T &Node) const {
-    return Node.isThisDeclarationADefinition();
-  }
-};
-
-/// \brief Matches on template instantiations for FunctionDecl, VarDecl or
-/// CXXRecordDecl nodes.
-template 
-class IsTemplateInstantiationMatcher : public MatcherInterface {
-  TOOLING_COMPILE_ASSERT((llvm::is_base_of::value) ||
-                         (llvm::is_base_of::value) ||
-                         (llvm::is_base_of::value),
-                         requires_getTemplateSpecializationKind_method);
- public:
-  virtual bool matches(const T& Node,
-                       ASTMatchFinder* Finder,
-                       BoundNodesTreeBuilder* Builder) const {
-    return (Node.getTemplateSpecializationKind() ==
-                TSK_ImplicitInstantiation ||
-            Node.getTemplateSpecializationKind() ==
-                TSK_ExplicitInstantiationDefinition);
-  }
-};
-
-/// \brief Matches on explicit template specializations for FunctionDecl,
-/// VarDecl or CXXRecordDecl nodes.
-template 
-class IsExplicitTemplateSpecializationMatcher : public MatcherInterface {
-  TOOLING_COMPILE_ASSERT((llvm::is_base_of::value) ||
-                         (llvm::is_base_of::value) ||
-                         (llvm::is_base_of::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 {
-public:
-  virtual bool matchesNode(const MemberExpr &Node) const {
-    return Node.isArrow();
-  }
-};
-
-class IsConstQualifiedMatcher
-    : public SingleNodeMatcherInterface {
- public:
-  virtual bool matchesNode(const QualType& Node) const {
-    return Node.isConstQualified();
-  }
-};
-
 /// \brief A VariadicDynCastAllOfMatcher object is a
 /// variadic functor that takes a number of Matcher and returns a
 /// Matcher that matches TargetT nodes that are matched by all of the
@@ -1154,50 +1091,6 @@ private:
   const Matcher InnerMatcher;
 };
 
-/// \brief Matches \c NestedNameSpecifiers with a prefix matching another
-/// \c Matcher.
-class NestedNameSpecifierPrefixMatcher
-  : public MatcherInterface {
-public:
-  explicit NestedNameSpecifierPrefixMatcher(
-    const Matcher &InnerMatcher)
-    : InnerMatcher(InnerMatcher) {}
-
-  virtual bool matches(const NestedNameSpecifier &Node,
-                       ASTMatchFinder *Finder,
-                       BoundNodesTreeBuilder *Builder) const {
-    NestedNameSpecifier *NextNode = Node.getPrefix();
-    if (NextNode == NULL)
-      return false;
-    return InnerMatcher.matches(*NextNode, Finder, Builder);
-  }
-
-private:
-  const Matcher InnerMatcher;
-};
-
-/// \brief Matches \c NestedNameSpecifierLocs with a prefix matching another
-/// \c Matcher.
-class NestedNameSpecifierLocPrefixMatcher
-  : public MatcherInterface {
-public:
-  explicit NestedNameSpecifierLocPrefixMatcher(
-    const Matcher &InnerMatcher)
-    : InnerMatcher(InnerMatcher) {}
-
-  virtual bool matches(const NestedNameSpecifierLoc &Node,
-                       ASTMatchFinder *Finder,
-                       BoundNodesTreeBuilder *Builder) const {
-    NestedNameSpecifierLoc NextNode = Node.getPrefix();
-    if (!NextNode)
-      return false;
-    return InnerMatcher.matches(NextNode, Finder, Builder);
-  }
-
-private:
-  const Matcher InnerMatcher;
-};
-
 /// \brief Matches \c TypeLocs based on an inner matcher matching a certain
 /// \c QualType.
 ///
diff --git a/clang/include/clang/ASTMatchers/ASTMatchersMacros.h b/clang/include/clang/ASTMatchers/ASTMatchersMacros.h
index 0a470d0..b2629c6 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchersMacros.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchersMacros.h
@@ -49,20 +49,23 @@
 ///
 /// The code should return true if 'Node' matches.
 #define AST_MATCHER(Type, DefineMatcher)                                       \
+  AST_MATCHER_OVERLOAD(Type, DefineMatcher, 0)
+
+#define AST_MATCHER_OVERLOAD(Type, DefineMatcher, OverloadId)                  \
   namespace internal {                                                         \
-  class matcher_##DefineMatcher##Matcher : public MatcherInterface {     \
+  class matcher_##DefineMatcher##OverloadId##Matcher                           \
+      : public MatcherInterface {                                        \
   public:                                                                      \
-    explicit matcher_##DefineMatcher##Matcher() {                              \
-    }                                                                          \
+    explicit matcher_##DefineMatcher##OverloadId##Matcher() {}                 \
     virtual bool matches(const Type &Node, ASTMatchFinder *Finder,             \
                          BoundNodesTreeBuilder *Builder) const;                \
   };                                                                           \
   }                                                                            \
   inline internal::Matcher DefineMatcher() {                             \
     return internal::makeMatcher(                                              \
-        new internal::matcher_##DefineMatcher##Matcher());                     \
+        new internal::matcher_##DefineMatcher##OverloadId##Matcher());         \
   }                                                                            \
-  inline bool internal::matcher_##DefineMatcher##Matcher::matches(             \
+  inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
       const Type &Node, ASTMatchFinder *Finder,                                \
       BoundNodesTreeBuilder *Builder) const
 
@@ -80,10 +83,16 @@
 ///
 /// The code should return true if 'Node' matches.
 #define AST_MATCHER_P(Type, DefineMatcher, ParamType, Param)                   \
+  AST_MATCHER_P_OVERLOAD(Type, DefineMatcher, ParamType, Param, 0)
+
+#define AST_MATCHER_P_OVERLOAD(Type, DefineMatcher, ParamType, Param,          \
+                               OverloadId)                                     \
   namespace internal {                                                         \
-  class matcher_##DefineMatcher##Matcher : public MatcherInterface {     \
+  class matcher_##DefineMatcher##OverloadId##Matcher                           \
+      : public MatcherInterface {                                        \
   public:                                                                      \
-    explicit matcher_##DefineMatcher##Matcher(const ParamType &A##Param)       \
+    explicit matcher_##DefineMatcher##OverloadId##Matcher(                     \
+        const ParamType &A##Param)                                             \
         : Param(A##Param) {                                                    \
     }                                                                          \
     virtual bool matches(const Type &Node, ASTMatchFinder *Finder,             \
@@ -94,9 +103,9 @@
   }                                                                            \
   inline internal::Matcher DefineMatcher(const ParamType &Param) {       \
     return internal::makeMatcher(                                              \
-        new internal::matcher_##DefineMatcher##Matcher(Param));                \
+        new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param));    \
   }                                                                            \
-  inline bool internal::matcher_##DefineMatcher##Matcher::matches(             \
+  inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
       const Type &Node, ASTMatchFinder *Finder,                                \
       BoundNodesTreeBuilder *Builder) const
 
@@ -116,11 +125,17 @@
 /// The code should return true if 'Node' matches.
 #define AST_MATCHER_P2(Type, DefineMatcher, ParamType1, Param1, ParamType2,    \
                        Param2)                                                 \
+  AST_MATCHER_P2_OVERLOAD(Type, DefineMatcher, ParamType1, Param1, ParamType2, \
+                          Param2, 0)
+
+#define AST_MATCHER_P2_OVERLOAD(Type, DefineMatcher, ParamType1, Param1,       \
+                                ParamType2, Param2, OverloadId)                \
   namespace internal {                                                         \
-  class matcher_##DefineMatcher##Matcher : public MatcherInterface {     \
+  class matcher_##DefineMatcher##OverloadId##Matcher                           \
+      : public MatcherInterface {                                        \
   public:                                                                      \
-    matcher_##DefineMatcher##Matcher(const ParamType1 &A##Param1,              \
-                                     const ParamType2 &A##Param2)              \
+    matcher_##DefineMatcher##OverloadId##Matcher(const ParamType1 &A##Param1,  \
+                                                 const ParamType2 &A##Param2)  \
         : Param1(A##Param1), Param2(A##Param2) {                               \
     }                                                                          \
     virtual bool matches(const Type &Node, ASTMatchFinder *Finder,             \
@@ -130,15 +145,45 @@
     const ParamType2 Param2;                                                   \
   };                                                                           \
   }                                                                            \
-  inline internal::Matcher DefineMatcher(const ParamType1 &Param1,       \
-                                               const ParamType2 &Param2) {     \
+  inline internal::Matcher                                               \
+  DefineMatcher(const ParamType1 &Param1, const ParamType2 &Param2) {          \
     return internal::makeMatcher(                                              \
-        new internal::matcher_##DefineMatcher##Matcher(Param1, Param2));       \
+        new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param1,     \
+                                                                   Param2));   \
   }                                                                            \
-  inline bool internal::matcher_##DefineMatcher##Matcher::matches(             \
+  inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
       const Type &Node, ASTMatchFinder *Finder,                                \
       BoundNodesTreeBuilder *Builder) const
 
+/// \brief AST_POLYMORPHIC_MATCHER(DefineMatcher) { ... }
+/// defines a single-parameter function named DefineMatcher() that is
+/// polymorphic in the return type.
+///
+/// The variables are the same as for AST_MATCHER, but NodeType will be deduced
+/// from the calling context.
+#define AST_POLYMORPHIC_MATCHER(DefineMatcher)                                 \
+  AST_POLYMORPHIC_MATCHER_OVERLOAD(DefineMatcher, 0)
+
+#define AST_POLYMORPHIC_MATCHER_OVERLOAD(DefineMatcher, OverloadId)            \
+  namespace internal {                                                         \
+  template                                                  \
+  class matcher_##DefineMatcher##OverloadId##Matcher                           \
+      : public MatcherInterface {                                    \
+  public:                                                                      \
+    virtual bool matches(const NodeType &Node, ASTMatchFinder *Finder,         \
+                         BoundNodesTreeBuilder *Builder) const;                \
+  };                                                                           \
+  }                                                                            \
+  inline internal::PolymorphicMatcherWithParam0<                               \
+      internal::matcher_##DefineMatcher##OverloadId##Matcher> DefineMatcher() {\
+    return internal::PolymorphicMatcherWithParam0<                             \
+        internal::matcher_##DefineMatcher##OverloadId##Matcher>();             \
+  }                                                                            \
+  template                                                  \
+  bool internal::matcher_##DefineMatcher##OverloadId##Matcher<                 \
+      NodeType>::matches(const NodeType &Node, ASTMatchFinder *Finder,         \
+                         BoundNodesTreeBuilder *Builder) const
+
 /// \brief AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) { ... }
 /// defines a single-parameter function named DefineMatcher() that is
 /// polymorphic in the return type.
@@ -149,11 +194,17 @@
 ///
 /// FIXME: Pull out common code with above macro?
 #define AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param)             \
+  AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ParamType, Param, 0)
+
+#define AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ParamType, Param,    \
+                                           OverloadId)                         \
   namespace internal {                                                         \
   template                                 \
-  class matcher_##DefineMatcher##Matcher : public MatcherInterface { \
+  class matcher_##DefineMatcher##OverloadId##Matcher                           \
+      : public MatcherInterface {                                    \
   public:                                                                      \
-    explicit matcher_##DefineMatcher##Matcher(const ParamType &A##Param)       \
+    explicit matcher_##DefineMatcher##OverloadId##Matcher(                     \
+        const ParamType &A##Param)                                             \
         : Param(A##Param) {                                                    \
     }                                                                          \
     virtual bool matches(const NodeType &Node, ASTMatchFinder *Finder,         \
@@ -163,15 +214,16 @@
   };                                                                           \
   }                                                                            \
   inline internal::PolymorphicMatcherWithParam1<                               \
-      internal::matcher_##DefineMatcher##Matcher,                              \
-      ParamType> DefineMatcher(const ParamType &Param) {                       \
+      internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType>       \
+  DefineMatcher(const ParamType &Param) {                                      \
     return internal::PolymorphicMatcherWithParam1<                             \
-        internal::matcher_##DefineMatcher##Matcher, ParamType>(Param);         \
+        internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType>(    \
+        Param);                                                                \
   }                                                                            \
   template                                 \
-  bool internal::matcher_##DefineMatcher##Matcher::matches(  \
-          const NodeType &Node, ASTMatchFinder *Finder,                        \
-          BoundNodesTreeBuilder *Builder) const
+  bool internal::matcher_##DefineMatcher##OverloadId##Matcher<                 \
+      NodeType, ParamT>::matches(const NodeType &Node, ASTMatchFinder *Finder, \
+                                 BoundNodesTreeBuilder *Builder) const
 
 /// \brief AST_POLYMORPHIC_MATCHER_P2(
 ///     DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... }
@@ -183,12 +235,18 @@
 /// Matcher returned by the function DefineMatcher().
 #define AST_POLYMORPHIC_MATCHER_P2(DefineMatcher, ParamType1, Param1,          \
                                    ParamType2, Param2)                         \
+  AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ParamType1, Param1,       \
+                                      ParamType2, Param2, 0)
+
+#define AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ParamType1, Param1, \
+                                            ParamType2, Param2, OverloadId)    \
   namespace internal {                                                         \
   template              \
-  class matcher_##DefineMatcher##Matcher : public MatcherInterface { \
+  class matcher_##DefineMatcher##OverloadId##Matcher                           \
+      : public MatcherInterface {                                    \
   public:                                                                      \
-    matcher_##DefineMatcher##Matcher(const ParamType1 &A##Param1,              \
-                                     const ParamType2 &A##Param2)              \
+    matcher_##DefineMatcher##OverloadId##Matcher(const ParamType1 &A##Param1,  \
+                                                 const ParamType2 &A##Param2)  \
         : Param1(A##Param1), Param2(A##Param2) {                               \
     }                                                                          \
     virtual bool matches(const NodeType &Node, ASTMatchFinder *Finder,         \
@@ -199,18 +257,18 @@
   };                                                                           \
   }                                                                            \
   inline internal::PolymorphicMatcherWithParam2<                               \
-      internal::matcher_##DefineMatcher##Matcher, ParamType1,                  \
-      ParamType2> DefineMatcher(const ParamType1 &Param1,                      \
-                                const ParamType2 &Param2) {                    \
+      internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1,      \
+      ParamType2>                                                              \
+  DefineMatcher(const ParamType1 &Param1, const ParamType2 &Param2) {          \
     return internal::PolymorphicMatcherWithParam2<                             \
-        internal::matcher_##DefineMatcher##Matcher, ParamType1,                \
+        internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1,    \
         ParamType2>(Param1, Param2);                                           \
   }                                                                            \
   template              \
-  bool internal::matcher_##DefineMatcher##Matcher<                             \
-          NodeType, ParamT1,                                                   \
-          ParamT2>::matches(const NodeType &Node, ASTMatchFinder *Finder,      \
-                            BoundNodesTreeBuilder *Builder) const
+  bool internal::matcher_##DefineMatcher##OverloadId##Matcher<                 \
+      NodeType, ParamT1, ParamT2>::matches(                                    \
+      const NodeType &Node, ASTMatchFinder *Finder,                            \
+      BoundNodesTreeBuilder *Builder) const
 
 /// \brief Creates a variadic matcher for both a specific \c Type as well as
 /// the corresponding \c TypeLoc.
-- 
2.7.4