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

Samuel Benzaquen sbenza at google.com
Fri Jun 21 08:51:31 PDT 2013


Author: sbenza
Date: Fri Jun 21 10:51:31 2013
New Revision: 184558

URL: http://llvm.org/viewvc/llvm-project?rev=184558&view=rev
Log:
Add support for polymorphic matchers. Use runtime type checking to determine the right polymorphic overload to use.

Modified:
    cfe/trunk/docs/LibASTMatchersReference.html
    cfe/trunk/docs/tools/dump_ast_matchers.py
    cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
    cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h
    cfe/trunk/include/clang/ASTMatchers/ASTMatchersMacros.h
    cfe/trunk/include/clang/ASTMatchers/Dynamic/Diagnostics.h
    cfe/trunk/include/clang/ASTMatchers/Dynamic/Parser.h
    cfe/trunk/include/clang/ASTMatchers/Dynamic/Registry.h
    cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h
    cfe/trunk/lib/ASTMatchers/Dynamic/Diagnostics.cpp
    cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h
    cfe/trunk/lib/ASTMatchers/Dynamic/Parser.cpp
    cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
    cfe/trunk/lib/ASTMatchers/Dynamic/VariantValue.cpp
    cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
    cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp
    cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
    cfe/trunk/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp

Modified: cfe/trunk/docs/LibASTMatchersReference.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LibASTMatchersReference.html?rev=184558&r1=184557&r2=184558&view=diff
==============================================================================
--- cfe/trunk/docs/LibASTMatchersReference.html (original)
+++ cfe/trunk/docs/LibASTMatchersReference.html Fri Jun 21 10:51:31 2013
@@ -1547,6 +1547,16 @@ Usable as: Matcher&lt<a href="http://cla
 </pre></td></tr>
 
 
+<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>></td><td class="name" onclick="toggle('argumentCountIs1')"><a name="argumentCountIs1Anchor">argumentCountIs</a></td><td>unsigned N</td></tr>
+<tr><td colspan="4" class="doc" id="argumentCountIs1"><pre>Checks that a call expression or a constructor call expression has
+a specific number of arguments (including absent default arguments).
+
+Example matches f(0, 0) (matcher = callExpr(argumentCountIs(2)))
+  void f(int x, int y);
+  f(0, 0);
+</pre></td></tr>
+
+
 <tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html">CXXConstructorDecl</a>></td><td class="name" onclick="toggle('isImplicit0')"><a name="isImplicit0Anchor">isImplicit</a></td><td></td></tr>
 <tr><td colspan="4" class="doc" id="isImplicit0"><pre>Matches a constructor declaration that has been implicitly added
 by the compiler (eg. implicit defaultcopy constructors).
@@ -2483,6 +2493,34 @@ Usable as: Matcher&lt<a href="http://cla
 </pre></td></tr>
 
 
+<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>></td><td class="name" onclick="toggle('hasAnyArgument1')"><a name="hasAnyArgument1Anchor">hasAnyArgument</a></td><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasAnyArgument1"><pre>Matches any argument of a call expression or a constructor call
+expression.
+
+Given
+  void x(int, int, int) { int y; x(1, y, 42); }
+callExpr(hasAnyArgument(declRefExpr()))
+  matches x(1, y, 42)
+with hasAnyArgument(...)
+  matching y
+
+FIXME: Currently this will ignore parentheses and implicit casts on
+the argument before applying the inner matcher. We'll want to remove
+this to allow for greater control by the user once ignoreImplicit()
+has been implemented.
+</pre></td></tr>
+
+
+<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>></td><td class="name" onclick="toggle('hasArgument1')"><a name="hasArgument1Anchor">hasArgument</a></td><td>unsigned N, Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasArgument1"><pre>Matches the n'th argument of a call expression or a constructor
+call expression.
+
+Example matches y in x(y)
+    (matcher = callExpr(hasArgument(0, declRefExpr())))
+  void x(int) { int y; x(y); }
+</pre></td></tr>
+
+
 <tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>></td><td class="name" onclick="toggle('hasDeclaration3')"><a name="hasDeclaration3Anchor">hasDeclaration</a></td><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>>  InnerMatcher</td></tr>
 <tr><td colspan="4" class="doc" id="hasDeclaration3"><pre>Matches a node if the declaration associated with that node
 matches the given matcher.

Modified: cfe/trunk/docs/tools/dump_ast_matchers.py
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/tools/dump_ast_matchers.py?rev=184558&r1=184557&r2=184558&view=diff
==============================================================================
--- cfe/trunk/docs/tools/dump_ast_matchers.py (original)
+++ cfe/trunk/docs/tools/dump_ast_matchers.py Fri Jun 21 10:51:31 2013
@@ -175,7 +175,31 @@ def act_on_decl(declaration, comment, al
                       comment)
       return
 
-    m = re.match(r"""^\s*AST_(POLYMORPHIC_)?MATCHER(_P)?(.?)(?:_OVERLOAD)?\(
+    m = re.match(r"""^\s*AST_POLYMORPHIC_MATCHER(_P)?(.?)(?:_OVERLOAD)?\(
+                          \s*([^\s,]+)\s*,
+                          \s*AST_POLYMORPHIC_SUPPORTED_TYPES_([^(]*)\(([^)]*)\)
+                       (?:,\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, name, n_results, results = m.groups()[0:5]
+      args = m.groups()[5:]
+      result_types = [r.strip() for r in results.split(',')]
+      if allowed_types and allowed_types != result_types:
+        raise Exception('Inconsistent documentation for: %s' % name)
+      if n not in ['', '2']:
+        raise Exception('Cannot parse "%s"' % declaration)
+      args = ', '.join('%s %s' % (args[i], args[i+1])
+                       for i in range(0, len(args), 2) if args[i])
+      for result_type in result_types:
+        add_matcher(result_type, name, args, comment)
+      return
+
+    m = re.match(r"""^\s*AST_MATCHER(_P)?(.?)(?:_OVERLOAD)?\(
                        (?:\s*([^\s,]+)\s*,)?
                           \s*([^\s,]+)\s*
                        (?:,\s*([^\s,]+)\s*
@@ -185,8 +209,8 @@ def act_on_decl(declaration, comment, al
                        (?:,\s*\d+\s*)?
                       \)\s*{\s*$""", declaration, flags=re.X)
     if m:
-      p, n, result, name = m.groups()[1:5]
-      args = m.groups()[5:]
+      p, n, result, name = m.groups()[0:4]
+      args = m.groups()[4:]
       if not result:
         if not allowed_types:
           raise Exception('Did not find allowed result types for: %s' % name)

Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=184558&r1=184557&r2=184558&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Fri Jun 21 10:51:31 2013
@@ -1451,10 +1451,13 @@ AST_MATCHER_P(NamedDecl, matchesName, st
 ///
 /// Usable as: Matcher<CXXOperatorCallExpr>, Matcher<CXXMethodDecl>
 inline internal::PolymorphicMatcherWithParam1<
-    internal::HasOverloadedOperatorNameMatcher, StringRef>
+    internal::HasOverloadedOperatorNameMatcher, StringRef,
+    AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, CXXMethodDecl)>
 hasOverloadedOperatorName(const StringRef Name) {
   return internal::PolymorphicMatcherWithParam1<
-      internal::HasOverloadedOperatorNameMatcher, StringRef>(Name);
+      internal::HasOverloadedOperatorNameMatcher, StringRef,
+      AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, CXXMethodDecl)>(
+      Name);
 }
 
 /// \brief Matches C++ classes that are directly or indirectly derived from
@@ -1784,11 +1787,9 @@ inline internal::Matcher<CallExpr> calle
 ///  class X {};
 ///  void y(X &x) { x; X z; }
 /// \endcode
-AST_POLYMORPHIC_MATCHER_P(hasType, internal::Matcher<QualType>,
-                          InnerMatcher) {
-  TOOLING_COMPILE_ASSERT((llvm::is_base_of<Expr, NodeType>::value ||
-                          llvm::is_base_of<ValueDecl, NodeType>::value),
-                         instantiated_with_wrong_types);
+AST_POLYMORPHIC_MATCHER_P(hasType,
+                          AST_POLYMORPHIC_SUPPORTED_TYPES_2(Expr, ValueDecl),
+                          internal::Matcher<QualType>, InnerMatcher) {
   return InnerMatcher.matches(Node.getType(), Finder, Builder);
 }
 
@@ -1810,8 +1811,8 @@ AST_POLYMORPHIC_MATCHER_P(hasType, inter
 ///
 /// Usable as: Matcher<Expr>, Matcher<ValueDecl>
 inline internal::PolymorphicMatcherWithParam1<
-  internal::matcher_hasType0Matcher,
-  internal::Matcher<QualType> >
+    internal::matcher_hasType0Matcher, internal::Matcher<QualType>,
+    AST_POLYMORPHIC_SUPPORTED_TYPES_2(Expr, ValueDecl)>
 hasType(const internal::Matcher<Decl> &InnerMatcher) {
   return hasType(qualType(hasDeclaration(InnerMatcher)));
 }
@@ -2013,11 +2014,9 @@ AST_MATCHER_P(
 ///   void f(int x, int y);
 ///   f(0, 0);
 /// \endcode
-AST_POLYMORPHIC_MATCHER_P(argumentCountIs, unsigned, N) {
-  TOOLING_COMPILE_ASSERT((llvm::is_base_of<CallExpr, NodeType>::value ||
-                          llvm::is_base_of<CXXConstructExpr,
-                                           NodeType>::value),
-                         instantiated_with_wrong_types);
+AST_POLYMORPHIC_MATCHER_P(argumentCountIs, AST_POLYMORPHIC_SUPPORTED_TYPES_2(
+                                               CallExpr, CXXConstructExpr),
+                          unsigned, N) {
   return Node.getNumArgs() == N;
 }
 
@@ -2030,11 +2029,9 @@ AST_POLYMORPHIC_MATCHER_P(argumentCountI
 ///   void x(int) { int y; x(y); }
 /// \endcode
 AST_POLYMORPHIC_MATCHER_P2(
-    hasArgument, unsigned, N, internal::Matcher<Expr>, InnerMatcher) {
-  TOOLING_COMPILE_ASSERT((llvm::is_base_of<CallExpr, NodeType>::value ||
-                         llvm::is_base_of<CXXConstructExpr,
-                                          NodeType>::value),
-                         instantiated_with_wrong_types);
+    hasArgument,
+    AST_POLYMORPHIC_SUPPORTED_TYPES_2(CallExpr, CXXConstructExpr),
+    unsigned, N, internal::Matcher<Expr>, InnerMatcher) {
   return (N < Node.getNumArgs() &&
           InnerMatcher.matches(
               *Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder));
@@ -2180,12 +2177,9 @@ AST_MATCHER(CXXConstructorDecl, isImplic
 /// the argument before applying the inner matcher. We'll want to remove
 /// this to allow for greater control by the user once \c ignoreImplicit()
 /// has been implemented.
-AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, internal::Matcher<Expr>,
-                          InnerMatcher) {
-  TOOLING_COMPILE_ASSERT((llvm::is_base_of<CallExpr, NodeType>::value ||
-                         llvm::is_base_of<CXXConstructExpr,
-                                          NodeType>::value),
-                         instantiated_with_wrong_types);
+AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, AST_POLYMORPHIC_SUPPORTED_TYPES_2(
+                                              CallExpr, CXXConstructExpr),
+                          internal::Matcher<Expr>, InnerMatcher) {
   for (unsigned I = 0; I < Node.getNumArgs(); ++I) {
     BoundNodesTreeBuilder Result(*Builder);
     if (InnerMatcher.matches(*Node.getArg(I)->IgnoreParenImpCasts(), Finder,
@@ -2280,15 +2274,10 @@ AST_MATCHER(FunctionDecl, isExternC) {
 /// \code
 ///   if (true) {}
 /// \endcode
-AST_POLYMORPHIC_MATCHER_P(hasCondition, internal::Matcher<Expr>,
-                          InnerMatcher) {
-  TOOLING_COMPILE_ASSERT(
-    (llvm::is_base_of<IfStmt, NodeType>::value) ||
-    (llvm::is_base_of<ForStmt, NodeType>::value) ||
-    (llvm::is_base_of<WhileStmt, NodeType>::value) ||
-    (llvm::is_base_of<DoStmt, NodeType>::value) ||
-    (llvm::is_base_of<ConditionalOperator, NodeType>::value),
-    has_condition_requires_if_statement_conditional_operator_or_loop);
+AST_POLYMORPHIC_MATCHER_P(
+    hasCondition, AST_POLYMORPHIC_SUPPORTED_TYPES_5(
+                      IfStmt, ForStmt, WhileStmt, DoStmt, ConditionalOperator),
+    internal::Matcher<Expr>, InnerMatcher) {
   const Expr *const Condition = Node.getCond();
   return (Condition != NULL &&
           InnerMatcher.matches(*Condition, Finder, Builder));
@@ -2325,18 +2314,15 @@ struct NotEqualsBoundNodePredicate {
 ///     forEachDescendant(declRefExpr(to(decl(equalsBoundNode("d"))))))
 /// will trigger a match for each combination of variable declaration
 /// and reference to that variable declaration within a compound statement.
-AST_POLYMORPHIC_MATCHER_P(equalsBoundNode, std::string, ID) {
+AST_POLYMORPHIC_MATCHER_P(equalsBoundNode, AST_POLYMORPHIC_SUPPORTED_TYPES_4(
+                                               Stmt, Decl, Type, QualType),
+                          std::string, ID) {
   // FIXME: Figure out whether it makes sense to allow this
   // on any other node types.
   // For *Loc it probably does not make sense, as those seem
   // unique. For NestedNameSepcifier it might make sense, as
   // those also have pointer identity, but I'm not sure whether
   // they're ever reused.
-  TOOLING_COMPILE_ASSERT((llvm::is_base_of<Stmt, NodeType>::value ||
-                          llvm::is_base_of<Decl, NodeType>::value ||
-                          llvm::is_base_of<Type, NodeType>::value ||
-                          llvm::is_base_of<QualType, NodeType>::value),
-                         equals_bound_node_requires_non_unique_node_class);
   internal::NotEqualsBoundNodePredicate Predicate;
   Predicate.ID = ID;
   Predicate.Node = ast_type_traits::DynTypedNode::create(Node);
@@ -2403,13 +2389,9 @@ AST_MATCHER_P(ArraySubscriptExpr, hasBas
 ///   matches 'for (;;) {}'
 /// with compoundStmt()
 ///   matching '{}'
-AST_POLYMORPHIC_MATCHER_P(hasBody, internal::Matcher<Stmt>,
-                          InnerMatcher) {
-  TOOLING_COMPILE_ASSERT(
-      (llvm::is_base_of<DoStmt, NodeType>::value) ||
-      (llvm::is_base_of<ForStmt, NodeType>::value) ||
-      (llvm::is_base_of<WhileStmt, NodeType>::value),
-      has_body_requires_for_while_or_do_statement);
+AST_POLYMORPHIC_MATCHER_P(
+    hasBody, AST_POLYMORPHIC_SUPPORTED_TYPES_3(DoStmt, ForStmt, WhileStmt),
+    internal::Matcher<Stmt>, InnerMatcher) {
   const Stmt *const Statement = Node.getBody();
   return (Statement != NULL &&
           InnerMatcher.matches(*Statement, Finder, Builder));
@@ -2470,11 +2452,9 @@ equals(const ValueT &Value) {
 /// \code
 ///   !(a || b)
 /// \endcode
-AST_POLYMORPHIC_MATCHER_P(hasOperatorName, std::string, Name) {
-  TOOLING_COMPILE_ASSERT(
-    (llvm::is_base_of<BinaryOperator, NodeType>::value) ||
-    (llvm::is_base_of<UnaryOperator, NodeType>::value),
-    has_condition_requires_if_statement_or_conditional_operator);
+AST_POLYMORPHIC_MATCHER_P(hasOperatorName, AST_POLYMORPHIC_SUPPORTED_TYPES_2(
+                                               BinaryOperator, UnaryOperator),
+                          std::string, Name) {
   return Name == Node.getOpcodeStr(Node.getOpcode());
 }
 
@@ -2596,12 +2576,8 @@ AST_MATCHER_P(ConditionalOperator, hasFa
 /// \endcode
 ///
 /// Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl>
-AST_POLYMORPHIC_MATCHER(isDefinition) {
-  TOOLING_COMPILE_ASSERT(
-      (llvm::is_base_of<TagDecl, NodeType>::value) ||
-      (llvm::is_base_of<VarDecl, NodeType>::value) ||
-      (llvm::is_base_of<FunctionDecl, NodeType>::value),
-      is_definition_requires_isThisDeclarationADefinition_method);
+AST_POLYMORPHIC_MATCHER(isDefinition, AST_POLYMORPHIC_SUPPORTED_TYPES_3(
+                                          TagDecl, VarDecl, FunctionDecl)) {
   return Node.isThisDeclarationADefinition();
 }
 
@@ -2834,11 +2810,9 @@ AST_MATCHER_P(UsingShadowDecl, hasTarget
 ///   does not match, as X<A> is an explicit template specialization.
 ///
 /// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl>
-AST_POLYMORPHIC_MATCHER(isTemplateInstantiation) {
-  TOOLING_COMPILE_ASSERT((llvm::is_base_of<FunctionDecl, NodeType>::value) ||
-                         (llvm::is_base_of<VarDecl, NodeType>::value) ||
-                         (llvm::is_base_of<CXXRecordDecl, NodeType>::value),
-                         requires_getTemplateSpecializationKind_method);
+AST_POLYMORPHIC_MATCHER(
+    isTemplateInstantiation,
+    AST_POLYMORPHIC_SUPPORTED_TYPES_3(FunctionDecl, VarDecl, CXXRecordDecl)) {
   return (Node.getTemplateSpecializationKind() == TSK_ImplicitInstantiation ||
           Node.getTemplateSpecializationKind() ==
           TSK_ExplicitInstantiationDefinition);
@@ -2856,11 +2830,9 @@ AST_POLYMORPHIC_MATCHER(isTemplateInstan
 ///   matches the specialization A<int>().
 ///
 /// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl>
-AST_POLYMORPHIC_MATCHER(isExplicitTemplateSpecialization) {
-  TOOLING_COMPILE_ASSERT((llvm::is_base_of<FunctionDecl, NodeType>::value) ||
-                         (llvm::is_base_of<VarDecl, NodeType>::value) ||
-                         (llvm::is_base_of<CXXRecordDecl, NodeType>::value),
-                         requires_getTemplateSpecializationKind_method);
+AST_POLYMORPHIC_MATCHER(
+    isExplicitTemplateSpecialization,
+    AST_POLYMORPHIC_SUPPORTED_TYPES_3(FunctionDecl, VarDecl, CXXRecordDecl)) {
   return (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization);
 }
 

Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h?rev=184558&r1=184557&r2=184558&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h Fri Jun 21 10:51:31 2013
@@ -761,6 +761,58 @@ private:
   const Matcher<T> InnerMatcher;
 };
 
+/// \brief A simple type-list implementation.
+///
+/// It is implemented as a flat struct with a maximum number of arguments to
+/// simplify compiler error messages.
+/// However, it is used as a "linked list" of types.
+///
+/// Note: If you need to extend for more types, add them as template arguments
+///       and to the "typedef TypeList<...> tail" below. Nothing else is needed.
+template <typename T1 = void, typename T2 = void, typename T3 = void,
+          typename T4 = void, typename T5 = void, typename T6 = void,
+          typename T7 = void, typename T8 = void>
+struct TypeList {
+  /// \brief The first type on the list.
+  typedef T1 head;
+
+  /// \brief A sub list with the tail. ie everything but the head.
+  ///
+  /// This type is used to do recursion. TypeList<>/EmptyTypeList indicates the
+  /// end of the list.
+  typedef TypeList<T2, T3, T4, T5, T6, T7, T8> tail;
+
+  /// \brief Helper meta-function to determine if some type \c T is present or
+  ///   a parent type in the list.
+  template <typename T> struct ContainsSuperOf {
+    static const bool value = llvm::is_base_of<head, T>::value ||
+                              tail::template ContainsSuperOf<T>::value;
+  };
+};
+
+/// \brief Specialization of ContainsSuperOf for the empty list.
+template <> template <typename T> struct TypeList<>::ContainsSuperOf {
+  static const bool value = false;
+};
+
+/// \brief The empty type list.
+typedef TypeList<> EmptyTypeList;
+
+/// \brief A "type list" that contains all types.
+///
+/// Useful for matchers like \c anything and \c unless.
+typedef TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc,
+        QualType, Type, TypeLoc, CXXCtorInitializer> AllNodeBaseTypes;
+
+/// \brief Helper meta-function to extract the argument out of a function of
+///   type void(Arg).
+///
+/// See AST_POLYMORPHIC_SUPPORTED_TYPES_* for details.
+template <class T> struct ExtractFunctionArgMeta;
+template <class T> struct ExtractFunctionArgMeta<void(T)> {
+  typedef T type;
+};
+
 /// \brief A PolymorphicMatcherWithParamN<MatcherT, P1, ..., PN> object can be
 /// created from N parameters p1, ..., pN (of type P1, ..., PN) and
 /// used as a Matcher<T> where a MatcherT<T, P1, ..., PN>(p1, ..., pN)
@@ -773,24 +825,33 @@ private:
 /// - PolymorphicMatcherWithParam1<ValueEqualsMatcher, int>(42)
 ///   creates an object that can be used as a Matcher<T> for any type T
 ///   where a ValueEqualsMatcher<T, int>(42) can be constructed.
-template <template <typename T> class MatcherT>
+template <template <typename T> class MatcherT,
+          typename ReturnTypesF = void(AllNodeBaseTypes)>
 class PolymorphicMatcherWithParam0 {
 public:
+  typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes;
   template <typename T>
   operator Matcher<T>() const {
+    TOOLING_COMPILE_ASSERT(ReturnTypes::template ContainsSuperOf<T>::value,
+                           right_polymorphic_conversion);
     return Matcher<T>(new MatcherT<T>());
   }
 };
 
 template <template <typename T, typename P1> class MatcherT,
-          typename P1>
+          typename P1,
+          typename ReturnTypesF = void(AllNodeBaseTypes)>
 class PolymorphicMatcherWithParam1 {
 public:
   explicit PolymorphicMatcherWithParam1(const P1 &Param1)
       : Param1(Param1) {}
 
+  typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes;
+
   template <typename T>
   operator Matcher<T>() const {
+    TOOLING_COMPILE_ASSERT(ReturnTypes::template ContainsSuperOf<T>::value,
+                           right_polymorphic_conversion);
     return Matcher<T>(new MatcherT<T, P1>(Param1));
   }
 
@@ -799,14 +860,19 @@ private:
 };
 
 template <template <typename T, typename P1, typename P2> class MatcherT,
-          typename P1, typename P2>
+          typename P1, typename P2,
+          typename ReturnTypesF = void(AllNodeBaseTypes)>
 class PolymorphicMatcherWithParam2 {
 public:
   PolymorphicMatcherWithParam2(const P1 &Param1, const P2 &Param2)
       : Param1(Param1), Param2(Param2) {}
 
+  typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes;
+
   template <typename T>
   operator Matcher<T>() const {
+    TOOLING_COMPILE_ASSERT(ReturnTypes::template ContainsSuperOf<T>::value,
+                           right_polymorphic_conversion);
     return Matcher<T>(new MatcherT<T, P1, P2>(Param1, Param2));
   }
 

Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchersMacros.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchersMacros.h?rev=184558&r1=184557&r2=184558&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchersMacros.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchersMacros.h Fri Jun 21 10:51:31 2013
@@ -155,16 +155,34 @@
       const Type &Node, ASTMatchFinder *Finder,                                \
       BoundNodesTreeBuilder *Builder) const
 
+/// \brief Construct a type-list to be passed to the AST_POLYMORPHIC_MATCHER*
+///   macros.
+///
+/// You can't pass something like \c TypeList<Foo, Bar> to a macro, because it
+/// will look at that as two arguments. However, you can pass
+/// \c void(TypeList<Foo, Bar>), which works thanks to the parenthesis.
+/// The \c PolymorphicMatcherWithParam* classes will unpack the function type to
+/// extract the TypeList object.
+#define AST_POLYMORPHIC_SUPPORTED_TYPES_2(t1, t2)                              \
+  void(internal::TypeList<t1, t2>)
+#define AST_POLYMORPHIC_SUPPORTED_TYPES_3(t1, t2, t3)                          \
+  void(internal::TypeList<t1, t2, t3>)
+#define AST_POLYMORPHIC_SUPPORTED_TYPES_4(t1, t2, t3, t4)                      \
+  void(internal::TypeList<t1, t2, t3, t4>)
+#define AST_POLYMORPHIC_SUPPORTED_TYPES_5(t1, t2, t3, t4, t5)                  \
+  void(internal::TypeList<t1, t2, t3, t4, t5>)
+
 /// \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(DefineMatcher, ReturnTypesF)                   \
+  AST_POLYMORPHIC_MATCHER_OVERLOAD(DefineMatcher, ReturnTypesF, 0)
 
-#define AST_POLYMORPHIC_MATCHER_OVERLOAD(DefineMatcher, OverloadId)            \
+#define AST_POLYMORPHIC_MATCHER_OVERLOAD(DefineMatcher, ReturnTypesF,          \
+                                         OverloadId)                           \
   namespace internal {                                                         \
   template <typename NodeType>                                                 \
   class matcher_##DefineMatcher##OverloadId##Matcher                           \
@@ -175,9 +193,11 @@
   };                                                                           \
   }                                                                            \
   inline internal::PolymorphicMatcherWithParam0<                               \
-      internal::matcher_##DefineMatcher##OverloadId##Matcher> DefineMatcher() {\
+      internal::matcher_##DefineMatcher##OverloadId##Matcher, ReturnTypesF>    \
+  DefineMatcher() {                                                            \
     return internal::PolymorphicMatcherWithParam0<                             \
-        internal::matcher_##DefineMatcher##OverloadId##Matcher>();             \
+        internal::matcher_##DefineMatcher##OverloadId##Matcher,                \
+        ReturnTypesF>();                                                       \
   }                                                                            \
   template <typename NodeType>                                                 \
   bool internal::matcher_##DefineMatcher##OverloadId##Matcher<                 \
@@ -193,11 +213,13 @@
 /// of the matcher Matcher<NodeType> returned by the function matcher().
 ///
 /// 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(DefineMatcher, ReturnTypesF, ParamType,      \
+                                  Param)                                       \
+  AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ReturnTypesF, ParamType,   \
+                                     Param, 0)
 
-#define AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ParamType, Param,    \
-                                           OverloadId)                         \
+#define AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ReturnTypesF,        \
+                                           ParamType, Param, OverloadId)       \
   namespace internal {                                                         \
   template <typename NodeType, typename ParamT>                                \
   class matcher_##DefineMatcher##OverloadId##Matcher                           \
@@ -214,11 +236,11 @@
   };                                                                           \
   }                                                                            \
   inline internal::PolymorphicMatcherWithParam1<                               \
-      internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType>       \
-  DefineMatcher(const ParamType &Param) {                                      \
+      internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType,       \
+      ReturnTypesF> DefineMatcher(const ParamType & Param) {                   \
     return internal::PolymorphicMatcherWithParam1<                             \
-        internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType>(    \
-        Param);                                                                \
+        internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType,     \
+        ReturnTypesF>(Param);                                                  \
   }                                                                            \
   template <typename NodeType, typename ParamT>                                \
   bool internal::matcher_##DefineMatcher##OverloadId##Matcher<                 \
@@ -233,13 +255,14 @@
 /// The variables are the same as for AST_MATCHER_P2, with the
 /// addition of NodeType, which specifies the node type of the matcher
 /// Matcher<NodeType> 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)    \
+#define AST_POLYMORPHIC_MATCHER_P2(DefineMatcher, ReturnTypesF, ParamType1,    \
+                                   Param1, ParamType2, Param2)                 \
+  AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ReturnTypesF, ParamType1, \
+                                      Param1, ParamType2, Param2, 0)
+
+#define AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ReturnTypesF,       \
+                                            ParamType1, Param1, ParamType2,    \
+                                            Param2, OverloadId)                \
   namespace internal {                                                         \
   template <typename NodeType, typename ParamT1, typename ParamT2>             \
   class matcher_##DefineMatcher##OverloadId##Matcher                           \
@@ -258,11 +281,11 @@
   }                                                                            \
   inline internal::PolymorphicMatcherWithParam2<                               \
       internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1,      \
-      ParamType2>                                                              \
-  DefineMatcher(const ParamType1 &Param1, const ParamType2 &Param2) {          \
+      ParamType2, ReturnTypesF> DefineMatcher(const ParamType1 & Param1,       \
+                                              const ParamType2 & Param2) {     \
     return internal::PolymorphicMatcherWithParam2<                             \
         internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1,    \
-        ParamType2>(Param1, Param2);                                           \
+        ParamType2, ReturnTypesF>(Param1, Param2);                             \
   }                                                                            \
   template <typename NodeType, typename ParamT1, typename ParamT2>             \
   bool internal::matcher_##DefineMatcher##OverloadId##Matcher<                 \

Modified: cfe/trunk/include/clang/ASTMatchers/Dynamic/Diagnostics.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/Dynamic/Diagnostics.h?rev=184558&r1=184557&r2=184558&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/Dynamic/Diagnostics.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/Dynamic/Diagnostics.h Fri Jun 21 10:51:31 2013
@@ -70,7 +70,8 @@ class Diagnostics {
     ET_ParserInvalidToken = 108,
     ET_ParserMalformedBindExpr = 109,
     ET_ParserTrailingCode = 110,
-    ET_ParserUnsignedError = 111
+    ET_ParserUnsignedError = 111,
+    ET_ParserOverloadedType = 112
   };
 
   /// \brief Helper stream class.

Modified: cfe/trunk/include/clang/ASTMatchers/Dynamic/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/Dynamic/Parser.h?rev=184558&r1=184557&r2=184558&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/Dynamic/Parser.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/Dynamic/Parser.h Fri Jun 21 10:51:31 2013
@@ -74,13 +74,14 @@ public:
     ///
     /// \param Args The argument list for the matcher.
     ///
-    /// \return The matcher object constructed by the processor, or NULL
-    ///   if an error occurred. In that case, \c Error will contain a
+    /// \return The matcher objects constructed by the processor, or an empty
+    ///   list if an error occurred. In that case, \c Error will contain a
     ///   description of the error.
-    ///   The caller takes ownership of the DynTypedMatcher object returned.
-    virtual DynTypedMatcher *actOnMatcherExpression(
-        StringRef MatcherName, const SourceRange &NameRange, StringRef BindID,
-        ArrayRef<ParserValue> Args, Diagnostics *Error) = 0;
+    virtual MatcherList actOnMatcherExpression(StringRef MatcherName,
+                                               const SourceRange &NameRange,
+                                               StringRef BindID,
+                                               ArrayRef<ParserValue> Args,
+                                               Diagnostics *Error) = 0;
   };
 
   /// \brief Parse a matcher expression, creating matchers from the registry.

Modified: cfe/trunk/include/clang/ASTMatchers/Dynamic/Registry.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/Dynamic/Registry.h?rev=184558&r1=184557&r2=184558&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/Dynamic/Registry.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/Dynamic/Registry.h Fri Jun 21 10:51:31 2013
@@ -43,26 +43,26 @@ public:
   ///   values must be valid for the matcher requested. Otherwise, the function
   ///   will return an error.
   ///
-  /// \return The matcher if no error was found. NULL if the matcher is not
-  //    found, or if the number of arguments or argument types do not
-  ///   match the signature. In that case \c Error will contain the description
-  ///   of the error.
-  static DynTypedMatcher *constructMatcher(StringRef MatcherName,
-                                           const SourceRange &NameRange,
-                                           ArrayRef<ParserValue> Args,
-                                           Diagnostics *Error);
+  /// \return The matcher objects constructed if no error was found.
+  ///   An empty list if the matcher is not found, or if the number of
+  ///   arguments or argument types do not match the signature.
+  ///   In that case \c Error will contain the description of the error.
+  static MatcherList constructMatcher(StringRef MatcherName,
+                                      const SourceRange &NameRange,
+                                      ArrayRef<ParserValue> Args,
+                                      Diagnostics *Error);
 
   /// \brief Construct a matcher from the registry and bind it.
   ///
   /// Similar the \c constructMatcher() above, but it then tries to bind the
   /// matcher to the specified \c BindID.
   /// If the matcher is not bindable, it sets an error in \c Error and returns
-  /// \c NULL.
-  static DynTypedMatcher *constructBoundMatcher(StringRef MatcherName,
-                                                const SourceRange &NameRange,
-                                                StringRef BindID,
-                                                ArrayRef<ParserValue> Args,
-                                                Diagnostics *Error);
+  /// an empty list.
+  static MatcherList constructBoundMatcher(StringRef MatcherName,
+                                           const SourceRange &NameRange,
+                                           StringRef BindID,
+                                           ArrayRef<ParserValue> Args,
+                                           Diagnostics *Error);
 
 private:
   Registry() LLVM_DELETED_FUNCTION;

Modified: cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h?rev=184558&r1=184557&r2=184558&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h Fri Jun 21 10:51:31 2013
@@ -17,6 +17,8 @@
 #ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
 #define LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
 
+#include <vector>
+
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/ASTMatchers/ASTMatchersInternal.h"
 #include "llvm/ADT/Twine.h"
@@ -28,6 +30,73 @@ namespace dynamic {
 
 using ast_matchers::internal::DynTypedMatcher;
 
+/// \brief A list of \c DynTypedMatcher objects.
+///
+/// The purpose of this list is to wrap multiple different matchers and
+/// provide the right one when calling \c hasTypedMatcher/getTypedMatcher.
+class MatcherList {
+public:
+  /// \brief An empty list.
+  MatcherList();
+  /// \brief Clones the matcher objects.
+  MatcherList(const MatcherList &Other);
+  /// \brief Clones the provided matcher.
+  MatcherList(const DynTypedMatcher &Matcher);
+  ~MatcherList();
+
+  MatcherList &operator=(const MatcherList &Other);
+
+  /// \brief Add a matcher to this list. The matcher is cloned.
+  void add(const DynTypedMatcher &Matcher);
+
+  /// \brief Empties the list.
+  void reset();
+
+  /// \brief Whether the list is empty.
+  bool empty() const { return List.empty(); }
+
+  ArrayRef<const DynTypedMatcher *> matchers() const { return List; }
+
+  /// \brief Determines if any of the contained matchers can be converted
+  ///   to \c Matcher<T>.
+  ///
+  /// Returns true if one, and only one, of the contained matchers can be
+  /// converted to \c Matcher<T>. If there are more than one that can, the
+  /// result would be ambigous and false is returned.
+  template <class T>
+  bool hasTypedMatcher() const {
+    size_t Matches = 0;
+    for (size_t I = 0, E = List.size(); I != E; ++I) {
+      Matches += ast_matchers::internal::Matcher<T>::canConstructFrom(*List[I]);
+    }
+    return Matches == 1;
+  }
+
+  /// \brief Wrap the correct matcher as a \c Matcher<T>.
+  ///
+  /// Selects the appropriate matcher from the list and returns it as a
+  /// \c Matcher<T>.
+  /// Asserts that \c hasTypedMatcher<T>() is true.
+  template <class T>
+  ast_matchers::internal::Matcher<T> getTypedMatcher() const {
+    assert(hasTypedMatcher<T>());
+    for (size_t I = 0, E = List.size(); I != E; ++I) {
+      if (ast_matchers::internal::Matcher<T>::canConstructFrom(*List[I]))
+        return ast_matchers::internal::Matcher<T>::constructFrom(*List[I]);
+    }
+    llvm_unreachable("!hasTypedMatcher<T>()");
+  }
+
+  /// \brief String representation of the type of the value.
+  ///
+  /// If there are more than one matcher on the list, the string will show all
+  /// the types.
+  std::string getTypeAsString() const;
+
+private:
+  std::vector<const DynTypedMatcher *> List;
+};
+
 /// \brief Variant value class.
 ///
 /// Basically, a tagged union with value type semantics.
@@ -39,7 +108,7 @@ using ast_matchers::internal::DynTypedMa
 /// Supported types:
 ///  - \c unsigned
 ///  - \c std::string
-///  - \c DynTypedMatcher, and any \c Matcher<T>
+///  - \c MatcherList (\c DynTypedMatcher / \c Matcher<T>)
 class VariantValue {
 public:
   VariantValue() : Type(VT_Nothing) {}
@@ -52,6 +121,7 @@ public:
   VariantValue(unsigned Unsigned);
   VariantValue(const std::string &String);
   VariantValue(const DynTypedMatcher &Matcher);
+  VariantValue(const MatcherList &Matchers);
 
   /// \brief Unsigned value functions.
   bool isUnsigned() const;
@@ -64,22 +134,19 @@ public:
   void setString(const std::string &String);
 
   /// \brief Matcher value functions.
-  bool isMatcher() const;
-  const DynTypedMatcher &getMatcher() const;
-  void setMatcher(const DynTypedMatcher &Matcher);
-  /// \brief Set the value to be \c Matcher by taking ownership of the object.
-  void takeMatcher(DynTypedMatcher *Matcher);
+  bool isMatchers() const;
+  const MatcherList &getMatchers() const;
+  void setMatchers(const MatcherList &Matchers);
 
-  /// \brief Specialized Matcher<T> functions.
+  /// \brief Shortcut functions.
   template <class T>
   bool hasTypedMatcher() const {
-    return isMatcher() &&
-           ast_matchers::internal::Matcher<T>::canConstructFrom(getMatcher());
+    return isMatchers() && getMatchers().hasTypedMatcher<T>();
   }
 
   template <class T>
   ast_matchers::internal::Matcher<T> getTypedMatcher() const {
-    return ast_matchers::internal::Matcher<T>::constructFrom(getMatcher());
+    return getMatchers().getTypedMatcher<T>();
   }
 
   /// \brief String representation of the type of the value.
@@ -93,14 +160,14 @@ private:
     VT_Nothing,
     VT_Unsigned,
     VT_String,
-    VT_Matcher
+    VT_Matchers
   };
 
   /// \brief All supported value types.
   union AllValues {
     unsigned Unsigned;
     std::string *String;
-    DynTypedMatcher *Matcher;
+    MatcherList *Matchers;
   };
 
   ValueType Type;

Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Diagnostics.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Diagnostics.cpp?rev=184558&r1=184557&r2=184558&view=diff
==============================================================================
--- cfe/trunk/lib/ASTMatchers/Dynamic/Diagnostics.cpp (original)
+++ cfe/trunk/lib/ASTMatchers/Dynamic/Diagnostics.cpp Fri Jun 21 10:51:31 2013
@@ -64,6 +64,8 @@ StringRef ErrorTypeToString(Diagnostics:
     return "Expected end of code.";
   case Diagnostics::ET_ParserUnsignedError:
     return "Error parsing unsigned token: <$0>";
+  case Diagnostics::ET_ParserOverloadedType:
+    return "Input value has unresolved overloaded type: $0";
 
   case Diagnostics::ET_None:
     return "<N/A>";

Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h?rev=184558&r1=184557&r2=184558&view=diff
==============================================================================
--- cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h (original)
+++ cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h Fri Jun 21 10:51:31 2013
@@ -49,6 +49,10 @@ template <> struct ArgTypeTraits<std::st
   }
 };
 
+template <>
+struct ArgTypeTraits<StringRef> : public ArgTypeTraits<std::string> {
+};
+
 template <class T> struct ArgTypeTraits<ast_matchers::internal::Matcher<T> > {
   static std::string asString() {
     return (Twine("Matcher<") +
@@ -78,9 +82,9 @@ template <> struct ArgTypeTraits<unsigne
 class MatcherCreateCallback {
 public:
   virtual ~MatcherCreateCallback() {}
-  virtual DynTypedMatcher *run(const SourceRange &NameRange,
-                               ArrayRef<ParserValue> Args,
-                               Diagnostics *Error) const = 0;
+  virtual MatcherList run(const SourceRange &NameRange,
+                          ArrayRef<ParserValue> Args,
+                          Diagnostics *Error) const = 0;
 };
 
 /// \brief Simple callback implementation. Marshaller and function are provided.
@@ -95,10 +99,10 @@ public:
   /// FIXME: Use void(*)() as FuncType on this interface to remove the template
   /// argument of this class. The marshaller can cast the function pointer back
   /// to the original type.
-  typedef DynTypedMatcher *(*MarshallerType)(FuncType, StringRef,
-                                             const SourceRange &,
-                                             ArrayRef<ParserValue>,
-                                             Diagnostics *);
+  typedef MatcherList (*MarshallerType)(FuncType, StringRef,
+                                        const SourceRange &,
+                                        ArrayRef<ParserValue>,
+                                        Diagnostics *);
 
   /// \param Marshaller Function to unpack the arguments and call \c Func
   /// \param Func Matcher construct function. This is the function that
@@ -107,8 +111,8 @@ public:
                                      StringRef MatcherName)
       : Marshaller(Marshaller), Func(Func), MatcherName(MatcherName.str()) {}
 
-  DynTypedMatcher *run(const SourceRange &NameRange,
-                       ArrayRef<ParserValue> Args, Diagnostics *Error) const {
+  MatcherList run(const SourceRange &NameRange, ArrayRef<ParserValue> Args,
+                  Diagnostics *Error) const {
     return Marshaller(Func, MatcherName, NameRange, Args, Error);
   }
 
@@ -127,16 +131,16 @@ private:
 /// object file.
 class FreeFuncMatcherCreateCallback : public MatcherCreateCallback {
 public:
-  typedef DynTypedMatcher *(*RunFunc)(StringRef MatcherName,
-                                      const SourceRange &NameRange,
-                                      ArrayRef<ParserValue> Args,
-                                      Diagnostics *Error);
+  typedef MatcherList (*RunFunc)(StringRef MatcherName,
+                                 const SourceRange &NameRange,
+                                 ArrayRef<ParserValue> Args,
+                                 Diagnostics *Error);
 
   FreeFuncMatcherCreateCallback(RunFunc Func, StringRef MatcherName)
       : Func(Func), MatcherName(MatcherName.str()) {}
 
-  DynTypedMatcher *run(const SourceRange &NameRange, ArrayRef<ParserValue> Args,
-                       Diagnostics *Error) const {
+  MatcherList run(const SourceRange &NameRange, ArrayRef<ParserValue> Args,
+                  Diagnostics *Error) const {
     return Func(MatcherName, NameRange, Args, Error);
   }
 
@@ -150,7 +154,7 @@ private:
   if (Args.size() != count) {                                                  \
     Error->pushErrorFrame(NameRange, Error->ET_RegistryWrongArgCount)          \
         << count << Args.size();                                               \
-    return NULL;                                                               \
+    return MatcherList();                                                      \
   }
 
 #define CHECK_ARG_TYPE(index, type)                                            \
@@ -158,43 +162,78 @@ private:
     Error->pushErrorFrame(Args[index].Range, Error->ET_RegistryWrongArgType)   \
         << (index + 1) << ArgTypeTraits<type>::asString()                      \
         << Args[index].Value.getTypeAsString();                                \
-    return NULL;                                                               \
+    return MatcherList();                                                      \
   }
 
+/// \brief Helper methods to extract and merge all possible typed matchers
+/// out of the polymorphic object.
+template <class PolyMatcher>
+static void mergePolyMatchers(const PolyMatcher &Poly, MatcherList *Out,
+                              ast_matchers::internal::EmptyTypeList) {}
+
+template <class PolyMatcher, class TypeList>
+static void mergePolyMatchers(const PolyMatcher &Poly, MatcherList *Out,
+                              TypeList) {
+  Out->add(ast_matchers::internal::Matcher<typename TypeList::head>(Poly));
+  mergePolyMatchers(Poly, Out, typename TypeList::tail());
+}
+
+/// \brief Convert the return values of the functions into a MatcherList.
+///
+/// There are 2 cases right now: The return value is a Matcher<T> or is a
+/// polymorphic matcher. For the former, we just construct the MatcherList. For
+/// the latter, we instantiate all the possible Matcher<T> of the poly matcher.
+template <typename T>
+static MatcherList
+outvalueToMatcherList(const ast_matchers::internal::Matcher<T> &Matcher) {
+  return MatcherList(Matcher);
+}
+
+template <typename T>
+static MatcherList
+outvalueToMatcherList(const T& PolyMatcher, typename T::ReturnTypes* = NULL) {
+  MatcherList Matchers;
+  mergePolyMatchers(PolyMatcher, &Matchers, typename T::ReturnTypes());
+  return Matchers;
+}
+
 /// \brief 0-arg marshaller function.
 template <typename ReturnType>
-DynTypedMatcher *matcherMarshall0(ReturnType (*Func)(), StringRef MatcherName,
-                                  const SourceRange &NameRange,
-                                  ArrayRef<ParserValue> Args,
-                                  Diagnostics *Error) {
+static MatcherList matcherMarshall0(ReturnType (*Func)(),
+                                    StringRef MatcherName,
+                                    const SourceRange &NameRange,
+                                    ArrayRef<ParserValue> Args,
+                                    Diagnostics *Error) {
   CHECK_ARG_COUNT(0);
-  return Func().clone();
+  return outvalueToMatcherList(Func());
 }
 
 /// \brief 1-arg marshaller function.
 template <typename ReturnType, typename ArgType1>
-DynTypedMatcher *matcherMarshall1(ReturnType (*Func)(ArgType1),
-                                  StringRef MatcherName,
-                                  const SourceRange &NameRange,
-                                  ArrayRef<ParserValue> Args,
-                                  Diagnostics *Error) {
+static MatcherList matcherMarshall1(ReturnType (*Func)(ArgType1),
+                                    StringRef MatcherName,
+                                    const SourceRange &NameRange,
+                                    ArrayRef<ParserValue> Args,
+                                    Diagnostics *Error) {
   CHECK_ARG_COUNT(1);
   CHECK_ARG_TYPE(0, ArgType1);
-  return Func(ArgTypeTraits<ArgType1>::get(Args[0].Value)).clone();
+  return outvalueToMatcherList(
+      Func(ArgTypeTraits<ArgType1>::get(Args[0].Value)));
 }
 
 /// \brief 2-arg marshaller function.
 template <typename ReturnType, typename ArgType1, typename ArgType2>
-DynTypedMatcher *matcherMarshall2(ReturnType (*Func)(ArgType1, ArgType2),
-                                  StringRef MatcherName,
-                                  const SourceRange &NameRange,
-                                  ArrayRef<ParserValue> Args,
-                                  Diagnostics *Error) {
+static MatcherList matcherMarshall2(ReturnType (*Func)(ArgType1, ArgType2),
+                                    StringRef MatcherName,
+                                    const SourceRange &NameRange,
+                                    ArrayRef<ParserValue> Args,
+                                    Diagnostics *Error) {
   CHECK_ARG_COUNT(2);
   CHECK_ARG_TYPE(0, ArgType1);
   CHECK_ARG_TYPE(1, ArgType2);
-  return Func(ArgTypeTraits<ArgType1>::get(Args[0].Value),
-              ArgTypeTraits<ArgType2>::get(Args[1].Value)).clone();
+  return outvalueToMatcherList(
+      Func(ArgTypeTraits<ArgType1>::get(Args[0].Value),
+           ArgTypeTraits<ArgType2>::get(Args[1].Value)));
 }
 
 #undef CHECK_ARG_COUNT
@@ -202,10 +241,10 @@ DynTypedMatcher *matcherMarshall2(Return
 
 /// \brief Variadic marshaller function.
 template <typename BaseType, typename DerivedType>
-DynTypedMatcher *VariadicMatcherCreateCallback(StringRef MatcherName,
-                                               const SourceRange &NameRange,
-                                               ArrayRef<ParserValue> Args,
-                                               Diagnostics *Error) {
+MatcherList VariadicMatcherCreateCallback(StringRef MatcherName,
+                                          const SourceRange &NameRange,
+                                          ArrayRef<ParserValue> Args,
+                                          Diagnostics *Error) {
   typedef ast_matchers::internal::Matcher<DerivedType> DerivedMatcherType;
   DerivedMatcherType **InnerArgs = new DerivedMatcherType *[Args.size()]();
 
@@ -223,10 +262,10 @@ DynTypedMatcher *VariadicMatcherCreateCa
     InnerArgs[i] = new DerivedMatcherType(DerivedTraits::get(Value));
   }
 
-  DynTypedMatcher *Out = NULL;
+  MatcherList Out;
   if (!HasError) {
     Out = ast_matchers::internal::makeDynCastAllOfComposite<BaseType>(
-        ArrayRef<const DerivedMatcherType *>(InnerArgs, Args.size())).clone();
+        ArrayRef<const DerivedMatcherType *>(InnerArgs, Args.size()));
   }
 
   for (size_t i = 0, e = Args.size(); i != e; ++i) {
@@ -264,7 +303,7 @@ MatcherCreateCallback *makeMatcherAutoMa
       ReturnType (*)(ArgType1, ArgType2)>(matcherMarshall2, Func, MatcherName);
 }
 
-/// \brief Variadic overload.
+/// \brief Variadic overloads.
 template <typename MatcherType>
 MatcherCreateCallback *makeMatcherAutoMarshall(
     ast_matchers::internal::VariadicAllOfMatcher<MatcherType> Func,

Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Parser.cpp?rev=184558&r1=184557&r2=184558&view=diff
==============================================================================
--- cfe/trunk/lib/ASTMatchers/Dynamic/Parser.cpp (original)
+++ cfe/trunk/lib/ASTMatchers/Dynamic/Parser.cpp Fri Jun 21 10:51:31 2013
@@ -315,15 +315,15 @@ bool Parser::parseMatcherExpressionImpl(
   // Merge the start and end infos.
   SourceRange MatcherRange = NameToken.Range;
   MatcherRange.End = EndToken.Range.End;
-  DynTypedMatcher *Result = S->actOnMatcherExpression(
+  MatcherList Result = S->actOnMatcherExpression(
       NameToken.Text, MatcherRange, BindID, Args, Error);
-  if (Result == NULL) {
+  if (Result.empty()) {
     Error->pushErrorFrame(NameToken.Range, Error->ET_ParserMatcherFailure)
         << NameToken.Text;
     return false;
   }
 
-  Value->takeMatcher(Result);
+  *Value = Result;
   return true;
 }
 
@@ -367,11 +367,11 @@ Parser::Parser(CodeTokenizer *Tokenizer,
 class RegistrySema : public Parser::Sema {
 public:
   virtual ~RegistrySema() {}
-  DynTypedMatcher *actOnMatcherExpression(StringRef MatcherName,
-                                          const SourceRange &NameRange,
-                                          StringRef BindID,
-                                          ArrayRef<ParserValue> Args,
-                                          Diagnostics *Error) {
+  MatcherList actOnMatcherExpression(StringRef MatcherName,
+                                     const SourceRange &NameRange,
+                                     StringRef BindID,
+                                     ArrayRef<ParserValue> Args,
+                                     Diagnostics *Error) {
     if (BindID.empty()) {
       return Registry::constructMatcher(MatcherName, NameRange, Args, Error);
     } else {
@@ -411,11 +411,16 @@ DynTypedMatcher *Parser::parseMatcherExp
   VariantValue Value;
   if (!parseExpression(Code, S, &Value, Error))
     return NULL;
-  if (!Value.isMatcher()) {
+  if (!Value.isMatchers()) {
     Error->pushErrorFrame(SourceRange(), Error->ET_ParserNotAMatcher);
     return NULL;
   }
-  return Value.getMatcher().clone();
+  if (Value.getMatchers().matchers().size() != 1) {
+    Error->pushErrorFrame(SourceRange(), Error->ET_ParserOverloadedType)
+        << Value.getTypeAsString();
+    return NULL;
+  }
+  return Value.getMatchers().matchers()[0]->clone();
 }
 
 }  // namespace dynamic

Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp?rev=184558&r1=184557&r2=184558&view=diff
==============================================================================
--- cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp (original)
+++ cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp Fri Jun 21 10:51:31 2013
@@ -68,7 +68,6 @@ RegistryMaps::RegistryMaps() {
   // forField
   // withInitializer
   // isWritten
-  // isImplicit
   //
   // Type traversal:
   // hasElementType
@@ -87,19 +86,6 @@ RegistryMaps::RegistryMaps() {
   // references
   // thisPointerType
   //
-  // Polymorphic matchers:
-  // anything
-  // hasAnyArgument
-  // isTemplateInstantiation
-  // isExplicitTemplateSpecialization
-  // isDefinition
-  // hasOperatorName
-  // hasOverloadedOperatorName
-  // hasCondition
-  // hasBody
-  // argumentCountIs
-  // hasArgument
-  //
   // Polymorphic + argument overload:
   // unless
   // eachOf
@@ -123,6 +109,8 @@ RegistryMaps::RegistryMaps() {
 
   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 @@ RegistryMaps::RegistryMaps() {
   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 @@ RegistryMaps::RegistryMaps() {
   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 @@ RegistryMaps::RegistryMaps() {
   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 @@ RegistryMaps::RegistryMaps() {
   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 @@ static llvm::ManagedStatic<RegistryMaps>
 } // 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

Modified: cfe/trunk/lib/ASTMatchers/Dynamic/VariantValue.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/VariantValue.cpp?rev=184558&r1=184557&r2=184558&view=diff
==============================================================================
--- cfe/trunk/lib/ASTMatchers/Dynamic/VariantValue.cpp (original)
+++ cfe/trunk/lib/ASTMatchers/Dynamic/VariantValue.cpp Fri Jun 21 10:51:31 2013
@@ -20,6 +20,48 @@ namespace clang {
 namespace ast_matchers {
 namespace dynamic {
 
+MatcherList::MatcherList() : List() {}
+
+MatcherList::MatcherList(const DynTypedMatcher &Matcher)
+    : List(1, Matcher.clone()) {}
+
+MatcherList::MatcherList(const MatcherList& Other) {
+  *this = Other;
+}
+
+MatcherList::~MatcherList() {
+  reset();
+}
+
+MatcherList &MatcherList::operator=(const MatcherList &Other) {
+  if (this == &Other) return *this;
+  reset();
+  for (size_t i = 0, e = Other.List.size(); i != e; ++i) {
+    List.push_back(Other.List[i]->clone());
+  }
+  return *this;
+}
+
+void MatcherList::add(const DynTypedMatcher &Matcher) {
+  List.push_back(Matcher.clone());
+}
+
+void MatcherList::reset() {
+  for (size_t i = 0, e = List.size(); i != e; ++i) {
+    delete List[i];
+  }
+  List.resize(0);
+}
+
+std::string MatcherList::getTypeAsString() const {
+  std::string Inner;
+  for (size_t I = 0, E = List.size(); I != E; ++I) {
+    if (I != 0) Inner += "|";
+    Inner += List[I]->getSupportedKind().asStringRef();
+  }
+  return (Twine("Matcher<") + Inner + ">").str();
+}
+
 VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
   *this = Other;
 }
@@ -33,7 +75,11 @@ VariantValue::VariantValue(const std::st
 }
 
 VariantValue::VariantValue(const DynTypedMatcher &Matcher) : Type(VT_Nothing) {
-  setMatcher(Matcher);
+  setMatchers(MatcherList(Matcher));
+}
+
+VariantValue::VariantValue(const MatcherList &Matchers) : Type(VT_Nothing) {
+  setMatchers(Matchers);
 }
 
 VariantValue::~VariantValue() { reset(); }
@@ -48,8 +94,8 @@ VariantValue &VariantValue::operator=(co
   case VT_String:
     setString(Other.getString());
     break;
-  case VT_Matcher:
-    setMatcher(Other.getMatcher());
+  case VT_Matchers:
+    setMatchers(Other.getMatchers());
     break;
   case VT_Nothing:
     Type = VT_Nothing;
@@ -63,8 +109,8 @@ void VariantValue::reset() {
   case VT_String:
     delete Value.String;
     break;
-  case VT_Matcher:
-    delete Value.Matcher;
+  case VT_Matchers:
+    delete Value.Matchers;
     break;
   // Cases that do nothing.
   case VT_Unsigned:
@@ -104,33 +150,25 @@ void VariantValue::setString(const std::
   Value.String = new std::string(NewValue);
 }
 
-bool VariantValue::isMatcher() const {
-  return Type == VT_Matcher;
+bool VariantValue::isMatchers() const {
+  return Type == VT_Matchers;
 }
 
-const DynTypedMatcher &VariantValue::getMatcher() const {
-  assert(isMatcher());
-  return *Value.Matcher;
-}
-
-void VariantValue::setMatcher(const DynTypedMatcher &NewValue) {
-  reset();
-  Type = VT_Matcher;
-  Value.Matcher = NewValue.clone();
+const MatcherList &VariantValue::getMatchers() const {
+  assert(isMatchers());
+  return *Value.Matchers;
 }
 
-void VariantValue::takeMatcher(DynTypedMatcher *NewValue) {
+void VariantValue::setMatchers(const MatcherList &NewValue) {
   reset();
-  Type = VT_Matcher;
-  Value.Matcher = NewValue;
+  Type = VT_Matchers;
+  Value.Matchers = new MatcherList(NewValue);
 }
 
 std::string VariantValue::getTypeAsString() const {
   switch (Type) {
   case VT_String: return "String";
-  case VT_Matcher:
-    return (Twine("Matcher<") + getMatcher().getSupportedKind().asStringRef() +
-            ">").str();
+  case VT_Matchers: return getMatchers().getTypeAsString();
   case VT_Unsigned: return "Unsigned";
   case VT_Nothing: return "Nothing";
   }

Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp?rev=184558&r1=184557&r2=184558&view=diff
==============================================================================
--- cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp Fri Jun 21 10:51:31 2013
@@ -2250,10 +2250,9 @@ TEST(AstMatcherPMacro, Works) {
 }
 
 AST_POLYMORPHIC_MATCHER_P(
-    polymorphicHas, internal::Matcher<Decl>, AMatcher) {
-  TOOLING_COMPILE_ASSERT((llvm::is_same<NodeType, Decl>::value) ||
-                         (llvm::is_same<NodeType, Stmt>::value),
-                         assert_node_type_is_accessible);
+    polymorphicHas,
+    AST_POLYMORPHIC_SUPPORTED_TYPES_2(Decl, Stmt),
+    internal::Matcher<Decl>, AMatcher) {
   return Finder->matchesChildOf(
       Node, AMatcher, Builder,
       ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses,

Modified: cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp?rev=184558&r1=184557&r2=184558&view=diff
==============================================================================
--- cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp Fri Jun 21 10:51:31 2013
@@ -52,6 +52,7 @@ public:
   virtual ast_type_traits::ASTNodeKind getSupportedKind() const {
     return ast_type_traits::ASTNodeKind();
   }
+
 private:
   uint64_t ID;
   std::string BoundID;
@@ -75,15 +76,16 @@ public:
     Errors.push_back(Error.ToStringFull());
   }
 
-  DynTypedMatcher *actOnMatcherExpression(StringRef MatcherName,
-                                          const SourceRange &NameRange,
-                                          StringRef BindID,
-                                          ArrayRef<ParserValue> Args,
-                                          Diagnostics *Error) {
+  MatcherList actOnMatcherExpression(StringRef MatcherName,
+                                     const SourceRange &NameRange,
+                                     StringRef BindID,
+                                     ArrayRef<ParserValue> Args,
+                                     Diagnostics *Error) {
     MatcherInfo ToStore = { MatcherName, NameRange, Args, BindID };
     Matchers.push_back(ToStore);
     DummyDynTypedMatcher Matcher(ExpectedMatchers[MatcherName]);
-    return Matcher.tryBind(BindID);
+    OwningPtr<DynTypedMatcher> Out(Matcher.tryBind(BindID));
+    return *Out;
   }
 
   struct MatcherInfo {
@@ -146,9 +148,9 @@ TEST(ParserTest, ParseMatcher) {
   }
 
   EXPECT_EQ(1ULL, Sema.Values.size());
-  EXPECT_EQ(ExpectedFoo, Sema.Values[0].getMatcher().getID());
-  EXPECT_EQ("Yo!", static_cast<const DummyDynTypedMatcher &>(
-                       Sema.Values[0].getMatcher()).boundID());
+  EXPECT_EQ(ExpectedFoo, Sema.Values[0].getMatchers().matchers()[0]->getID());
+  EXPECT_EQ("Yo!", static_cast<const DummyDynTypedMatcher *>(
+                       Sema.Values[0].getMatchers().matchers()[0])->boundID());
 
   EXPECT_EQ(3ULL, Sema.Matchers.size());
   const MockSema::MatcherInfo Bar = Sema.Matchers[0];
@@ -167,8 +169,10 @@ TEST(ParserTest, ParseMatcher) {
   EXPECT_EQ("Foo", Foo.MatcherName);
   EXPECT_TRUE(matchesRange(Foo.NameRange, 1, 2, 2, 12));
   EXPECT_EQ(2ULL, Foo.Args.size());
-  EXPECT_EQ(ExpectedBar, Foo.Args[0].Value.getMatcher().getID());
-  EXPECT_EQ(ExpectedBaz, Foo.Args[1].Value.getMatcher().getID());
+  EXPECT_EQ(ExpectedBar,
+            Foo.Args[0].Value.getMatchers().matchers()[0]->getID());
+  EXPECT_EQ(ExpectedBaz,
+            Foo.Args[1].Value.getMatchers().matchers()[0]->getID());
   EXPECT_EQ("Yo!", Foo.BoundID);
 }
 
@@ -176,11 +180,14 @@ using ast_matchers::internal::Matcher;
 
 TEST(ParserTest, FullParserTest) {
   OwningPtr<DynTypedMatcher> VarDecl(Parser::parseMatcherExpression(
-      "varDecl(hasInitializer(binaryOperator(hasLHS(integerLiteral()))))",
+      "varDecl(hasInitializer(binaryOperator(hasLHS(integerLiteral()),"
+      "                                      hasOperatorName(\"+\"))))",
       NULL));
   Matcher<Decl> M = Matcher<Decl>::constructFrom(*VarDecl);
   EXPECT_TRUE(matches("int x = 1 + false;", M));
   EXPECT_FALSE(matches("int x = true + 1;", M));
+  EXPECT_FALSE(matches("int x = 1 - false;", M));
+  EXPECT_FALSE(matches("int x = true - 1;", M));
 
   OwningPtr<DynTypedMatcher> HasParameter(Parser::parseMatcherExpression(
       "functionDecl(hasParameter(1, hasName(\"x\")))", NULL));
@@ -242,6 +249,9 @@ TEST(ParserTest, Errors) {
   EXPECT_EQ("1:1: Error building matcher isArrow.\n"
             "1:1: Matcher does not support binding.",
             ParseWithError("isArrow().bind(\"foo\")"));
+  EXPECT_EQ("Input value has unresolved overloaded type: "
+            "Matcher<DoStmt|ForStmt|WhileStmt>",
+            ParseMatcherWithError("hasBody(stmt())"));
 }
 
 }  // end anonymous namespace

Modified: cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp?rev=184558&r1=184557&r2=184558&view=diff
==============================================================================
--- cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp Fri Jun 21 10:51:31 2013
@@ -38,25 +38,23 @@ public:
 
   template <class T>
   Matcher<T> constructMatcher(StringRef MatcherName, Diagnostics *Error) {
-    OwningPtr<DynTypedMatcher> Out(
-        Registry::constructMatcher(MatcherName, SourceRange(), Args(), Error));
-    return Matcher<T>::constructFrom(*Out);
+    return Registry::constructMatcher(MatcherName, SourceRange(), Args(), Error)
+        .getTypedMatcher<T>();
   }
 
   template <class T>
   Matcher<T> constructMatcher(StringRef MatcherName, const VariantValue &Arg1,
                               Diagnostics *Error) {
-    OwningPtr<DynTypedMatcher> Out(Registry::constructMatcher(
-        MatcherName, SourceRange(), Args(Arg1), Error));
-    return Matcher<T>::constructFrom(*Out);
+    return Registry::constructMatcher(MatcherName, SourceRange(), Args(Arg1),
+                                      Error).getTypedMatcher<T>();
   }
 
   template <class T>
   Matcher<T> constructMatcher(StringRef MatcherName, const VariantValue &Arg1,
                               const VariantValue &Arg2, Diagnostics *Error) {
-    OwningPtr<DynTypedMatcher> Out(Registry::constructMatcher(
-        MatcherName, SourceRange(), Args(Arg1, Arg2), Error));
-    return Matcher<T>::constructFrom(*Out);
+    return Registry::constructMatcher(MatcherName, SourceRange(),
+                                      Args(Arg1, Arg2), Error)
+        .getTypedMatcher<T>();
   }
 };
 
@@ -115,34 +113,57 @@ TEST_F(RegistryTest, ConstructWithMatche
   EXPECT_FALSE(matches("void f(int x, int a);", HasParameter));
 }
 
+TEST_F(RegistryTest, PolymorphicMatchers) {
+  const MatcherList IsDefinition =
+      Registry::constructMatcher("isDefinition", SourceRange(), Args(), NULL);
+  Matcher<Decl> Var = constructMatcher<Decl>("varDecl", IsDefinition, NULL);
+  Matcher<Decl> Class =
+      constructMatcher<Decl>("recordDecl", IsDefinition, NULL);
+  Matcher<Decl> Func =
+      constructMatcher<Decl>("functionDecl", IsDefinition, NULL);
+  EXPECT_TRUE(matches("int a;", Var));
+  EXPECT_FALSE(matches("extern int a;", Var));
+  EXPECT_TRUE(matches("class A {};", Class));
+  EXPECT_FALSE(matches("class A;", Class));
+  EXPECT_TRUE(matches("void f(){};", Func));
+  EXPECT_FALSE(matches("void f();", Func));
+
+  Matcher<Decl> Anything = constructMatcher<Decl>("anything", NULL);
+  Matcher<Decl> RecordDecl =
+      constructMatcher<Decl>("recordDecl", Anything, NULL);
+
+  EXPECT_TRUE(matches("int a;", Anything));
+  EXPECT_TRUE(matches("class A {};", Anything));
+  EXPECT_TRUE(matches("void f(){};", Anything));
+  EXPECT_FALSE(matches("int a;", RecordDecl));
+  EXPECT_TRUE(matches("class A {};", RecordDecl));
+  EXPECT_FALSE(matches("void f(){};", RecordDecl));
+}
+
 TEST_F(RegistryTest, Errors) {
   // Incorrect argument count.
   OwningPtr<Diagnostics> Error(new Diagnostics());
-  EXPECT_TRUE(NULL ==
-              Registry::constructMatcher("hasInitializer", SourceRange(),
-                                         Args(), Error.get()));
+  EXPECT_TRUE(Registry::constructMatcher("hasInitializer", SourceRange(),
+                                         Args(), Error.get()).empty());
   EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)",
             Error->ToString());
   Error.reset(new Diagnostics());
-  EXPECT_TRUE(NULL ==
-              Registry::constructMatcher("isArrow", SourceRange(),
-                                         Args(std::string()), Error.get()));
+  EXPECT_TRUE(Registry::constructMatcher(
+      "isArrow", SourceRange(), Args(std::string()), Error.get()).empty());
   EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)",
             Error->ToString());
 
   // Bad argument type
   Error.reset(new Diagnostics());
-  EXPECT_TRUE(NULL ==
-              Registry::constructMatcher("ofClass", SourceRange(),
-                                         Args(std::string()), Error.get()));
+  EXPECT_TRUE(Registry::constructMatcher(
+      "ofClass", SourceRange(), Args(std::string()), Error.get()).empty());
   EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != "
             "(Actual = String)",
             Error->ToString());
   Error.reset(new Diagnostics());
-  EXPECT_TRUE(NULL ==
-              Registry::constructMatcher(
-                  "recordDecl", SourceRange(),
-                  Args(recordDecl(), parameterCountIs(3)), Error.get()));
+  EXPECT_TRUE(Registry::constructMatcher(
+      "recordDecl", SourceRange(), Args(recordDecl(), parameterCountIs(3)),
+      Error.get()).empty());
   EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != "
             "(Actual = Matcher<FunctionDecl>)",
             Error->ToString());

Modified: cfe/trunk/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp?rev=184558&r1=184557&r2=184558&view=diff
==============================================================================
--- cfe/trunk/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp Fri Jun 21 10:51:31 2013
@@ -27,9 +27,9 @@ TEST(VariantValueTest, Unsigned) {
   EXPECT_EQ(kUnsigned, Value.getUnsigned());
 
   EXPECT_FALSE(Value.isString());
-  EXPECT_FALSE(Value.isMatcher());
-  EXPECT_FALSE(Value.hasTypedMatcher<clang::Decl>());
-  EXPECT_FALSE(Value.hasTypedMatcher<clang::UnaryOperator>());
+  EXPECT_FALSE(Value.isMatchers());
+  EXPECT_FALSE(Value.hasTypedMatcher<Decl>());
+  EXPECT_FALSE(Value.hasTypedMatcher<UnaryOperator>());
 }
 
 TEST(VariantValueTest, String) {
@@ -41,9 +41,7 @@ TEST(VariantValueTest, String) {
   EXPECT_EQ("String", Value.getTypeAsString());
 
   EXPECT_FALSE(Value.isUnsigned());
-  EXPECT_FALSE(Value.isMatcher());
-  EXPECT_FALSE(Value.hasTypedMatcher<clang::Decl>());
-  EXPECT_FALSE(Value.hasTypedMatcher<clang::UnaryOperator>());
+  EXPECT_FALSE(Value.isMatchers());
 }
 
 TEST(VariantValueTest, DynTypedMatcher) {
@@ -52,25 +50,25 @@ TEST(VariantValueTest, DynTypedMatcher)
   EXPECT_FALSE(Value.isUnsigned());
   EXPECT_FALSE(Value.isString());
 
-  EXPECT_TRUE(Value.isMatcher());
-  EXPECT_FALSE(Value.hasTypedMatcher<clang::Decl>());
-  EXPECT_TRUE(Value.hasTypedMatcher<clang::UnaryOperator>());
+  EXPECT_TRUE(Value.isMatchers());
+  EXPECT_FALSE(Value.hasTypedMatcher<Decl>());
+  EXPECT_TRUE(Value.hasTypedMatcher<UnaryOperator>());
   EXPECT_EQ("Matcher<Stmt>", Value.getTypeAsString());
 
   // Can only convert to compatible matchers.
   Value = recordDecl();
-  EXPECT_TRUE(Value.isMatcher());
-  EXPECT_TRUE(Value.hasTypedMatcher<clang::Decl>());
-  EXPECT_FALSE(Value.hasTypedMatcher<clang::UnaryOperator>());
+  EXPECT_TRUE(Value.isMatchers());
+  EXPECT_TRUE(Value.hasTypedMatcher<Decl>());
+  EXPECT_FALSE(Value.hasTypedMatcher<UnaryOperator>());
   EXPECT_EQ("Matcher<Decl>", Value.getTypeAsString());
 
   Value = ignoringImpCasts(expr());
-  EXPECT_TRUE(Value.isMatcher());
-  EXPECT_FALSE(Value.hasTypedMatcher<clang::Decl>());
-  EXPECT_FALSE(Value.hasTypedMatcher<clang::Stmt>());
-  EXPECT_TRUE(Value.hasTypedMatcher<clang::Expr>());
-  EXPECT_TRUE(Value.hasTypedMatcher<clang::IntegerLiteral>());
-  EXPECT_FALSE(Value.hasTypedMatcher<clang::GotoStmt>());
+  EXPECT_TRUE(Value.isMatchers());
+  EXPECT_FALSE(Value.hasTypedMatcher<Decl>());
+  EXPECT_FALSE(Value.hasTypedMatcher<Stmt>());
+  EXPECT_TRUE(Value.hasTypedMatcher<Expr>());
+  EXPECT_TRUE(Value.hasTypedMatcher<IntegerLiteral>());
+  EXPECT_FALSE(Value.hasTypedMatcher<GotoStmt>());
   EXPECT_EQ("Matcher<Expr>", Value.getTypeAsString());
 }
 
@@ -79,31 +77,31 @@ TEST(VariantValueTest, Assignment) {
   EXPECT_TRUE(Value.isString());
   EXPECT_EQ("A", Value.getString());
   EXPECT_FALSE(Value.isUnsigned());
-  EXPECT_FALSE(Value.isMatcher());
+  EXPECT_FALSE(Value.isMatchers());
   EXPECT_EQ("String", Value.getTypeAsString());
 
   Value = recordDecl();
   EXPECT_FALSE(Value.isUnsigned());
   EXPECT_FALSE(Value.isString());
-  EXPECT_TRUE(Value.isMatcher());
-  EXPECT_TRUE(Value.hasTypedMatcher<clang::Decl>());
-  EXPECT_FALSE(Value.hasTypedMatcher<clang::UnaryOperator>());
+  EXPECT_TRUE(Value.isMatchers());
+  EXPECT_TRUE(Value.hasTypedMatcher<Decl>());
+  EXPECT_FALSE(Value.hasTypedMatcher<UnaryOperator>());
   EXPECT_EQ("Matcher<Decl>", Value.getTypeAsString());
 
   Value = 17;
   EXPECT_TRUE(Value.isUnsigned());
   EXPECT_EQ(17U, Value.getUnsigned());
-  EXPECT_FALSE(Value.isMatcher());
+  EXPECT_FALSE(Value.isMatchers());
   EXPECT_FALSE(Value.isString());
 
   Value = VariantValue();
   EXPECT_FALSE(Value.isUnsigned());
   EXPECT_FALSE(Value.isString());
-  EXPECT_FALSE(Value.isMatcher());
+  EXPECT_FALSE(Value.isMatchers());
   EXPECT_EQ("Nothing", Value.getTypeAsString());
 }
 
-TEST(GenericValueTest, Matcher) {
+TEST(VariantValueTest, Matcher) {
   EXPECT_TRUE(matches("class X {};", VariantValue(recordDecl(hasName("X")))
                                          .getTypedMatcher<Decl>()));
   EXPECT_TRUE(
@@ -117,13 +115,15 @@ TEST(GenericValueTest, Matcher) {
   // do this test when building with MSVC because its debug C runtime prints the
   // assertion failure message as a wide string, which gtest doesn't understand.
   EXPECT_DEATH(VariantValue(varDecl()).getTypedMatcher<Stmt>(),
-               "canConstructFrom");
+               "hasTypedMatcher");
 #endif
 
   EXPECT_FALSE(
       matches("int x;", VariantValue(functionDecl()).getTypedMatcher<Decl>()));
-  EXPECT_FALSE(matches("int foo() { return 1 + 1; }",
-                       VariantValue(declRefExpr()).getTypedMatcher<Stmt>()));
+  EXPECT_FALSE(
+      matches("int foo() { return 1 + 1; }",
+
+              VariantValue(declRefExpr()).getTypedMatcher<Stmt>()));
 }
 
 } // end anonymous namespace





More information about the cfe-commits mailing list