Add support for polymorphic matchers. Use runtime type checking to determine the right polymorphic overload to use.

llvm-svn: 184558
diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
index 5f6b35d..c887f3d 100644
--- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -68,7 +68,6 @@
   // forField
   // withInitializer
   // isWritten
-  // isImplicit
   //
   // Type traversal:
   // hasElementType
@@ -87,19 +86,6 @@
   // references
   // thisPointerType
   //
-  // Polymorphic matchers:
-  // anything
-  // hasAnyArgument
-  // isTemplateInstantiation
-  // isExplicitTemplateSpecialization
-  // isDefinition
-  // hasOperatorName
-  // hasOverloadedOperatorName
-  // hasCondition
-  // hasBody
-  // argumentCountIs
-  // hasArgument
-  //
   // Polymorphic + argument overload:
   // unless
   // eachOf
@@ -123,6 +109,8 @@
 
   REGISTER_MATCHER(accessSpecDecl);
   REGISTER_MATCHER(alignOfExpr);
+  REGISTER_MATCHER(anything);
+  REGISTER_MATCHER(argumentCountIs);
   REGISTER_MATCHER(arraySubscriptExpr);
   REGISTER_MATCHER(arrayType);
   REGISTER_MATCHER(asString);
@@ -175,12 +163,16 @@
   REGISTER_MATCHER(functionType);
   REGISTER_MATCHER(functionalCastExpr);
   REGISTER_MATCHER(gotoStmt);
+  REGISTER_MATCHER(hasAnyArgument);
   REGISTER_MATCHER(hasAnyParameter);
   REGISTER_MATCHER(hasAnySubstatement);
   REGISTER_MATCHER(hasAnyUsingShadowDecl);
+  REGISTER_MATCHER(hasArgument);
   REGISTER_MATCHER(hasArgumentOfType);
   REGISTER_MATCHER(hasBase);
+  REGISTER_MATCHER(hasBody);
   REGISTER_MATCHER(hasCanonicalType);
+  REGISTER_MATCHER(hasCondition);
   REGISTER_MATCHER(hasConditionVariableStatement);
   REGISTER_MATCHER(hasDeclContext);
   REGISTER_MATCHER(hasDestinationType);
@@ -196,6 +188,8 @@
   REGISTER_MATCHER(hasMethod);
   REGISTER_MATCHER(hasName);
   REGISTER_MATCHER(hasObjectExpression);
+  REGISTER_MATCHER(hasOperatorName);
+  REGISTER_MATCHER(hasOverloadedOperatorName);
   REGISTER_MATCHER(hasParameter);
   REGISTER_MATCHER(hasQualifier);
   REGISTER_MATCHER(hasRHS);
@@ -216,6 +210,8 @@
   REGISTER_MATCHER(integerLiteral);
   REGISTER_MATCHER(isArrow);
   REGISTER_MATCHER(isConstQualified);
+  REGISTER_MATCHER(isDefinition);
+  REGISTER_MATCHER(isExplicitTemplateSpecialization);
   REGISTER_MATCHER(isExternC);
   REGISTER_MATCHER(isImplicit);
   REGISTER_MATCHER(isInteger);
@@ -223,6 +219,7 @@
   REGISTER_MATCHER(isPrivate);
   REGISTER_MATCHER(isProtected);
   REGISTER_MATCHER(isPublic);
+  REGISTER_MATCHER(isTemplateInstantiation);
   REGISTER_MATCHER(isVirtual);
   REGISTER_MATCHER(lValueReferenceType);
   REGISTER_MATCHER(labelStmt);
@@ -300,36 +297,39 @@
 } // anonymous namespace
 
 // static
-DynTypedMatcher *Registry::constructMatcher(StringRef MatcherName,
-                                            const SourceRange &NameRange,
-                                            ArrayRef<ParserValue> Args,
-                                            Diagnostics *Error) {
+MatcherList Registry::constructMatcher(StringRef MatcherName,
+                                       const SourceRange &NameRange,
+                                       ArrayRef<ParserValue> Args,
+                                       Diagnostics *Error) {
   ConstructorMap::const_iterator it =
       RegistryData->constructors().find(MatcherName);
   if (it == RegistryData->constructors().end()) {
     Error->pushErrorFrame(NameRange, Error->ET_RegistryNotFound)
         << MatcherName;
-    return NULL;
+    return MatcherList();
   }
 
   return it->second->run(NameRange, Args, Error);
 }
 
 // static
-DynTypedMatcher *Registry::constructBoundMatcher(StringRef MatcherName,
-                                                 const SourceRange &NameRange,
-                                                 StringRef BindID,
-                                                 ArrayRef<ParserValue> Args,
-                                                 Diagnostics *Error) {
-  OwningPtr<DynTypedMatcher> Out(
-      constructMatcher(MatcherName, NameRange, Args, Error));
-  if (!Out) return NULL;
-  DynTypedMatcher *Bound = Out->tryBind(BindID);
-  if (!Bound) {
-    Error->pushErrorFrame(NameRange, Error->ET_RegistryNotBindable);
-    return NULL;
+MatcherList Registry::constructBoundMatcher(StringRef MatcherName,
+                                            const SourceRange &NameRange,
+                                            StringRef BindID,
+                                            ArrayRef<ParserValue> Args,
+                                            Diagnostics *Error) {
+  MatcherList Out = constructMatcher(MatcherName, NameRange, Args, Error);
+  if (Out.empty()) return Out;
+
+  ArrayRef<const DynTypedMatcher*> Matchers = Out.matchers();
+  if (Matchers.size() == 1) {
+    OwningPtr<DynTypedMatcher> Bound(Matchers[0]->tryBind(BindID));
+    if (Bound) {
+      return *Bound;
+    }
   }
-  return Bound;
+  Error->pushErrorFrame(NameRange, Error->ET_RegistryNotBindable);
+  return MatcherList();
 }
 
 }  // namespace dynamic