Add support for eachOf/allOf/anyOf variadic matchers in the dynamic layer.

Summary:
Add support for eachOf/allOf/anyOf variadic matchers in the dynamic layer.
These function require some late binding behavior for the type conversions, thus changes in VariadicValue's MatcherList.
Second try. This time with a fix for C++11 builds.

Reviewers: klimek

CC: cfe-commits, revane

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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@189500 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/ASTMatchers/Dynamic/VariantValue.cpp b/lib/ASTMatchers/Dynamic/VariantValue.cpp
index 87aca7d..c350d78 100644
--- a/lib/ASTMatchers/Dynamic/VariantValue.cpp
+++ b/lib/ASTMatchers/Dynamic/VariantValue.cpp
@@ -38,13 +38,9 @@
         .str();
   }
 
-  virtual bool hasTypedMatcher(const MatcherOps &Ops) const {
-    return Ops.canConstructFrom(*Matcher);
-  }
-
-  virtual const DynTypedMatcher *getTypedMatcher(const MatcherOps &Ops) const {
-    assert(hasTypedMatcher(Ops));
-    return Matcher.get();
+  virtual void makeTypedMatcher(MatcherOps &Ops) const {
+    if (Ops.canConstructFrom(*Matcher))
+      Ops.constructFrom(*Matcher);
   }
 
 private:
@@ -80,23 +76,49 @@
     return (Twine("Matcher<") + Inner + ">").str();
   }
 
-  virtual bool hasTypedMatcher(const MatcherOps &Ops) const {
-    return getTypedMatcher(Ops) != NULL;
-  }
-
-  virtual const DynTypedMatcher *getTypedMatcher(const MatcherOps &Ops) const {
-    const DynTypedMatcher* Found = NULL;
+  virtual void makeTypedMatcher(MatcherOps &Ops) const {
+    const DynTypedMatcher *Found = NULL;
     for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
       if (Ops.canConstructFrom(*Matchers[i])) {
-        if (Found) return NULL;
+        if (Found)
+          return;
         Found = Matchers[i];
       }
     }
-    return Found;
+    if (Found)
+      Ops.constructFrom(*Found);
+  }
+
+  std::vector<const DynTypedMatcher *> Matchers;
+};
+
+class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
+public:
+  VariadicOpPayload(ast_matchers::internal::VariadicOperatorFunction Func,
+                    ArrayRef<VariantMatcher> Args)
+      : Func(Func), Args(Args) {}
+
+  virtual bool getSingleMatcher(const DynTypedMatcher *&Out) const {
+    return false;
+  }
+
+  virtual std::string getTypeAsString() const {
+    std::string Inner;
+    for (size_t i = 0, e = Args.size(); i != e; ++i) {
+      if (i != 0)
+        Inner += "&";
+      Inner += Args[i].getTypeAsString();
+    }
+    return Inner;
+  }
+
+  virtual void makeTypedMatcher(MatcherOps &Ops) const {
+    Ops.constructVariadicOperator(Func, Args);
   }
 
 private:
-  std::vector<const DynTypedMatcher *> Matchers;
+  const ast_matchers::internal::VariadicOperatorFunction Func;
+  const std::vector<VariantMatcher> Args;
 };
 
 VariantMatcher::VariantMatcher() {}
@@ -110,6 +132,12 @@
   return VariantMatcher(new PolymorphicPayload(Matchers));
 }
 
+VariantMatcher VariantMatcher::VariadicOperatorMatcher(
+    ast_matchers::internal::VariadicOperatorFunction Func,
+    ArrayRef<VariantMatcher> Args) {
+  return VariantMatcher(new VariadicOpPayload(Func, Args));
+}
+
 bool VariantMatcher::getSingleMatcher(const DynTypedMatcher *&Out) const {
   if (Value) return Value->getSingleMatcher(Out);
   return false;