Add support for Adaptative matchers on the dynamic registry.

Summary:
Add support for Adaptative matchers on the dynamic registry.
Each adaptative matcher is created with a function template. We instantiate the function N times, one for each possible From type and apply the techniques used on argument overloaded and polymorphic matchers to add them to the registry.

Reviewers: klimek

CC: cfe-commits, revane

Differential Revision: http://llvm-reviews.chandlerc.com/D1201

llvm-svn: 187044
diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
index 2daaa88..ac3241c 100644
--- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -109,6 +109,64 @@
     registerMatcher(#name, new OverloadedMatcherCreateCallback(Callbacks));    \
   } while (0)
 
+/// \brief Class that allows us to bind to the constructor of an
+///   \c ArgumentAdaptingMatcher.
+/// This class, together with \c collectAdaptativeMatcherOverloads below, help
+/// us detect the Adapter class and create overload functions for the
+/// appropriate To/From types.
+/// We instantiate the \c createAdatingMatcher function for every type in
+/// \c FromTypes. \c ToTypes is handled on the marshaller side by using the
+/// \c ReturnTypes typedef in \c ArgumentAdaptingMatcher.
+template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
+          typename FromTypes, typename ToTypes>
+struct AdaptativeMatcherWrapper {
+  template <typename FromArg>
+  static ast_matchers::internal::ArgumentAdaptingMatcher<
+      ArgumentAdapterT, FromArg, FromTypes, ToTypes>
+  createAdatingMatcher(
+      const ast_matchers::internal::Matcher<FromArg> &InnerMatcher) {
+    return ast_matchers::internal::ArgumentAdaptingMatcher<
+        ArgumentAdapterT, FromArg, FromTypes, ToTypes>(InnerMatcher);
+  }
+
+  static void collectOverloads(StringRef Name,
+                               std::vector<MatcherCreateCallback *> &Out,
+                               ast_matchers::internal::EmptyTypeList) {}
+
+  template <typename FromTypeList>
+  static void collectOverloads(StringRef Name,
+                               std::vector<MatcherCreateCallback *> &Out,
+                               FromTypeList TypeList) {
+    Out.push_back(internal::makeMatcherAutoMarshall(
+        &createAdatingMatcher<typename FromTypeList::head>, Name));
+    collectOverloads(Name, Out, typename FromTypeList::tail());
+  }
+
+  static void collectOverloads(StringRef Name,
+                               std::vector<MatcherCreateCallback *> &Out) {
+    collectOverloads(Name, Out, FromTypes());
+  }
+};
+
+template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
+          typename DummyArg, typename FromTypes, typename ToTypes>
+void collectAdaptativeMatcherOverloads(
+    StringRef Name,
+    ast_matchers::internal::ArgumentAdaptingMatcher<ArgumentAdapterT, DummyArg,
+                                                    FromTypes, ToTypes>(
+        *func)(const ast_matchers::internal::Matcher<DummyArg> &),
+    std::vector<MatcherCreateCallback *> &Out) {
+  AdaptativeMatcherWrapper<ArgumentAdapterT, FromTypes,
+                           ToTypes>::collectOverloads(Name, Out);
+}
+
+#define REGISTER_ADAPTATIVE(name)                                              \
+  do {                                                                         \
+    std::vector<MatcherCreateCallback *> Overloads;                            \
+    collectAdaptativeMatcherOverloads(#name, &name<Decl>, Overloads);          \
+    registerMatcher(#name, new OverloadedMatcherCreateCallback(Overloads));    \
+  } while (0)
+
 /// \brief Generate a registry map with all the known matchers.
 RegistryMaps::RegistryMaps() {
   // TODO: Here is the list of the missing matchers, grouped by reason.
@@ -123,14 +181,6 @@
   // allOf
   // findAll
   //
-  // Adaptative matcher (similar to polymorphic matcher):
-  // has
-  // forEach
-  // forEachDescendant
-  // hasDescendant
-  // hasParent
-  // hasAncestor
-  //
   // Other:
   // loc
   // equals
@@ -146,6 +196,13 @@
   REGISTER_OVERLOADED_2(references);
   REGISTER_OVERLOADED_2(thisPointerType);
 
+  REGISTER_ADAPTATIVE(forEach);
+  REGISTER_ADAPTATIVE(forEachDescendant);
+  REGISTER_ADAPTATIVE(has);
+  REGISTER_ADAPTATIVE(hasAncestor);
+  REGISTER_ADAPTATIVE(hasDescendant);
+  REGISTER_ADAPTATIVE(hasParent);
+
   REGISTER_MATCHER(accessSpecDecl);
   REGISTER_MATCHER(alignOfExpr);
   REGISTER_MATCHER(anything);