Refactor VariantMatcher::MatcherOps to reduce the amount of generated code.

Summary:
Refactor VariantMatcher::MatcherOps to reduce the amount of generated code.
 - Make some code type agnostic and move it to the cpp file.
 - Return a DynTypedMatcher instead of storing the object in MatcherOps.

This change reduces the number of symbols generated in Registry.cpp by
~19%, the object byte size by ~17% and the compilation time (in non-release mode) by ~20%.

Reviewers: klimek

Subscribers: klimek, cfe-commits

Differential Revision: http://reviews.llvm.org/D5124

llvm-svn: 217152
diff --git a/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp b/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
index 57c7b80..3d14157 100644
--- a/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
+++ b/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
@@ -49,7 +49,32 @@
   return true;
 }
 
-VariantMatcher::MatcherOps::~MatcherOps() {}
+bool
+VariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher &Matcher,
+                                             bool &IsExactMatch) const {
+  IsExactMatch = Matcher.getSupportedKind().isSame(NodeKind);
+  return Matcher.canConvertTo(NodeKind);
+}
+
+llvm::Optional<DynTypedMatcher>
+VariantMatcher::MatcherOps::constructVariadicOperator(
+    ast_matchers::internal::VariadicOperatorFunction Func,
+    ArrayRef<VariantMatcher> InnerMatchers) const {
+  std::vector<DynTypedMatcher> DynMatchers;
+  for (const auto &InnerMatcher : InnerMatchers) {
+    // Abort if any of the inner matchers can't be converted to
+    // Matcher<T>.
+    if (!InnerMatcher.Value)
+      return llvm::None;
+    llvm::Optional<DynTypedMatcher> Inner =
+        InnerMatcher.Value->getTypedMatcher(*this);
+    if (!Inner)
+      return llvm::None;
+    DynMatchers.push_back(*Inner);
+  }
+  return DynTypedMatcher::constructVariadic(Func, DynMatchers);
+}
+
 VariantMatcher::Payload::~Payload() {}
 
 class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
@@ -65,10 +90,12 @@
         .str();
   }
 
-  void makeTypedMatcher(MatcherOps &Ops) const override {
+  llvm::Optional<DynTypedMatcher>
+  getTypedMatcher(const MatcherOps &Ops) const override {
     bool Ignore;
     if (Ops.canConstructFrom(Matcher, Ignore))
-      Ops.constructFrom(Matcher);
+      return Matcher;
+    return llvm::None;
   }
 
   bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
@@ -104,7 +131,8 @@
     return (Twine("Matcher<") + Inner + ">").str();
   }
 
-  void makeTypedMatcher(MatcherOps &Ops) const override {
+  llvm::Optional<DynTypedMatcher>
+  getTypedMatcher(const MatcherOps &Ops) const override {
     bool FoundIsExact = false;
     const DynTypedMatcher *Found = nullptr;
     int NumFound = 0;
@@ -124,7 +152,8 @@
     }
     // We only succeed if we found exactly one, or if we found an exact match.
     if (Found && (FoundIsExact || NumFound == 1))
-      Ops.constructFrom(*Found);
+      return *Found;
+    return llvm::None;
   }
 
   bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
@@ -165,8 +194,9 @@
     return Inner;
   }
 
-  void makeTypedMatcher(MatcherOps &Ops) const override {
-    Ops.constructVariadicOperator(Func, Args);
+  llvm::Optional<DynTypedMatcher>
+  getTypedMatcher(const MatcherOps &Ops) const override {
+    return Ops.constructVariadicOperator(Func, Args);
   }
 
   bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,