[cfe-commits] r159805 - in /cfe/trunk: include/clang/ASTMatchers/ lib/ lib/ASTMatchers/ unittests/ unittests/ASTMatchers/

Galina Kistanova gkistanova at gmail.com
Mon Jul 9 17:42:20 PDT 2012


Sorry,
Here is the correct link:
http://lab.llvm.org:8011/builders/clang-X86_64-freebsd/builds/3461/steps/compile/logs/stdio

Thanks

Galina


On Mon, Jul 9, 2012 at 1:38 PM, Galina Kistanova <gkistanova at gmail.com> wrote:
> Hi Manuel,
>
> Seems this revision causes failures on one of the builders:
> http://lab.llvm.org:8011/builders/clang-X86_64-freebsd/builds/3461/steps/compile/logs/stdio
> The previous build is successful. Please have a look at this?
>
> Thanks
>
> Galina
>
>
> On Thu, Jul 5, 2012 at 10:48 PM, Manuel Klimek <klimek at google.com> wrote:
>>
>> Author: klimek
>> Date: Fri Jul  6 00:48:52 2012
>> New Revision: 159805
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=159805&view=rev
>> Log:
>> Adds the AST Matcher library, which provides a in-C++ DSL to express
>> matches on interesting parts of the AST, and callback mechanisms to
>> act on them.
>>
>>
>>
>> Added:
>>     cfe/trunk/include/clang/ASTMatchers/
>>     cfe/trunk/include/clang/ASTMatchers/ASTMatchFinder.h
>>     cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
>>     cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h
>>     cfe/trunk/include/clang/ASTMatchers/ASTMatchersMacros.h
>>     cfe/trunk/lib/ASTMatchers/
>>     cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp
>>     cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp
>>     cfe/trunk/lib/ASTMatchers/CMakeLists.txt
>>     cfe/trunk/lib/ASTMatchers/Makefile
>>     cfe/trunk/unittests/ASTMatchers/
>>     cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
>>     cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.h
>>     cfe/trunk/unittests/ASTMatchers/CMakeLists.txt
>>     cfe/trunk/unittests/ASTMatchers/Makefile
>> Modified:
>>     cfe/trunk/lib/CMakeLists.txt
>>     cfe/trunk/lib/Makefile
>>     cfe/trunk/unittests/CMakeLists.txt
>>     cfe/trunk/unittests/Makefile
>>
>> Added: cfe/trunk/include/clang/ASTMatchers/ASTMatchFinder.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchFinder.h?rev=159805&view=auto
>>
>> ==============================================================================
>> --- cfe/trunk/include/clang/ASTMatchers/ASTMatchFinder.h (added)
>> +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchFinder.h Fri Jul  6
>> 00:48:52 2012
>> @@ -0,0 +1,141 @@
>> +//===--- ASTMatchFinder.h - Structural query framework ----------*- C++
>> -*-===//
>> +//
>> +//                     The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +//
>> +//  Provides a way to construct an ASTConsumer that runs given matchers
>> +//  over the AST and invokes a given callback on every match.
>> +//
>> +//  The general idea is to construct a matcher expression that describes
>> a
>> +//  subtree match on the AST. Next, a callback that is executed every
>> time the
>> +//  expression matches is registered, and the matcher is run over the AST
>> of
>> +//  some code. Matched subexpressions can be bound to string IDs and
>> easily
>> +//  be accessed from the registered callback. The callback can than use
>> the
>> +//  AST nodes that the subexpressions matched on to output information
>> about
>> +//  the match or construct changes that can be applied to the code.
>> +//
>> +//  Example:
>> +//  class HandleMatch : public MatchFinder::MatchCallback {
>> +//  public:
>> +//    virtual void Run(const MatchFinder::MatchResult &Result) {
>> +//      const CXXRecordDecl *Class =
>> +//          Result.Nodes.GetDeclAs<CXXRecordDecl>("id");
>> +//      ...
>> +//    }
>> +//  };
>> +//
>> +//  int main(int argc, char **argv) {
>> +//    ClangTool Tool(argc, argv);
>> +//    MatchFinder finder;
>> +//    finder.AddMatcher(Id("id",
>> record(hasName("::a_namespace::AClass"))),
>> +//                      new HandleMatch);
>> +//    return Tool.Run(newFrontendActionFactory(&finder));
>> +//  }
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H
>> +#define LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H
>> +
>> +#include "clang/ASTMatchers/ASTMatchers.h"
>> +
>> +namespace clang {
>> +
>> +namespace ast_matchers {
>> +
>> +/// \brief A class to allow finding matches over the Clang AST.
>> +///
>> +/// After creation, you can add multiple matchers to the MatchFinder via
>> +/// calls to addMatcher(...).
>> +///
>> +/// Once all matchers are added, newASTConsumer() returns an ASTConsumer
>> +/// that will trigger the callbacks specified via addMatcher(...) when a
>> match
>> +/// is found.
>> +///
>> +/// See ASTMatchers.h for more information about how to create matchers.
>> +///
>> +/// Not intended to be subclassed.
>> +class MatchFinder {
>> +public:
>> +  /// \brief Contains all information for a given match.
>> +  ///
>> +  /// Every time a match is found, the MatchFinder will invoke the
>> registered
>> +  /// MatchCallback with a MatchResult containing information about the
>> match.
>> +  struct MatchResult {
>> +    MatchResult(const BoundNodes &Nodes, clang::ASTContext *Context);
>> +
>> +    /// \brief Contains the nodes bound on the current match.
>> +    ///
>> +    /// This allows user code to easily extract matched AST nodes.
>> +    const BoundNodes Nodes;
>> +
>> +    /// \brief Utilities for interpreting the matched AST structures.
>> +    /// @{
>> +    clang::ASTContext * const Context;
>> +    clang::SourceManager * const SourceManager;
>> +    /// @}
>> +  };
>> +
>> +  /// \brief Called when the Match registered for it was successfully
>> found
>> +  /// in the AST.
>> +  class MatchCallback {
>> +  public:
>> +    virtual ~MatchCallback();
>> +    virtual void run(const MatchResult &Result) = 0;
>> +  };
>> +
>> +  /// \brief Called when parsing is finished. Intended for testing only.
>> +  class ParsingDoneTestCallback {
>> +  public:
>> +    virtual ~ParsingDoneTestCallback();
>> +    virtual void run() = 0;
>> +  };
>> +
>> +  MatchFinder();
>> +  ~MatchFinder();
>> +
>> +  /// \brief Adds a matcher to execute when running over the AST.
>> +  ///
>> +  /// Calls 'Action' with the BoundNodes on every match.
>> +  /// Adding more than one 'NodeMatch' allows finding different matches
>> in a
>> +  /// single pass over the AST.
>> +  ///
>> +  /// Does not take ownership of 'Action'.
>> +  /// @{
>> +  void addMatcher(const DeclarationMatcher &NodeMatch,
>> +                  MatchCallback *Action);
>> +  void addMatcher(const TypeMatcher &NodeMatch,
>> +                  MatchCallback *Action);
>> +  void addMatcher(const StatementMatcher &NodeMatch,
>> +                  MatchCallback *Action);
>> +  /// @}
>> +
>> +  /// \brief Creates a clang ASTConsumer that finds all matches.
>> +  clang::ASTConsumer *newASTConsumer();
>> +
>> +  /// \brief Registers a callback to notify the end of parsing.
>> +  ///
>> +  /// The provided closure is called after parsing is done, before the
>> AST is
>> +  /// traversed. Useful for benchmarking.
>> +  /// Each call to FindAll(...) will call the closure once.
>> +  void registerTestCallbackAfterParsing(ParsingDoneTestCallback
>> *ParsingDone);
>> +
>> +private:
>> +  /// \brief The MatchCallback*'s will be called every time the
>> +  /// UntypedBaseMatcher matches on the AST.
>> +  std::vector< std::pair<
>> +    const internal::UntypedBaseMatcher*,
>> +    MatchCallback*> > Triggers;
>> +
>> +  /// \brief Called when parsing is done.
>> +  ParsingDoneTestCallback *ParsingDone;
>> +};
>> +
>> +} // end namespace ast_matchers
>> +} // end namespace clang
>> +
>> +#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H
>>
>> Added: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=159805&view=auto
>>
>> ==============================================================================
>> --- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (added)
>> +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Fri Jul  6 00:48:52
>> 2012
>> @@ -0,0 +1,1403 @@
>> +//===--- ASTMatchers.h - Structural query framework -------------*- C++
>> -*-===//
>> +//
>> +//                     The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +//
>> +//  This file implements matchers to be used together with the
>> MatchFinder to
>> +//  match AST nodes.
>> +//
>> +//  Matchers are created by generator functions, which can be combined in
>> +//  a functional in-language DSL to express queries over the C++ AST.
>> +//
>> +//  For example, to match a class with a certain name, one would call:
>> +//    record(hasName("MyClass"))
>> +//  which returns a matcher that can be used to find all AST nodes that
>> declare
>> +//  a class named 'MyClass'.
>> +//
>> +//  For more complicated match expressions we're often interested in
>> accessing
>> +//  multiple parts of the matched AST nodes once a match is found. In
>> that case,
>> +//  use the id(...) matcher around the match expressions that match the
>> nodes
>> +//  you want to access.
>> +//
>> +//  For example, when we're interested in child classes of a certain
>> class, we
>> +//  would write:
>> +//    record(hasName("MyClass"), hasChild(id("child", record())))
>> +//  When the match is found via the MatchFinder, a user provided callback
>> will
>> +//  be called with a BoundNodes instance that contains a mapping from the
>> +//  strings that we provided for the id(...) calls to the nodes that were
>> +//  matched.
>> +//  In the given example, each time our matcher finds a match we get a
>> callback
>> +//  where "child" is bound to the CXXRecordDecl node of the matching
>> child
>> +//  class declaration.
>> +//
>> +//  See ASTMatchersInternal.h for a more in-depth explanation of the
>> +//  implementation details of the matcher framework.
>> +//
>> +//  See ASTMatchFinder.h for how to use the generated matchers to run
>> over
>> +//  an AST.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H
>> +#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H
>> +
>> +#include "clang/ASTMatchers/ASTMatchersInternal.h"
>> +#include "clang/ASTMatchers/ASTMatchersMacros.h"
>> +#include "llvm/ADT/Twine.h"
>> +
>> +namespace clang {
>> +namespace ast_matchers {
>> +
>> +/// \brief Maps string IDs to AST nodes matched by parts of a matcher.
>> +///
>> +/// The bound nodes are generated by adding id(...) matchers into the
>> +/// match expression around the matchers for the nodes we want to access
>> later.
>> +///
>> +/// The instances of BoundNodes are created by MatchFinder when the
>> user's
>> +/// callbacks are executed every time a match is found.
>> +class BoundNodes {
>> +public:
>> +  /// \brief Returns the AST node bound to 'ID'.
>> +  /// Returns NULL if there was no node bound to 'ID' or if there is a
>> node but
>> +  /// it cannot be converted to the specified type.
>> +  /// FIXME: We'll need one of those for every base type.
>> +  /// @{
>> +  template <typename T>
>> +  const T *getDeclAs(StringRef ID) const {
>> +    return getNodeAs<T>(DeclBindings, ID);
>> +  }
>> +  template <typename T>
>> +  const T *getStmtAs(StringRef ID) const {
>> +    return getNodeAs<T>(StmtBindings, ID);
>> +  }
>> +  /// @}
>> +
>> +private:
>> +  /// \brief Create BoundNodes from a pre-filled map of bindings.
>> +  BoundNodes(const std::map<std::string, const clang::Decl*>
>> &DeclBindings,
>> +             const std::map<std::string, const clang::Stmt*>
>> &StmtBindings)
>> +      : DeclBindings(DeclBindings), StmtBindings(StmtBindings) {}
>> +
>> +  template <typename T, typename MapT>
>> +  const T *getNodeAs(const MapT &Bindings, StringRef ID) const {
>> +    typename MapT::const_iterator It = Bindings.find(ID);
>> +    if (It == Bindings.end()) {
>> +      return NULL;
>> +    }
>> +    return llvm::dyn_cast<T>(It->second);
>> +  }
>> +
>> +  std::map<std::string, const clang::Decl*> DeclBindings;
>> +  std::map<std::string, const clang::Stmt*> StmtBindings;
>> +
>> +  friend class internal::BoundNodesTree;
>> +};
>> +
>> +/// \brief If the provided matcher matches a node, binds the node to
>> 'ID'.
>> +///
>> +/// FIXME: Add example for accessing it.
>> +template <typename T>
>> +internal::Matcher<T> id(const std::string &ID,
>> +                        const internal::Matcher<T> &InnerMatcher) {
>> +  return internal::Matcher<T>(new internal::IdMatcher<T>(ID,
>> InnerMatcher));
>> +}
>> +
>> +/// \brief Types of matchers for the top-level classes in the AST class
>> +/// hierarchy.
>> +/// @{
>> +typedef internal::Matcher<clang::Decl> DeclarationMatcher;
>> +typedef internal::Matcher<clang::QualType> TypeMatcher;
>> +typedef internal::Matcher<clang::Stmt> StatementMatcher;
>> +/// @}
>> +
>> +/// \brief Matches any node.
>> +///
>> +/// Useful when another matcher requires a child matcher, but there's no
>> +/// additional constraint. This will often be used with an explicit
>> conversion
>> +/// to a internal::Matcher<> type such as TypeMatcher.
>> +///
>> +/// Example: DeclarationMatcher(anything()) matches all declarations,
>> e.g.,
>> +/// "int* p" and "void f()" in
>> +///   int* p;
>> +///   void f();
>> +inline internal::PolymorphicMatcherWithParam0<internal::TrueMatcher>
>> anything() {
>> +  return internal::PolymorphicMatcherWithParam0<internal::TrueMatcher>();
>> +}
>> +
>> +/// \brief Matches a declaration of anything that could have a name.
>> +///
>> +/// Example matches X, S, the anonymous union type, i, and U;
>> +///   typedef int X;
>> +///   struct S {
>> +///     union {
>> +///       int i;
>> +///     } U;
>> +///   };
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Decl,
>> +  clang::NamedDecl> nameableDeclaration;
>> +
>> +/// \brief Matches C++ class declarations.
>> +///
>> +/// Example matches X, Z
>> +///   class X;
>> +///   template<class T> class Z {};
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Decl,
>> +  clang::CXXRecordDecl> record;
>> +
>> +/// \brief Matches C++ constructor declarations.
>> +///
>> +/// Example matches Foo::Foo() and Foo::Foo(int)
>> +///   class Foo {
>> +///    public:
>> +///     Foo();
>> +///     Foo(int);
>> +///     int DoSomething();
>> +///   };
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Decl,
>> +  clang::CXXConstructorDecl> constructor;
>> +
>> +/// \brief Matches method declarations.
>> +///
>> +/// Example matches y
>> +///   class X { void y() };
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Decl,
>> +  clang::CXXMethodDecl> method;
>> +
>> +/// \brief Matches variable declarations.
>> +///
>> +/// Note: this does not match declarations of member variables, which are
>> +/// "field" declarations in Clang parlance.
>> +///
>> +/// Example matches a
>> +///   int a;
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Decl,
>> +  clang::VarDecl> variable;
>> +
>> +/// \brief Matches field declarations.
>> +///
>> +/// Given
>> +///   class X { int m; };
>> +/// field()
>> +///   matches 'm'.
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Decl,
>> +  clang::FieldDecl> field;
>> +
>> +/// \brief Matches function declarations.
>> +///
>> +/// Example matches f
>> +///   void f();
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Decl,
>> +  clang::FunctionDecl> function;
>> +
>> +
>> +/// \brief Matches statements.
>> +///
>> +/// Given
>> +///   { ++a; }
>> +/// statement()
>> +///   matches both the compound statement '{ ++a; }' and '++a'.
>> +const internal::VariadicDynCastAllOfMatcher<clang::Stmt, clang::Stmt>
>> statement;
>> +
>> +/// \brief Matches declaration statements.
>> +///
>> +/// Given
>> +///   int a;
>> +/// declarationStatement()
>> +///   matches 'int a'.
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Stmt,
>> +  clang::DeclStmt> declarationStatement;
>> +
>> +/// \brief Matches member expressions.
>> +///
>> +/// Given
>> +///   class Y {
>> +///     void x() { this->x(); x(); Y y; y.x(); a; this->b; Y::b; }
>> +///     int a; static int b;
>> +///   };
>> +/// memberExpression()
>> +///   matches this->x, x, y.x, a, this->b
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Stmt,
>> +  clang::MemberExpr> memberExpression;
>> +
>> +/// \brief Matches call expressions.
>> +///
>> +/// Example matches x.y()
>> +///   X x;
>> +///   x.y();
>> +const internal::VariadicDynCastAllOfMatcher<clang::Stmt, clang::CallExpr>
>> call;
>> +
>> +/// \brief Matches constructor call expressions (including implicit
>> ones).
>> +///
>> +/// Example matches string(ptr, n) and ptr within arguments of f
>> +///     (matcher = constructorCall())
>> +///   void f(const string &a, const string &b);
>> +///   char *ptr;
>> +///   int n;
>> +///   f(string(ptr, n), ptr);
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Stmt,
>> +  clang::CXXConstructExpr> constructorCall;
>> +
>> +/// \brief Matches nodes where temporaries are created.
>> +///
>> +/// Example matches FunctionTakesString(GetStringByValue())
>> +///     (matcher = bindTemporaryExpr())
>> +///   FunctionTakesString(GetStringByValue());
>> +///   FunctionTakesStringByPointer(GetStringPointer());
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Stmt,
>> +  clang::CXXBindTemporaryExpr> bindTemporaryExpression;
>> +
>> +/// \brief Matches new expressions.
>> +///
>> +/// Given
>> +///   new X;
>> +/// newExpression()
>> +///   matches 'new X'.
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Stmt,
>> +  clang::CXXNewExpr> newExpression;
>> +
>> +/// \brief Matches the value of a default argument at the call site.
>> +///
>> +/// Example matches the CXXDefaultArgExpr placeholder inserted for the
>> +///     default value of the second parameter in the call expression
>> f(42)
>> +///     (matcher = defaultArgument())
>> +///   void f(int x, int y = 0);
>> +///   f(42);
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Stmt,
>> +  clang::CXXDefaultArgExpr> defaultArgument;
>> +
>> +/// \brief Matches overloaded operator calls.
>> +///
>> +/// Note that if an operator isn't overloaded, it won't match. Instead,
>> use
>> +/// binaryOperator matcher.
>> +/// Currently it does not match operators such as new delete.
>> +/// FIXME: figure out why these do not match?
>> +///
>> +/// Example matches both operator<<((o << b), c) and operator<<(o, b)
>> +///     (matcher = overloadedOperatorCall())
>> +///   ostream &operator<< (ostream &out, int i) { };
>> +///   ostream &o; int b = 1, c = 1;
>> +///   o << b << c;
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Stmt,
>> +  clang::CXXOperatorCallExpr> overloadedOperatorCall;
>> +
>> +/// \brief Matches expressions.
>> +///
>> +/// Example matches x()
>> +///   void f() { x(); }
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Stmt,
>> +  clang::Expr> expression;
>> +
>> +/// \brief Matches expressions that refer to declarations.
>> +///
>> +/// Example matches x in if (x)
>> +///   bool x;
>> +///   if (x) {}
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Stmt,
>> +  clang::DeclRefExpr> declarationReference;
>> +
>> +/// \brief Matches if statements.
>> +///
>> +/// Example matches 'if (x) {}'
>> +///   if (x) {}
>> +const internal::VariadicDynCastAllOfMatcher<clang::Stmt, clang::IfStmt>
>> ifStmt;
>> +
>> +/// \brief Matches for statements.
>> +///
>> +/// Example matches 'for (;;) {}'
>> +///   for (;;) {}
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Stmt, clang::ForStmt> forStmt;
>> +
>> +/// \brief Matches while statements.
>> +///
>> +/// Given
>> +///   while (true) {}
>> +/// whileStmt()
>> +///   matches 'while (true) {}'.
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Stmt,
>> +  clang::WhileStmt> whileStmt;
>> +
>> +/// \brief Matches do statements.
>> +///
>> +/// Given
>> +///   do {} while (true);
>> +/// doStmt()
>> +///   matches 'do {} while(true)'
>> +const internal::VariadicDynCastAllOfMatcher<clang::Stmt, clang::DoStmt>
>> doStmt;
>> +
>> +/// \brief Matches case and default statements inside switch statements.
>> +///
>> +/// Given
>> +///   switch(a) { case 42: break; default: break; }
>> +/// switchCase()
>> +///   matches 'case 42: break;' and 'default: break;'.
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Stmt,
>> +  clang::SwitchCase> switchCase;
>> +
>> +/// \brief Matches compound statements.
>> +///
>> +/// Example matches '{}' and '{{}}'in 'for (;;) {{}}'
>> +///   for (;;) {{}}
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Stmt,
>> +  clang::CompoundStmt> compoundStatement;
>> +
>> +/// \brief Matches bool literals.
>> +///
>> +/// Example matches true
>> +///   true
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Expr,
>> +  clang::CXXBoolLiteralExpr> boolLiteral;
>> +
>> +/// \brief Matches string literals (also matches wide string literals).
>> +///
>> +/// Example matches "abcd", L"abcd"
>> +///   char *s = "abcd"; wchar_t *ws = L"abcd"
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Expr,
>> +  clang::StringLiteral> stringLiteral;
>> +
>> +/// \brief Matches character literals (also matches wchar_t).
>> +///
>> +/// Not matching Hex-encoded chars (e.g. 0x1234, which is a
>> IntegerLiteral),
>> +/// though.
>> +///
>> +/// Example matches 'a', L'a'
>> +///   char ch = 'a'; wchar_t chw = L'a';
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Expr,
>> +  clang::CharacterLiteral> characterLiteral;
>> +
>> +/// \brief Matches integer literals of all sizes / encodings.
>> +///
>> +/// Not matching character-encoded integers such as L'a'.
>> +///
>> +/// Example matches 1, 1L, 0x1, 1U
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Expr,
>> +  clang::IntegerLiteral> integerLiteral;
>> +
>> +/// \brief Matches binary operator expressions.
>> +///
>> +/// Example matches a || b
>> +///   !(a || b)
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Stmt,
>> +  clang::BinaryOperator> binaryOperator;
>> +
>> +/// \brief Matches unary operator expressions.
>> +///
>> +/// Example matches !a
>> +///   !a || b
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Stmt,
>> +  clang::UnaryOperator> unaryOperator;
>> +
>> +/// \brief Matches conditional operator expressions.
>> +///
>> +/// Example matches a ? b : c
>> +///   (a ? b : c) + 42
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Stmt,
>> +  clang::ConditionalOperator> conditionalOperator;
>> +
>> +/// \brief Matches a reinterpret_cast expression.
>> +///
>> +/// Either the source expression or the destination type can be matched
>> +/// using has(), but hasDestinationType() is more specific and can be
>> +/// more readable.
>> +///
>> +/// Example matches reinterpret_cast<char*>(&p) in
>> +///   void* p = reinterpret_cast<char*>(&p);
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Expr,
>> +  clang::CXXReinterpretCastExpr> reinterpretCast;
>> +
>> +/// \brief Matches a C++ static_cast expression.
>> +///
>> +/// \see hasDestinationType
>> +/// \see reinterpretCast
>> +///
>> +/// Example:
>> +///   staticCast()
>> +/// matches
>> +///   static_cast<long>(8)
>> +/// in
>> +///   long eight(static_cast<long>(8));
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Expr,
>> +  clang::CXXStaticCastExpr> staticCast;
>> +
>> +/// \brief Matches a dynamic_cast expression.
>> +///
>> +/// Example:
>> +///   dynamicCast()
>> +/// matches
>> +///   dynamic_cast<D*>(&b);
>> +/// in
>> +///   struct B { virtual ~B() {} }; struct D : B {};
>> +///   B b;
>> +///   D* p = dynamic_cast<D*>(&b);
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Expr,
>> +  clang::CXXDynamicCastExpr> dynamicCast;
>> +
>> +/// \brief Matches a const_cast expression.
>> +///
>> +/// Example: Matches const_cast<int*>(&r) in
>> +///   int n = 42;
>> +///   const int& r(n);
>> +///   int* p = const_cast<int*>(&r);
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Expr,
>> +  clang::CXXConstCastExpr> constCast;
>> +
>> +/// \brief Matches explicit cast expressions.
>> +///
>> +/// Matches any cast expression written in user code, whether it be a
>> +/// C-style cast, a functional-style cast, or a keyword cast.
>> +///
>> +/// Does not match implicit conversions.
>> +///
>> +/// Note: the name "explicitCast" is chosen to match Clang's terminology,
>> as
>> +/// Clang uses the term "cast" to apply to implicit conversions as well
>> as to
>> +/// actual cast expressions.
>> +///
>> +/// \see hasDestinationType.
>> +///
>> +/// Example: matches all five of the casts in
>> +///
>> int((int)(reinterpret_cast<int>(static_cast<int>(const_cast<int>(42)))))
>> +/// but does not match the implicit conversion in
>> +///   long ell = 42;
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Expr,
>> +  clang::ExplicitCastExpr> explicitCast;
>> +
>> +/// \brief Matches the implicit cast nodes of Clang's AST.
>> +///
>> +/// This matches many different places, including function call return
>> value
>> +/// eliding, as well as any type conversions.
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Expr,
>> +  clang::ImplicitCastExpr> implicitCast;
>> +
>> +/// \brief Matches functional cast expressions
>> +///
>> +/// Example: Matches Foo(bar);
>> +///   Foo f = bar;
>> +///   Foo g = (Foo) bar;
>> +///   Foo h = Foo(bar);
>> +const internal::VariadicDynCastAllOfMatcher<
>> +  clang::Expr,
>> +  clang::CXXFunctionalCastExpr> functionalCast;
>> +
>> +/// \brief Various overloads for the anyOf matcher.
>> +/// @{
>> +template<typename C1, typename C2>
>> +internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C1, C2>
>> +anyOf(const C1 &P1, const C2 &P2) {
>> +  return internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher,
>> +                                                C1, C2 >(P1, P2);
>> +}
>> +template<typename C1, typename C2, typename C3>
>> +internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C1,
>> +    internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C2,
>> C3> >
>> +anyOf(const C1 &P1, const C2 &P2, const C3 &P3) {
>> +  return anyOf(P1, anyOf(P2, P3));
>> +}
>> +template<typename C1, typename C2, typename C3, typename C4>
>> +internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C1,
>> +    internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C2,
>> +        internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher,
>> +                                               C3, C4> > >
>> +anyOf(const C1 &P1, const C2 &P2, const C3 &P3, const C4 &P4) {
>> +  return AnyOf(P1, AnyOf(P2, AnyOf(P3, P4)));
>> +}
>> +template<typename C1, typename C2, typename C3, typename C4, typename C5>
>> +internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C1,
>> +    internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C2,
>> +        internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher,
>> C3,
>> +
>> internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher,
>> +                                                   C4, C5> > > >
>> +anyOf(const C1& P1, const C2& P2, const C3& P3, const C4& P4, const C5&
>> P5) {
>> +  return anyOf(P1, anyOf(P2, anyOf(P3, anyOf(P4, P5))));
>> +}
>> +/// @}
>> +
>> +/// \brief Various overloads for the allOf matcher.
>> +/// @{
>> +template<typename C1, typename C2>
>> +internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, C1, C2>
>> +allOf(const C1 &P1, const C2 &P2) {
>> +  return internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher,
>> +                                                C1, C2>(P1, P2);
>> +}
>> +template<typename C1, typename C2, typename C3>
>> +internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, C1,
>> +    internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, C2,
>> C3> >
>> +allOf(const C1& P1, const C2& P2, const C3& P3) {
>> +  return AllOf(P1, AllOf(P2, P3));
>> +}
>> +/// @}
>> +
>> +/// \brief Matches NamedDecl nodes that have the specified name.
>> +///
>> +/// Supports specifying enclosing namespaces or classes by prefixing the
>> name
>> +/// with '<enclosing>::'.
>> +/// Does not match typedefs of an underlying type with the given name.
>> +///
>> +/// Example matches X (Name == "X")
>> +///   class X;
>> +///
>> +/// Example matches X (Name is one of "::a::b::X", "a::b::X", "b::X",
>> "X")
>> +/// namespace a { namespace b { class X; } }
>> +AST_MATCHER_P(clang::NamedDecl, hasName, std::string, Name) {
>> +  assert(!Name.empty());
>> +  const std::string FullNameString = "::" +
>> Node.getQualifiedNameAsString();
>> +  const llvm::StringRef FullName = FullNameString;
>> +  const llvm::StringRef Pattern = Name;
>> +  if (Pattern.startswith("::")) {
>> +    return FullName == Pattern;
>> +  } else {
>> +    return FullName.endswith(("::" + Pattern).str());
>> +  }
>> +}
>> +
>> +/// \brief Matches overloaded operator names.
>> +///
>> +/// Matches overloaded operator names specified in strings without the
>> +/// "operator" prefix, such as "<<", for OverloadedOperatorCall's.
>> +///
>> +/// Example matches a << b
>> +///     (matcher ==
>> overloadedOperatorCall(hasOverloadedOperatorName("<<")))
>> +///   a << b;
>> +///   c && d;  // assuming both operator<<
>> +///            // and operator&& are overloaded somewhere.
>> +AST_MATCHER_P(clang::CXXOperatorCallExpr,
>> +              hasOverloadedOperatorName, std::string, Name) {
>> +  return clang::getOperatorSpelling(Node.getOperator()) == Name;
>> +}
>> +
>> +/// \brief Matches C++ classes that are directly or indirectly derived
>> from
>> +/// the given base class.
>> +///
>> +/// Note that a class is considered to be also derived from itself.
>> +/// The parameter specified the name of the base type (either a class or
>> a
>> +/// typedef), and does not allow structural matches for namespaces or
>> template
>> +/// type parameters.
>> +///
>> +/// Example matches X, Y, Z, C (Base == "X")
>> +///   class X;                // A class is considered to be derived from
>> itself
>> +///   class Y : public X {};  // directly derived
>> +///   class Z : public Y {};  // indirectly derived
>> +///   typedef X A;
>> +///   typedef A B;
>> +///   class C : public B {};  // derived from a typedef of X
>> +///
>> +/// In the following example, Bar matches isDerivedFrom("X"):
>> +///   class Foo;
>> +///   typedef Foo X;
>> +///   class Bar : public Foo {};  // derived from a type that X is a
>> typedef of
>> +AST_MATCHER_P(clang::CXXRecordDecl, isDerivedFrom, std::string, Base) {
>> +  assert(!Base.empty());
>> +  return Finder->classIsDerivedFrom(&Node, Base);
>> +}
>> +
>> +/// \brief Matches AST nodes that have child AST nodes that match the
>> +/// provided matcher.
>> +///
>> +/// Example matches X, Y (matcher = record(has(record(hasName("X")))
>> +///   class X {};  // Matches X, because X::X is a class of name X inside
>> X.
>> +///   class Y { class X {}; };
>> +///   class Z { class Y { class X {}; }; };  // Does not match Z.
>> +///
>> +/// ChildT must be an AST base type.
>> +template <typename ChildT>
>> +internal::ArgumentAdaptingMatcher<internal::HasMatcher, ChildT> has(
>> +    const internal::Matcher<ChildT> &ChildMatcher) {
>> +  return internal::ArgumentAdaptingMatcher<internal::HasMatcher,
>> +                                           ChildT>(ChildMatcher);
>> +}
>> +
>> +/// \brief Matches AST nodes that have descendant AST nodes that match
>> the
>> +/// provided matcher.
>> +///
>> +/// Example matches X, Y, Z
>> +///     (matcher = record(hasDescendant(record(hasName("X")))))
>> +///   class X {};  // Matches X, because X::X is a class of name X inside
>> X.
>> +///   class Y { class X {}; };
>> +///   class Z { class Y { class X {}; }; };
>> +///
>> +/// DescendantT must be an AST base type.
>> +template <typename DescendantT>
>> +internal::ArgumentAdaptingMatcher<internal::HasDescendantMatcher,
>> DescendantT>
>> +hasDescendant(const internal::Matcher<DescendantT> &DescendantMatcher) {
>> +  return internal::ArgumentAdaptingMatcher<
>> +    internal::HasDescendantMatcher,
>> +    DescendantT>(DescendantMatcher);
>> +}
>> +
>> +
>> +/// \brief Matches AST nodes that have child AST nodes that match the
>> +/// provided matcher.
>> +///
>> +/// Example matches X, Y (matcher = record(forEach(record(hasName("X")))
>> +///   class X {};  // Matches X, because X::X is a class of name X inside
>> X.
>> +///   class Y { class X {}; };
>> +///   class Z { class Y { class X {}; }; };  // Does not match Z.
>> +///
>> +/// ChildT must be an AST base type.
>> +///
>> +/// As opposed to 'has', 'forEach' will cause a match for each result
>> that
>> +/// matches instead of only on the first one.
>> +template <typename ChildT>
>> +internal::ArgumentAdaptingMatcher<internal::ForEachMatcher, ChildT>
>> forEach(
>> +    const internal::Matcher<ChildT>& ChildMatcher) {
>> +  return internal::ArgumentAdaptingMatcher<
>> +    internal::ForEachMatcher,
>> +    ChildT>(ChildMatcher);
>> +}
>> +
>> +/// \brief Matches AST nodes that have descendant AST nodes that match
>> the
>> +/// provided matcher.
>> +///
>> +/// Example matches X, A, B, C
>> +///     (matcher = record(forEachDescendant(record(hasName("X")))))
>> +///   class X {};  // Matches X, because X::X is a class of name X inside
>> X.
>> +///   class A { class X {}; };
>> +///   class B { class C { class X {}; }; };
>> +///
>> +/// DescendantT must be an AST base type.
>> +///
>> +/// As opposed to 'hasDescendant', 'forEachDescendant' will cause a match
>> for
>> +/// each result that matches instead of only on the first one.
>> +///
>> +/// Note: Recursively combined ForEachDescendant can cause many matches:
>> +///   record(forEachDescendant(record(forEachDescendant(record()))))
>> +/// will match 10 times (plus injected class name matches) on:
>> +///   class A { class B { class C { class D { class E {}; }; }; }; };
>> +template <typename DescendantT>
>> +internal::ArgumentAdaptingMatcher<internal::ForEachDescendantMatcher,
>> DescendantT>
>> +forEachDescendant(
>> +    const internal::Matcher<DescendantT>& DescendantMatcher) {
>> +  return internal::ArgumentAdaptingMatcher<
>> +    internal::ForEachDescendantMatcher,
>> +    DescendantT>(DescendantMatcher);
>> +}
>> +
>> +/// \brief Matches if the provided matcher does not match.
>> +///
>> +/// Example matches Y (matcher = record(unless(hasName("X"))))
>> +///   class X {};
>> +///   class Y {};
>> +template <typename M>
>> +internal::PolymorphicMatcherWithParam1<internal::NotMatcher, M>
>> unless(const M &InnerMatcher) {
>> +  return internal::PolymorphicMatcherWithParam1<
>> +    internal::NotMatcher, M>(InnerMatcher);
>> +}
>> +
>> +/// \brief Matches a type if the declaration of the type matches the
>> given
>> +/// matcher.
>> +inline internal::PolymorphicMatcherWithParam1<
>> internal::HasDeclarationMatcher,
>> +                                     internal::Matcher<clang::Decl> >
>> +    hasDeclaration(const internal::Matcher<clang::Decl> &InnerMatcher) {
>> +  return internal::PolymorphicMatcherWithParam1<
>> +    internal::HasDeclarationMatcher,
>> +    internal::Matcher<clang::Decl> >(InnerMatcher);
>> +}
>> +
>> +/// \brief Matches on the implicit object argument of a member call
>> expression.
>> +///
>> +/// Example matches y.x() (matcher =
>> call(on(hasType(record(hasName("Y"))))))
>> +///   class Y { public: void x(); };
>> +///   void z() { Y y; y.x(); }",
>> +///
>> +/// FIXME: Overload to allow directly matching types?
>> +AST_MATCHER_P(clang::CXXMemberCallExpr, on,
>> internal::Matcher<clang::Expr>,
>> +              InnerMatcher) {
>> +  const clang::Expr *ExprNode =
>> const_cast<clang::CXXMemberCallExpr&>(Node)
>> +      .getImplicitObjectArgument()
>> +      ->IgnoreParenImpCasts();
>> +  return (ExprNode != NULL &&
>> +          InnerMatcher.matches(*ExprNode, Finder, Builder));
>> +}
>> +
>> +/// \brief Matches if the call expression's callee expression matches.
>> +///
>> +/// Given
>> +///   class Y { void x() { this->x(); x(); Y y; y.x(); } };
>> +///   void f() { f(); }
>> +/// call(callee(expression()))
>> +///   matches this->x(), x(), y.x(), f()
>> +/// with callee(...)
>> +///   matching this->x, x, y.x, f respectively
>> +///
>> +/// Note: Callee cannot take the more general
>> internal::Matcher<clang::Expr>
>> +/// because this introduces ambiguous overloads with calls to Callee
>> taking a
>> +/// internal::Matcher<clang::Decl>, as the matcher hierarchy is purely
>> +/// implemented in terms of implicit casts.
>> +AST_MATCHER_P(clang::CallExpr, callee, internal::Matcher<clang::Stmt>,
>> +              InnerMatcher) {
>> +  const clang::Expr *ExprNode = Node.getCallee();
>> +  return (ExprNode != NULL &&
>> +          InnerMatcher.matches(*ExprNode, Finder, Builder));
>> +}
>> +
>> +/// \brief Matches if the call expression's callee's declaration matches
>> the
>> +/// given matcher.
>> +///
>> +/// Example matches y.x() (matcher = call(callee(method(hasName("x")))))
>> +///   class Y { public: void x(); };
>> +///   void z() { Y y; y.x();
>> +inline internal::Matcher<clang::CallExpr> callee(
>> +    const internal::Matcher<clang::Decl> &InnerMatcher) {
>> +  return
>> internal::Matcher<clang::CallExpr>(hasDeclaration(InnerMatcher));
>> +}
>> +
>> +/// \brief Matches if the expression's or declaration's type matches a
>> type
>> +/// matcher.
>> +///
>> +/// Example matches x (matcher = expression(hasType(
>> +///                        hasDeclaration(record(hasName("X"))))))
>> +///             and z (matcher = variable(hasType(
>> +///                        hasDeclaration(record(hasName("X"))))))
>> +///  class X {};
>> +///  void y(X &x) { x; X z; }
>> +AST_POLYMORPHIC_MATCHER_P(hasType, internal::Matcher<clang::QualType>,
>> +                          InnerMatcher) {
>> +  TOOLING_COMPILE_ASSERT((llvm::is_base_of<clang::Expr, NodeType>::value
>> ||
>> +                          llvm::is_base_of<clang::ValueDecl,
>> NodeType>::value),
>> +                         instantiated_with_wrong_types);
>> +  return InnerMatcher.matches(Node.getType(), Finder, Builder);
>> +}
>> +
>> +/// \brief Overloaded to match the declaration of the expression's or
>> value
>> +/// declaration's type.
>> +///
>> +/// In case of a value declaration (for example a variable declaration),
>> +/// this resolves one layer of indirection. For example, in the value
>> +/// declaration "X x;", record(hasName("X")) matches the declaration of
>> X,
>> +/// while variable(hasType(record(hasName("X")))) matches the declaration
>> +/// of x."
>> +///
>> +/// Example matches x (matcher =
>> expression(hasType(record(hasName("X")))))
>> +///             and z (matcher = variable(hasType(record(hasName("X")))))
>> +///  class X {};
>> +///  void y(X &x) { x; X z; }
>> +inline internal::PolymorphicMatcherWithParam1<
>> +  internal::matcher_hasTypeMatcher,
>> +  internal::Matcher<clang::QualType> >
>> +hasType(const internal::Matcher<clang::Decl> &InnerMatcher) {
>> +  return hasType(internal::Matcher<clang::QualType>(
>> +    hasDeclaration(InnerMatcher)));
>> +}
>> +
>> +/// \brief Matches if the matched type is a pointer type and the pointee
>> type
>> +/// matches the specified matcher.
>> +///
>> +/// Example matches y->x()
>> +///     (matcher = call(on(hasType(pointsTo(record(hasName("Y")))))))
>> +///   class Y { public: void x(); };
>> +///   void z() { Y *y; y->x(); }
>> +AST_MATCHER_P(
>> +    clang::QualType, pointsTo, internal::Matcher<clang::QualType>,
>> +    InnerMatcher) {
>> +  return (Node->isPointerType() &&
>> +          InnerMatcher.matches(Node->getPointeeType(), Finder, Builder));
>> +}
>> +
>> +/// \brief Overloaded to match the pointee type's declaration.
>> +inline internal::Matcher<clang::QualType> pointsTo(
>> +    const internal::Matcher<clang::Decl> &InnerMatcher) {
>> +  return pointsTo(internal::Matcher<clang::QualType>(
>> +    hasDeclaration(InnerMatcher)));
>> +}
>> +
>> +/// \brief Matches if the matched type is a reference type and the
>> referenced
>> +/// type matches the specified matcher.
>> +///
>> +/// Example matches X &x and const X &y
>> +///     (matcher = variable(hasType(references(record(hasName("X"))))))
>> +///   class X {
>> +///     void a(X b) {
>> +///       X &x = b;
>> +///       const X &y = b;
>> +///   };
>> +AST_MATCHER_P(clang::QualType, references,
>> internal::Matcher<clang::QualType>,
>> +              InnerMatcher) {
>> +  return (Node->isReferenceType() &&
>> +          InnerMatcher.matches(Node->getPointeeType(), Finder, Builder));
>> +}
>> +
>> +/// \brief Overloaded to match the referenced type's declaration.
>> +inline internal::Matcher<clang::QualType> references(
>> +    const internal::Matcher<clang::Decl> &InnerMatcher) {
>> +  return references(internal::Matcher<clang::QualType>(
>> +    hasDeclaration(InnerMatcher)));
>> +}
>> +
>> +AST_MATCHER_P(clang::CXXMemberCallExpr, onImplicitObjectArgument,
>> +              internal::Matcher<clang::Expr>, InnerMatcher) {
>> +  const clang::Expr *ExprNode =
>> +
>> const_cast<clang::CXXMemberCallExpr&>(Node).getImplicitObjectArgument();
>> +  return (ExprNode != NULL &&
>> +          InnerMatcher.matches(*ExprNode, Finder, Builder));
>> +}
>> +
>> +/// \brief Matches if the expression's type either matches the specified
>> +/// matcher, or is a pointer to a type that matches the InnerMatcher.
>> +inline internal::Matcher<clang::CallExpr> thisPointerType(
>> +    const internal::Matcher<clang::QualType> &InnerMatcher) {
>> +  return onImplicitObjectArgument(
>> +      anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher))));
>> +}
>> +
>> +/// \brief Overloaded to match the type's declaration.
>> +inline internal::Matcher<clang::CallExpr> thisPointerType(
>> +    const internal::Matcher<clang::Decl> &InnerMatcher) {
>> +  return onImplicitObjectArgument(
>> +      anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher))));
>> +}
>> +
>> +/// \brief Matches a DeclRefExpr that refers to a declaration that
>> matches the
>> +/// specified matcher.
>> +///
>> +/// Example matches x in if(x)
>> +///     (matcher = declarationReference(to(variable(hasName("x")))))
>> +///   bool x;
>> +///   if (x) {}
>> +AST_MATCHER_P(clang::DeclRefExpr, to, internal::Matcher<clang::Decl>,
>> +              InnerMatcher) {
>> +  const clang::Decl *DeclNode = Node.getDecl();
>> +  return (DeclNode != NULL &&
>> +          InnerMatcher.matches(*DeclNode, Finder, Builder));
>> +}
>> +
>> +/// \brief Matches a variable declaration that has an initializer
>> expression
>> +/// that matches the given matcher.
>> +///
>> +/// Example matches x (matcher = variable(hasInitializer(call())))
>> +///   bool y() { return true; }
>> +///   bool x = y();
>> +AST_MATCHER_P(
>> +    clang::VarDecl, hasInitializer, internal::Matcher<clang::Expr>,
>> +    InnerMatcher) {
>> +  const clang::Expr *Initializer = Node.getAnyInitializer();
>> +  return (Initializer != NULL &&
>> +          InnerMatcher.matches(*Initializer, Finder, Builder));
>> +}
>> +
>> +/// \brief 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 = call(argumentCountIs(2)))
>> +///   void f(int x, int y);
>> +///   f(0, 0);
>> +AST_POLYMORPHIC_MATCHER_P(argumentCountIs, unsigned, N) {
>> +  TOOLING_COMPILE_ASSERT((llvm::is_base_of<clang::CallExpr,
>> NodeType>::value ||
>> +                          llvm::is_base_of<clang::CXXConstructExpr,
>> +                                           NodeType>::value),
>> +                         instantiated_with_wrong_types);
>> +  return Node.getNumArgs() == N;
>> +}
>> +
>> +/// \brief Matches the n'th argument of a call expression or a
>> constructor
>> +/// call expression.
>> +///
>> +/// Example matches y in x(y)
>> +///     (matcher = call(hasArgument(0, declarationReference())))
>> +///   void x(int) { int y; x(y); }
>> +AST_POLYMORPHIC_MATCHER_P2(
>> +    hasArgument, unsigned, N, internal::Matcher<clang::Expr>,
>> InnerMatcher) {
>> +  TOOLING_COMPILE_ASSERT((llvm::is_base_of<clang::CallExpr,
>> NodeType>::value ||
>> +                         llvm::is_base_of<clang::CXXConstructExpr,
>> +                                          NodeType>::value),
>> +                         instantiated_with_wrong_types);
>> +  return (N < Node.getNumArgs() &&
>> +          InnerMatcher.matches(
>> +              *Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder));
>> +}
>> +
>> +/// \brief Matches a constructor initializer.
>> +///
>> +/// Given
>> +///   struct Foo {
>> +///     Foo() : foo_(1) { }
>> +///     int foo_;
>> +///   };
>> +/// record(Has(Constructor(hasAnyConstructorInitializer(anything()))))
>> +///   Class matches Foo, hasAnyConstructorInitializer matches foo_(1)
>> +AST_MATCHER_P(clang::CXXConstructorDecl, hasAnyConstructorInitializer,
>> +              internal::Matcher<clang::CXXCtorInitializer>, InnerMatcher)
>> {
>> +  for (clang::CXXConstructorDecl::init_const_iterator I =
>> Node.init_begin();
>> +       I != Node.init_end(); ++I) {
>> +    if (InnerMatcher.matches(**I, Finder, Builder)) {
>> +      return true;
>> +    }
>> +  }
>> +  return false;
>> +}
>> +
>> +/// \brief Matches the field declaration of a constructor initializer.
>> +///
>> +/// Given
>> +///   struct Foo {
>> +///     Foo() : foo_(1) { }
>> +///     int foo_;
>> +///   };
>> +/// record(has(constructor(hasAnyConstructorInitializer(
>> +///     forField(hasName("foo_"))))))
>> +///   matches Foo
>> +/// with forField matching foo_
>> +AST_MATCHER_P(clang::CXXCtorInitializer, forField,
>> +              internal::Matcher<clang::FieldDecl>, InnerMatcher) {
>> +  const clang::FieldDecl *NodeAsDecl = Node.getMember();
>> +  return (NodeAsDecl != NULL &&
>> +      InnerMatcher.matches(*NodeAsDecl, Finder, Builder));
>> +}
>> +
>> +/// \brief Matches the initializer expression of a constructor
>> initializer.
>> +///
>> +/// Given
>> +///   struct Foo {
>> +///     Foo() : foo_(1) { }
>> +///     int foo_;
>> +///   };
>> +/// record(has(constructor(hasAnyConstructorInitializer(
>> +///     withInitializer(integerLiteral(equals(1)))))))
>> +///   matches Foo
>> +/// with withInitializer matching (1)
>> +AST_MATCHER_P(clang::CXXCtorInitializer, withInitializer,
>> +              internal::Matcher<clang::Expr>, InnerMatcher) {
>> +  const clang::Expr* NodeAsExpr = Node.getInit();
>> +  return (NodeAsExpr != NULL &&
>> +      InnerMatcher.matches(*NodeAsExpr, Finder, Builder));
>> +}
>> +
>> +/// \brief Matches a contructor initializer if it is explicitly written
>> in
>> +/// code (as opposed to implicitly added by the compiler).
>> +///
>> +/// Given
>> +///   struct Foo {
>> +///     Foo() { }
>> +///     Foo(int) : foo_("A") { }
>> +///     string foo_;
>> +///   };
>> +/// constructor(hasAnyConstructorInitializer(isWritten()))
>> +///   will match Foo(int), but not Foo()
>> +AST_MATCHER(clang::CXXCtorInitializer, isWritten) {
>> +  return Node.isWritten();
>> +}
>> +
>> +/// \brief Matches a constructor declaration that has been implicitly
>> added
>> +/// by the compiler (eg. implicit default/copy constructors).
>> +AST_MATCHER(clang::CXXConstructorDecl, isImplicit) {
>> +  return Node.isImplicit();
>> +}
>> +
>> +/// \brief Matches any argument of a call expression or a constructor
>> call
>> +/// expression.
>> +///
>> +/// Given
>> +///   void x(int, int, int) { int y; x(1, y, 42); }
>> +/// call(hasAnyArgument(declarationReference()))
>> +///   matches x(1, y, 42)
>> +/// with hasAnyArgument(...)
>> +///   matching y
>> +AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, internal::Matcher<clang::Expr>,
>> +                          InnerMatcher) {
>> +  TOOLING_COMPILE_ASSERT((llvm::is_base_of<clang::CallExpr,
>> NodeType>::value ||
>> +                         llvm::is_base_of<clang::CXXConstructExpr,
>> +                                          NodeType>::value),
>> +                         instantiated_with_wrong_types);
>> +  for (unsigned I = 0; I < Node.getNumArgs(); ++I) {
>> +    if (InnerMatcher.matches(*Node.getArg(I)->IgnoreParenImpCasts(),
>> +                             Finder, Builder)) {
>> +      return true;
>> +    }
>> +  }
>> +  return false;
>> +}
>> +
>> +/// \brief Matches the n'th parameter of a function declaration.
>> +///
>> +/// Given
>> +///   class X { void f(int x) {} };
>> +/// method(hasParameter(0, hasType(variable())))
>> +///   matches f(int x) {}
>> +/// with hasParameter(...)
>> +///   matching int x
>> +AST_MATCHER_P2(clang::FunctionDecl, hasParameter,
>> +               unsigned, N, internal::Matcher<clang::ParmVarDecl>,
>> +               InnerMatcher) {
>> +  return (N < Node.getNumParams() &&
>> +          InnerMatcher.matches(
>> +              *Node.getParamDecl(N), Finder, Builder));
>> +}
>> +
>> +/// \brief Matches any parameter of a function declaration.
>> +///
>> +/// Does not match the 'this' parameter of a method.
>> +///
>> +/// Given
>> +///   class X { void f(int x, int y, int z) {} };
>> +/// method(hasAnyParameter(hasName("y")))
>> +///   matches f(int x, int y, int z) {}
>> +/// with hasAnyParameter(...)
>> +///   matching int y
>> +AST_MATCHER_P(clang::FunctionDecl, hasAnyParameter,
>> +              internal::Matcher<clang::ParmVarDecl>, InnerMatcher) {
>> +  for (unsigned I = 0; I < Node.getNumParams(); ++I) {
>> +    if (InnerMatcher.matches(*Node.getParamDecl(I), Finder, Builder)) {
>> +      return true;
>> +    }
>> +  }
>> +  return false;
>> +}
>> +
>> +/// \brief Matches the condition expression of an if statement or
>> conditional
>> +/// operator.
>> +///
>> +/// Example matches true (matcher =
>> hasCondition(boolLiteral(equals(true))))
>> +///   if (true) {}
>> +AST_POLYMORPHIC_MATCHER_P(hasCondition, internal::Matcher<clang::Expr>,
>> +                          InnerMatcher) {
>> +  TOOLING_COMPILE_ASSERT(
>> +    (llvm::is_base_of<clang::IfStmt, NodeType>::value) ||
>> +    (llvm::is_base_of<clang::ConditionalOperator, NodeType>::value),
>> +    has_condition_requires_if_statement_or_conditional_operator);
>> +  const clang::Expr *const Condition = Node.getCond();
>> +  return (Condition != NULL &&
>> +          InnerMatcher.matches(*Condition, Finder, Builder));
>> +}
>> +
>> +/// \brief Matches the condition variable statement in an if statement.
>> +///
>> +/// Given
>> +///   if (A* a = GetAPointer()) {}
>> +/// hasConditionVariableStatment(...)
>> +///   matches 'A* a = GetAPointer()'.
>> +AST_MATCHER_P(clang::IfStmt, hasConditionVariableStatement,
>> +              internal::Matcher<clang::DeclStmt>, InnerMatcher) {
>> +  const clang::DeclStmt* const DeclarationStatement =
>> +    Node.getConditionVariableDeclStmt();
>> +  return DeclarationStatement != NULL &&
>> +         InnerMatcher.matches(*DeclarationStatement, Finder, Builder);
>> +}
>> +
>> +/// \brief Matches a 'for' statement that has a given body.
>> +///
>> +/// Given
>> +///   for (;;) {}
>> +/// hasBody(compoundStatement())
>> +///   matches 'for (;;) {}'
>> +/// with compoundStatement()
>> +///   matching '{}'
>> +AST_MATCHER_P(clang::ForStmt, hasBody, internal::Matcher<clang::Stmt>,
>> +              InnerMatcher) {
>> +  const clang::Stmt *const Statement = Node.getBody();
>> +  return (Statement != NULL &&
>> +          InnerMatcher.matches(*Statement, Finder, Builder));
>> +}
>> +
>> +/// \brief Matches compound statements where at least one substatement
>> matches
>> +/// a given matcher.
>> +///
>> +/// Given
>> +///   { {}; 1+2; }
>> +/// hasAnySubstatement(compoundStatement())
>> +///   matches '{ {}; 1+2; }'
>> +/// with compoundStatement()
>> +///   matching '{}'
>> +AST_MATCHER_P(clang::CompoundStmt, hasAnySubstatement,
>> +              internal::Matcher<clang::Stmt>, InnerMatcher) {
>> +  for (clang::CompoundStmt::const_body_iterator It = Node.body_begin();
>> +       It != Node.body_end();
>> +       ++It) {
>> +    if (InnerMatcher.matches(**It, Finder, Builder)) return true;
>> +  }
>> +  return false;
>> +}
>> +
>> +/// \brief Checks that a compound statement contains a specific number of
>> +/// child statements.
>> +///
>> +/// Example: Given
>> +///   { for (;;) {} }
>> +/// compoundStatement(statementCountIs(0)))
>> +///   matches '{}'
>> +///   but does not match the outer compound statement.
>> +AST_MATCHER_P(clang::CompoundStmt, statementCountIs, unsigned, N) {
>> +  return Node.size() == N;
>> +}
>> +
>> +/// \brief Matches literals that are equal to the given value.
>> +///
>> +/// Example matches true (matcher = boolLiteral(equals(true)))
>> +///   true
>> +template <typename ValueT>
>> +internal::PolymorphicMatcherWithParam1<internal::ValueEqualsMatcher,
>> ValueT>
>> +equals(const ValueT &Value) {
>> +  return internal::PolymorphicMatcherWithParam1<
>> +    internal::ValueEqualsMatcher,
>> +    ValueT>(Value);
>> +}
>> +
>> +/// \brief Matches the operator Name of operator expressions (binary or
>> +/// unary).
>> +///
>> +/// Example matches a || b (matcher =
>> binaryOperator(hasOperatorName("||")))
>> +///   !(a || b)
>> +AST_POLYMORPHIC_MATCHER_P(hasOperatorName, std::string, Name) {
>> +  TOOLING_COMPILE_ASSERT(
>> +    (llvm::is_base_of<clang::BinaryOperator, NodeType>::value) ||
>> +    (llvm::is_base_of<clang::UnaryOperator, NodeType>::value),
>> +    has_condition_requires_if_statement_or_conditional_operator);
>> +  return Name == Node.getOpcodeStr(Node.getOpcode());
>> +}
>> +
>> +/// \brief Matches the left hand side of binary operator expressions.
>> +///
>> +/// Example matches a (matcher = binaryOperator(hasLHS()))
>> +///   a || b
>> +AST_MATCHER_P(clang::BinaryOperator, hasLHS,
>> +              internal::Matcher<clang::Expr>, InnerMatcher) {
>> +  clang::Expr *LeftHandSide = Node.getLHS();
>> +  return (LeftHandSide != NULL &&
>> +          InnerMatcher.matches(*LeftHandSide, Finder, Builder));
>> +}
>> +
>> +/// \brief Matches the right hand side of binary operator expressions.
>> +///
>> +/// Example matches b (matcher = binaryOperator(hasRHS()))
>> +///   a || b
>> +AST_MATCHER_P(clang::BinaryOperator, hasRHS,
>> +              internal::Matcher<clang::Expr>, InnerMatcher) {
>> +  clang::Expr *RightHandSide = Node.getRHS();
>> +  return (RightHandSide != NULL &&
>> +          InnerMatcher.matches(*RightHandSide, Finder, Builder));
>> +}
>> +
>> +/// \brief Matches if either the left hand side or the right hand side of
>> a
>> +/// binary operator matches.
>> +inline internal::Matcher<clang::BinaryOperator> hasEitherOperand(
>> +    const internal::Matcher<clang::Expr> &InnerMatcher) {
>> +  return anyOf(hasLHS(InnerMatcher), hasRHS(InnerMatcher));
>> +}
>> +
>> +/// \brief Matches if the operand of a unary operator matches.
>> +///
>> +/// Example matches true (matcher =
>> hasOperand(boolLiteral(equals(true))))
>> +///   !true
>> +AST_MATCHER_P(clang::UnaryOperator, hasUnaryOperand,
>> +              internal::Matcher<clang::Expr>, InnerMatcher) {
>> +  const clang::Expr * const Operand = Node.getSubExpr();
>> +  return (Operand != NULL &&
>> +          InnerMatcher.matches(*Operand, Finder, Builder));
>> +}
>> +
>> +/// Matches if the implicit cast's source expression matches the given
>> matcher.
>> +///
>> +/// Example: matches "a string" (matcher =
>> +///
>> hasSourceExpression(constructorCall()))
>> +///
>> +/// class URL { URL(string); };
>> +/// URL url = "a string";
>> +AST_MATCHER_P(clang::ImplicitCastExpr, hasSourceExpression,
>> +              internal::Matcher<clang::Expr>, InnerMatcher) {
>> +  const clang::Expr* const SubExpression = Node.getSubExpr();
>> +  return (SubExpression != NULL &&
>> +          InnerMatcher.matches(*SubExpression, Finder, Builder));
>> +}
>> +
>> +/// \brief Matches casts whose destination type matches a given matcher.
>> +///
>> +/// (Note: Clang's AST refers to other conversions as "casts" too, and
>> calls
>> +/// actual casts "explicit" casts.)
>> +AST_MATCHER_P(clang::ExplicitCastExpr, hasDestinationType,
>> +              internal::Matcher<clang::QualType>, InnerMatcher) {
>> +  const clang::QualType NodeType = Node.getTypeAsWritten();
>> +  return InnerMatcher.matches(NodeType, Finder, Builder);
>> +}
>> +
>> +/// \brief Matches implicit casts whose destination type matches a given
>> +/// matcher.
>> +///
>> +/// FIXME: Unit test this matcher
>> +AST_MATCHER_P(clang::ImplicitCastExpr, hasImplicitDestinationType,
>> +              internal::Matcher<clang::QualType>, InnerMatcher) {
>> +  return InnerMatcher.matches(Node.getType(), Finder, Builder);
>> +}
>> +
>> +/// \brief Matches the true branch expression of a conditional operator.
>> +///
>> +/// Example matches a
>> +///   condition ? a : b
>> +AST_MATCHER_P(clang::ConditionalOperator, hasTrueExpression,
>> +              internal::Matcher<clang::Expr>, InnerMatcher) {
>> +  clang::Expr *Expression = Node.getTrueExpr();
>> +  return (Expression != NULL &&
>> +          InnerMatcher.matches(*Expression, Finder, Builder));
>> +}
>> +
>> +/// \brief Matches the false branch expression of a conditional operator.
>> +///
>> +/// Example matches b
>> +///   condition ? a : b
>> +AST_MATCHER_P(clang::ConditionalOperator, hasFalseExpression,
>> +              internal::Matcher<clang::Expr>, InnerMatcher) {
>> +  clang::Expr *Expression = Node.getFalseExpr();
>> +  return (Expression != NULL &&
>> +          InnerMatcher.matches(*Expression, Finder, Builder));
>> +}
>> +
>> +/// \brief Matches if a declaration has a body attached.
>> +///
>> +/// Example matches A, va, fa
>> +///   class A {};
>> +///   class B;  // Doesn't match, as it has no body.
>> +///   int va;
>> +///   extern int vb;  // Doesn't match, as it doesn't define the
>> variable.
>> +///   void fa() {}
>> +///   void fb();  // Doesn't match, as it has no body.
>> +inline
>> internal::PolymorphicMatcherWithParam0<internal::IsDefinitionMatcher>
>> +isDefinition() {
>> +  return internal::PolymorphicMatcherWithParam0<
>> +    internal::IsDefinitionMatcher>();
>> +}
>> +
>> +/// \brief Matches the class declaration that the given method
>> declaration
>> +/// belongs to.
>> +///
>> +/// FIXME: Generalize this for other kinds of declarations.
>> +/// FIXME: What other kind of declarations would we need to generalize
>> +/// this to?
>> +///
>> +/// Example matches A() in the last line
>> +///     (matcher = constructorCall(hasDeclaration(method(
>> +///         ofClass(hasName("A"))))))
>> +///   class A {
>> +///    public:
>> +///     A();
>> +///   };
>> +///   A a = A();
>> +AST_MATCHER_P(clang::CXXMethodDecl, ofClass,
>> +              internal::Matcher<clang::CXXRecordDecl>, InnerMatcher) {
>> +  const clang::CXXRecordDecl *Parent = Node.getParent();
>> +  return (Parent != NULL &&
>> +          InnerMatcher.matches(*Parent, Finder, Builder));
>> +}
>> +
>> +/// \brief Matches member expressions that are called with '->' as
>> opposed
>> +/// to '.'.
>> +///
>> +/// Member calls on the implicit this pointer match as called with '->'.
>> +///
>> +/// Given
>> +///   class Y {
>> +///     void x() { this->x(); x(); Y y; y.x(); a; this->b; Y::b; }
>> +///     int a;
>> +///     static int b;
>> +///   };
>> +/// memberExpression(isArrow())
>> +///   matches this->x, x, y.x, a, this->b
>> +inline internal::Matcher<clang::MemberExpr> isArrow() {
>> +  return makeMatcher(new internal::IsArrowMatcher());
>> +}
>> +
>> +/// \brief Matches clang::QualType nodes that are const-qualified, i.e.,
>> that
>> +/// include "top-level" const.
>> +///
>> +/// Given
>> +///   void a(int);
>> +///   void b(int const);
>> +///   void c(const int);
>> +///   void d(const int*);
>> +///   void e(int const) {};
>> +/// function(hasAnyParameter(hasType(isConstQualified())))
>> +///   matches "void b(int const)", "void c(const int)" and
>> +///   "void e(int const) {}". It does not match d as there
>> +///   is no top-level const on the parameter type "const int *".
>> +inline internal::Matcher<clang::QualType> isConstQualified() {
>> +  return makeMatcher(new internal::IsConstQualifiedMatcher());
>> +}
>> +
>> +/// \brief Matches a member expression where the member is matched by a
>> +/// given matcher.
>> +///
>> +/// Given
>> +///   struct { int first, second; } first, second;
>> +///   int i(second.first);
>> +///   int j(first.second);
>> +/// memberExpression(member(hasName("first")))
>> +///   matches second.first
>> +///   but not first.second (because the member name there is "second").
>> +AST_MATCHER_P(clang::MemberExpr, member,
>> +              internal::Matcher<clang::ValueDecl>, InnerMatcher) {
>> +  return InnerMatcher.matches(*Node.getMemberDecl(), Finder, Builder);
>> +}
>> +
>> +/// \brief Matches a member expression where the object expression is
>> +/// matched by a given matcher.
>> +///
>> +/// Given
>> +///   struct X { int m; };
>> +///   void f(X x) { x.m; m; }
>> +///
>> memberExpression(hasObjectExpression(hasType(record(hasName("X")))))))
>> +///   matches "x.m" and "m"
>> +/// with hasObjectExpression(...)
>> +///   matching "x" and the implicit object expression of "m" which has
>> type X*.
>> +AST_MATCHER_P(clang::MemberExpr, hasObjectExpression,
>> +              internal::Matcher<clang::Expr>, InnerMatcher) {
>> +  return InnerMatcher.matches(*Node.getBase(), Finder, Builder);
>> +}
>> +
>> +/// \brief Matches template instantiations of function, class, or static
>> +/// member variable template instantiations.
>> +///
>> +/// Given
>> +///   template <typename T> class X {}; class A {}; X<A> x;
>> +/// or
>> +///   template <typename T> class X {}; class A {}; template class X<A>;
>> +/// record(hasName("::X"), isTemplateInstantiation())
>> +///   matches the template instantiation of X<A>.
>> +///
>> +/// But given
>> +///   template <typename T> class X {}; class A {};
>> +///   template <> class X<A> {}; X<A> x;
>> +/// record(hasName("::X"), isTemplateInstantiation())
>> +///   does not match, as X<A> is an explicit template specialization.
>> +inline internal::PolymorphicMatcherWithParam0<
>> +  internal::IsTemplateInstantiationMatcher>
>> +isTemplateInstantiation() {
>> +  return internal::PolymorphicMatcherWithParam0<
>> +    internal::IsTemplateInstantiationMatcher>();
>> +}
>> +
>> +} // end namespace ast_matchers
>> +} // end namespace clang
>> +
>> +#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H
>>
>> Added: cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h?rev=159805&view=auto
>>
>> ==============================================================================
>> --- cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h (added)
>> +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h Fri Jul  6
>> 00:48:52 2012
>> @@ -0,0 +1,888 @@
>> +//===--- ASTMatchersInternal.h - Structural query framework -----*- C++
>> -*-===//
>> +//
>> +//                     The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +//
>> +//  Implements the base layer of the matcher framework.
>> +//
>> +//  Matchers are methods that return a Matcher<T> which provides a method
>> +//  Matches(...) which is a predicate on an AST node. The Matches
>> method's
>> +//  parameters define the context of the match, which allows matchers to
>> recurse
>> +//  or store the current node as bound to a specific string, so that it
>> can be
>> +//  retrieved later.
>> +//
>> +//  In general, matchers have two parts:
>> +//  1. A function Matcher<T> MatcherName(<arguments>) which returns a
>> Matcher<T>
>> +//     based on the arguments and optionally on template type deduction
>> based
>> +//     on the arguments. Matcher<T>s form an implicit reverse hierarchy
>> +//     to clang's AST class hierarchy, meaning that you can use a
>> Matcher<Base>
>> +//     everywhere a Matcher<Derived> is required.
>> +//  2. An implementation of a class derived from MatcherInterface<T>.
>> +//
>> +//  The matcher functions are defined in ASTMatchers.h. To make it
>> possible
>> +//  to implement both the matcher function and the implementation of the
>> matcher
>> +//  interface in one place, ASTMatcherMacros.h defines macros that allow
>> +//  implementing a matcher in a single place.
>> +//
>> +//  This file contains the base classes needed to construct the actual
>> matchers.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H
>> +#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H
>> +
>> +#include "clang/AST/Decl.h"
>> +#include "clang/AST/DeclCXX.h"
>> +#include "clang/AST/ExprCXX.h"
>> +#include "clang/AST/Stmt.h"
>> +#include "llvm/ADT/VariadicFunction.h"
>> +#include <map>
>> +#include <string>
>> +#include <vector>
>> +
>> +/// FIXME: Move into the llvm support library.
>> +template <bool> struct CompileAssert {};
>> +#define TOOLING_COMPILE_ASSERT(Expr, Msg) \
>> +  typedef CompileAssert<(bool(Expr))> Msg[bool(Expr) ? 1 : -1]
>> +
>> +namespace clang {
>> +namespace ast_matchers {
>> +
>> +class BoundNodes;
>> +
>> +namespace internal {
>> +
>> +class BoundNodesTreeBuilder;
>> +
>> +/// \brief A tree of bound nodes in match results.
>> +///
>> +/// If a match can contain multiple matches on the same node with
>> different
>> +/// matching subexpressions, BoundNodesTree contains a branch for each of
>> +/// those matching subexpressions.
>> +///
>> +/// BoundNodesTree's are created during the matching process; when a
>> match
>> +/// is found, we iterate over the tree and create a BoundNodes object
>> containing
>> +/// the union of all bound nodes on the path from the root to a each
>> leaf.
>> +class BoundNodesTree {
>> +public:
>> +  /// \brief A visitor interface to visit all BoundNodes results for a
>> +  /// BoundNodesTree.
>> +  class Visitor {
>> +  public:
>> +    virtual ~Visitor() {}
>> +
>> +    /// \brief Called multiple times during a single call to
>> VisitMatches(...).
>> +    ///
>> +    /// 'BoundNodesView' contains the bound nodes for a single match.
>> +    virtual void visitMatch(const BoundNodes& BoundNodesView) = 0;
>> +  };
>> +
>> +  BoundNodesTree();
>> +
>> +  /// \brief Create a BoundNodesTree from pre-filled maps of bindings.
>> +  BoundNodesTree(const std::map<std::string, const clang::Decl*>&
>> DeclBindings,
>> +                 const std::map<std::string, const clang::Stmt*>&
>> StmtBindings,
>> +                 const std::vector<BoundNodesTree> RecursiveBindings);
>> +
>> +  /// \brief Adds all bound nodes to bound_nodes_builder.
>> +  void copyTo(BoundNodesTreeBuilder* Builder) const;
>> +
>> +  /// \brief Visits all matches that this BoundNodesTree represents.
>> +  ///
>> +  /// The ownership of 'ResultVisitor' remains at the caller.
>> +  void visitMatches(Visitor* ResultVisitor);
>> +
>> +private:
>> +  void visitMatchesRecursively(
>> +      Visitor* ResultVistior,
>> +      std::map<std::string, const clang::Decl*> DeclBindings,
>> +      std::map<std::string, const clang::Stmt*> StmtBindings);
>> +
>> +  template <typename T>
>> +  void copyBindingsTo(const T& bindings, BoundNodesTreeBuilder* Builder)
>> const;
>> +
>> +  // FIXME: Find out whether we want to use different data structures
>> here -
>> +  // first benchmarks indicate that it doesn't matter though.
>> +
>> +  std::map<std::string, const clang::Decl*> DeclBindings;
>> +  std::map<std::string, const clang::Stmt*> StmtBindings;
>> +
>> +  std::vector<BoundNodesTree> RecursiveBindings;
>> +};
>> +
>> +/// \brief Creates BoundNodesTree objects.
>> +///
>> +/// The tree builder is used during the matching process to insert the
>> bound
>> +/// nodes from the Id matcher.
>> +class BoundNodesTreeBuilder {
>> +public:
>> +  BoundNodesTreeBuilder();
>> +
>> +  /// \brief Add a binding from an id to a node.
>> +  ///
>> +  /// FIXME: Add overloads for all AST base types.
>> +  /// @{
>> +  void setBinding(const std::pair<const std::string,
>> +                                  const clang::Decl*>& binding);
>> +  void setBinding(const std::pair<const std::string,
>> +                                  const clang::Stmt*>& binding);
>> +  /// @}
>> +
>> +  /// \brief Adds a branch in the tree.
>> +  void addMatch(const BoundNodesTree& Bindings);
>> +
>> +  /// \brief Returns a BoundNodes object containing all current bindings.
>> +  BoundNodesTree build() const;
>> +
>> +private:
>> +  BoundNodesTreeBuilder(const BoundNodesTreeBuilder&);  // DO NOT
>> IMPLEMENT
>> +  void operator=(const BoundNodesTreeBuilder&);  // DO NOT IMPLEMENT
>> +
>> +  std::map<std::string, const clang::Decl*> DeclBindings;
>> +  std::map<std::string, const clang::Stmt*> StmtBindings;
>> +
>> +  std::vector<BoundNodesTree> RecursiveBindings;
>> +};
>> +
>> +class ASTMatchFinder;
>> +
>> +/// \brief Generic interface for matchers on an AST node of type T.
>> +///
>> +/// Implement this if your matcher may need to inspect the children or
>> +/// descendants of the node or bind matched nodes to names. If you are
>> +/// writing a simple matcher that only inspects properties of the
>> +/// current node and doesn't care about its children or descendants,
>> +/// implement SingleNodeMatcherInterface instead.
>> +template <typename T>
>> +class MatcherInterface : public llvm::RefCountedBaseVPTR {
>> +public:
>> +  virtual ~MatcherInterface() {}
>> +
>> +  /// \brief Returns true if 'Node' can be matched.
>> +  ///
>> +  /// May bind 'Node' to an ID via 'Builder', or recurse into
>> +  /// the AST via 'Finder'.
>> +  virtual bool matches(const T &Node,
>> +                       ASTMatchFinder *Finder,
>> +                       BoundNodesTreeBuilder *Builder) const = 0;
>> +};
>> +
>> +/// \brief Interface for matchers that only evaluate properties on a
>> single node.
>> +template <typename T>
>> +class SingleNodeMatcherInterface : public MatcherInterface<T> {
>> +public:
>> +  /// \brief Returns true if the matcher matches the provided node.
>> +  ///
>> +  /// A subclass must implement this instead of Matches().
>> +  virtual bool matchesNode(const T &Node) const = 0;
>> +
>> +private:
>> +  /// Implements MatcherInterface::Matches.
>> +  virtual bool matches(const T &Node,
>> +                       ASTMatchFinder * /* Finder */,
>> +                       BoundNodesTreeBuilder * /*  Builder */) const {
>> +    return matchesNode(Node);
>> +  }
>> +};
>> +
>> +/// \brief Wrapper of a MatcherInterface<T> *that allows copying.
>> +///
>> +/// A Matcher<Base> can be used anywhere a Matcher<Derived> is
>> +/// required. This establishes an is-a relationship which is reverse
>> +/// to the AST hierarchy. In other words, Matcher<T> is contravariant
>> +/// with respect to T. The relationship is built via a type conversion
>> +/// operator rather than a type hierarchy to be able to templatize the
>> +/// type hierarchy instead of spelling it out.
>> +template <typename T>
>> +class Matcher {
>> +public:
>> +  /// \brief Takes ownership of the provided implementation pointer.
>> +  explicit Matcher(MatcherInterface<T> *Implementation)
>> +      : Implementation(Implementation) {}
>> +
>> +  /// \brief Forwards the call to the underlying MatcherInterface<T>
>> pointer.
>> +  bool matches(const T &Node,
>> +               ASTMatchFinder *Finder,
>> +               BoundNodesTreeBuilder *Builder) const {
>> +    return Implementation->matches(Node, Finder, Builder);
>> +  }
>> +
>> +  /// \brief Implicitly converts this object to a Matcher<Derived>.
>> +  ///
>> +  /// Requires Derived to be derived from T.
>> +  template <typename Derived>
>> +  operator Matcher<Derived>() const {
>> +    return Matcher<Derived>(new ImplicitCastMatcher<Derived>(*this));
>> +  }
>> +
>> +  /// \brief Returns an ID that uniquely identifies the matcher.
>> +  uint64_t getID() const {
>> +    /// FIXME: Document the requirements this imposes on matcher
>> +    /// implementations (no new() implementation_ during a Matches()).
>> +    return reinterpret_cast<uint64_t>(Implementation.getPtr());
>> +  }
>> +
>> +private:
>> +  /// \brief Allows conversion from Matcher<T> to Matcher<Derived> if
>> Derived
>> +  /// is derived from T.
>> +  template <typename Derived>
>> +  class ImplicitCastMatcher : public MatcherInterface<Derived> {
>> +  public:
>> +    explicit ImplicitCastMatcher(const Matcher<T> &From)
>> +        : From(From) {}
>> +
>> +    virtual bool matches(const Derived &Node,
>> +                         ASTMatchFinder *Finder,
>> +                         BoundNodesTreeBuilder *Builder) const {
>> +      return From.matches(Node, Finder, Builder);
>> +    }
>> +
>> +  private:
>> +    const Matcher<T> From;
>> +  };
>> +
>> +  llvm::IntrusiveRefCntPtr< MatcherInterface<T> > Implementation;
>> +};  // class Matcher
>> +
>> +/// \brief A convenient helper for creating a Matcher<T> without
>> specifying
>> +/// the template type argument.
>> +template <typename T>
>> +inline Matcher<T> makeMatcher(MatcherInterface<T> *Implementation) {
>> +  return Matcher<T>(Implementation);
>> +}
>> +
>> +/// \brief Matches declarations for QualType and CallExpr.
>> +///
>> +/// Type argument DeclMatcherT is required by
>> PolymorphicMatcherWithParam1 but
>> +/// not actually used.
>> +template <typename T, typename DeclMatcherT>
>> +class HasDeclarationMatcher : public MatcherInterface<T> {
>> +  TOOLING_COMPILE_ASSERT((llvm::is_same< DeclMatcherT,
>> +                                         Matcher<clang::Decl> >::value),
>> +                          instantiated_with_wrong_types);
>> +public:
>> +  explicit HasDeclarationMatcher(const Matcher<clang::Decl>
>> &InnerMatcher)
>> +      : InnerMatcher(InnerMatcher) {}
>> +
>> +  virtual bool matches(const T &Node,
>> +                       ASTMatchFinder *Finder,
>> +                       BoundNodesTreeBuilder *Builder) const {
>> +    return matchesSpecialized(Node, Finder, Builder);
>> +  }
>> +
>> +private:
>> +  /// \brief Extracts the CXXRecordDecl of a QualType and returns whether
>> the
>> +  /// inner matcher matches on it.
>> +  bool matchesSpecialized(const clang::QualType &Node, ASTMatchFinder
>> *Finder,
>> +                          BoundNodesTreeBuilder *Builder) const {
>> +    /// FIXME: Add other ways to convert...
>> +    clang::CXXRecordDecl *NodeAsRecordDecl = Node->getAsCXXRecordDecl();
>> +    return NodeAsRecordDecl != NULL &&
>> +      InnerMatcher.matches(*NodeAsRecordDecl, Finder, Builder);
>> +  }
>> +
>> +  /// \brief Extracts the Decl of the callee of a CallExpr and returns
>> whether
>> +  /// the inner matcher matches on it.
>> +  bool matchesSpecialized(const clang::CallExpr &Node, ASTMatchFinder
>> *Finder,
>> +                          BoundNodesTreeBuilder *Builder) const {
>> +    const clang::Decl *NodeAsDecl = Node.getCalleeDecl();
>> +    return NodeAsDecl != NULL &&
>> +      InnerMatcher.matches(*NodeAsDecl, Finder, Builder);
>> +  }
>> +
>> +  /// \brief Extracts the Decl of the constructor call and returns
>> whether the
>> +  /// inner matcher matches on it.
>> +  bool matchesSpecialized(const clang::CXXConstructExpr &Node,
>> +                          ASTMatchFinder *Finder,
>> +                          BoundNodesTreeBuilder *Builder) const {
>> +    const clang::Decl *NodeAsDecl = Node.getConstructor();
>> +    return NodeAsDecl != NULL &&
>> +      InnerMatcher.matches(*NodeAsDecl, Finder, Builder);
>> +  }
>> +
>> +  const Matcher<clang::Decl> InnerMatcher;
>> +};
>> +
>> +/// \brief IsBaseType<T>::value is true if T is a "base" type in the AST
>> +/// node class hierarchies (i.e. if T is Decl, Stmt, or QualType).
>> +template <typename T>
>> +struct IsBaseType {
>> +  static const bool value =
>> +      (llvm::is_same<T, clang::Decl>::value ||
>> +       llvm::is_same<T, clang::Stmt>::value ||
>> +       llvm::is_same<T, clang::QualType>::value ||
>> +       llvm::is_same<T, clang::CXXCtorInitializer>::value);
>> +};
>> +template <typename T>
>> +const bool IsBaseType<T>::value;
>> +
>> +/// \brief Interface that can match any AST base node type and contains
>> default
>> +/// implementations returning false.
>> +class UntypedBaseMatcher : public llvm::RefCountedBaseVPTR {
>> +public:
>> +  virtual ~UntypedBaseMatcher() {}
>> +
>> +  virtual bool matches(const clang::Decl &DeclNode, ASTMatchFinder
>> *Finder,
>> +                       BoundNodesTreeBuilder *Builder) const {
>> +    return false;
>> +  }
>> +  virtual bool matches(const clang::QualType &TypeNode, ASTMatchFinder
>> *Finder,
>> +                       BoundNodesTreeBuilder *Builder) const {
>> +    return false;
>> +  }
>> +  virtual bool matches(const clang::Stmt &StmtNode, ASTMatchFinder
>> *Finder,
>> +                       BoundNodesTreeBuilder *Builder) const {
>> +    return false;
>> +  }
>> +  virtual bool matches(const clang::CXXCtorInitializer &CtorInitNode,
>> +                       ASTMatchFinder *Finder,
>> +                       BoundNodesTreeBuilder *Builder) const {
>> +    return false;
>> +  }
>> +
>> +  /// \brief Returns a unique ID for the matcher.
>> +  virtual uint64_t getID() const = 0;
>> +};
>> +
>> +/// \brief An UntypedBaseMatcher that overwrites the Matches(...) method
>> for
>> +/// node type T. T must be an AST base type.
>> +template <typename T>
>> +class TypedBaseMatcher : public UntypedBaseMatcher {
>> +  TOOLING_COMPILE_ASSERT(IsBaseType<T>::value,
>> +
>> typed_base_matcher_can_only_be_used_with_base_type);
>> +public:
>> +  explicit TypedBaseMatcher(const Matcher<T> &InnerMatcher)
>> +      : InnerMatcher(InnerMatcher) {}
>> +
>> +  using UntypedBaseMatcher::matches;
>> +  /// \brief Implements UntypedBaseMatcher::Matches.
>> +  ///
>> +  /// Since T is guaranteed to be a "base" AST node type, this method is
>> +  /// guaranteed to override one of the matches() methods from
>> +  /// UntypedBaseMatcher.
>> +  virtual bool matches(const T &Node,
>> +                       ASTMatchFinder *Finder,
>> +                       BoundNodesTreeBuilder *Builder) const {
>> +    return InnerMatcher.matches(Node, Finder, Builder);
>> +  }
>> +
>> +  /// \brief Implements UntypedBaseMatcher::getID.
>> +  virtual uint64_t getID() const {
>> +    return InnerMatcher.getID();
>> +  }
>> +
>> +private:
>> +  Matcher<T> InnerMatcher;
>> +};
>> +
>> +/// \brief Interface that allows matchers to traverse the AST.
>> +/// FIXME: Find a better name.
>> +///
>> +/// This provides two entry methods for each base node type in the AST:
>> +/// - matchesChildOf:
>> +///   Matches a matcher on every child node of the given node. Returns
>> true
>> +///   if at least one child node could be matched.
>> +/// - matchesDescendantOf:
>> +///   Matches a matcher on all descendant nodes of the given node.
>> Returns true
>> +///   if at least one descendant matched.
>> +class ASTMatchFinder {
>> +public:
>> +  /// \brief Defines how we descend a level in the AST when we pass
>> +  /// through expressions.
>> +  enum TraversalKind {
>> +    /// Will traverse any child nodes.
>> +    TK_AsIs,
>> +    /// Will not traverse implicit casts and parentheses.
>> +    TK_IgnoreImplicitCastsAndParentheses
>> +  };
>> +
>> +  /// \brief Defines how bindings are processed on recursive matches.
>> +  enum BindKind {
>> +    /// Stop at the first match and only bind the first match.
>> +    BK_First,
>> +    /// Create results for all combinations of bindings that match.
>> +    BK_All
>> +  };
>> +
>> +  virtual ~ASTMatchFinder() {}
>> +
>> +  /// \brief Returns true if the given class is directly or indirectly
>> derived
>> +  /// from a base type with the given name.
>> +  ///
>> +  /// A class is considered to be also derived from itself.
>> +  virtual bool classIsDerivedFrom(const clang::CXXRecordDecl
>> *Declaration,
>> +                                  StringRef BaseName) const = 0;
>> +
>> +  // FIXME: Implement for other base nodes.
>> +  virtual bool matchesChildOf(const clang::Decl &DeclNode,
>> +                              const UntypedBaseMatcher &BaseMatcher,
>> +                              BoundNodesTreeBuilder *Builder,
>> +                              TraversalKind Traverse,
>> +                              BindKind Bind) = 0;
>> +  virtual bool matchesChildOf(const clang::Stmt &StmtNode,
>> +                              const UntypedBaseMatcher &BaseMatcher,
>> +                              BoundNodesTreeBuilder *Builder,
>> +                              TraversalKind Traverse,
>> +                              BindKind Bind) = 0;
>> +
>> +  virtual bool matchesDescendantOf(const clang::Decl &DeclNode,
>> +                                   const UntypedBaseMatcher &BaseMatcher,
>> +                                   BoundNodesTreeBuilder *Builder,
>> +                                   BindKind Bind) = 0;
>> +  virtual bool matchesDescendantOf(const clang::Stmt &StmtNode,
>> +                                   const UntypedBaseMatcher &BaseMatcher,
>> +                                   BoundNodesTreeBuilder *Builder,
>> +                                   BindKind Bind) = 0;
>> +};
>> +
>> +/// \brief Converts a Matcher<T> to a matcher of desired type To by
>> "adapting"
>> +/// a To into a T.
>> +///
>> +/// The ArgumentAdapterT argument specifies how the adaptation is done.
>> +///
>> +/// For example:
>> +///   ArgumentAdaptingMatcher<DynCastMatcher, T>(InnerMatcher);
>> +/// returns a matcher that can be used where a Matcher<To> is required,
>> if
>> +/// To and T are in the same type hierarchy, and thus dyn_cast can be
>> +/// called to convert a To to a T.
>> +///
>> +/// FIXME: Make sure all our applications of this class actually require
>> +/// knowledge about the inner type. DynCastMatcher obviously does, but
>> the
>> +/// Has *matchers require the inner type solely for COMPILE_ASSERT
>> purposes.
>> +template <template <typename ToArg, typename FromArg> class
>> ArgumentAdapterT,
>> +          typename T>
>> +class ArgumentAdaptingMatcher {
>> +public:
>> +  explicit ArgumentAdaptingMatcher(const Matcher<T> &InnerMatcher)
>> +      : InnerMatcher(InnerMatcher) {}
>> +
>> +  template <typename To>
>> +  operator Matcher<To>() const {
>> +    return Matcher<To>(new ArgumentAdapterT<To, T>(InnerMatcher));
>> +  }
>> +
>> +private:
>> +  const Matcher<T> InnerMatcher;
>> +};
>> +
>> +/// \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)
>> +/// can be constructed.
>> +///
>> +/// For example:
>> +/// - PolymorphicMatcherWithParam0<IsDefinitionMatcher>()
>> +///   creates an object that can be used as a Matcher<T> for any type T
>> +///   where an IsDefinitionMatcher<T>() can be constructed.
>> +/// - 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>
>> +class PolymorphicMatcherWithParam0 {
>> +public:
>> +  template <typename T>
>> +  operator Matcher<T>() const {
>> +    return Matcher<T>(new MatcherT<T>());
>> +  }
>> +};
>> +
>> +template <template <typename T, typename P1> class MatcherT,
>> +          typename P1>
>> +class PolymorphicMatcherWithParam1 {
>> +public:
>> +  explicit PolymorphicMatcherWithParam1(const P1 &Param1)
>> +      : Param1(Param1) {}
>> +
>> +  template <typename T>
>> +  operator Matcher<T>() const {
>> +    return Matcher<T>(new MatcherT<T, P1>(Param1));
>> +  }
>> +
>> +private:
>> +  const P1 Param1;
>> +};
>> +
>> +template <template <typename T, typename P1, typename P2> class MatcherT,
>> +          typename P1, typename P2>
>> +class PolymorphicMatcherWithParam2 {
>> +public:
>> +  PolymorphicMatcherWithParam2(const P1 &Param1, const P2 &Param2)
>> +      : Param1(Param1), Param2(Param2) {}
>> +
>> +  template <typename T>
>> +  operator Matcher<T>() const {
>> +    return Matcher<T>(new MatcherT<T, P1, P2>(Param1, Param2));
>> +  }
>> +
>> +private:
>> +  const P1 Param1;
>> +  const P2 Param2;
>> +};
>> +
>> +/// \brief Matches any instance of the given NodeType.
>> +///
>> +/// This is useful when a matcher syntactically requires a child matcher,
>> +/// but the context doesn't care. See for example: anything().
>> +///
>> +/// FIXME: Alternatively we could also create a IsAMatcher or something
>> +/// that checks that a dyn_cast is possible. This is purely needed for
>> the
>> +/// difference between calling for example:
>> +///   record()
>> +/// and
>> +///   record(SomeMatcher)
>> +/// In the second case we need the correct type we were dyn_cast'ed to in
>> order
>> +/// to get the right type for the inner matcher. In the first case we
>> don't need
>> +/// that, but we use the type conversion anyway and insert a TrueMatcher.
>> +template <typename T>
>> +class TrueMatcher : public SingleNodeMatcherInterface<T>  {
>> +public:
>> +  virtual bool matchesNode(const T &Node) const {
>> +    return true;
>> +  }
>> +};
>> +
>> +/// \brief Provides a MatcherInterface<T> for a Matcher<To> that matches
>> if T is
>> +/// dyn_cast'able into To and the given Matcher<To> matches on the
>> dyn_cast'ed
>> +/// node.
>> +template <typename T, typename To>
>> +class DynCastMatcher : public MatcherInterface<T> {
>> +public:
>> +  explicit DynCastMatcher(const Matcher<To> &InnerMatcher)
>> +      : InnerMatcher(InnerMatcher) {}
>> +
>> +  virtual bool matches(const T &Node,
>> +                       ASTMatchFinder *Finder,
>> +                       BoundNodesTreeBuilder *Builder) const {
>> +    const To *InnerMatchValue = llvm::dyn_cast<To>(&Node);
>> +    return InnerMatchValue != NULL &&
>> +      InnerMatcher.matches(*InnerMatchValue, Finder, Builder);
>> +  }
>> +
>> +private:
>> +  const Matcher<To> InnerMatcher;
>> +};
>> +
>> +/// \brief Enables the user to pass a Matcher<clang::CXXMemberCallExpr>
>> to
>> +/// Call().
>> +///
>> +/// FIXME: Alternatives are using more specific methods than Call, like
>> +/// MemberCall, or not using VariadicFunction for Call and overloading
>> it.
>> +template <>
>> +template <>
>> +inline Matcher<clang::CXXMemberCallExpr>::
>> +operator Matcher<clang::CallExpr>() const {
>> +  return makeMatcher(
>> +    new DynCastMatcher<clang::CallExpr,
>> clang::CXXMemberCallExpr>(*this));
>> +}
>> +
>> +/// \brief Matcher<T> that wraps an inner Matcher<T> and binds the
>> matched node
>> +/// to an ID if the inner matcher matches on the node.
>> +template <typename T>
>> +class IdMatcher : public MatcherInterface<T> {
>> +public:
>> +  /// \brief Creates an IdMatcher that binds to 'ID' if 'InnerMatcher'
>> matches
>> +  /// the node.
>> +  IdMatcher(StringRef ID, const Matcher<T> &InnerMatcher)
>> +      : ID(ID), InnerMatcher(InnerMatcher) {}
>> +
>> +  virtual bool matches(const T &Node,
>> +                       ASTMatchFinder *Finder,
>> +                       BoundNodesTreeBuilder *Builder) const {
>> +    bool Result = InnerMatcher.matches(Node, Finder, Builder);
>> +    if (Result) {
>> +      Builder->setBinding(std::pair<const std::string, const T*>(ID,
>> &Node));
>> +    }
>> +    return Result;
>> +  }
>> +
>> +private:
>> +  const std::string ID;
>> +  const Matcher<T> InnerMatcher;
>> +};
>> +
>> +/// \brief Matches nodes of type T that have child nodes of type ChildT
>> for
>> +/// which a specified child matcher matches.
>> +///
>> +/// ChildT must be an AST base type.
>> +template <typename T, typename ChildT>
>> +class HasMatcher : public MatcherInterface<T> {
>> +  TOOLING_COMPILE_ASSERT(IsBaseType<ChildT>::value,
>> +                         has_only_accepts_base_type_matcher);
>> +public:
>> +  explicit HasMatcher(const Matcher<ChildT> &ChildMatcher)
>> +      : ChildMatcher(ChildMatcher) {}
>> +
>> +  virtual bool matches(const T &Node,
>> +                       ASTMatchFinder *Finder,
>> +                       BoundNodesTreeBuilder *Builder) const {
>> +    return Finder->matchesChildOf(
>> +        Node, ChildMatcher, Builder,
>> +        ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses,
>> +        ASTMatchFinder::BK_First);
>> +  }
>> +
>> + private:
>> +  const TypedBaseMatcher<ChildT> ChildMatcher;
>> +};
>> +
>> +/// \brief Matches nodes of type T that have child nodes of type ChildT
>> for
>> +/// which a specified child matcher matches. ChildT must be an AST base
>> +/// type.
>> +/// As opposed to the HasMatcher, the ForEachMatcher will produce a match
>> +/// for each child that matches.
>> +template <typename T, typename ChildT>
>> +class ForEachMatcher : public MatcherInterface<T> {
>> +  TOOLING_COMPILE_ASSERT(IsBaseType<ChildT>::value,
>> +                         for_each_only_accepts_base_type_matcher);
>> + public:
>> +  explicit ForEachMatcher(const Matcher<ChildT> &ChildMatcher)
>> +      : ChildMatcher(ChildMatcher) {}
>> +
>> +  virtual bool matches(const T& Node,
>> +                       ASTMatchFinder* Finder,
>> +                       BoundNodesTreeBuilder* Builder) const {
>> +    return Finder->matchesChildOf(
>> +      Node, ChildMatcher, Builder,
>> +      ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses,
>> +      ASTMatchFinder::BK_All);
>> +  }
>> +
>> +private:
>> +  const TypedBaseMatcher<ChildT> ChildMatcher;
>> +};
>> +
>> +/// \brief Matches nodes of type T if the given Matcher<T> does not
>> match.
>> +///
>> +/// Type argument MatcherT is required by PolymorphicMatcherWithParam1
>> +/// but not actually used. It will always be instantiated with a type
>> +/// convertible to Matcher<T>.
>> +template <typename T, typename MatcherT>
>> +class NotMatcher : public MatcherInterface<T> {
>> +public:
>> +  explicit NotMatcher(const Matcher<T> &InnerMatcher)
>> +      : InnerMatcher(InnerMatcher) {}
>> +
>> +  virtual bool matches(const T &Node,
>> +                       ASTMatchFinder *Finder,
>> +                       BoundNodesTreeBuilder *Builder) const {
>> +    return !InnerMatcher.matches(Node, Finder, Builder);
>> +  }
>> +
>> +private:
>> +  const Matcher<T> InnerMatcher;
>> +};
>> +
>> +/// \brief Matches nodes of type T for which both provided matchers
>> match.
>> +///
>> +/// Type arguments MatcherT1 and MatcherT2 are required by
>> +/// PolymorphicMatcherWithParam2 but not actually used. They will
>> +/// always be instantiated with types convertible to Matcher<T>.
>> +template <typename T, typename MatcherT1, typename MatcherT2>
>> +class AllOfMatcher : public MatcherInterface<T> {
>> +public:
>> +  AllOfMatcher(const Matcher<T> &InnerMatcher1, const Matcher<T>
>> &InnerMatcher2)
>> +      : InnerMatcher1(InnerMatcher1), InnerMatcher2(InnerMatcher2) {}
>> +
>> +  virtual bool matches(const T &Node,
>> +                       ASTMatchFinder *Finder,
>> +                       BoundNodesTreeBuilder *Builder) const {
>> +    return InnerMatcher1.matches(Node, Finder, Builder) &&
>> +           InnerMatcher2.matches(Node, Finder, Builder);
>> +  }
>> +
>> +private:
>> +  const Matcher<T> InnerMatcher1;
>> +  const Matcher<T> InnerMatcher2;
>> +};
>> +
>> +/// \brief Matches nodes of type T for which at least one of the two
>> provided
>> +/// matchers matches.
>> +///
>> +/// Type arguments MatcherT1 and MatcherT2 are
>> +/// required by PolymorphicMatcherWithParam2 but not actually
>> +/// used. They will always be instantiated with types convertible to
>> +/// Matcher<T>.
>> +template <typename T, typename MatcherT1, typename MatcherT2>
>> +class AnyOfMatcher : public MatcherInterface<T> {
>> +public:
>> +  AnyOfMatcher(const Matcher<T> &InnerMatcher1, const Matcher<T>
>> &InnerMatcher2)
>> +      : InnerMatcher1(InnerMatcher1), InnertMatcher2(InnerMatcher2) {}
>> +
>> +  virtual bool matches(const T &Node,
>> +                       ASTMatchFinder *Finder,
>> +                       BoundNodesTreeBuilder *Builder) const {
>> +    return InnerMatcher1.matches(Node, Finder, Builder) ||
>> +           InnertMatcher2.matches(Node, Finder, Builder);
>> +  }
>> +
>> +private:
>> +  const Matcher<T> InnerMatcher1;
>> +  const Matcher<T> InnertMatcher2;
>> +};
>> +
>> +/// \brief Creates a Matcher<T> that matches if
>> +/// T is dyn_cast'able into InnerT and all inner matchers match.
>> +template<typename T, typename InnerT>
>> +Matcher<T> makeDynCastAllOfComposite(
>> +    ArrayRef<const Matcher<InnerT> *> InnerMatchers) {
>> +  if (InnerMatchers.empty()) {
>> +    return ArgumentAdaptingMatcher<DynCastMatcher, InnerT>(
>> +        makeMatcher(new TrueMatcher<InnerT>));
>> +  }
>> +  Matcher<InnerT> InnerMatcher = *InnerMatchers.back();
>> +  for (int i = InnerMatchers.size() - 2; i >= 0; --i) {
>> +    InnerMatcher = makeMatcher(
>> +        new AllOfMatcher<InnerT, Matcher<InnerT>, Matcher<InnerT> >(
>> +            *InnerMatchers[i], InnerMatcher));
>> +  }
>> +  return ArgumentAdaptingMatcher<DynCastMatcher, InnerT>(InnerMatcher);
>> +}
>> +
>> +/// \brief Matches nodes of type T that have at least one descendant node
>> of
>> +/// type DescendantT for which the given inner matcher matches.
>> +///
>> +/// DescendantT must be an AST base type.
>> +template <typename T, typename DescendantT>
>> +class HasDescendantMatcher : public MatcherInterface<T> {
>> +  TOOLING_COMPILE_ASSERT(IsBaseType<DescendantT>::value,
>> +                         has_descendant_only_accepts_base_type_matcher);
>> +public:
>> +  explicit HasDescendantMatcher(const Matcher<DescendantT>
>> &DescendantMatcher)
>> +      : DescendantMatcher(DescendantMatcher) {}
>> +
>> +  virtual bool matches(const T &Node,
>> +                       ASTMatchFinder *Finder,
>> +                       BoundNodesTreeBuilder *Builder) const {
>> +    return Finder->matchesDescendantOf(
>> +        Node, DescendantMatcher, Builder, ASTMatchFinder::BK_First);
>> +  }
>> +
>> + private:
>> +  const TypedBaseMatcher<DescendantT> DescendantMatcher;
>> +};
>> +
>> +/// \brief Matches nodes of type T that have at least one descendant node
>> of
>> +/// type DescendantT for which the given inner matcher matches.
>> +///
>> +/// DescendantT must be an AST base type.
>> +/// As opposed to HasDescendantMatcher, ForEachDescendantMatcher will
>> match
>> +/// for each descendant node that matches instead of only for the first.
>> +template <typename T, typename DescendantT>
>> +class ForEachDescendantMatcher : public MatcherInterface<T> {
>> +  TOOLING_COMPILE_ASSERT(IsBaseType<DescendantT>::value,
>> +
>> for_each_descendant_only_accepts_base_type_matcher);
>> + public:
>> +  explicit ForEachDescendantMatcher(
>> +      const Matcher<DescendantT>& DescendantMatcher)
>> +      : DescendantMatcher(DescendantMatcher) {}
>> +
>> +  virtual bool matches(const T& Node,
>> +                       ASTMatchFinder* Finder,
>> +                       BoundNodesTreeBuilder* Builder) const {
>> +    return Finder->matchesDescendantOf(Node, DescendantMatcher, Builder,
>> +                                       ASTMatchFinder::BK_All);
>> +  }
>> +
>> +private:
>> +  const TypedBaseMatcher<DescendantT> DescendantMatcher;
>> +};
>> +
>> +/// \brief Matches on nodes that have a getValue() method if getValue()
>> equals
>> +/// the value the ValueEqualsMatcher was constructed with.
>> +template <typename T, typename ValueT>
>> +class ValueEqualsMatcher : public SingleNodeMatcherInterface<T> {
>> +  TOOLING_COMPILE_ASSERT((llvm::is_base_of<clang::CharacterLiteral,
>> T>::value ||
>> +                         llvm::is_base_of<clang::CXXBoolLiteralExpr,
>> +                                          T>::value ||
>> +                         llvm::is_base_of<clang::FloatingLiteral,
>> T>::value ||
>> +                         llvm::is_base_of<clang::IntegerLiteral,
>> T>::value),
>> +                         the_node_must_have_a_getValue_method);
>> +public:
>> +  explicit ValueEqualsMatcher(const ValueT &ExpectedValue)
>> +      : ExpectedValue(ExpectedValue) {}
>> +
>> +  virtual bool matchesNode(const T &Node) const {
>> +    return Node.getValue() == ExpectedValue;
>> +  }
>> +
>> +private:
>> +  const ValueT ExpectedValue;
>> +};
>> +
>> +template <typename T>
>> +class IsDefinitionMatcher : public SingleNodeMatcherInterface<T> {
>> +  TOOLING_COMPILE_ASSERT(
>> +    (llvm::is_base_of<clang::TagDecl, T>::value) ||
>> +    (llvm::is_base_of<clang::VarDecl, T>::value) ||
>> +    (llvm::is_base_of<clang::FunctionDecl, T>::value),
>> +    is_definition_requires_isThisDeclarationADefinition_method);
>> +public:
>> +  virtual bool matchesNode(const T &Node) const {
>> +    return Node.isThisDeclarationADefinition();
>> +  }
>> +};
>> +
>> +/// \brief Matches on template instantiations for FunctionDecl, VarDecl
>> or
>> +/// CXXRecordDecl nodes.
>> +template <typename T>
>> +class IsTemplateInstantiationMatcher : public MatcherInterface<T> {
>> +  TOOLING_COMPILE_ASSERT((llvm::is_base_of<clang::FunctionDecl,
>> T>::value) ||
>> +                         (llvm::is_base_of<clang::VarDecl, T>::value) ||
>> +                         (llvm::is_base_of<clang::CXXRecordDecl,
>> T>::value),
>> +                         requires_getTemplateSpecializationKind_method);
>> + public:
>> +  virtual bool matches(const T& Node,
>> +                       ASTMatchFinder* Finder,
>> +                       BoundNodesTreeBuilder* Builder) const {
>> +    return (Node.getTemplateSpecializationKind() ==
>> +                clang::TSK_ImplicitInstantiation ||
>> +            Node.getTemplateSpecializationKind() ==
>> +                clang::TSK_ExplicitInstantiationDefinition);
>> +  }
>> +};
>> +
>> +class IsArrowMatcher : public
>> SingleNodeMatcherInterface<clang::MemberExpr> {
>> +public:
>> +  virtual bool matchesNode(const clang::MemberExpr &Node) const {
>> +    return Node.isArrow();
>> +  }
>> +};
>> +
>> +class IsConstQualifiedMatcher
>> +    : public SingleNodeMatcherInterface<clang::QualType> {
>> + public:
>> +  virtual bool matchesNode(const clang::QualType& Node) const {
>> +    return Node.isConstQualified();
>> +  }
>> +};
>> +
>> +/// \brief A VariadicDynCastAllOfMatcher<SourceT, TargetT> object is a
>> +/// variadic functor that takes a number of Matcher<TargetT> and returns
>> a
>> +/// Matcher<SourceT> that matches TargetT nodes that are matched by all
>> of the
>> +/// given matchers, if SourceT can be dynamically casted into TargetT.
>> +///
>> +/// For example:
>> +///   const VariadicDynCastAllOfMatcher<
>> +///       clang::Decl, clang::CXXRecordDecl> record;
>> +/// Creates a functor record(...) that creates a Matcher<clang::Decl>
>> given
>> +/// a variable number of arguments of type Matcher<clang::CXXRecordDecl>.
>> +/// The returned matcher matches if the given clang::Decl can by
>> dynamically
>> +/// casted to clang::CXXRecordDecl and all given matchers match.
>> +template <typename SourceT, typename TargetT>
>> +class VariadicDynCastAllOfMatcher
>> +    : public llvm::VariadicFunction<
>> +        Matcher<SourceT>, Matcher<TargetT>,
>> +        makeDynCastAllOfComposite<SourceT, TargetT> > {
>> +public:
>> +  VariadicDynCastAllOfMatcher() {}
>> +};
>> +
>> +} // end namespace internal
>> +} // end namespace ast_matchers
>> +} // end namespace clang
>> +
>> +#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H
>>
>> Added: cfe/trunk/include/clang/ASTMatchers/ASTMatchersMacros.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchersMacros.h?rev=159805&view=auto
>>
>> ==============================================================================
>> --- cfe/trunk/include/clang/ASTMatchers/ASTMatchersMacros.h (added)
>> +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchersMacros.h Fri Jul  6
>> 00:48:52 2012
>> @@ -0,0 +1,224 @@
>> +//===--- ASTMatchersMacros.h - Structural query framework -------*- C++
>> -*-===//
>> +//
>> +//                     The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +//
>> +//  Defines macros that enable us to define new matchers in a single
>> place.
>> +//  Since a matcher is a function which returns a Matcher<T> object,
>> where
>> +//  T is the type of the actual implementation of the matcher, the macros
>> allow
>> +//  us to write matchers like functions and take care of the definition
>> of the
>> +//  class boilerplate.
>> +//
>> +//  Note that when you define a matcher with an AST_MATCHER* macro, only
>> the
>> +//  function which creates the matcher goes into the current namespace -
>> the
>> +//  class that implements the actual matcher, which gets returned by the
>> +//  generator function, is put into the 'internal' namespace. This allows
>> us
>> +//  to only have the functions (which is all the user cares about) in the
>> +//  'ast_matchers' namespace and hide the boilerplate.
>> +//
>> +//  To define a matcher in user code, always put it into the
>> clang::ast_matchers
>> +//  namespace and refer to the internal types via the 'internal::':
>> +//
>> +//  namespace clang {
>> +//  namespace ast_matchers {
>> +//  AST_MATCHER_P(MemberExpr, Member,
>> +//                internal::Matcher<ValueDecl>, InnerMatcher) {
>> +//    return InnerMatcher.matches(*Node.getMemberDecl(), Finder,
>> Builder);
>> +//  }
>> +//  } // end namespace ast_matchers
>> +//  } // end namespace clang
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
>> +#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
>> +
>> +/// \brief AST_MATCHER(Type, DefineMatcher) { ... }
>> +/// defines a zero parameter function named DefineMatcher() that returns
>> a
>> +/// Matcher<Type> object.
>> +///
>> +/// The code between the curly braces has access to the following
>> variables:
>> +///
>> +///   Node:                  the AST node being matched; its type is
>> Type.
>> +///   Finder:                an ASTMatchFinder*.
>> +///   Builder:               a BoundNodesTreeBuilder*.
>> +///
>> +/// The code should return true if 'Node' matches.
>> +#define AST_MATCHER(Type, DefineMatcher)
>> \
>> +  namespace internal {
>> \
>> +  class matcher_##DefineMatcher##Matcher
>> \
>> +      : public MatcherInterface<Type> {
>> \
>> +   public:
>> \
>> +    explicit matcher_##DefineMatcher##Matcher() {}
>> \
>> +    virtual bool matches(
>> \
>> +        const Type &Node, ASTMatchFinder *Finder,
>> \
>> +        BoundNodesTreeBuilder *Builder) const;
>> \
>> +  };
>> \
>> +  }
>> \
>> +  inline internal::Matcher<Type> DefineMatcher() {
>> \
>> +    return internal::makeMatcher(
>> \
>> +      new internal::matcher_##DefineMatcher##Matcher());
>> \
>> +  }
>> \
>> +  inline bool internal::matcher_##DefineMatcher##Matcher::matches(
>> \
>> +      const Type &Node, ASTMatchFinder *Finder,
>> \
>> +      BoundNodesTreeBuilder *Builder) const
>> +
>> +/// \brief AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) { ... }
>> +/// defines a single-parameter function named DefineMatcher() that
>> returns a
>> +/// Matcher<Type> object.
>> +///
>> +/// The code between the curly braces has access to the following
>> variables:
>> +///
>> +///   Node:                  the AST node being matched; its type is
>> Type.
>> +///   Param:                 the parameter passed to the function; its
>> type
>> +///                          is ParamType.
>> +///   Finder:                an ASTMatchFinder*.
>> +///   Builder:               a BoundNodesTreeBuilder*.
>> +///
>> +/// The code should return true if 'Node' matches.
>> +#define AST_MATCHER_P(Type, DefineMatcher, ParamType, Param)
>> \
>> +  namespace internal {
>> \
>> +  class matcher_##DefineMatcher##Matcher
>> \
>> +      : public MatcherInterface<Type> {
>> \
>> +   public:
>> \
>> +    explicit matcher_##DefineMatcher##Matcher(
>> \
>> +        const ParamType &A##Param) : Param(A##Param) {}
>> \
>> +    virtual bool matches(
>> \
>> +        const Type &Node, ASTMatchFinder *Finder,
>> \
>> +        BoundNodesTreeBuilder *Builder) const;
>> \
>> +   private:
>> \
>> +    const ParamType Param;
>> \
>> +  };
>> \
>> +  }
>> \
>> +  inline internal::Matcher<Type> DefineMatcher(const ParamType &Param) {
>> \
>> +    return internal::makeMatcher(
>> \
>> +      new internal::matcher_##DefineMatcher##Matcher(Param));
>> \
>> +  }
>> \
>> +  inline bool internal::matcher_##DefineMatcher##Matcher::matches(
>> \
>> +      const Type &Node, ASTMatchFinder *Finder,
>> \
>> +      BoundNodesTreeBuilder *Builder) const
>> +
>> +/// \brief AST_MATCHER_P2(
>> +///     Type, DefineMatcher, ParamType1, Param1, ParamType2, Param2) {
>> ... }
>> +/// defines a two-parameter function named DefineMatcher() that returns a
>> +/// Matcher<Type> object.
>> +///
>> +/// The code between the curly braces has access to the following
>> variables:
>> +///
>> +///   Node:                  the AST node being matched; its type is
>> Type.
>> +///   Param1, Param2:        the parameters passed to the function; their
>> types
>> +///                          are ParamType1 and ParamType2.
>> +///   Finder:                an ASTMatchFinder*.
>> +///   Builder:               a BoundNodesTreeBuilder*.
>> +///
>> +/// The code should return true if 'Node' matches.
>> +#define AST_MATCHER_P2(
>> \
>> +    Type, DefineMatcher, ParamType1, Param1, ParamType2, Param2)
>> \
>> +  namespace internal {
>> \
>> +  class matcher_##DefineMatcher##Matcher
>> \
>> +      : public MatcherInterface<Type> {
>> \
>> +   public:
>> \
>> +    matcher_##DefineMatcher##Matcher(
>> \
>> +        const ParamType1 &A##Param1, const ParamType2 &A##Param2)
>> \
>> +        : Param1(A##Param1), Param2(A##Param2) {}
>> \
>> +    virtual bool matches(
>> \
>> +        const Type &Node, ASTMatchFinder *Finder,
>> \
>> +        BoundNodesTreeBuilder *Builder) const;
>> \
>> +   private:
>> \
>> +    const ParamType1 Param1;
>> \
>> +    const ParamType2 Param2;
>> \
>> +  };
>> \
>> +  }
>> \
>> +  inline internal::Matcher<Type> DefineMatcher(
>> \
>> +      const ParamType1 &Param1, const ParamType2 &Param2) {
>> \
>> +    return internal::makeMatcher(
>> \
>> +      new internal::matcher_##DefineMatcher##Matcher(
>> \
>> +        Param1, Param2));
>> \
>> +  }
>> \
>> +  inline bool internal::matcher_##DefineMatcher##Matcher::matches(
>> \
>> +      const Type &Node, ASTMatchFinder *Finder,
>> \
>> +      BoundNodesTreeBuilder *Builder) const
>> +
>> +/// \brief AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) {
>> ... }
>> +/// defines a single-parameter function named DefineMatcher() that is
>> +/// polymorphic in the return type.
>> +///
>> +/// The variables are the same as for
>> +/// AST_MATCHER_P, with the addition of NodeType, which specifies the
>> node type
>> +/// 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)
>> \
>> +  namespace internal {
>> \
>> +  template <typename NodeType, typename ParamT>
>> \
>> +  class matcher_##DefineMatcher##Matcher
>> \
>> +      : public MatcherInterface<NodeType> {
>> \
>> +   public:
>> \
>> +    explicit matcher_##DefineMatcher##Matcher(
>> \
>> +        const ParamType &A##Param) : Param(A##Param) {}
>> \
>> +    virtual bool matches(
>> \
>> +        const NodeType &Node, ASTMatchFinder *Finder,
>> \
>> +        BoundNodesTreeBuilder *Builder) const;
>> \
>> +   private:
>> \
>> +    const ParamType Param;
>> \
>> +  };
>> \
>> +  }
>> \
>> +  inline internal::PolymorphicMatcherWithParam1<
>> \
>> +      internal::matcher_##DefineMatcher##Matcher,
>> \
>> +      ParamType >
>> \
>> +    DefineMatcher(const ParamType &Param) {
>> \
>> +    return internal::PolymorphicMatcherWithParam1<
>> \
>> +        internal::matcher_##DefineMatcher##Matcher,
>> \
>> +        ParamType >(Param);
>> \
>> +  }
>> \
>> +  template <typename NodeType, typename ParamT>
>> \
>> +  bool internal::matcher_##DefineMatcher##Matcher<NodeType,
>> ParamT>::matches(  \
>> +      const NodeType &Node, ASTMatchFinder *Finder,
>> \
>> +      BoundNodesTreeBuilder *Builder) const
>> +
>> +/// \brief AST_POLYMORPHIC_MATCHER_P2(
>> +///     DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... }
>> +/// defines a two-parameter function named matcher() that is polymorphic
>> in
>> +/// the return type.
>> +///
>> +/// 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)
>> \
>> +  namespace internal {
>> \
>> +  template <typename NodeType, typename ParamT1, typename ParamT2>
>> \
>> +  class matcher_##DefineMatcher##Matcher
>> \
>> +      : public MatcherInterface<NodeType> {
>> \
>> +   public:
>> \
>> +    matcher_##DefineMatcher##Matcher(
>> \
>> +        const ParamType1 &A##Param1, const ParamType2 &A##Param2)
>> \
>> +        : Param1(A##Param1), Param2(A##Param2) {}
>> \
>> +    virtual bool matches(
>> \
>> +        const NodeType &Node, ASTMatchFinder *Finder,
>> \
>> +        BoundNodesTreeBuilder *Builder) const;
>> \
>> +   private:
>> \
>> +    const ParamType1 Param1;
>> \
>> +    const ParamType2 Param2;
>> \
>> +  };
>> \
>> +  }
>> \
>> +  inline internal::PolymorphicMatcherWithParam2<
>> \
>> +      internal::matcher_##DefineMatcher##Matcher,
>> \
>> +      ParamType1, ParamType2 >
>> \
>> +    DefineMatcher(const ParamType1 &Param1, const ParamType2 &Param2) {
>> \
>> +    return internal::PolymorphicMatcherWithParam2<
>> \
>> +        internal::matcher_##DefineMatcher##Matcher,
>> \
>> +        ParamType1, ParamType2 >(
>> \
>> +        Param1, Param2);
>> \
>> +  }
>> \
>> +  template <typename NodeType, typename ParamT1, typename ParamT2>
>> \
>> +  bool internal::matcher_##DefineMatcher##Matcher<
>> \
>> +      NodeType, ParamT1, ParamT2>::matches(
>> \
>> +      const NodeType &Node, ASTMatchFinder *Finder,
>> \
>> +      BoundNodesTreeBuilder *Builder) const
>> +
>> +#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
>>
>> Added: cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp?rev=159805&view=auto
>>
>> ==============================================================================
>> --- cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp (added)
>> +++ cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp Fri Jul  6 00:48:52 2012
>> @@ -0,0 +1,556 @@
>> +//===--- ASTMatchFinder.cpp - Structural query framework
>> ------------------===//
>> +//
>> +//                     The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +//
>> +//  Implements an algorithm to efficiently search for matches on AST
>> nodes.
>> +//  Uses memoization to support recursive matches like HasDescendant.
>> +//
>> +//  The general idea is to visit all AST nodes with a
>> RecursiveASTVisitor,
>> +//  calling the Matches(...) method of each matcher we are running on
>> each
>> +//  AST node. The matcher can recurse via the ASTMatchFinder interface.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#include "clang/ASTMatchers/ASTMatchFinder.h"
>> +#include "clang/AST/ASTConsumer.h"
>> +#include "clang/AST/ASTContext.h"
>> +#include "clang/AST/RecursiveASTVisitor.h"
>> +#include <set>
>> +
>> +namespace clang {
>> +namespace ast_matchers {
>> +namespace internal {
>> +namespace {
>> +
>> +// Returns the value that 'AMap' maps 'Key' to, or NULL if 'Key' is
>> +// not in 'AMap'.
>> +template <typename Map>
>> +static const typename Map::mapped_type *
>> +find(const Map &AMap, const typename Map::key_type &Key) {
>> +  typename Map::const_iterator It = AMap.find(Key);
>> +  return It == AMap.end() ? NULL : &It->second;
>> +}
>> +
>> +// We use memoization to avoid running the same matcher on the same
>> +// AST node twice.  This pair is the key for looking up match
>> +// result.  It consists of an ID of the MatcherInterface (for
>> +// identifying the matcher) and a pointer to the AST node.
>> +typedef std::pair<uint64_t, const void*> UntypedMatchInput;
>> +
>> +// Used to store the result of a match and possibly bound nodes.
>> +struct MemoizedMatchResult {
>> +  bool ResultOfMatch;
>> +  BoundNodesTree Nodes;
>> +};
>> +
>> +// A RecursiveASTVisitor that traverses all children or all descendants
>> of
>> +// a node.
>> +class MatchChildASTVisitor
>> +    : public clang::RecursiveASTVisitor<MatchChildASTVisitor> {
>> +public:
>> +  typedef clang::RecursiveASTVisitor<MatchChildASTVisitor> VisitorBase;
>> +
>> +  // Creates an AST visitor that matches 'matcher' on all children or
>> +  // descendants of a traversed node. max_depth is the maximum depth
>> +  // to traverse: use 1 for matching the children and INT_MAX for
>> +  // matching the descendants.
>> +  MatchChildASTVisitor(const UntypedBaseMatcher *BaseMatcher,
>> +                       ASTMatchFinder *Finder,
>> +                       BoundNodesTreeBuilder *Builder,
>> +                       int MaxDepth,
>> +                       ASTMatchFinder::TraversalKind Traversal,
>> +                       ASTMatchFinder::BindKind Bind)
>> +      : BaseMatcher(BaseMatcher),
>> +        Finder(Finder),
>> +        Builder(Builder),
>> +        CurrentDepth(-1),
>> +        MaxDepth(MaxDepth),
>> +        Traversal(Traversal),
>> +        Bind(Bind),
>> +        Matches(false) {}
>> +
>> +  // Returns true if a match is found in the subtree rooted at the
>> +  // given AST node. This is done via a set of mutually recursive
>> +  // functions. Here's how the recursion is done (the  *wildcard can
>> +  // actually be Decl, Stmt, or Type):
>> +  //
>> +  //   - Traverse(node) calls BaseTraverse(node) when it needs
>> +  //     to visit the descendants of node.
>> +  //   - BaseTraverse(node) then calls (via VisitorBase::Traverse*(node))
>> +  //     Traverse*(c) for each child c of 'node'.
>> +  //   - Traverse*(c) in turn calls Traverse(c), completing the
>> +  //     recursion.
>> +  template <typename T>
>> +  bool findMatch(const T &Node) {
>> +    reset();
>> +    traverse(Node);
>> +    return Matches;
>> +  }
>> +
>> +  // The following are overriding methods from the base visitor class.
>> +  // They are public only to allow CRTP to work. They are *not *part
>> +  // of the public API of this class.
>> +  bool TraverseDecl(clang::Decl *DeclNode) {
>> +    return (DeclNode == NULL) || traverse(*DeclNode);
>> +  }
>> +  bool TraverseStmt(clang::Stmt *StmtNode) {
>> +    const clang::Stmt *StmtToTraverse = StmtNode;
>> +    if (Traversal ==
>> +        ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses) {
>> +      const clang::Expr *ExprNode =
>> dyn_cast_or_null<clang::Expr>(StmtNode);
>> +      if (ExprNode != NULL) {
>> +        StmtToTraverse = ExprNode->IgnoreParenImpCasts();
>> +      }
>> +    }
>> +    return (StmtToTraverse == NULL) || traverse(*StmtToTraverse);
>> +  }
>> +  bool TraverseType(clang::QualType TypeNode) {
>> +    return traverse(TypeNode);
>> +  }
>> +
>> +  bool shouldVisitTemplateInstantiations() const { return true; }
>> +  bool shouldVisitImplicitCode() const { return true; }
>> +
>> +private:
>> +  // Used for updating the depth during traversal.
>> +  struct ScopedIncrement {
>> +    explicit ScopedIncrement(int *Depth) : Depth(Depth) { ++(*Depth); }
>> +    ~ScopedIncrement() { --(*Depth); }
>> +
>> +   private:
>> +    int *Depth;
>> +  };
>> +
>> +  // Resets the state of this object.
>> +  void reset() {
>> +    Matches = false;
>> +    CurrentDepth = -1;
>> +  }
>> +
>> +  // Forwards the call to the corresponding Traverse*() method in the
>> +  // base visitor class.
>> +  bool baseTraverse(const clang::Decl &DeclNode) {
>> +    return
>> VisitorBase::TraverseDecl(const_cast<clang::Decl*>(&DeclNode));
>> +  }
>> +  bool baseTraverse(const clang::Stmt &StmtNode) {
>> +    return
>> VisitorBase::TraverseStmt(const_cast<clang::Stmt*>(&StmtNode));
>> +  }
>> +  bool baseTraverse(clang::QualType TypeNode) {
>> +    return VisitorBase::TraverseType(TypeNode);
>> +  }
>> +
>> +  // Traverses the subtree rooted at 'node'; returns true if the
>> +  // traversal should continue after this function returns; also sets
>> +  // matched_ to true if a match is found during the traversal.
>> +  template <typename T>
>> +  bool traverse(const T &Node) {
>> +    TOOLING_COMPILE_ASSERT(IsBaseType<T>::value,
>> +
>> traverse_can_only_be_instantiated_with_base_type);
>> +    ScopedIncrement ScopedDepth(&CurrentDepth);
>> +    if (CurrentDepth == 0) {
>> +      // We don't want to match the root node, so just recurse.
>> +      return baseTraverse(Node);
>> +    }
>> +    if (Bind != ASTMatchFinder::BK_All) {
>> +      if (BaseMatcher->matches(Node, Finder, Builder)) {
>> +        Matches = true;
>> +        return false;  // Abort as soon as a match is found.
>> +      }
>> +      if (CurrentDepth < MaxDepth) {
>> +        // The current node doesn't match, and we haven't reached the
>> +        // maximum depth yet, so recurse.
>> +        return baseTraverse(Node);
>> +      }
>> +      // The current node doesn't match, and we have reached the
>> +      // maximum depth, so don't recurse (but continue the traversal
>> +      // such that other nodes at the current level can be visited).
>> +      return true;
>> +    } else {
>> +      BoundNodesTreeBuilder RecursiveBuilder;
>> +      if (BaseMatcher->matches(Node, Finder, &RecursiveBuilder)) {
>> +        // After the first match the matcher succeeds.
>> +        Matches = true;
>> +        Builder->addMatch(RecursiveBuilder.build());
>> +      }
>> +      if (CurrentDepth < MaxDepth) {
>> +        baseTraverse(Node);
>> +      }
>> +      // In kBindAll mode we always search for more matches.
>> +      return true;
>> +    }
>> +  }
>> +
>> +  const UntypedBaseMatcher *const BaseMatcher;
>> +  ASTMatchFinder *const Finder;
>> +  BoundNodesTreeBuilder *const Builder;
>> +  int CurrentDepth;
>> +  const int MaxDepth;
>> +  const ASTMatchFinder::TraversalKind Traversal;
>> +  const ASTMatchFinder::BindKind Bind;
>> +  bool Matches;
>> +};
>> +
>> +// Controls the outermost traversal of the AST and allows to match
>> multiple
>> +// matchers.
>> +class MatchASTVisitor : public
>> clang::RecursiveASTVisitor<MatchASTVisitor>,
>> +                        public ASTMatchFinder {
>> +public:
>> +  MatchASTVisitor(std::vector< std::pair<const UntypedBaseMatcher*,
>> +                               MatchFinder::MatchCallback*> > *Triggers)
>> +     : Triggers(Triggers),
>> +       ActiveASTContext(NULL) {
>> +  }
>> +
>> +  void set_active_ast_context(clang::ASTContext *NewActiveASTContext) {
>> +    ActiveASTContext = NewActiveASTContext;
>> +  }
>> +
>> +  // The following Visit*() and Traverse*() functions "override"
>> +  // methods in RecursiveASTVisitor.
>> +
>> +  bool VisitTypedefDecl(clang::TypedefDecl *DeclNode) {
>> +    // When we see 'typedef A B', we add name 'B' to the set of names
>> +    // A's canonical type maps to.  This is necessary for implementing
>> +    // IsDerivedFrom(x) properly, where x can be the name of the base
>> +    // class or any of its aliases.
>> +    //
>> +    // In general, the is-alias-of (as defined by typedefs) relation
>> +    // is tree-shaped, as you can typedef a type more than once.  For
>> +    // example,
>> +    //
>> +    //   typedef A B;
>> +    //   typedef A C;
>> +    //   typedef C D;
>> +    //   typedef C E;
>> +    //
>> +    // gives you
>> +    //
>> +    //   A
>> +    //   |- B
>> +    //   `- C
>> +    //      |- D
>> +    //      `- E
>> +    //
>> +    // It is wrong to assume that the relation is a chain.  A correct
>> +    // implementation of IsDerivedFrom() needs to recognize that B and
>> +    // E are aliases, even though neither is a typedef of the other.
>> +    // Therefore, we cannot simply walk through one typedef chain to
>> +    // find out whether the type name matches.
>> +    const clang::Type *TypeNode =
>> DeclNode->getUnderlyingType().getTypePtr();
>> +    const clang::Type *CanonicalType =  // root of the typedef tree
>> +        ActiveASTContext->getCanonicalType(TypeNode);
>> +    TypeToUnqualifiedAliases[CanonicalType].insert(
>> +        DeclNode->getName().str());
>> +    return true;
>> +  }
>> +
>> +  bool TraverseDecl(clang::Decl *DeclNode);
>> +  bool TraverseStmt(clang::Stmt *StmtNode);
>> +  bool TraverseType(clang::QualType TypeNode);
>> +  bool TraverseTypeLoc(clang::TypeLoc TypeNode);
>> +
>> +  // Matches children or descendants of 'Node' with 'BaseMatcher'.
>> +  template <typename T>
>> +  bool memoizedMatchesRecursively(const T &Node,
>> +                                  const UntypedBaseMatcher &BaseMatcher,
>> +                                  BoundNodesTreeBuilder *Builder, int
>> MaxDepth,
>> +                                  TraversalKind Traversal, BindKind Bind)
>> {
>> +    TOOLING_COMPILE_ASSERT((llvm::is_same<T, clang::Decl>::value) ||
>> +                           (llvm::is_same<T, clang::Stmt>::value),
>> +                           type_does_not_support_memoization);
>> +    const UntypedMatchInput input(BaseMatcher.getID(), &Node);
>> +    std::pair<MemoizationMap::iterator, bool> InsertResult
>> +      = ResultCache.insert(std::make_pair(input, MemoizedMatchResult()));
>> +    if (InsertResult.second) {
>> +      BoundNodesTreeBuilder DescendantBoundNodesBuilder;
>> +      InsertResult.first->second.ResultOfMatch =
>> +        matchesRecursively(Node, BaseMatcher,
>> &DescendantBoundNodesBuilder,
>> +                           MaxDepth, Traversal, Bind);
>> +      InsertResult.first->second.Nodes =
>> +        DescendantBoundNodesBuilder.build();
>> +    }
>> +    InsertResult.first->second.Nodes.copyTo(Builder);
>> +    return InsertResult.first->second.ResultOfMatch;
>> +  }
>> +
>> +  // Matches children or descendants of 'Node' with 'BaseMatcher'.
>> +  template <typename T>
>> +  bool matchesRecursively(const T &Node, const UntypedBaseMatcher
>> &BaseMatcher,
>> +                          BoundNodesTreeBuilder *Builder, int MaxDepth,
>> +                          TraversalKind Traversal, BindKind Bind) {
>> +    MatchChildASTVisitor Visitor(
>> +      &BaseMatcher, this, Builder, MaxDepth, Traversal, Bind);
>> +    return Visitor.findMatch(Node);
>> +  }
>> +
>> +  virtual bool classIsDerivedFrom(const clang::CXXRecordDecl
>> *Declaration,
>> +                                  StringRef BaseName) const;
>> +
>> +  // Implements ASTMatchFinder::MatchesChildOf.
>> +  virtual bool matchesChildOf(const clang::Decl &DeclNode,
>> +                              const UntypedBaseMatcher &BaseMatcher,
>> +                              BoundNodesTreeBuilder *Builder,
>> +                              TraversalKind Traversal,
>> +                              BindKind Bind) {
>> +    return matchesRecursively(DeclNode, BaseMatcher, Builder, 1,
>> Traversal,
>> +                              Bind);
>> +  }
>> +  virtual bool matchesChildOf(const clang::Stmt &StmtNode,
>> +                              const UntypedBaseMatcher &BaseMatcher,
>> +                              BoundNodesTreeBuilder *Builder,
>> +                              TraversalKind Traversal,
>> +                              BindKind Bind) {
>> +    return matchesRecursively(StmtNode, BaseMatcher, Builder, 1,
>> Traversal,
>> +                              Bind);
>> +  }
>> +
>> +  // Implements ASTMatchFinder::MatchesDescendantOf.
>> +  virtual bool matchesDescendantOf(const clang::Decl &DeclNode,
>> +                                   const UntypedBaseMatcher &BaseMatcher,
>> +                                   BoundNodesTreeBuilder *Builder,
>> +                                   BindKind Bind) {
>> +    return memoizedMatchesRecursively(DeclNode, BaseMatcher, Builder,
>> INT_MAX,
>> +                                      TK_AsIs, Bind);
>> +  }
>> +  virtual bool matchesDescendantOf(const clang::Stmt &StmtNode,
>> +                                   const UntypedBaseMatcher &BaseMatcher,
>> +                                   BoundNodesTreeBuilder *Builder,
>> +                                   BindKind Bind) {
>> +    return memoizedMatchesRecursively(StmtNode, BaseMatcher, Builder,
>> INT_MAX,
>> +                                      TK_AsIs, Bind);
>> +  }
>> +
>> +  bool shouldVisitTemplateInstantiations() const { return true; }
>> +  bool shouldVisitImplicitCode() const { return true; }
>> +
>> +private:
>> +  // Implements a BoundNodesTree::Visitor that calls a MatchCallback with
>> +  // the aggregated bound nodes for each match.
>> +  class MatchVisitor : public BoundNodesTree::Visitor {
>> +  public:
>> +    MatchVisitor(clang::ASTContext* Context,
>> +                 MatchFinder::MatchCallback* Callback)
>> +      : Context(Context),
>> +        Callback(Callback) {}
>> +
>> +    virtual void visitMatch(const BoundNodes& BoundNodesView) {
>> +      Callback->run(MatchFinder::MatchResult(BoundNodesView, Context));
>> +    }
>> +
>> +  private:
>> +    clang::ASTContext* Context;
>> +    MatchFinder::MatchCallback* Callback;
>> +  };
>> +
>> +  // Returns true if 'TypeNode' is also known by the name 'Name'.  In
>> other
>> +  // words, there is a type (including typedef) with the name 'Name'
>> +  // that is equal to 'TypeNode'.
>> +  bool typeHasAlias(const clang::Type *TypeNode,
>> +                    StringRef Name) const {
>> +    const clang::Type *const CanonicalType =
>> +      ActiveASTContext->getCanonicalType(TypeNode);
>> +    const std::set<std::string> *UnqualifiedAlias =
>> +      find(TypeToUnqualifiedAliases, CanonicalType);
>> +    return UnqualifiedAlias != NULL && UnqualifiedAlias->count(Name) > 0;
>> +  }
>> +
>> +  // Matches all registered matchers on the given node and calls the
>> +  // result callback for every node that matches.
>> +  template <typename T>
>> +  void match(const T &node) {
>> +    for (std::vector< std::pair<const UntypedBaseMatcher*,
>> +                      MatchFinder::MatchCallback*> >::const_iterator
>> +             It = Triggers->begin(), End = Triggers->end();
>> +         It != End; ++It) {
>> +      BoundNodesTreeBuilder Builder;
>> +      if (It->first->matches(node, this, &Builder)) {
>> +        BoundNodesTree BoundNodes = Builder.build();
>> +        MatchVisitor Visitor(ActiveASTContext, It->second);
>> +        BoundNodes.visitMatches(&Visitor);
>> +      }
>> +    }
>> +  }
>> +
>> +  std::vector< std::pair<const UntypedBaseMatcher*,
>> +               MatchFinder::MatchCallback*> > *const Triggers;
>> +  clang::ASTContext *ActiveASTContext;
>> +
>> +  // Maps a canonical type to the names of its typedefs.
>> +  llvm::DenseMap<const clang::Type*, std::set<std::string> >
>> +    TypeToUnqualifiedAliases;
>> +
>> +  // Maps (matcher, node) -> the match result for memoization.
>> +  typedef llvm::DenseMap<UntypedMatchInput, MemoizedMatchResult>
>> MemoizationMap;
>> +  MemoizationMap ResultCache;
>> +};
>> +
>> +// Returns true if the given class is directly or indirectly derived
>> +// from a base type with the given name.  A class is considered to be
>> +// also derived from itself.
>> +bool
>> +MatchASTVisitor::classIsDerivedFrom(const clang::CXXRecordDecl
>> *Declaration,
>> +                                    StringRef BaseName) const {
>> +  if (Declaration->getName() == BaseName) {
>> +    return true;
>> +  }
>> +  if (!Declaration->hasDefinition()) {
>> +    return false;
>> +  }
>> +  typedef clang::CXXRecordDecl::base_class_const_iterator BaseIterator;
>> +  for (BaseIterator It = Declaration->bases_begin(),
>> +                    End = Declaration->bases_end(); It != End; ++It) {
>> +    const clang::Type *TypeNode = It->getType().getTypePtr();
>> +
>> +    if (typeHasAlias(TypeNode, BaseName))
>> +      return true;
>> +
>> +    // clang::Type::getAs<...>() drills through typedefs.
>> +    if (TypeNode->getAs<clang::DependentNameType>() != NULL ||
>> +        TypeNode->getAs<clang::TemplateTypeParmType>() != NULL) {
>> +      // Dependent names and template TypeNode parameters will be matched
>> when
>> +      // the template is instantiated.
>> +      continue;
>> +    }
>> +    clang::CXXRecordDecl *ClassDecl = NULL;
>> +    clang::TemplateSpecializationType const *TemplateType =
>> +      TypeNode->getAs<clang::TemplateSpecializationType>();
>> +    if (TemplateType != NULL) {
>> +      if (TemplateType->getTemplateName().isDependent()) {
>> +        // Dependent template specializations will be matched when the
>> +        // template is instantiated.
>> +        continue;
>> +      }
>> +      // For template specialization types which are specializing a
>> template
>> +      // declaration which is an explicit or partial specialization of
>> another
>> +      // template declaration, getAsCXXRecordDecl() returns the
>> corresponding
>> +      // ClassTemplateSpecializationDecl.
>> +      //
>> +      // For template specialization types which are specializing a
>> template
>> +      // declaration which is neither an explicit nor partial
>> specialization of
>> +      // another template declaration, getAsCXXRecordDecl() returns NULL
>> and
>> +      // we get the CXXRecordDecl of the templated declaration.
>> +      clang::CXXRecordDecl *SpecializationDecl =
>> +        TemplateType->getAsCXXRecordDecl();
>> +      if (SpecializationDecl != NULL) {
>> +        ClassDecl = SpecializationDecl;
>> +      } else {
>> +        ClassDecl = llvm::dyn_cast<clang::CXXRecordDecl>(
>> +            TemplateType->getTemplateName()
>> +                .getAsTemplateDecl()->getTemplatedDecl());
>> +      }
>> +    } else {
>> +      ClassDecl = TypeNode->getAsCXXRecordDecl();
>> +    }
>> +    assert(ClassDecl != NULL);
>> +    assert(ClassDecl != Declaration);
>> +    if (classIsDerivedFrom(ClassDecl, BaseName)) {
>> +      return true;
>> +    }
>> +  }
>> +  return false;
>> +}
>> +
>> +bool MatchASTVisitor::TraverseDecl(clang::Decl *DeclNode) {
>> +  if (DeclNode == NULL) {
>> +    return true;
>> +  }
>> +  match(*DeclNode);
>> +  return
>> clang::RecursiveASTVisitor<MatchASTVisitor>::TraverseDecl(DeclNode);
>> +}
>> +
>> +bool MatchASTVisitor::TraverseStmt(clang::Stmt *StmtNode) {
>> +  if (StmtNode == NULL) {
>> +    return true;
>> +  }
>> +  match(*StmtNode);
>> +  return
>> clang::RecursiveASTVisitor<MatchASTVisitor>::TraverseStmt(StmtNode);
>> +}
>> +
>> +bool MatchASTVisitor::TraverseType(clang::QualType TypeNode) {
>> +  match(TypeNode);
>> +  return
>> clang::RecursiveASTVisitor<MatchASTVisitor>::TraverseType(TypeNode);
>> +}
>> +
>> +bool MatchASTVisitor::TraverseTypeLoc(clang::TypeLoc TypeLoc) {
>> +  return clang::RecursiveASTVisitor<MatchASTVisitor>::
>> +      TraverseType(TypeLoc.getType());
>> +}
>> +
>> +class MatchASTConsumer : public clang::ASTConsumer {
>> +public:
>> +  MatchASTConsumer(std::vector< std::pair<const UntypedBaseMatcher*,
>> +                                MatchFinder::MatchCallback*> > *Triggers,
>> +                   MatchFinder::ParsingDoneTestCallback *ParsingDone)
>> +      : Visitor(Triggers),
>> +        ParsingDone(ParsingDone) {}
>> +
>> +private:
>> +  virtual void HandleTranslationUnit(clang::ASTContext &Context) {
>> +    if (ParsingDone != NULL) {
>> +      ParsingDone->run();
>> +    }
>> +    Visitor.set_active_ast_context(&Context);
>> +    Visitor.TraverseDecl(Context.getTranslationUnitDecl());
>> +    Visitor.set_active_ast_context(NULL);
>> +  }
>> +
>> +  MatchASTVisitor Visitor;
>> +  MatchFinder::ParsingDoneTestCallback *ParsingDone;
>> +};
>> +
>> +} // end namespace
>> +} // end namespace internal
>> +
>> +MatchFinder::MatchResult::MatchResult(const BoundNodes &Nodes,
>> +                                      clang::ASTContext *Context)
>> +  : Nodes(Nodes), Context(Context),
>> +    SourceManager(&Context->getSourceManager()) {}
>> +
>> +MatchFinder::MatchCallback::~MatchCallback() {}
>> +MatchFinder::ParsingDoneTestCallback::~ParsingDoneTestCallback() {}
>> +
>> +MatchFinder::MatchFinder() : ParsingDone(NULL) {}
>> +
>> +MatchFinder::~MatchFinder() {
>> +  for (std::vector< std::pair<const internal::UntypedBaseMatcher*,
>> +                    MatchFinder::MatchCallback*> >::const_iterator
>> +           It = Triggers.begin(), End = Triggers.end();
>> +       It != End; ++It) {
>> +    delete It->first;
>> +  }
>> +}
>> +
>> +void MatchFinder::addMatcher(const DeclarationMatcher &NodeMatch,
>> +                             MatchCallback *Action) {
>> +  Triggers.push_back(std::make_pair(
>> +    new internal::TypedBaseMatcher<clang::Decl>(NodeMatch), Action));
>> +}
>> +
>> +void MatchFinder::addMatcher(const TypeMatcher &NodeMatch,
>> +                             MatchCallback *Action) {
>> +  Triggers.push_back(std::make_pair(
>> +    new internal::TypedBaseMatcher<clang::QualType>(NodeMatch), Action));
>> +}
>> +
>> +void MatchFinder::addMatcher(const StatementMatcher &NodeMatch,
>> +                             MatchCallback *Action) {
>> +  Triggers.push_back(std::make_pair(
>> +    new internal::TypedBaseMatcher<clang::Stmt>(NodeMatch), Action));
>> +}
>> +
>> +clang::ASTConsumer *MatchFinder::newASTConsumer() {
>> +  return new internal::MatchASTConsumer(&Triggers, ParsingDone);
>> +}
>> +
>> +void MatchFinder::registerTestCallbackAfterParsing(
>> +    MatchFinder::ParsingDoneTestCallback *NewParsingDone) {
>> +  ParsingDone = NewParsingDone;
>> +}
>> +
>> +} // end namespace ast_matchers
>> +} // end namespace clang
>>
>> Added: cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp?rev=159805&view=auto
>>
>> ==============================================================================
>> --- cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp (added)
>> +++ cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp Fri Jul  6 00:48:52
>> 2012
>> @@ -0,0 +1,102 @@
>> +//===--- ASTMatchersInternal.cpp - Structural query framework
>> -------------===//
>> +//
>> +//                     The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +//
>> +//  Implements the base layer of the matcher framework.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#include "clang/ASTMatchers/ASTMatchers.h"
>> +#include "clang/ASTMatchers/ASTMatchersInternal.h"
>> +
>> +namespace clang {
>> +namespace ast_matchers {
>> +namespace internal {
>> +
>> +BoundNodesTree::BoundNodesTree() {}
>> +
>> +BoundNodesTree::BoundNodesTree(
>> +  const std::map<std::string, const clang::Decl*>& DeclBindings,
>> +  const std::map<std::string, const clang::Stmt*>& StmtBindings,
>> +  const std::vector<BoundNodesTree> RecursiveBindings)
>> +  : DeclBindings(DeclBindings), StmtBindings(StmtBindings),
>> +    RecursiveBindings(RecursiveBindings) {}
>> +
>> +void BoundNodesTree::copyTo(BoundNodesTreeBuilder* Builder) const {
>> +  copyBindingsTo(DeclBindings, Builder);
>> +  copyBindingsTo(StmtBindings, Builder);
>> +  for (std::vector<BoundNodesTree>::const_iterator
>> +         I = RecursiveBindings.begin(),
>> +         E = RecursiveBindings.end();
>> +       I != E; ++I) {
>> +    Builder->addMatch(*I);
>> +  }
>> +}
>> +
>> +template <typename T>
>> +void BoundNodesTree::copyBindingsTo(
>> +    const T& Bindings, BoundNodesTreeBuilder* Builder) const {
>> +  for (typename T::const_iterator I = Bindings.begin(),
>> +                                  E = Bindings.end();
>> +       I != E; ++I) {
>> +    Builder->setBinding(*I);
>> +  }
>> +}
>> +
>> +void BoundNodesTree::visitMatches(Visitor* ResultVisitor) {
>> +  std::map<std::string, const clang::Decl*> AggregatedDeclBindings;
>> +  std::map<std::string, const clang::Stmt*> AggregatedStmtBindings;
>> +  visitMatchesRecursively(ResultVisitor, AggregatedDeclBindings,
>> +                          AggregatedStmtBindings);
>> +}
>> +
>> +void BoundNodesTree::
>> +visitMatchesRecursively(Visitor* ResultVisitor,
>> +                        std::map<std::string, const clang::Decl*>
>> +                          AggregatedDeclBindings,
>> +                        std::map<std::string, const clang::Stmt*>
>> +                          AggregatedStmtBindings) {
>> +  copy(DeclBindings.begin(), DeclBindings.end(),
>> +       inserter(AggregatedDeclBindings, AggregatedDeclBindings.begin()));
>> +  copy(StmtBindings.begin(), StmtBindings.end(),
>> +       inserter(AggregatedStmtBindings, AggregatedStmtBindings.begin()));
>> +  if (RecursiveBindings.empty()) {
>> +    ResultVisitor->visitMatch(BoundNodes(AggregatedDeclBindings,
>> +                                         AggregatedStmtBindings));
>> +  } else {
>> +    for (unsigned I = 0; I < RecursiveBindings.size(); ++I) {
>> +      RecursiveBindings[I].visitMatchesRecursively(ResultVisitor,
>> +
>> AggregatedDeclBindings,
>> +
>> AggregatedStmtBindings);
>> +    }
>> +  }
>> +}
>> +
>> +BoundNodesTreeBuilder::BoundNodesTreeBuilder() {}
>> +
>> +void BoundNodesTreeBuilder::
>> +setBinding(const std::pair<const std::string, const clang::Decl*>&
>> Binding) {
>> +  DeclBindings.insert(Binding);
>> +}
>> +
>> +void BoundNodesTreeBuilder::
>> +setBinding(const std::pair<const std::string, const clang::Stmt*>&
>> Binding) {
>> +  StmtBindings.insert(Binding);
>> +}
>> +
>> +void BoundNodesTreeBuilder::addMatch(const BoundNodesTree& Bindings) {
>> +  RecursiveBindings.push_back(Bindings);
>> +}
>> +
>> +BoundNodesTree BoundNodesTreeBuilder::build() const {
>> +  return BoundNodesTree(DeclBindings, StmtBindings, RecursiveBindings);
>> +}
>> +
>> +} // end namespace internal
>> +} // end namespace ast_matchers
>> +} // end namespace clang
>>
>> Added: cfe/trunk/lib/ASTMatchers/CMakeLists.txt
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/CMakeLists.txt?rev=159805&view=auto
>>
>> ==============================================================================
>> --- cfe/trunk/lib/ASTMatchers/CMakeLists.txt (added)
>> +++ cfe/trunk/lib/ASTMatchers/CMakeLists.txt Fri Jul  6 00:48:52 2012
>> @@ -0,0 +1,7 @@
>> +set(LLVM_LINK_COMPONENTS support)
>> +set(LLVM_USED_LIBS clangBasic clangAST)
>> +
>> +add_clang_library(clangASTMatchers
>> +  ASTMatchFinder.cpp
>> +  ASTMatchersInternal.cpp
>> +  )
>>
>> Added: cfe/trunk/lib/ASTMatchers/Makefile
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Makefile?rev=159805&view=auto
>>
>> ==============================================================================
>> --- cfe/trunk/lib/ASTMatchers/Makefile (added)
>> +++ cfe/trunk/lib/ASTMatchers/Makefile Fri Jul  6 00:48:52 2012
>> @@ -0,0 +1,15 @@
>> +##===- clang/lib/ASTMatchers/Makefile ----------------------*- Makefile
>> -*-===##
>> +#
>> +#                     The LLVM Compiler Infrastructure
>> +#
>> +# This file is distributed under the University of Illinois Open Source
>> +# License. See LICENSE.TXT for details.
>> +#
>>
>> +##===----------------------------------------------------------------------===##
>> +
>> +CLANG_LEVEL := ../..
>> +LIBRARYNAME := clangASTMatchers
>> +
>> +PARALLEL_DIRS = Dynamic
>> +
>> +include $(CLANG_LEVEL)/Makefile
>>
>> Modified: cfe/trunk/lib/CMakeLists.txt
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CMakeLists.txt?rev=159805&r1=159804&r2=159805&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/CMakeLists.txt (original)
>> +++ cfe/trunk/lib/CMakeLists.txt Fri Jul  6 00:48:52 2012
>> @@ -3,6 +3,7 @@
>>  add_subdirectory(Lex)
>>  add_subdirectory(Parse)
>>  add_subdirectory(AST)
>> +add_subdirectory(ASTMatchers)
>>  add_subdirectory(Sema)
>>  add_subdirectory(CodeGen)
>>  add_subdirectory(Analysis)
>>
>> Modified: cfe/trunk/lib/Makefile
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Makefile?rev=159805&r1=159804&r2=159805&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/Makefile (original)
>> +++ cfe/trunk/lib/Makefile Fri Jul  6 00:48:52 2012
>> @@ -8,7 +8,7 @@
>>
>> ##===----------------------------------------------------------------------===##
>>  CLANG_LEVEL := ..
>>
>> -PARALLEL_DIRS = Headers Basic Lex Parse AST Sema CodeGen Analysis \
>> +PARALLEL_DIRS = Headers Basic Lex Parse AST ASTMatchers Sema CodeGen
>> Analysis \
>>                  StaticAnalyzer Edit Rewrite ARCMigrate Serialization
>> Frontend \
>>                  FrontendTool Tooling Driver
>>
>>
>> Added: cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp?rev=159805&view=auto
>>
>> ==============================================================================
>> --- cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp (added)
>> +++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp Fri Jul  6
>> 00:48:52 2012
>> @@ -0,0 +1,1979 @@
>> +//===- unittest/Tooling/ASTMatchersTest.cpp - AST matcher unit tests
>> ------===//
>> +//
>> +//                     The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#include "ASTMatchersTest.h"
>> +#include "clang/ASTMatchers/ASTMatchers.h"
>> +#include "clang/ASTMatchers/ASTMatchFinder.h"
>> +#include "clang/Tooling/Tooling.h"
>> +#include "gtest/gtest.h"
>> +
>> +namespace clang {
>> +namespace ast_matchers {
>> +
>> +TEST(HasNameDeathTest, DiesOnEmptyName) {
>> +  ASSERT_DEBUG_DEATH({
>> +    DeclarationMatcher HasEmptyName = record(hasName(""));
>> +    EXPECT_TRUE(notMatches("class X {};", HasEmptyName));
>> +  }, "");
>> +}
>> +
>> +TEST(IsDerivedFromDeathTest, DiesOnEmptyBaseName) {
>> +  ASSERT_DEBUG_DEATH({
>> +    DeclarationMatcher IsDerivedFromEmpty = record(isDerivedFrom(""));
>> +    EXPECT_TRUE(notMatches("class X {};", IsDerivedFromEmpty));
>> +  }, "");
>> +}
>> +
>> +TEST(NameableDeclaration, MatchesVariousDecls) {
>> +  DeclarationMatcher NamedX = nameableDeclaration(hasName("X"));
>> +  EXPECT_TRUE(matches("typedef int X;", NamedX));
>> +  EXPECT_TRUE(matches("int X;", NamedX));
>> +  EXPECT_TRUE(matches("class foo { virtual void X(); };", NamedX));
>> +  EXPECT_TRUE(matches("void foo() try { } catch(int X) { }", NamedX));
>> +  EXPECT_TRUE(matches("void foo() { int X; }", NamedX));
>> +  EXPECT_TRUE(matches("namespace X { }", NamedX));
>> +
>> +  EXPECT_TRUE(notMatches("#define X 1", NamedX));
>> +}
>> +
>> +TEST(DeclarationMatcher, MatchClass) {
>> +  DeclarationMatcher ClassMatcher(record());
>> +  EXPECT_FALSE(matches("", ClassMatcher));
>> +
>> +  DeclarationMatcher ClassX = record(record(hasName("X")));
>> +  EXPECT_TRUE(matches("class X;", ClassX));
>> +  EXPECT_TRUE(matches("class X {};", ClassX));
>> +  EXPECT_TRUE(matches("template<class T> class X {};", ClassX));
>> +  EXPECT_TRUE(notMatches("", ClassX));
>> +}
>> +
>> +TEST(DeclarationMatcher, ClassIsDerived) {
>> +  DeclarationMatcher IsDerivedFromX = record(isDerivedFrom("X"));
>> +
>> +  EXPECT_TRUE(matches("class X {}; class Y : public X {};",
>> IsDerivedFromX));
>> +  EXPECT_TRUE(matches("class X {}; class Y : public X {};",
>> IsDerivedFromX));
>> +  EXPECT_TRUE(matches("class X {};", IsDerivedFromX));
>> +  EXPECT_TRUE(matches("class X;", IsDerivedFromX));
>> +  EXPECT_TRUE(notMatches("class Y;", IsDerivedFromX));
>> +  EXPECT_TRUE(notMatches("", IsDerivedFromX));
>> +
>> +  DeclarationMatcher ZIsDerivedFromX =
>> +      record(hasName("Z"), isDerivedFrom("X"));
>> +  EXPECT_TRUE(
>> +      matches("class X {}; class Y : public X {}; class Z : public Y
>> {};",
>> +              ZIsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      matches("class X {};"
>> +              "template<class T> class Y : public X {};"
>> +              "class Z : public Y<int> {};", ZIsDerivedFromX));
>> +  EXPECT_TRUE(matches("class X {}; template<class T> class Z : public X
>> {};",
>> +                      ZIsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      matches("template<class T> class X {}; "
>> +              "template<class T> class Z : public X<T> {};",
>> +              ZIsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      matches("template<class T, class U=T> class X {}; "
>> +              "template<class T> class Z : public X<T> {};",
>> +              ZIsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      notMatches("template<class X> class A { class Z : public X {}; };",
>> +                 ZIsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      matches("template<class X> class A { public: class Z : public X {};
>> }; "
>> +              "class X{}; void y() { A<X>::Z z; }", ZIsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      matches("template <class T> class X {}; "
>> +              "template<class Y> class A { class Z : public X<Y> {}; };",
>> +              ZIsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      notMatches("template<template<class T> class X> class A { "
>> +                 "  class Z : public X<int> {}; };", ZIsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      matches("template<template<class T> class X> class A { "
>> +              "  public: class Z : public X<int> {}; }; "
>> +              "template<class T> class X {}; void y() { A<X>::Z z; }",
>> +              ZIsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      notMatches("template<class X> class A { class Z : public X::D {};
>> };",
>> +                 ZIsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      matches("template<class X> class A { public: "
>> +              "  class Z : public X::D {}; }; "
>> +              "class Y { public: class X {}; typedef X D; }; "
>> +              "void y() { A<Y>::Z z; }", ZIsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      matches("class X {}; typedef X Y; class Z : public Y {};",
>> +              ZIsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      matches("template<class T> class Y { typedef typename T::U X; "
>> +              "  class Z : public X {}; };", ZIsDerivedFromX));
>> +  EXPECT_TRUE(matches("class X {}; class Z : public ::X {};",
>> +                      ZIsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      notMatches("template<class T> class X {}; "
>> +                "template<class T> class A { class Z : public X<T>::D {};
>> };",
>> +                ZIsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      matches("template<class T> class X { public: typedef X<T> D; }; "
>> +              "template<class T> class A { public: "
>> +              "  class Z : public X<T>::D {}; }; void y() { A<int>::Z z;
>> }",
>> +              ZIsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      notMatches("template<class X> class A { class Z : public X::D::E
>> {}; };",
>> +                 ZIsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      matches("class X {}; typedef X V; typedef V W; class Z : public W
>> {};",
>> +              ZIsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      matches("class X {}; class Y : public X {}; "
>> +              "typedef Y V; typedef V W; class Z : public W {};",
>> +              ZIsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      matches("template<class T, class U> class X {}; "
>> +              "template<class T> class A { class Z : public X<T, int> {};
>> };",
>> +              ZIsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      notMatches("template<class X> class D { typedef X A; typedef A B; "
>> +                 "  typedef B C; class Z : public C {}; };",
>> +                 ZIsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      matches("class X {}; typedef X A; typedef A B; "
>> +              "class Z : public B {};", ZIsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      matches("class X {}; typedef X A; typedef A B; typedef B C; "
>> +              "class Z : public C {};", ZIsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      matches("class U {}; typedef U X; typedef X V; "
>> +              "class Z : public V {};", ZIsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      matches("class Base {}; typedef Base X; "
>> +              "class Z : public Base {};", ZIsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      matches("class Base {}; typedef Base Base2; typedef Base2 X; "
>> +              "class Z : public Base {};", ZIsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      notMatches("class Base {}; class Base2 {}; typedef Base2 X; "
>> +                 "class Z : public Base {};", ZIsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      matches("class A {}; typedef A X; typedef A Y; "
>> +              "class Z : public Y {};", ZIsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      notMatches("template <typename T> class Z;"
>> +                 "template <> class Z<void> {};"
>> +                 "template <typename T> class Z : public Z<void> {};",
>> +                 IsDerivedFromX));
>> +  EXPECT_TRUE(
>> +      matches("template <typename T> class X;"
>> +              "template <> class X<void> {};"
>> +              "template <typename T> class X : public X<void> {};",
>> +              IsDerivedFromX));
>> +  EXPECT_TRUE(matches(
>> +      "class X {};"
>> +      "template <typename T> class Z;"
>> +      "template <> class Z<void> {};"
>> +      "template <typename T> class Z : public Z<void>, public X {};",
>> +      ZIsDerivedFromX));
>> +
>> +  // FIXME: Once we have better matchers for template type matching,
>> +  // get rid of the Variable(...) matching and match the right template
>> +  // declarations directly.
>> +  const char *RecursiveTemplateOneParameter =
>> +      "class Base1 {}; class Base2 {};"
>> +      "template <typename T> class Z;"
>> +      "template <> class Z<void> : public Base1 {};"
>> +      "template <> class Z<int> : public Base2 {};"
>> +      "template <> class Z<float> : public Z<void> {};"
>> +      "template <> class Z<double> : public Z<int> {};"
>> +      "template <typename T> class Z : public Z<float>, public Z<double>
>> {};"
>> +      "void f() { Z<float> z_float; Z<double> z_double; Z<char> z_char;
>> }";
>> +  EXPECT_TRUE(matches(
>> +      RecursiveTemplateOneParameter,
>> +      variable(hasName("z_float"),
>> +
>> hasInitializer(hasType(record(isDerivedFrom("Base1")))))));
>> +  EXPECT_TRUE(notMatches(
>> +      RecursiveTemplateOneParameter,
>> +      variable(
>> +          hasName("z_float"),
>> +          hasInitializer(hasType(record(isDerivedFrom("Base2")))))));
>> +  EXPECT_TRUE(matches(
>> +      RecursiveTemplateOneParameter,
>> +      variable(
>> +          hasName("z_char"),
>> +          hasInitializer(hasType(record(isDerivedFrom("Base1"),
>> +                                       isDerivedFrom("Base2")))))));
>> +
>> +  const char *RecursiveTemplateTwoParameters =
>> +      "class Base1 {}; class Base2 {};"
>> +      "template <typename T1, typename T2> class Z;"
>> +      "template <typename T> class Z<void, T> : public Base1 {};"
>> +      "template <typename T> class Z<int, T> : public Base2 {};"
>> +      "template <typename T> class Z<float, T> : public Z<void, T> {};"
>> +      "template <typename T> class Z<double, T> : public Z<int, T> {};"
>> +      "template <typename T1, typename T2> class Z : "
>> +      "    public Z<float, T2>, public Z<double, T2> {};"
>> +      "void f() { Z<float, void> z_float; Z<double, void> z_double; "
>> +      "           Z<char, void> z_char; }";
>> +  EXPECT_TRUE(matches(
>> +      RecursiveTemplateTwoParameters,
>> +      variable(
>> +          hasName("z_float"),
>> +          hasInitializer(hasType(record(isDerivedFrom("Base1")))))));
>> +  EXPECT_TRUE(notMatches(
>> +      RecursiveTemplateTwoParameters,
>> +      variable(
>> +          hasName("z_float"),
>> +          hasInitializer(hasType(record(isDerivedFrom("Base2")))))));
>> +  EXPECT_TRUE(matches(
>> +      RecursiveTemplateTwoParameters,
>> +      variable(
>> +          hasName("z_char"),
>> +          hasInitializer(hasType(record(isDerivedFrom("Base1"),
>> +                                       isDerivedFrom("Base2")))))));
>> +}
>> +
>> +TEST(DeclarationMatcher, MatchAnyOf) {
>> +  DeclarationMatcher YOrZDerivedFromX =
>> +      record(anyOf(hasName("Y"), allOf(isDerivedFrom("X"),
>> hasName("Z"))));
>> +
>> +  EXPECT_TRUE(
>> +      matches("class X {}; class Z : public X {};", YOrZDerivedFromX));
>> +  EXPECT_TRUE(matches("class Y {};", YOrZDerivedFromX));
>> +  EXPECT_TRUE(
>> +      notMatches("class X {}; class W : public X {};",
>> YOrZDerivedFromX));
>> +  EXPECT_TRUE(notMatches("class Z {};", YOrZDerivedFromX));
>> +
>> +  DeclarationMatcher XOrYOrZOrUOrV =
>> +      record(anyOf(hasName("X"), hasName("Y"), hasName("Z"),
>> hasName("U"),
>> +                  hasName("V")));
>> +
>> +  EXPECT_TRUE(matches("class X {};", XOrYOrZOrUOrV));
>> +  EXPECT_TRUE(matches("class Y {};", XOrYOrZOrUOrV));
>> +  EXPECT_TRUE(matches("class Z {};", XOrYOrZOrUOrV));
>> +  EXPECT_TRUE(matches("class U {};", XOrYOrZOrUOrV));
>> +  EXPECT_TRUE(matches("class V {};", XOrYOrZOrUOrV));
>> +  EXPECT_TRUE(notMatches("class A {};", XOrYOrZOrUOrV));
>> +}
>> +
>> +TEST(DeclarationMatcher, MatchHas) {
>> +  DeclarationMatcher HasClassX = record(has(record(hasName("X"))));
>> +
>> +  EXPECT_TRUE(matches("class Y { class X {}; };", HasClassX));
>> +  EXPECT_TRUE(matches("class X {};", HasClassX));
>> +
>> +  DeclarationMatcher YHasClassX =
>> +      record(hasName("Y"), has(record(hasName("X"))));
>> +  EXPECT_TRUE(matches("class Y { class X {}; };", YHasClassX));
>> +  EXPECT_TRUE(notMatches("class X {};", YHasClassX));
>> +  EXPECT_TRUE(
>> +      notMatches("class Y { class Z { class X {}; }; };", YHasClassX));
>> +}
>> +
>> +TEST(DeclarationMatcher, MatchHasRecursiveAllOf) {
>> +  DeclarationMatcher Recursive =
>> +    record(
>> +      has(record(
>> +        has(record(hasName("X"))),
>> +        has(record(hasName("Y"))),
>> +        hasName("Z"))),
>> +      has(record(
>> +        has(record(hasName("A"))),
>> +        has(record(hasName("B"))),
>> +        hasName("C"))),
>> +      hasName("F"));
>> +
>> +  EXPECT_TRUE(matches(
>> +      "class F {"
>> +      "  class Z {"
>> +      "    class X {};"
>> +      "    class Y {};"
>> +      "  };"
>> +      "  class C {"
>> +      "    class A {};"
>> +      "    class B {};"
>> +      "  };"
>> +      "};", Recursive));
>> +
>> +  EXPECT_TRUE(matches(
>> +      "class F {"
>> +      "  class Z {"
>> +      "    class A {};"
>> +      "    class X {};"
>> +      "    class Y {};"
>> +      "  };"
>> +      "  class C {"
>> +      "    class X {};"
>> +      "    class A {};"
>> +      "    class B {};"
>> +      "  };"
>> +      "};", Recursive));
>> +
>> +  EXPECT_TRUE(matches(
>> +      "class O1 {"
>> +      "  class O2 {"
>> +      "    class F {"
>> +      "      class Z {"
>> +      "        class A {};"
>> +      "        class X {};"
>> +      "        class Y {};"
>> +      "      };"
>> +      "      class C {"
>> +      "        class X {};"
>> +      "        class A {};"
>> +      "        class B {};"
>> +      "      };"
>> +      "    };"
>> +      "  };"
>> +      "};", Recursive));
>> +}
>> +
>> +TEST(DeclarationMatcher, MatchHasRecursiveAnyOf) {
>> +  DeclarationMatcher Recursive =
>> +      record(
>> +          anyOf(
>> +              has(record(
>> +                  anyOf(
>> +                      has(record(
>> +                          hasName("X"))),
>> +                      has(record(
>> +                          hasName("Y"))),
>> +                      hasName("Z")))),
>> +              has(record(
>> +                  anyOf(
>> +                      hasName("C"),
>> +                      has(record(
>> +                          hasName("A"))),
>> +                      has(record(
>> +                          hasName("B")))))),
>> +              hasName("F")));
>> +
>> +  EXPECT_TRUE(matches("class F {};", Recursive));
>> +  EXPECT_TRUE(matches("class Z {};", Recursive));
>> +  EXPECT_TRUE(matches("class C {};", Recursive));
>> +  EXPECT_TRUE(matches("class M { class N { class X {}; }; };",
>> Recursive));
>> +  EXPECT_TRUE(matches("class M { class N { class B {}; }; };",
>> Recursive));
>> +  EXPECT_TRUE(
>> +      matches("class O1 { class O2 {"
>> +              "  class M { class N { class B {}; }; }; "
>> +              "}; };", Recursive));
>> +}
>> +
>> +TEST(DeclarationMatcher, MatchNot) {
>> +  DeclarationMatcher NotClassX =
>> +      record(
>> +          isDerivedFrom("Y"),
>> +          unless(hasName("Y")),
>> +          unless(hasName("X")));
>> +  EXPECT_TRUE(notMatches("", NotClassX));
>> +  EXPECT_TRUE(notMatches("class Y {};", NotClassX));
>> +  EXPECT_TRUE(matches("class Y {}; class Z : public Y {};", NotClassX));
>> +  EXPECT_TRUE(notMatches("class Y {}; class X : public Y {};",
>> NotClassX));
>> +  EXPECT_TRUE(
>> +      notMatches("class Y {}; class Z {}; class X : public Y {};",
>> +                 NotClassX));
>> +
>> +  DeclarationMatcher ClassXHasNotClassY =
>> +      record(
>> +          hasName("X"),
>> +          has(record(hasName("Z"))),
>> +          unless(
>> +              has(record(hasName("Y")))));
>> +  EXPECT_TRUE(matches("class X { class Z {}; };", ClassXHasNotClassY));
>> +  EXPECT_TRUE(notMatches("class X { class Y {}; class Z {}; };",
>> +                         ClassXHasNotClassY));
>> +}
>> +
>> +TEST(DeclarationMatcher, HasDescendant) {
>> +  DeclarationMatcher ZDescendantClassX =
>> +      record(
>> +          hasDescendant(record(hasName("X"))),
>> +          hasName("Z"));
>> +  EXPECT_TRUE(matches("class Z { class X {}; };", ZDescendantClassX));
>> +  EXPECT_TRUE(
>> +      matches("class Z { class Y { class X {}; }; };",
>> ZDescendantClassX));
>> +  EXPECT_TRUE(
>> +      matches("class Z { class A { class Y { class X {}; }; }; };",
>> +              ZDescendantClassX));
>> +  EXPECT_TRUE(
>> +      matches("class Z { class A { class B { class Y { class X {}; }; };
>> }; };",
>> +              ZDescendantClassX));
>> +  EXPECT_TRUE(notMatches("class Z {};", ZDescendantClassX));
>> +
>> +  DeclarationMatcher ZDescendantClassXHasClassY =
>> +      record(
>> +          hasDescendant(record(has(record(hasName("Y"))),
>> +                              hasName("X"))),
>> +          hasName("Z"));
>> +  EXPECT_TRUE(matches("class Z { class X { class Y {}; }; };",
>> +              ZDescendantClassXHasClassY));
>> +  EXPECT_TRUE(
>> +      matches("class Z { class A { class B { class X { class Y {}; }; };
>> }; };",
>> +              ZDescendantClassXHasClassY));
>> +  EXPECT_TRUE(notMatches(
>> +      "class Z {"
>> +      "  class A {"
>> +      "    class B {"
>> +      "      class X {"
>> +      "        class C {"
>> +      "          class Y {};"
>> +      "        };"
>> +      "      };"
>> +      "    }; "
>> +      "  };"
>> +      "};", ZDescendantClassXHasClassY));
>> +
>> +  DeclarationMatcher ZDescendantClassXDescendantClassY =
>> +      record(
>> +          hasDescendant(record(hasDescendant(record(hasName("Y"))),
>> +                              hasName("X"))),
>> +          hasName("Z"));
>> +  EXPECT_TRUE(
>> +      matches("class Z { class A { class X { class B { class Y {}; }; };
>> }; };",
>> +              ZDescendantClassXDescendantClassY));
>> +  EXPECT_TRUE(matches(
>> +      "class Z {"
>> +      "  class A {"
>> +      "    class X {"
>> +      "      class B {"
>> +      "        class Y {};"
>> +      "      };"
>> +      "      class Y {};"
>> +      "    };"
>> +      "  };"
>> +      "};", ZDescendantClassXDescendantClassY));
>> +}
>> +
>> +TEST(StatementMatcher, Has) {
>> +  StatementMatcher HasVariableI =
>> +      expression(
>> +          hasType(pointsTo(record(hasName("X")))),
>> +          has(declarationReference(to(variable(hasName("i"))))));
>> +
>> +  EXPECT_TRUE(matches(
>> +      "class X; X *x(int); void c() { int i; x(i); }", HasVariableI));
>> +  EXPECT_TRUE(notMatches(
>> +      "class X; X *x(int); void c() { int i; x(42); }", HasVariableI));
>> +}
>> +
>> +TEST(StatementMatcher, HasDescendant) {
>> +  StatementMatcher HasDescendantVariableI =
>> +      expression(
>> +          hasType(pointsTo(record(hasName("X")))),
>> +
>> hasDescendant(declarationReference(to(variable(hasName("i"))))));
>> +
>> +  EXPECT_TRUE(matches(
>> +      "class X; X *x(bool); bool b(int); void c() { int i; x(b(i)); }",
>> +      HasDescendantVariableI));
>> +  EXPECT_TRUE(notMatches(
>> +      "class X; X *x(bool); bool b(int); void c() { int i; x(b(42)); }",
>> +      HasDescendantVariableI));
>> +}
>> +
>> +TEST(TypeMatcher, MatchesClassType) {
>> +  TypeMatcher TypeA = hasDeclaration(record(hasName("A")));
>> +
>> +  EXPECT_TRUE(matches("class A { public: A *a; };", TypeA));
>> +  EXPECT_TRUE(notMatches("class A {};", TypeA));
>> +
>> +  TypeMatcher TypeDerivedFromA =
>> hasDeclaration(record(isDerivedFrom("A")));
>> +
>> +  EXPECT_TRUE(matches("class A {}; class B : public A { public: B *b;
>> };",
>> +              TypeDerivedFromA));
>> +  EXPECT_TRUE(notMatches("class A {};", TypeA));
>> +
>> +  TypeMatcher TypeAHasClassB = hasDeclaration(
>> +      record(hasName("A"), has(record(hasName("B")))));
>> +
>> +  EXPECT_TRUE(
>> +      matches("class A { public: A *a; class B {}; };", TypeAHasClassB));
>> +}
>> +
>> +// Returns from Run whether 'bound_nodes' contain a Decl bound to 'Id',
>> which
>> +// can be dynamically casted to T.
>> +// Optionally checks that the check succeeded a specific number of times.
>> +template <typename T>
>> +class VerifyIdIsBoundToDecl : public BoundNodesCallback {
>> +public:
>> +  // Create an object that checks that a node of type 'T' was bound to
>> 'Id'.
>> +  // Does not check for a certain number of matches.
>> +  explicit VerifyIdIsBoundToDecl(const std::string& Id)
>> +    : Id(Id), ExpectedCount(-1), Count(0) {}
>> +
>> +  // Create an object that checks that a node of type 'T' was bound to
>> 'Id'.
>> +  // Checks that there were exactly 'ExpectedCount' matches.
>> +  explicit VerifyIdIsBoundToDecl(const std::string& Id, int
>> ExpectedCount)
>> +    : Id(Id), ExpectedCount(ExpectedCount), Count(0) {}
>> +
>> +  ~VerifyIdIsBoundToDecl() {
>> +    if (ExpectedCount != -1) {
>> +      EXPECT_EQ(ExpectedCount, Count);
>> +    }
>> +  }
>> +
>> +  virtual bool run(const BoundNodes *Nodes) {
>> +    if (Nodes->getDeclAs<T>(Id) != NULL) {
>> +      ++Count;
>> +      return true;
>> +    }
>> +    return false;
>> +  }
>> +
>> +private:
>> +  const std::string Id;
>> +  const int ExpectedCount;
>> +  int Count;
>> +};
>> +template <typename T>
>> +class VerifyIdIsBoundToStmt : public BoundNodesCallback {
>> +public:
>> +  explicit VerifyIdIsBoundToStmt(const std::string &Id) : Id(Id) {}
>> +  virtual bool run(const BoundNodes *Nodes) {
>> +    const T *Node = Nodes->getStmtAs<T>(Id);
>> +    return Node != NULL;
>> +  }
>> +private:
>> +  const std::string Id;
>> +};
>> +
>> +TEST(Matcher, BindMatchedNodes) {
>> +  DeclarationMatcher ClassX = has(id("x", record(hasName("X"))));
>> +
>> +  EXPECT_TRUE(matchAndVerifyResultTrue("class X {};",
>> +      ClassX, new VerifyIdIsBoundToDecl<clang::CXXRecordDecl>("x")));
>> +
>> +  EXPECT_TRUE(matchAndVerifyResultFalse("class X {};",
>> +      ClassX, new
>> VerifyIdIsBoundToDecl<clang::CXXRecordDecl>("other-id")));
>> +
>> +  TypeMatcher TypeAHasClassB = hasDeclaration(
>> +      record(hasName("A"), has(id("b", record(hasName("B"))))));
>> +
>> +  EXPECT_TRUE(matchAndVerifyResultTrue("class A { public: A *a; class B
>> {}; };",
>> +      TypeAHasClassB,
>> +      new VerifyIdIsBoundToDecl<clang::Decl>("b")));
>> +
>> +  StatementMatcher MethodX = id("x", call(callee(method(hasName("x")))));
>> +
>> +  EXPECT_TRUE(matchAndVerifyResultTrue("class A { void x() { x(); } };",
>> +      MethodX,
>> +      new VerifyIdIsBoundToStmt<clang::CXXMemberCallExpr>("x")));
>> +}
>> +
>> +TEST(HasType, TakesQualTypeMatcherAndMatchesExpr) {
>> +  TypeMatcher ClassX = hasDeclaration(record(hasName("X")));
>> +  EXPECT_TRUE(
>> +      matches("class X {}; void y(X &x) { x; }",
>> expression(hasType(ClassX))));
>> +  EXPECT_TRUE(
>> +      notMatches("class X {}; void y(X *x) { x; }",
>> +                 expression(hasType(ClassX))));
>> +  EXPECT_TRUE(
>> +      matches("class X {}; void y(X *x) { x; }",
>> +              expression(hasType(pointsTo(ClassX)))));
>> +}
>> +
>> +TEST(HasType, TakesQualTypeMatcherAndMatchesValueDecl) {
>> +  TypeMatcher ClassX = hasDeclaration(record(hasName("X")));
>> +  EXPECT_TRUE(
>> +      matches("class X {}; void y() { X x; }",
>> variable(hasType(ClassX))));
>> +  EXPECT_TRUE(
>> +      notMatches("class X {}; void y() { X *x; }",
>> variable(hasType(ClassX))));
>> +  EXPECT_TRUE(
>> +      matches("class X {}; void y() { X *x; }",
>> +              variable(hasType(pointsTo(ClassX)))));
>> +}
>> +
>> +TEST(HasType, TakesDeclMatcherAndMatchesExpr) {
>> +  DeclarationMatcher ClassX = record(hasName("X"));
>> +  EXPECT_TRUE(
>> +      matches("class X {}; void y(X &x) { x; }",
>> expression(hasType(ClassX))));
>> +  EXPECT_TRUE(
>> +      notMatches("class X {}; void y(X *x) { x; }",
>> +                 expression(hasType(ClassX))));
>> +}
>> +
>> +TEST(HasType, TakesDeclMatcherAndMatchesValueDecl) {
>> +  DeclarationMatcher ClassX = record(hasName("X"));
>> +  EXPECT_TRUE(
>> +      matches("class X {}; void y() { X x; }",
>> variable(hasType(ClassX))));
>> +  EXPECT_TRUE(
>> +      notMatches("class X {}; void y() { X *x; }",
>> variable(hasType(ClassX))));
>> +}
>> +
>> +TEST(Matcher, Call) {
>> +  // FIXME: Do we want to overload Call() to directly take
>> +  // Matcher<clang::Decl>, too?
>> +  StatementMatcher MethodX = call(hasDeclaration(method(hasName("x"))));
>> +
>> +  EXPECT_TRUE(matches("class Y { void x() { x(); } };", MethodX));
>> +  EXPECT_TRUE(notMatches("class Y { void x() {} };", MethodX));
>> +
>> +  StatementMatcher MethodOnY = call(on(hasType(record(hasName("Y")))));
>> +
>> +  EXPECT_TRUE(
>> +      matches("class Y { public: void x(); }; void z() { Y y; y.x(); }",
>> +              MethodOnY));
>> +  EXPECT_TRUE(
>> +      matches("class Y { public: void x(); }; void z(Y &y) { y.x(); }",
>> +              MethodOnY));
>> +  EXPECT_TRUE(
>> +      notMatches("class Y { public: void x(); }; void z(Y *&y) { y->x();
>> }",
>> +                 MethodOnY));
>> +  EXPECT_TRUE(
>> +      notMatches("class Y { public: void x(); }; void z(Y y[]) { y->x();
>> }",
>> +                 MethodOnY));
>> +  EXPECT_TRUE(
>> +      notMatches("class Y { public: void x(); }; void z() { Y *y; y->x();
>> }",
>> +                 MethodOnY));
>> +
>> +  StatementMatcher MethodOnYPointer =
>> +      call(on(hasType(pointsTo(record(hasName("Y"))))));
>> +
>> +  EXPECT_TRUE(
>> +      matches("class Y { public: void x(); }; void z() { Y *y; y->x();
>> }",
>> +              MethodOnYPointer));
>> +  EXPECT_TRUE(
>> +      matches("class Y { public: void x(); }; void z(Y *&y) { y->x(); }",
>> +              MethodOnYPointer));
>> +  EXPECT_TRUE(
>> +      matches("class Y { public: void x(); }; void z(Y y[]) { y->x(); }",
>> +              MethodOnYPointer));
>> +  EXPECT_TRUE(
>> +      notMatches("class Y { public: void x(); }; void z() { Y y; y.x();
>> }",
>> +                 MethodOnYPointer));
>> +  EXPECT_TRUE(
>> +      notMatches("class Y { public: void x(); }; void z(Y &y) { y.x();
>> }",
>> +                 MethodOnYPointer));
>> +}
>> +
>> +TEST(Matcher, OverloadedOperatorCall) {
>> +  StatementMatcher OpCall = overloadedOperatorCall();
>> +  // Unary operator
>> +  EXPECT_TRUE(matches("class Y { }; "
>> +              "bool operator!(Y x) { return false; }; "
>> +              "Y y; bool c = !y;", OpCall));
>> +  // No match -- special operators like "new", "delete"
>> +  // FIXME: operator new takes size_t, for which we need stddef.h, for
>> which
>> +  // we need to figure out include paths in the test.
>> +  // EXPECT_TRUE(NotMatches("#include <stddef.h>\n"
>> +  //             "class Y { }; "
>> +  //             "void *operator new(size_t size) { return 0; } "
>> +  //             "Y *y = new Y;", OpCall));
>> +  EXPECT_TRUE(notMatches("class Y { }; "
>> +              "void operator delete(void *p) { } "
>> +              "void a() {Y *y = new Y; delete y;}", OpCall));
>> +  // Binary operator
>> +  EXPECT_TRUE(matches("class Y { }; "
>> +              "bool operator&&(Y x, Y y) { return true; }; "
>> +              "Y a; Y b; bool c = a && b;",
>> +              OpCall));
>> +  // No match -- normal operator, not an overloaded one.
>> +  EXPECT_TRUE(notMatches("bool x = true, y = true; bool t = x && y;",
>> OpCall));
>> +  EXPECT_TRUE(notMatches("int t = 5 << 2;", OpCall));
>> +}
>> +
>> +TEST(Matcher, HasOperatorNameForOverloadedOperatorCall) {
>> +  StatementMatcher OpCallAndAnd =
>> +      overloadedOperatorCall(hasOverloadedOperatorName("&&"));
>> +  EXPECT_TRUE(matches("class Y { }; "
>> +              "bool operator&&(Y x, Y y) { return true; }; "
>> +              "Y a; Y b; bool c = a && b;", OpCallAndAnd));
>> +  StatementMatcher OpCallLessLess =
>> +      overloadedOperatorCall(hasOverloadedOperatorName("<<"));
>> +  EXPECT_TRUE(notMatches("class Y { }; "
>> +              "bool operator&&(Y x, Y y) { return true; }; "
>> +              "Y a; Y b; bool c = a && b;",
>> +              OpCallLessLess));
>> +}
>> +
>> +TEST(Matcher, ThisPointerType) {
>> +  StatementMatcher MethodOnY =
>> call(thisPointerType(record(hasName("Y"))));
>> +
>> +  EXPECT_TRUE(
>> +      matches("class Y { public: void x(); }; void z() { Y y; y.x(); }",
>> +              MethodOnY));
>> +  EXPECT_TRUE(
>> +      matches("class Y { public: void x(); }; void z(Y &y) { y.x(); }",
>> +              MethodOnY));
>> +  EXPECT_TRUE(
>> +      matches("class Y { public: void x(); }; void z(Y *&y) { y->x(); }",
>> +              MethodOnY));
>> +  EXPECT_TRUE(
>> +      matches("class Y { public: void x(); }; void z(Y y[]) { y->x(); }",
>> +              MethodOnY));
>> +  EXPECT_TRUE(
>> +      matches("class Y { public: void x(); }; void z() { Y *y; y->x();
>> }",
>> +              MethodOnY));
>> +
>> +  EXPECT_TRUE(matches(
>> +      "class Y {"
>> +      "  public: virtual void x();"
>> +      "};"
>> +      "class X : public Y {"
>> +      "  public: virtual void x();"
>> +      "};"
>> +      "void z() { X *x; x->Y::x(); }", MethodOnY));
>> +}
>> +
>> +TEST(Matcher, VariableUsage) {
>> +  StatementMatcher Reference =
>> +      declarationReference(to(
>> +          variable(hasInitializer(
>> +              call(thisPointerType(record(hasName("Y"))))))));
>> +
>> +  EXPECT_TRUE(matches(
>> +      "class Y {"
>> +      " public:"
>> +      "  bool x() const;"
>> +      "};"
>> +      "void z(const Y &y) {"
>> +      "  bool b = y.x();"
>> +      "  if (b) {}"
>> +      "}", Reference));
>> +
>> +  EXPECT_TRUE(notMatches(
>> +      "class Y {"
>> +      " public:"
>> +      "  bool x() const;"
>> +      "};"
>> +      "void z(const Y &y) {"
>> +      "  bool b = y.x();"
>> +      "}", Reference));
>> +}
>> +
>> +TEST(Matcher, CalledVariable) {
>> +  StatementMatcher CallOnVariableY = expression(
>> +      call(on(declarationReference(to(variable(hasName("y")))))));
>> +
>> +  EXPECT_TRUE(matches(
>> +      "class Y { public: void x() { Y y; y.x(); } };", CallOnVariableY));
>> +  EXPECT_TRUE(matches(
>> +      "class Y { public: void x() const { Y y; y.x(); } };",
>> CallOnVariableY));
>> +  EXPECT_TRUE(matches(
>> +      "class Y { public: void x(); };"
>> +      "class X : public Y { void z() { X y; y.x(); } };",
>> CallOnVariableY));
>> +  EXPECT_TRUE(matches(
>> +      "class Y { public: void x(); };"
>> +      "class X : public Y { void z() { X *y; y->x(); } };",
>> CallOnVariableY));
>> +  EXPECT_TRUE(notMatches(
>> +      "class Y { public: void x(); };"
>> +      "class X : public Y { void z() { unsigned long y; ((X*)y)->x(); }
>> };",
>> +      CallOnVariableY));
>> +}
>> +
>> +TEST(MemberExpression, DoesNotMatchClasses) {
>> +  EXPECT_TRUE(notMatches("class Y { void x() {} };",
>> memberExpression()));
>> +}
>> +
>> +TEST(MemberExpression, MatchesMemberFunctionCall) {
>> +  EXPECT_TRUE(matches("class Y { void x() { x(); } };",
>> memberExpression()));
>> +}
>> +
>> +TEST(MemberExpression, MatchesVariable) {
>> +  EXPECT_TRUE(
>> +      matches("class Y { void x() { this->y; } int y; };",
>> memberExpression()));
>> +  EXPECT_TRUE(
>> +      matches("class Y { void x() { y; } int y; };",
>> memberExpression()));
>> +  EXPECT_TRUE(
>> +      matches("class Y { void x() { Y y; y.y; } int y; };",
>> +              memberExpression()));
>> +}
>> +
>> +TEST(MemberExpression, MatchesStaticVariable) {
>> +  EXPECT_TRUE(matches("class Y { void x() { this->y; } static int y; };",
>> +              memberExpression()));
>> +  EXPECT_TRUE(notMatches("class Y { void x() { y; } static int y; };",
>> +              memberExpression()));
>> +  EXPECT_TRUE(notMatches("class Y { void x() { Y::y; } static int y; };",
>> +              memberExpression()));
>> +}
>> +
>> +TEST(IsArrow, MatchesMemberVariablesViaArrow) {
>> +  EXPECT_TRUE(matches("class Y { void x() { this->y; } int y; };",
>> +              memberExpression(isArrow())));
>> +  EXPECT_TRUE(matches("class Y { void x() { y; } int y; };",
>> +              memberExpression(isArrow())));
>> +  EXPECT_TRUE(notMatches("class Y { void x() { (*this).y; } int y; };",
>> +              memberExpression(isArrow())));
>> +}
>> +
>> +TEST(IsArrow, MatchesStaticMemberVariablesViaArrow) {
>> +  EXPECT_TRUE(matches("class Y { void x() { this->y; } static int y; };",
>> +              memberExpression(isArrow())));
>> +  EXPECT_TRUE(notMatches("class Y { void x() { y; } static int y; };",
>> +              memberExpression(isArrow())));
>> +  EXPECT_TRUE(notMatches("class Y { void x() { (*this).y; } static int y;
>> };",
>> +              memberExpression(isArrow())));
>> +}
>> +
>> +TEST(IsArrow, MatchesMemberCallsViaArrow) {
>> +  EXPECT_TRUE(matches("class Y { void x() { this->x(); } };",
>> +              memberExpression(isArrow())));
>> +  EXPECT_TRUE(matches("class Y { void x() { x(); } };",
>> +              memberExpression(isArrow())));
>> +  EXPECT_TRUE(notMatches("class Y { void x() { Y y; y.x(); } };",
>> +              memberExpression(isArrow())));
>> +}
>> +
>> +TEST(Callee, MatchesDeclarations) {
>> +  StatementMatcher CallMethodX = call(callee(method(hasName("x"))));
>> +
>> +  EXPECT_TRUE(matches("class Y { void x() { x(); } };", CallMethodX));
>> +  EXPECT_TRUE(notMatches("class Y { void x() {} };", CallMethodX));
>> +}
>> +
>> +TEST(Callee, MatchesMemberExpressions) {
>> +  EXPECT_TRUE(matches("class Y { void x() { this->x(); } };",
>> +              call(callee(memberExpression()))));
>> +  EXPECT_TRUE(
>> +      notMatches("class Y { void x() { this->x(); } };",
>> call(callee(call()))));
>> +}
>> +
>> +TEST(Function, MatchesFunctionDeclarations) {
>> +  StatementMatcher CallFunctionF = call(callee(function(hasName("f"))));
>> +
>> +  EXPECT_TRUE(matches("void f() { f(); }", CallFunctionF));
>> +  EXPECT_TRUE(notMatches("void f() { }", CallFunctionF));
>> +
>> +  // Dependent contexts, but a non-dependent call.
>> +  EXPECT_TRUE(matches("void f(); template <int N> void g() { f(); }",
>> +                      CallFunctionF));
>> +  EXPECT_TRUE(
>> +      matches("void f(); template <int N> struct S { void g() { f(); }
>> };",
>> +              CallFunctionF));
>> +
>> +  // Depedent calls don't match.
>> +  EXPECT_TRUE(
>> +      notMatches("void f(int); template <typename T> void g(T t) { f(t);
>> }",
>> +                 CallFunctionF));
>> +  EXPECT_TRUE(
>> +      notMatches("void f(int);"
>> +                 "template <typename T> struct S { void g(T t) { f(t); }
>> };",
>> +                 CallFunctionF));
>> +}
>> +
>> +TEST(Matcher, Argument) {
>> +  StatementMatcher CallArgumentY = expression(call(
>> +      hasArgument(0, declarationReference(to(variable(hasName("y")))))));
>> +
>> +  EXPECT_TRUE(matches("void x(int) { int y; x(y); }", CallArgumentY));
>> +  EXPECT_TRUE(
>> +      matches("class X { void x(int) { int y; x(y); } };",
>> CallArgumentY));
>> +  EXPECT_TRUE(notMatches("void x(int) { int z; x(z); }", CallArgumentY));
>> +
>> +  StatementMatcher WrongIndex = expression(call(
>> +      hasArgument(42,
>> declarationReference(to(variable(hasName("y")))))));
>> +  EXPECT_TRUE(notMatches("void x(int) { int y; x(y); }", WrongIndex));
>> +}
>> +
>> +TEST(Matcher, AnyArgument) {
>> +  StatementMatcher CallArgumentY = expression(call(
>> +      hasAnyArgument(declarationReference(to(variable(hasName("y")))))));
>> +  EXPECT_TRUE(matches("void x(int, int) { int y; x(1, y); }",
>> CallArgumentY));
>> +  EXPECT_TRUE(matches("void x(int, int) { int y; x(y, 42); }",
>> CallArgumentY));
>> +  EXPECT_TRUE(notMatches("void x(int, int) { x(1, 2); }",
>> CallArgumentY));
>> +}
>> +
>> +TEST(Matcher, ArgumentCount) {
>> +  StatementMatcher Call1Arg = expression(call(argumentCountIs(1)));
>> +
>> +  EXPECT_TRUE(matches("void x(int) { x(0); }", Call1Arg));
>> +  EXPECT_TRUE(matches("class X { void x(int) { x(0); } };", Call1Arg));
>> +  EXPECT_TRUE(notMatches("void x(int, int) { x(0, 0); }", Call1Arg));
>> +}
>> +
>> +TEST(Matcher, References) {
>> +  DeclarationMatcher ReferenceClassX = variable(
>> +      hasType(references(record(hasName("X")))));
>> +  EXPECT_TRUE(matches("class X {}; void y(X y) { X &x = y; }",
>> +                      ReferenceClassX));
>> +  EXPECT_TRUE(
>> +      matches("class X {}; void y(X y) { const X &x = y; }",
>> ReferenceClassX));
>> +  EXPECT_TRUE(
>> +      notMatches("class X {}; void y(X y) { X x = y; }",
>> ReferenceClassX));
>> +  EXPECT_TRUE(
>> +      notMatches("class X {}; void y(X *y) { X *&x = y; }",
>> ReferenceClassX));
>> +}
>> +
>> +TEST(HasParameter, CallsInnerMatcher) {
>> +  EXPECT_TRUE(matches("class X { void x(int) {} };",
>> +      method(hasParameter(0, variable()))));
>> +  EXPECT_TRUE(notMatches("class X { void x(int) {} };",
>> +      method(hasParameter(0, hasName("x")))));
>> +}
>> +
>> +TEST(HasParameter, DoesNotMatchIfIndexOutOfBounds) {
>> +  EXPECT_TRUE(notMatches("class X { void x(int) {} };",
>> +      method(hasParameter(42, variable()))));
>> +}
>> +
>> +TEST(HasType, MatchesParameterVariableTypesStrictly) {
>> +  EXPECT_TRUE(matches("class X { void x(X x) {} };",
>> +      method(hasParameter(0, hasType(record(hasName("X")))))));
>> +  EXPECT_TRUE(notMatches("class X { void x(const X &x) {} };",
>> +      method(hasParameter(0, hasType(record(hasName("X")))))));
>> +  EXPECT_TRUE(matches("class X { void x(const X *x) {} };",
>> +      method(hasParameter(0, hasType(pointsTo(record(hasName("X"))))))));
>> +  EXPECT_TRUE(matches("class X { void x(const X &x) {} };",
>> +      method(hasParameter(0,
>> hasType(references(record(hasName("X"))))))));
>> +}
>> +
>> +TEST(HasAnyParameter, MatchesIndependentlyOfPosition) {
>> +  EXPECT_TRUE(matches("class Y {}; class X { void x(X x, Y y) {} };",
>> +      method(hasAnyParameter(hasType(record(hasName("X")))))));
>> +  EXPECT_TRUE(matches("class Y {}; class X { void x(Y y, X x) {} };",
>> +      method(hasAnyParameter(hasType(record(hasName("X")))))));
>> +}
>> +
>> +TEST(HasAnyParameter, DoesntMatchIfInnerMatcherDoesntMatch) {
>> +  EXPECT_TRUE(notMatches("class Y {}; class X { void x(int) {} };",
>> +      method(hasAnyParameter(hasType(record(hasName("X")))))));
>> +}
>> +
>> +TEST(HasAnyParameter, DoesNotMatchThisPointer) {
>> +  EXPECT_TRUE(notMatches("class Y {}; class X { void x() {} };",
>> +      method(hasAnyParameter(hasType(pointsTo(record(hasName("X"))))))));
>> +}
>> +
>> +TEST(HasName, MatchesParameterVariableDeclartions) {
>> +  EXPECT_TRUE(matches("class Y {}; class X { void x(int x) {} };",
>> +      method(hasAnyParameter(hasName("x")))));
>> +  EXPECT_TRUE(notMatches("class Y {}; class X { void x(int) {} };",
>> +      method(hasAnyParameter(hasName("x")))));
>> +}
>> +
>> +TEST(Matcher, ConstructorCall) {
>> +  StatementMatcher Constructor = expression(constructorCall());
>> +
>> +  EXPECT_TRUE(
>> +      matches("class X { public: X(); }; void x() { X x; }",
>> Constructor));
>> +  EXPECT_TRUE(
>> +      matches("class X { public: X(); }; void x() { X x = X(); }",
>> +              Constructor));
>> +  EXPECT_TRUE(
>> +      matches("class X { public: X(int); }; void x() { X x = 0; }",
>> +              Constructor));
>> +  EXPECT_TRUE(matches("class X {}; void x(int) { X x; }", Constructor));
>> +}
>> +
>> +TEST(Matcher, ConstructorArgument) {
>> +  StatementMatcher Constructor = expression(constructorCall(
>> +      hasArgument(0, declarationReference(to(variable(hasName("y")))))));
>> +
>> +  EXPECT_TRUE(
>> +      matches("class X { public: X(int); }; void x() { int y; X x(y); }",
>> +              Constructor));
>> +  EXPECT_TRUE(
>> +      matches("class X { public: X(int); }; void x() { int y; X x = X(y);
>> }",
>> +              Constructor));
>> +  EXPECT_TRUE(
>> +      matches("class X { public: X(int); }; void x() { int y; X x = y;
>> }",
>> +              Constructor));
>> +  EXPECT_TRUE(
>> +      notMatches("class X { public: X(int); }; void x() { int z; X x(z);
>> }",
>> +                 Constructor));
>> +
>> +  StatementMatcher WrongIndex = expression(constructorCall(
>> +      hasArgument(42,
>> declarationReference(to(variable(hasName("y")))))));
>> +  EXPECT_TRUE(
>> +      notMatches("class X { public: X(int); }; void x() { int y; X x(y);
>> }",
>> +                 WrongIndex));
>> +}
>> +
>> +TEST(Matcher, ConstructorArgumentCount) {
>> +  StatementMatcher Constructor1Arg =
>> +      expression(constructorCall(argumentCountIs(1)));
>> +
>> +  EXPECT_TRUE(
>> +      matches("class X { public: X(int); }; void x() { X x(0); }",
>> +              Constructor1Arg));
>> +  EXPECT_TRUE(
>> +      matches("class X { public: X(int); }; void x() { X x = X(0); }",
>> +              Constructor1Arg));
>> +  EXPECT_TRUE(
>> +      matches("class X { public: X(int); }; void x() { X x = 0; }",
>> +              Constructor1Arg));
>> +  EXPECT_TRUE(
>> +      notMatches("class X { public: X(int, int); }; void x() { X x(0, 0);
>> }",
>> +                 Constructor1Arg));
>> +}
>> +
>> +TEST(Matcher, BindTemporaryExpression) {
>> +  StatementMatcher TempExpression =
>> expression(bindTemporaryExpression());
>> +
>> +  std::string ClassString = "class string { public: string(); ~string();
>> }; ";
>> +
>> +  EXPECT_TRUE(
>> +      matches(ClassString +
>> +              "string GetStringByValue();"
>> +              "void FunctionTakesString(string s);"
>> +              "void run() { FunctionTakesString(GetStringByValue()); }",
>> +              TempExpression));
>> +
>> +  EXPECT_TRUE(
>> +      notMatches(ClassString +
>> +                 "string* GetStringPointer(); "
>> +                 "void FunctionTakesStringPtr(string* s);"
>> +                 "void run() {"
>> +                 "  string* s = GetStringPointer();"
>> +                 "  FunctionTakesStringPtr(GetStringPointer());"
>> +                 "  FunctionTakesStringPtr(s);"
>> +                 "}",
>> +                 TempExpression));
>> +
>> +  EXPECT_TRUE(
>> +      notMatches("class no_dtor {};"
>> +                 "no_dtor GetObjByValue();"
>> +                 "void ConsumeObj(no_dtor param);"
>> +                 "void run() { ConsumeObj(GetObjByValue()); }",
>> +                 TempExpression));
>> +}
>> +
>> +TEST(ConstructorDeclaration, SimpleCase) {
>> +  EXPECT_TRUE(matches("class Foo { Foo(int i); };",
>> +                      constructor(ofClass(hasName("Foo")))));
>> +  EXPECT_TRUE(notMatches("class Foo { Foo(int i); };",
>> +                         constructor(ofClass(hasName("Bar")))));
>> +}
>> +
>> +TEST(ConstructorDeclaration, IsImplicit) {
>> +  // This one doesn't match because the constructor is not added by the
>> +  // compiler (it is not needed).
>> +  EXPECT_TRUE(notMatches("class Foo { };",
>> +                         constructor(isImplicit())));
>> +  // The compiler added the implicit default constructor.
>> +  EXPECT_TRUE(matches("class Foo { }; Foo* f = new Foo();",
>> +                      constructor(isImplicit())));
>> +  EXPECT_TRUE(matches("class Foo { Foo(){} };",
>> +                      constructor(unless(isImplicit()))));
>> +}
>> +
>> +TEST(HasAnyConstructorInitializer, SimpleCase) {
>> +  EXPECT_TRUE(notMatches(
>> +      "class Foo { Foo() { } };",
>> +      constructor(hasAnyConstructorInitializer(anything()))));
>> +  EXPECT_TRUE(matches(
>> +      "class Foo {"
>> +      "  Foo() : foo_() { }"
>> +      "  int foo_;"
>> +      "};",
>> +      constructor(hasAnyConstructorInitializer(anything()))));
>> +}
>> +
>> +TEST(HasAnyConstructorInitializer, ForField) {
>> +  static const char Code[] =
>> +      "class Baz { };"
>> +      "class Foo {"
>> +      "  Foo() : foo_() { }"
>> +      "  Baz foo_;"
>> +      "  Baz bar_;"
>> +      "};";
>> +  EXPECT_TRUE(matches(Code, constructor(hasAnyConstructorInitializer(
>> +      forField(hasType(record(hasName("Baz"))))))));
>> +  EXPECT_TRUE(matches(Code, constructor(hasAnyConstructorInitializer(
>> +      forField(hasName("foo_"))))));
>> +  EXPECT_TRUE(notMatches(Code, constructor(hasAnyConstructorInitializer(
>> +      forField(hasType(record(hasName("Bar"))))))));
>> +}
>> +
>> +TEST(HasAnyConstructorInitializer, WithInitializer) {
>> +  static const char Code[] =
>> +      "class Foo {"
>> +      "  Foo() : foo_(0) { }"
>> +      "  int foo_;"
>> +      "};";
>> +  EXPECT_TRUE(matches(Code, constructor(hasAnyConstructorInitializer(
>> +      withInitializer(integerLiteral(equals(0)))))));
>> +  EXPECT_TRUE(notMatches(Code, constructor(hasAnyConstructorInitializer(
>> +      withInitializer(integerLiteral(equals(1)))))));
>> +}
>> +
>> +TEST(HasAnyConstructorInitializer, IsWritten) {
>> +  static const char Code[] =
>> +      "struct Bar { Bar(){} };"
>> +      "class Foo {"
>> +      "  Foo() : foo_() { }"
>> +      "  Bar foo_;"
>> +      "  Bar bar_;"
>> +      "};";
>> +  EXPECT_TRUE(matches(Code, constructor(hasAnyConstructorInitializer(
>> +      allOf(forField(hasName("foo_")), isWritten())))));
>> +  EXPECT_TRUE(notMatches(Code, constructor(hasAnyConstructorInitializer(
>> +      allOf(forField(hasName("bar_")), isWritten())))));
>> +  EXPECT_TRUE(matches(Code, constructor(hasAnyConstructorInitializer(
>> +      allOf(forField(hasName("bar_")), unless(isWritten()))))));
>> +}
>> +
>> +TEST(Matcher, NewExpression) {
>> +  StatementMatcher New = expression(newExpression());
>> +
>> +  EXPECT_TRUE(matches("class X { public: X(); }; void x() { new X; }",
>> New));
>> +  EXPECT_TRUE(
>> +      matches("class X { public: X(); }; void x() { new X(); }", New));
>> +  EXPECT_TRUE(
>> +      matches("class X { public: X(int); }; void x() { new X(0); }",
>> New));
>> +  EXPECT_TRUE(matches("class X {}; void x(int) { new X; }", New));
>> +}
>> +
>> +TEST(Matcher, NewExpressionArgument) {
>> +  StatementMatcher New = expression(constructorCall(
>> +      hasArgument(
>> +          0, declarationReference(to(variable(hasName("y")))))));
>> +
>> +  EXPECT_TRUE(
>> +      matches("class X { public: X(int); }; void x() { int y; new X(y);
>> }",
>> +              New));
>> +  EXPECT_TRUE(
>> +      matches("class X { public: X(int); }; void x() { int y; new X(y);
>> }",
>> +              New));
>> +  EXPECT_TRUE(
>> +      notMatches("class X { public: X(int); }; void x() { int z; new
>> X(z); }",
>> +                 New));
>> +
>> +  StatementMatcher WrongIndex = expression(constructorCall(
>> +      hasArgument(
>> +          42, declarationReference(to(variable(hasName("y")))))));
>> +  EXPECT_TRUE(
>> +      notMatches("class X { public: X(int); }; void x() { int y; new
>> X(y); }",
>> +                 WrongIndex));
>> +}
>> +
>> +TEST(Matcher, NewExpressionArgumentCount) {
>> +  StatementMatcher New = constructorCall(argumentCountIs(1));
>> +
>> +  EXPECT_TRUE(
>> +      matches("class X { public: X(int); }; void x() { new X(0); }",
>> New));
>> +  EXPECT_TRUE(
>> +      notMatches("class X { public: X(int, int); }; void x() { new X(0,
>> 0); }",
>> +                 New));
>> +}
>> +
>> +TEST(Matcher, DefaultArgument) {
>> +  StatementMatcher Arg = defaultArgument();
>> +
>> +  EXPECT_TRUE(matches("void x(int, int = 0) { int y; x(y); }", Arg));
>> +  EXPECT_TRUE(
>> +      matches("class X { void x(int, int = 0) { int y; x(y); } };",
>> Arg));
>> +  EXPECT_TRUE(notMatches("void x(int, int = 0) { int y; x(y, 0); }",
>> Arg));
>> +}
>> +
>> +TEST(Matcher, StringLiterals) {
>> +  StatementMatcher Literal = expression(stringLiteral());
>> +  EXPECT_TRUE(matches("const char *s = \"string\";", Literal));
>> +  // wide string
>> +  EXPECT_TRUE(matches("const wchar_t *s = L\"string\";", Literal));
>> +  // with escaped characters
>> +  EXPECT_TRUE(matches("const char *s = \"\x05five\";", Literal));
>> +  // no matching -- though the data type is the same, there is no string
>> literal
>> +  EXPECT_TRUE(notMatches("const char s[1] = {'a'};", Literal));
>> +}
>> +
>> +TEST(Matcher, CharacterLiterals) {
>> +  StatementMatcher CharLiteral = expression(characterLiteral());
>> +  EXPECT_TRUE(matches("const char c = 'c';", CharLiteral));
>> +  // wide character
>> +  EXPECT_TRUE(matches("const char c = L'c';", CharLiteral));
>> +  // wide character, Hex encoded, NOT MATCHED!
>> +  EXPECT_TRUE(notMatches("const wchar_t c = 0x2126;", CharLiteral));
>> +  EXPECT_TRUE(notMatches("const char c = 0x1;", CharLiteral));
>> +}
>> +
>> +TEST(Matcher, IntegerLiterals) {
>> +  StatementMatcher HasIntLiteral = expression(integerLiteral());
>> +  EXPECT_TRUE(matches("int i = 10;", HasIntLiteral));
>> +  EXPECT_TRUE(matches("int i = 0x1AB;", HasIntLiteral));
>> +  EXPECT_TRUE(matches("int i = 10L;", HasIntLiteral));
>> +  EXPECT_TRUE(matches("int i = 10U;", HasIntLiteral));
>> +
>> +  // Non-matching cases (character literals, float and double)
>> +  EXPECT_TRUE(notMatches("int i = L'a';",
>> +                HasIntLiteral));  // this is actually a character
>> +                                  // literal cast to int
>> +  EXPECT_TRUE(notMatches("int i = 'a';", HasIntLiteral));
>> +  EXPECT_TRUE(notMatches("int i = 1e10;", HasIntLiteral));
>> +  EXPECT_TRUE(notMatches("int i = 10.0;", HasIntLiteral));
>> +}
>> +
>> +TEST(Matcher, Conditions) {
>> +  StatementMatcher Condition =
>> ifStmt(hasCondition(boolLiteral(equals(true))));
>> +
>> +  EXPECT_TRUE(matches("void x() { if (true) {} }", Condition));
>> +  EXPECT_TRUE(notMatches("void x() { if (false) {} }", Condition));
>> +  EXPECT_TRUE(notMatches("void x() { bool a = true; if (a) {} }",
>> Condition));
>> +  EXPECT_TRUE(notMatches("void x() { if (true || false) {} }",
>> Condition));
>> +  EXPECT_TRUE(notMatches("void x() { if (1) {} }", Condition));
>> +}
>> +
>> +TEST(MatchBinaryOperator, HasOperatorName) {
>> +  StatementMatcher OperatorOr = binaryOperator(hasOperatorName("||"));
>> +
>> +  EXPECT_TRUE(matches("void x() { true || false; }", OperatorOr));
>> +  EXPECT_TRUE(notMatches("void x() { true && false; }", OperatorOr));
>> +}
>> +
>> +TEST(MatchBinaryOperator, HasLHSAndHasRHS) {
>> +  StatementMatcher OperatorTrueFalse =
>> +      binaryOperator(hasLHS(boolLiteral(equals(true))),
>> +                     hasRHS(boolLiteral(equals(false))));
>> +
>> +  EXPECT_TRUE(matches("void x() { true || false; }", OperatorTrueFalse));
>> +  EXPECT_TRUE(matches("void x() { true && false; }", OperatorTrueFalse));
>> +  EXPECT_TRUE(notMatches("void x() { false || true; }",
>> OperatorTrueFalse));
>> +}
>> +
>> +TEST(MatchBinaryOperator, HasEitherOperand) {
>> +  StatementMatcher HasOperand =
>> +      binaryOperator(hasEitherOperand(boolLiteral(equals(false))));
>> +
>> +  EXPECT_TRUE(matches("void x() { true || false; }", HasOperand));
>> +  EXPECT_TRUE(matches("void x() { false && true; }", HasOperand));
>> +  EXPECT_TRUE(notMatches("void x() { true || true; }", HasOperand));
>> +}
>> +
>> +TEST(Matcher, BinaryOperatorTypes) {
>> +  // Integration test that verifies the AST provides all binary operators
>> in
>> +  // a way we expect.
>> +  // FIXME: Operator ','
>> +  EXPECT_TRUE(
>> +      matches("void x() { 3, 4; }",
>> binaryOperator(hasOperatorName(","))));
>> +  EXPECT_TRUE(
>> +      matches("bool b; bool c = (b = true);",
>> +              binaryOperator(hasOperatorName("="))));
>> +  EXPECT_TRUE(
>> +      matches("bool b = 1 != 2;",
>> binaryOperator(hasOperatorName("!="))));
>> +  EXPECT_TRUE(
>> +      matches("bool b = 1 == 2;",
>> binaryOperator(hasOperatorName("=="))));
>> +  EXPECT_TRUE(matches("bool b = 1 < 2;",
>> binaryOperator(hasOperatorName("<"))));
>> +  EXPECT_TRUE(
>> +      matches("bool b = 1 <= 2;",
>> binaryOperator(hasOperatorName("<="))));
>> +  EXPECT_TRUE(
>> +      matches("int i = 1 << 2;", binaryOperator(hasOperatorName("<<"))));
>> +  EXPECT_TRUE(
>> +      matches("int i = 1; int j = (i <<= 2);",
>> +              binaryOperator(hasOperatorName("<<="))));
>> +  EXPECT_TRUE(matches("bool b = 1 > 2;",
>> binaryOperator(hasOperatorName(">"))));
>> +  EXPECT_TRUE(
>> +      matches("bool b = 1 >= 2;",
>> binaryOperator(hasOperatorName(">="))));
>> +  EXPECT_TRUE(
>> +      matches("int i = 1 >> 2;", binaryOperator(hasOperatorName(">>"))));
>> +  EXPECT_TRUE(
>> +      matches("int i = 1; int j = (i >>= 2);",
>> +              binaryOperator(hasOperatorName(">>="))));
>> +  EXPECT_TRUE(
>> +      matches("int i = 42 ^ 23;", binaryOperator(hasOperatorName("^"))));
>> +  EXPECT_TRUE(
>> +      matches("int i = 42; int j = (i ^= 42);",
>> +              binaryOperator(hasOperatorName("^="))));
>> +  EXPECT_TRUE(
>> +      matches("int i = 42 % 23;", binaryOperator(hasOperatorName("%"))));
>> +  EXPECT_TRUE(
>> +      matches("int i = 42; int j = (i %= 42);",
>> +              binaryOperator(hasOperatorName("%="))));
>> +  EXPECT_TRUE(
>> +      matches("bool b = 42  &23;",
>> binaryOperator(hasOperatorName("&"))));
>> +  EXPECT_TRUE(
>> +      matches("bool b = true && false;",
>> +              binaryOperator(hasOperatorName("&&"))));
>> +  EXPECT_TRUE(
>> +      matches("bool b = true; bool c = (b &= false);",
>> +              binaryOperator(hasOperatorName("&="))));
>> +  EXPECT_TRUE(
>> +      matches("bool b = 42 | 23;",
>> binaryOperator(hasOperatorName("|"))));
>> +  EXPECT_TRUE(
>> +      matches("bool b = true || false;",
>> +              binaryOperator(hasOperatorName("||"))));
>> +  EXPECT_TRUE(
>> +      matches("bool b = true; bool c = (b |= false);",
>> +              binaryOperator(hasOperatorName("|="))));
>> +  EXPECT_TRUE(
>> +      matches("int i = 42  *23;", binaryOperator(hasOperatorName("*"))));
>> +  EXPECT_TRUE(
>> +      matches("int i = 42; int j = (i *= 23);",
>> +              binaryOperator(hasOperatorName("*="))));
>> +  EXPECT_TRUE(
>> +      matches("int i = 42 / 23;", binaryOperator(hasOperatorName("/"))));
>> +  EXPECT_TRUE(
>> +      matches("int i = 42; int j = (i /= 23);",
>> +              binaryOperator(hasOperatorName("/="))));
>> +  EXPECT_TRUE(
>> +      matches("int i = 42 + 23;", binaryOperator(hasOperatorName("+"))));
>> +  EXPECT_TRUE(
>> +      matches("int i = 42; int j = (i += 23);",
>> +              binaryOperator(hasOperatorName("+="))));
>> +  EXPECT_TRUE(
>> +      matches("int i = 42 - 23;", binaryOperator(hasOperatorName("-"))));
>> +  EXPECT_TRUE(
>> +      matches("int i = 42; int j = (i -= 23);",
>> +              binaryOperator(hasOperatorName("-="))));
>> +  EXPECT_TRUE(
>> +      matches("struct A { void x() { void (A::*a)(); (this->*a)(); } };",
>> +              binaryOperator(hasOperatorName("->*"))));
>> +  EXPECT_TRUE(
>> +      matches("struct A { void x() { void (A::*a)(); ((*this).*a)(); }
>> };",
>> +              binaryOperator(hasOperatorName(".*"))));
>> +
>> +  // Member expressions as operators are not supported in matches.
>> +  EXPECT_TRUE(
>> +      notMatches("struct A { void x(A *a) { a->x(this); } };",
>> +                 binaryOperator(hasOperatorName("->"))));
>> +
>> +  // Initializer assignments are not represented as operator equals.
>> +  EXPECT_TRUE(
>> +      notMatches("bool b = true;",
>> binaryOperator(hasOperatorName("="))));
>> +
>> +  // Array indexing is not represented as operator.
>> +  EXPECT_TRUE(notMatches("int a[42]; void x() { a[23]; }",
>> unaryOperator()));
>> +
>> +  // Overloaded operators do not match at all.
>> +  EXPECT_TRUE(notMatches(
>> +      "struct A { bool operator&&(const A &a) const { return false; } };"
>> +      "void x() { A a, b; a && b; }",
>> +      binaryOperator()));
>> +}
>> +
>> +TEST(MatchUnaryOperator, HasOperatorName) {
>> +  StatementMatcher OperatorNot = unaryOperator(hasOperatorName("!"));
>> +
>> +  EXPECT_TRUE(matches("void x() { !true; } ", OperatorNot));
>> +  EXPECT_TRUE(notMatches("void x() { true; } ", OperatorNot));
>> +}
>> +
>> +TEST(MatchUnaryOperator, HasUnaryOperand) {
>> +  StatementMatcher OperatorOnFalse =
>> +      unaryOperator(hasUnaryOperand(boolLiteral(equals(false))));
>> +
>> +  EXPECT_TRUE(matches("void x() { !false; }", OperatorOnFalse));
>> +  EXPECT_TRUE(notMatches("void x() { !true; }", OperatorOnFalse));
>> +}
>> +
>> +TEST(Matcher, UnaryOperatorTypes) {
>> +  // Integration test that verifies the AST provides all unary operators
>> in
>> +  // a way we expect.
>> +  EXPECT_TRUE(matches("bool b = !true;",
>> unaryOperator(hasOperatorName("!"))));
>> +  EXPECT_TRUE(
>> +      matches("bool b; bool *p = &b;",
>> unaryOperator(hasOperatorName("&"))));
>> +  EXPECT_TRUE(matches("int i = ~ 1;",
>> unaryOperator(hasOperatorName("~"))));
>> +  EXPECT_TRUE(
>> +      matches("bool *p; bool b = *p;",
>> unaryOperator(hasOperatorName("*"))));
>> +  EXPECT_TRUE(
>> +      matches("int i; int j = +i;",
>> unaryOperator(hasOperatorName("+"))));
>> +  EXPECT_TRUE(
>> +      matches("int i; int j = -i;",
>> unaryOperator(hasOperatorName("-"))));
>> +  EXPECT_TRUE(
>> +      matches("int i; int j = ++i;",
>> unaryOperator(hasOperatorName("++"))));
>> +  EXPECT_TRUE(
>> +      matches("int i; int j = i++;",
>> unaryOperator(hasOperatorName("++"))));
>> +  EXPECT_TRUE(
>> +      matches("int i; int j = --i;",
>> unaryOperator(hasOperatorName("--"))));
>> +  EXPECT_TRUE(
>> +      matches("int i; int j = i--;",
>> unaryOperator(hasOperatorName("--"))));
>> +
>> +  // We don't match conversion operators.
>> +  EXPECT_TRUE(notMatches("int i; double d = (double)i;",
>> unaryOperator()));
>> +
>> +  // Function calls are not represented as operator.
>> +  EXPECT_TRUE(notMatches("void f(); void x() { f(); }",
>> unaryOperator()));
>> +
>> +  // Overloaded operators do not match at all.
>> +  // FIXME: We probably want to add that.
>> +  EXPECT_TRUE(notMatches(
>> +      "struct A { bool operator!() const { return false; } };"
>> +      "void x() { A a; !a; }", unaryOperator(hasOperatorName("!"))));
>> +}
>> +
>> +TEST(Matcher, ConditionalOperator) {
>> +  StatementMatcher Conditional = conditionalOperator(
>> +      hasCondition(boolLiteral(equals(true))),
>> +      hasTrueExpression(boolLiteral(equals(false))));
>> +
>> +  EXPECT_TRUE(matches("void x() { true ? false : true; }", Conditional));
>> +  EXPECT_TRUE(notMatches("void x() { false ? false : true; }",
>> Conditional));
>> +  EXPECT_TRUE(notMatches("void x() { true ? true : false; }",
>> Conditional));
>> +
>> +  StatementMatcher ConditionalFalse = conditionalOperator(
>> +      hasFalseExpression(boolLiteral(equals(false))));
>> +
>> +  EXPECT_TRUE(matches("void x() { true ? true : false; }",
>> ConditionalFalse));
>> +  EXPECT_TRUE(
>> +      notMatches("void x() { true ? false : true; }", ConditionalFalse));
>> +}
>> +
>> +TEST(Matcher, HasNameSupportsNamespaces) {
>> +  EXPECT_TRUE(matches("namespace a { namespace b { class C; } }",
>> +              record(hasName("a::b::C"))));
>> +  EXPECT_TRUE(matches("namespace a { namespace b { class C; } }",
>> +              record(hasName("::a::b::C"))));
>> +  EXPECT_TRUE(matches("namespace a { namespace b { class C; } }",
>> +              record(hasName("b::C"))));
>> +  EXPECT_TRUE(matches("namespace a { namespace b { class C; } }",
>> +              record(hasName("C"))));
>> +  EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
>> +              record(hasName("c::b::C"))));
>> +  EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
>> +              record(hasName("a::c::C"))));
>> +  EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
>> +              record(hasName("a::b::A"))));
>> +  EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
>> +              record(hasName("::C"))));
>> +  EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
>> +              record(hasName("::b::C"))));
>> +  EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
>> +              record(hasName("z::a::b::C"))));
>> +  EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
>> +              record(hasName("a+b::C"))));
>> +  EXPECT_TRUE(notMatches("namespace a { namespace b { class AC; } }",
>> +              record(hasName("C"))));
>> +}
>> +
>> +TEST(Matcher, HasNameSupportsOuterClasses) {
>> +  EXPECT_TRUE(
>> +      matches("class A { class B { class C; }; };",
>> record(hasName("A::B::C"))));
>> +  EXPECT_TRUE(
>> +      matches("class A { class B { class C; }; };",
>> +              record(hasName("::A::B::C"))));
>> +  EXPECT_TRUE(
>> +      matches("class A { class B { class C; }; };",
>> record(hasName("B::C"))));
>> +  EXPECT_TRUE(
>> +      matches("class A { class B { class C; }; };",
>> record(hasName("C"))));
>> +  EXPECT_TRUE(
>> +      notMatches("class A { class B { class C; }; };",
>> +                 record(hasName("c::B::C"))));
>> +  EXPECT_TRUE(
>> +      notMatches("class A { class B { class C; }; };",
>> +                 record(hasName("A::c::C"))));
>> +  EXPECT_TRUE(
>> +      notMatches("class A { class B { class C; }; };",
>> +                 record(hasName("A::B::A"))));
>> +  EXPECT_TRUE(
>> +      notMatches("class A { class B { class C; }; };",
>> record(hasName("::C"))));
>> +  EXPECT_TRUE(
>> +      notMatches("class A { class B { class C; }; };",
>> +                 record(hasName("::B::C"))));
>> +  EXPECT_TRUE(notMatches("class A { class B { class C; }; };",
>> +              record(hasName("z::A::B::C"))));
>> +  EXPECT_TRUE(
>> +      notMatches("class A { class B { class C; }; };",
>> +                 record(hasName("A+B::C"))));
>> +}
>> +
>> +TEST(Matcher, IsDefinition) {
>> +  DeclarationMatcher DefinitionOfClassA =
>> +      record(hasName("A"), isDefinition());
>> +  EXPECT_TRUE(matches("class A {};", DefinitionOfClassA));
>> +  EXPECT_TRUE(notMatches("class A;", DefinitionOfClassA));
>> +
>> +  DeclarationMatcher DefinitionOfVariableA =
>> +      variable(hasName("a"), isDefinition());
>> +  EXPECT_TRUE(matches("int a;", DefinitionOfVariableA));
>> +  EXPECT_TRUE(notMatches("extern int a;", DefinitionOfVariableA));
>> +
>> +  DeclarationMatcher DefinitionOfMethodA =
>> +      method(hasName("a"), isDefinition());
>> +  EXPECT_TRUE(matches("class A { void a() {} };", DefinitionOfMethodA));
>> +  EXPECT_TRUE(notMatches("class A { void a(); };", DefinitionOfMethodA));
>> +}
>> +
>> +TEST(Matcher, OfClass) {
>> +  StatementMatcher Constructor = constructorCall(hasDeclaration(method(
>> +      ofClass(hasName("X")))));
>> +
>> +  EXPECT_TRUE(
>> +      matches("class X { public: X(); }; void x(int) { X x; }",
>> Constructor));
>> +  EXPECT_TRUE(
>> +      matches("class X { public: X(); }; void x(int) { X x = X(); }",
>> +              Constructor));
>> +  EXPECT_TRUE(
>> +      notMatches("class Y { public: Y(); }; void x(int) { Y y; }",
>> +                 Constructor));
>> +}
>> +
>> +TEST(Matcher, VisitsTemplateInstantiations) {
>> +  EXPECT_TRUE(matches(
>> +      "class A { public: void x(); };"
>> +      "template <typename T> class B { public: void y() { T t; t.x(); }
>> };"
>> +      "void f() { B<A> b; b.y(); }",
>> call(callee(method(hasName("x"))))));
>> +
>> +  EXPECT_TRUE(matches(
>> +      "class A { public: void x(); };"
>> +      "class C {"
>> +      " public:"
>> +      "  template <typename T> class B { public: void y() { T t; t.x(); }
>> };"
>> +      "};"
>> +      "void f() {"
>> +      "  C::B<A> b; b.y();"
>> +      "}", record(hasName("C"),
>> +                 hasDescendant(call(callee(method(hasName("x"))))))));
>> +}
>> +
>> +// For testing AST_MATCHER_P().
>> +AST_MATCHER_P(clang::Decl, just, internal::Matcher<clang::Decl>,
>> AMatcher) {
>> +  // Make sure all special variables are used: node, match_finder,
>> +  // bound_nodes_builder, and the parameter named 'AMatcher'.
>> +  return AMatcher.matches(Node, Finder, Builder);
>> +}
>> +
>> +TEST(AstMatcherPMacro, Works) {
>> +  DeclarationMatcher HasClassB = just(has(id("b",
>> record(hasName("B")))));
>> +
>> +  EXPECT_TRUE(matchAndVerifyResultTrue("class A { class B {}; };",
>> +      HasClassB, new VerifyIdIsBoundToDecl<clang::Decl>("b")));
>> +
>> +  EXPECT_TRUE(matchAndVerifyResultFalse("class A { class B {}; };",
>> +      HasClassB, new VerifyIdIsBoundToDecl<clang::Decl>("a")));
>> +
>> +  EXPECT_TRUE(matchAndVerifyResultFalse("class A { class C {}; };",
>> +      HasClassB, new VerifyIdIsBoundToDecl<clang::Decl>("b")));
>> +}
>> +
>> +AST_POLYMORPHIC_MATCHER_P(
>> +    polymorphicHas, internal::Matcher<clang::Decl>, AMatcher) {
>> +  TOOLING_COMPILE_ASSERT((llvm::is_same<NodeType, clang::Decl>::value) ||
>> +                         (llvm::is_same<NodeType, clang::Stmt>::value),
>> +                         assert_node_type_is_accessible);
>> +  internal::TypedBaseMatcher<clang::Decl> ChildMatcher(AMatcher);
>> +  return Finder->matchesChildOf(
>> +      Node, ChildMatcher, Builder,
>> +      ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses,
>> +      ASTMatchFinder::BK_First);
>> +}
>> +
>> +TEST(AstPolymorphicMatcherPMacro, Works) {
>> +  DeclarationMatcher HasClassB = polymorphicHas(id("b",
>> record(hasName("B"))));
>> +
>> +  EXPECT_TRUE(matchAndVerifyResultTrue("class A { class B {}; };",
>> +      HasClassB, new VerifyIdIsBoundToDecl<clang::Decl>("b")));
>> +
>> +  EXPECT_TRUE(matchAndVerifyResultFalse("class A { class B {}; };",
>> +      HasClassB, new VerifyIdIsBoundToDecl<clang::Decl>("a")));
>> +
>> +  EXPECT_TRUE(matchAndVerifyResultFalse("class A { class C {}; };",
>> +      HasClassB, new VerifyIdIsBoundToDecl<clang::Decl>("b")));
>> +
>> +  StatementMatcher StatementHasClassB =
>> +      polymorphicHas(record(hasName("B")));
>> +
>> +  EXPECT_TRUE(matches("void x() { class B {}; }", StatementHasClassB));
>> +}
>> +
>> +TEST(For, FindsForLoops) {
>> +  EXPECT_TRUE(matches("void f() { for(;;); }", forStmt()));
>> +  EXPECT_TRUE(matches("void f() { if(true) for(;;); }", forStmt()));
>> +}
>> +
>> +TEST(For, ReportsNoFalsePositives) {
>> +  EXPECT_TRUE(notMatches("void f() { ; }", forStmt()));
>> +  EXPECT_TRUE(notMatches("void f() { if(true); }", forStmt()));
>> +}
>> +
>> +TEST(CompoundStatement, HandlesSimpleCases) {
>> +  EXPECT_TRUE(notMatches("void f();", compoundStatement()));
>> +  EXPECT_TRUE(matches("void f() {}", compoundStatement()));
>> +  EXPECT_TRUE(matches("void f() {{}}", compoundStatement()));
>> +}
>> +
>> +TEST(CompoundStatement, DoesNotMatchEmptyStruct) {
>> +  // It's not a compound statement just because there's "{}" in the
>> source
>> +  // text. This is an AST search, not grep.
>> +  EXPECT_TRUE(notMatches("namespace n { struct S {}; }",
>> +              compoundStatement()));
>> +  EXPECT_TRUE(matches("namespace n { struct S { void f() {{}} }; }",
>> +              compoundStatement()));
>> +}
>> +
>> +TEST(HasBody, FindsBodyOfForLoop) {
>> +  StatementMatcher HasCompoundStatementBody =
>> +      forStmt(hasBody(compoundStatement()));
>> +  EXPECT_TRUE(matches("void f() { for(;;) {} }",
>> +              HasCompoundStatementBody));
>> +  EXPECT_TRUE(notMatches("void f() { for(;;); }",
>> +              HasCompoundStatementBody));
>> +}
>> +
>> +TEST(HasAnySubstatement, MatchesForTopLevelCompoundStatement) {
>> +  // The simplest case: every compound statement is in a function
>> +  // definition, and the function body itself must be a compound
>> +  // statement.
>> +  EXPECT_TRUE(matches("void f() { for (;;); }",
>> +              compoundStatement(hasAnySubstatement(forStmt()))));
>> +}
>> +
>> +TEST(HasAnySubstatement, IsNotRecursive) {
>> +  // It's really "has any immediate substatement".
>> +  EXPECT_TRUE(notMatches("void f() { if (true) for (;;); }",
>> +              compoundStatement(hasAnySubstatement(forStmt()))));
>> +}
>> +
>> +TEST(HasAnySubstatement, MatchesInNestedCompoundStatements) {
>> +  EXPECT_TRUE(matches("void f() { if (true) { for (;;); } }",
>> +              compoundStatement(hasAnySubstatement(forStmt()))));
>> +}
>> +
>> +TEST(HasAnySubstatement, FindsSubstatementBetweenOthers) {
>> +  EXPECT_TRUE(matches("void f() { 1; 2; 3; for (;;); 4; 5; 6; }",
>> +              compoundStatement(hasAnySubstatement(forStmt()))));
>> +}
>> +
>> +TEST(StatementCountIs, FindsNoStatementsInAnEmptyCompoundStatement) {
>> +  EXPECT_TRUE(matches("void f() { }",
>> +              compoundStatement(statementCountIs(0))));
>> +  EXPECT_TRUE(notMatches("void f() {}",
>> +              compoundStatement(statementCountIs(1))));
>> +}
>> +
>> +TEST(StatementCountIs, AppearsToMatchOnlyOneCount) {
>> +  EXPECT_TRUE(matches("void f() { 1; }",
>> +              compoundStatement(statementCountIs(1))));
>> +  EXPECT_TRUE(notMatches("void f() { 1; }",
>> +              compoundStatement(statementCountIs(0))));
>> +  EXPECT_TRUE(notMatches("void f() { 1; }",
>> +              compoundStatement(statementCountIs(2))));
>> +}
>> +
>> +TEST(StatementCountIs, WorksWithMultipleStatements) {
>> +  EXPECT_TRUE(matches("void f() { 1; 2; 3; }",
>> +              compoundStatement(statementCountIs(3))));
>> +}
>> +
>> +TEST(StatementCountIs, WorksWithNestedCompoundStatements) {
>> +  EXPECT_TRUE(matches("void f() { { 1; } { 1; 2; 3; 4; } }",
>> +              compoundStatement(statementCountIs(1))));
>> +  EXPECT_TRUE(matches("void f() { { 1; } { 1; 2; 3; 4; } }",
>> +              compoundStatement(statementCountIs(2))));
>> +  EXPECT_TRUE(notMatches("void f() { { 1; } { 1; 2; 3; 4; } }",
>> +              compoundStatement(statementCountIs(3))));
>> +  EXPECT_TRUE(matches("void f() { { 1; } { 1; 2; 3; 4; } }",
>> +              compoundStatement(statementCountIs(4))));
>> +}
>> +
>> +TEST(Member, WorksInSimplestCase) {
>> +  EXPECT_TRUE(matches("struct { int first; } s; int i(s.first);",
>> +                      memberExpression(member(hasName("first")))));
>> +}
>> +
>> +TEST(Member, DoesNotMatchTheBaseExpression) {
>> +  // Don't pick out the wrong part of the member expression, this should
>> +  // be checking the member (name) only.
>> +  EXPECT_TRUE(notMatches("struct { int i; } first; int i(first.i);",
>> +                         memberExpression(member(hasName("first")))));
>> +}
>> +
>> +TEST(Member, MatchesInMemberFunctionCall) {
>> +  EXPECT_TRUE(matches("void f() {"
>> +                      "  struct { void first() {}; } s;"
>> +                      "  s.first();"
>> +                      "};",
>> +                      memberExpression(member(hasName("first")))));
>> +}
>> +
>> +TEST(HasObjectExpression, DoesNotMatchMember) {
>> +  EXPECT_TRUE(notMatches(
>> +      "class X {}; struct Z { X m; }; void f(Z z) { z.m; }",
>> +
>> memberExpression(hasObjectExpression(hasType(record(hasName("X")))))));
>> +}
>> +
>> +TEST(HasObjectExpression, MatchesBaseOfVariable) {
>> +  EXPECT_TRUE(matches(
>> +      "struct X { int m; }; void f(X x) { x.m; }",
>> +
>> memberExpression(hasObjectExpression(hasType(record(hasName("X")))))));
>> +  EXPECT_TRUE(matches(
>> +      "struct X { int m; }; void f(X* x) { x->m; }",
>> +      memberExpression(hasObjectExpression(
>> +          hasType(pointsTo(record(hasName("X"))))))));
>> +}
>> +
>> +TEST(HasObjectExpression,
>> +     MatchesObjectExpressionOfImplicitlyFormedMemberExpression) {
>> +  EXPECT_TRUE(matches(
>> +      "class X {}; struct S { X m; void f() { this->m; } };",
>> +      memberExpression(hasObjectExpression(
>> +          hasType(pointsTo(record(hasName("S"))))))));
>> +  EXPECT_TRUE(matches(
>> +      "class X {}; struct S { X m; void f() { m; } };",
>> +      memberExpression(hasObjectExpression(
>> +          hasType(pointsTo(record(hasName("S"))))))));
>> +}
>> +
>> +TEST(Field, DoesNotMatchNonFieldMembers) {
>> +  EXPECT_TRUE(notMatches("class X { void m(); };", field(hasName("m"))));
>> +  EXPECT_TRUE(notMatches("class X { class m {}; };",
>> field(hasName("m"))));
>> +  EXPECT_TRUE(notMatches("class X { enum { m }; };",
>> field(hasName("m"))));
>> +  EXPECT_TRUE(notMatches("class X { enum m {}; };",
>> field(hasName("m"))));
>> +}
>> +
>> +TEST(Field, MatchesField) {
>> +  EXPECT_TRUE(matches("class X { int m; };", field(hasName("m"))));
>> +}
>> +
>> +TEST(IsConstQualified, MatchesConstInt) {
>> +  EXPECT_TRUE(matches("const int i = 42;",
>> +                      variable(hasType(isConstQualified()))));
>> +}
>> +
>> +TEST(IsConstQualified, MatchesConstPointer) {
>> +  EXPECT_TRUE(matches("int i = 42; int* const p(&i);",
>> +                      variable(hasType(isConstQualified()))));
>> +}
>> +
>> +TEST(IsConstQualified, MatchesThroughTypedef) {
>> +  EXPECT_TRUE(matches("typedef const int const_int; const_int i = 42;",
>> +                      variable(hasType(isConstQualified()))));
>> +  EXPECT_TRUE(matches("typedef int* int_ptr; const int_ptr p(0);",
>> +                      variable(hasType(isConstQualified()))));
>> +}
>> +
>> +TEST(IsConstQualified, DoesNotMatchInappropriately) {
>> +  EXPECT_TRUE(notMatches("typedef int nonconst_int; nonconst_int i =
>> 42;",
>> +                         variable(hasType(isConstQualified()))));
>> +  EXPECT_TRUE(notMatches("int const* p;",
>> +                         variable(hasType(isConstQualified()))));
>> +}
>> +
>> +TEST(ReinterpretCast, MatchesSimpleCase) {
>> +  EXPECT_TRUE(matches("char* p = reinterpret_cast<char*>(&p);",
>> +                      expression(reinterpretCast())));
>> +}
>> +
>> +TEST(ReinterpretCast, DoesNotMatchOtherCasts) {
>> +  EXPECT_TRUE(notMatches("char* p = (char*)(&p);",
>> +                         expression(reinterpretCast())));
>> +  EXPECT_TRUE(notMatches("char q, *p = const_cast<char*>(&q);",
>> +                         expression(reinterpretCast())));
>> +  EXPECT_TRUE(notMatches("void* p = static_cast<void*>(&p);",
>> +                         expression(reinterpretCast())));
>> +  EXPECT_TRUE(notMatches("struct B { virtual ~B() {} }; struct D : B {};"
>> +                         "B b;"
>> +                         "D* p = dynamic_cast<D*>(&b);",
>> +                         expression(reinterpretCast())));
>> +}
>> +
>> +TEST(FunctionalCast, MatchesSimpleCase) {
>> +  std::string foo_class = "class Foo { public: Foo(char*); };";
>> +  EXPECT_TRUE(matches(foo_class + "void r() { Foo f = Foo(\"hello
>> world\"); }",
>> +                      expression(functionalCast())));
>> +}
>> +
>> +TEST(FunctionalCast, DoesNotMatchOtherCasts) {
>> +  std::string FooClass = "class Foo { public: Foo(char*); };";
>> +  EXPECT_TRUE(
>> +      notMatches(FooClass + "void r() { Foo f = (Foo) \"hello world\";
>> }",
>> +                 expression(functionalCast())));
>> +  EXPECT_TRUE(
>> +      notMatches(FooClass + "void r() { Foo f = \"hello world\"; }",
>> +                 expression(functionalCast())));
>> +}
>> +
>> +TEST(DynamicCast, MatchesSimpleCase) {
>> +  EXPECT_TRUE(matches("struct B { virtual ~B() {} }; struct D : B {};"
>> +                      "B b;"
>> +                      "D* p = dynamic_cast<D*>(&b);",
>> +                      expression(dynamicCast())));
>> +}
>> +
>> +TEST(StaticCast, MatchesSimpleCase) {
>> +  EXPECT_TRUE(matches("void* p(static_cast<void*>(&p));",
>> +                      expression(staticCast())));
>> +}
>> +
>> +TEST(StaticCast, DoesNotMatchOtherCasts) {
>> +  EXPECT_TRUE(notMatches("char* p = (char*)(&p);",
>> +                         expression(staticCast())));
>> +  EXPECT_TRUE(notMatches("char q, *p = const_cast<char*>(&q);",
>> +                         expression(staticCast())));
>> +  EXPECT_TRUE(notMatches("void* p = reinterpret_cast<char*>(&p);",
>> +                         expression(staticCast())));
>> +  EXPECT_TRUE(notMatches("struct B { virtual ~B() {} }; struct D : B {};"
>> +                         "B b;"
>> +                         "D* p = dynamic_cast<D*>(&b);",
>> +                         expression(staticCast())));
>> +}
>> +
>> +TEST(HasDestinationType, MatchesSimpleCase) {
>> +  EXPECT_TRUE(matches("char* p = static_cast<char*>(0);",
>> +                      expression(
>> +                          staticCast(hasDestinationType(
>> +                              pointsTo(TypeMatcher(anything())))))));
>> +}
>> +
>> +TEST(HasSourceExpression, MatchesSimpleCase) {
>> +  EXPECT_TRUE(matches("class string {}; class URL { public: URL(string
>> s); };"
>> +                      "void r() {string a_string; URL url = a_string; }",
>> +                      expression(implicitCast(
>> +                          hasSourceExpression(constructorCall())))));
>> +}
>> +
>> +TEST(Statement, DoesNotMatchDeclarations) {
>> +  EXPECT_TRUE(notMatches("class X {};", statement()));
>> +}
>> +
>> +TEST(Statement, MatchesCompoundStatments) {
>> +  EXPECT_TRUE(matches("void x() {}", statement()));
>> +}
>> +
>> +TEST(DeclarationStatement, DoesNotMatchCompoundStatements) {
>> +  EXPECT_TRUE(notMatches("void x() {}", declarationStatement()));
>> +}
>> +
>> +TEST(DeclarationStatement, MatchesVariableDeclarationStatements) {
>> +  EXPECT_TRUE(matches("void x() { int a; }", declarationStatement()));
>> +}
>> +
>> +TEST(While, MatchesWhileLoops) {
>> +  EXPECT_TRUE(notMatches("void x() {}", whileStmt()));
>> +  EXPECT_TRUE(matches("void x() { while(true); }", whileStmt()));
>> +  EXPECT_TRUE(notMatches("void x() { do {} while(true); }",
>> whileStmt()));
>> +}
>> +
>> +TEST(Do, MatchesDoLoops) {
>> +  EXPECT_TRUE(matches("void x() { do {} while(true); }", doStmt()));
>> +  EXPECT_TRUE(matches("void x() { do ; while(false); }", doStmt()));
>> +}
>> +
>> +TEST(Do, DoesNotMatchWhileLoops) {
>> +  EXPECT_TRUE(notMatches("void x() { while(true) {} }", doStmt()));
>> +}
>> +
>> +TEST(SwitchCase, MatchesCase) {
>> +  EXPECT_TRUE(matches("void x() { switch(42) { case 42:; } }",
>> switchCase()));
>> +  EXPECT_TRUE(matches("void x() { switch(42) { default:; } }",
>> switchCase()));
>> +  EXPECT_TRUE(matches("void x() { switch(42) default:; }",
>> switchCase()));
>> +  EXPECT_TRUE(notMatches("void x() { switch(42) {} }", switchCase()));
>> +}
>> +
>> +TEST(HasConditionVariableStatement, DoesNotMatchCondition) {
>> +  EXPECT_TRUE(notMatches(
>> +      "void x() { if(true) {} }",
>> +      ifStmt(hasConditionVariableStatement(declarationStatement()))));
>> +  EXPECT_TRUE(notMatches(
>> +      "void x() { int x; if((x = 42)) {} }",
>> +      ifStmt(hasConditionVariableStatement(declarationStatement()))));
>> +}
>> +
>> +TEST(HasConditionVariableStatement, MatchesConditionVariables) {
>> +  EXPECT_TRUE(matches(
>> +      "void x() { if(int* a = 0) {} }",
>> +      ifStmt(hasConditionVariableStatement(declarationStatement()))));
>> +}
>> +
>> +TEST(ForEach, BindsOneNode) {
>> +  EXPECT_TRUE(matchAndVerifyResultTrue("class C { int x; };",
>> +      record(hasName("C"), forEach(id("x", field(hasName("x"))))),
>> +      new VerifyIdIsBoundToDecl<clang::FieldDecl>("x", 1)));
>> +}
>> +
>> +TEST(ForEach, BindsMultipleNodes) {
>> +  EXPECT_TRUE(matchAndVerifyResultTrue("class C { int x; int y; int z;
>> };",
>> +      record(hasName("C"), forEach(id("f", field()))),
>> +      new VerifyIdIsBoundToDecl<clang::FieldDecl>("f", 3)));
>> +}
>> +
>> +TEST(ForEach, BindsRecursiveCombinations) {
>> +  EXPECT_TRUE(matchAndVerifyResultTrue(
>> +      "class C { class D { int x; int y; }; class E { int y; int z; };
>> };",
>> +      record(hasName("C"), forEach(record(forEach(id("f", field()))))),
>> +      new VerifyIdIsBoundToDecl<clang::FieldDecl>("f", 4)));
>> +}
>> +
>> +TEST(ForEachDescendant, BindsOneNode) {
>> +  EXPECT_TRUE(matchAndVerifyResultTrue("class C { class D { int x; };
>> };",
>> +      record(hasName("C"), forEachDescendant(id("x",
>> field(hasName("x"))))),
>> +      new VerifyIdIsBoundToDecl<clang::FieldDecl>("x", 1)));
>> +}
>> +
>> +TEST(ForEachDescendant, BindsMultipleNodes) {
>> +  EXPECT_TRUE(matchAndVerifyResultTrue(
>> +      "class C { class D { int x; int y; }; "
>> +      "          class E { class F { int y; int z; }; }; };",
>> +      record(hasName("C"), forEachDescendant(id("f", field()))),
>> +      new VerifyIdIsBoundToDecl<clang::FieldDecl>("f", 4)));
>> +}
>> +
>> +TEST(ForEachDescendant, BindsRecursiveCombinations) {
>> +  EXPECT_TRUE(matchAndVerifyResultTrue(
>> +      "class C { class D { "
>> +      "          class E { class F { class G { int y; int z; }; }; }; };
>> };",
>> +      record(hasName("C"), forEachDescendant(record(
>> +          forEachDescendant(id("f", field()))))),
>> +      new VerifyIdIsBoundToDecl<clang::FieldDecl>("f", 8)));
>> +}
>> +
>> +
>> +TEST(IsTemplateInstantiation, MatchesImplicitClassTemplateInstantiation)
>> {
>> +  // Make sure that we can both match the class by name (::X) and by the
>> type
>> +  // the template was instantiated with (via a field).
>> +
>> +  EXPECT_TRUE(matches(
>> +      "template <typename T> class X {}; class A {}; X<A> x;",
>> +      record(hasName("::X"), isTemplateInstantiation())));
>> +
>> +  EXPECT_TRUE(matches(
>> +      "template <typename T> class X { T t; }; class A {}; X<A> x;",
>> +      record(isTemplateInstantiation(), hasDescendant(
>> +          field(hasType(record(hasName("A"))))))));
>> +}
>> +
>> +TEST(IsTemplateInstantiation,
>> MatchesImplicitFunctionTemplateInstantiation) {
>> +  EXPECT_TRUE(matches(
>> +      "template <typename T> void f(T t) {} class A {}; void g() {
>> f(A()); }",
>> +      function(hasParameter(0, hasType(record(hasName("A")))),
>> +               isTemplateInstantiation())));
>> +}
>> +
>> +TEST(IsTemplateInstantiation, MatchesExplicitClassTemplateInstantiation)
>> {
>> +  EXPECT_TRUE(matches(
>> +      "template <typename T> class X { T t; }; class A {};"
>> +      "template class X<A>;",
>> +      record(isTemplateInstantiation(), hasDescendant(
>> +          field(hasType(record(hasName("A"))))))));
>> +}
>> +
>> +TEST(IsTemplateInstantiation,
>> +     MatchesInstantiationOfPartiallySpecializedClassTemplate) {
>> +  EXPECT_TRUE(matches(
>> +      "template <typename T> class X {};"
>> +      "template <typename T> class X<T*> {}; class A {}; X<A*> x;",
>> +      record(hasName("::X"), isTemplateInstantiation())));
>> +}
>> +
>> +TEST(IsTemplateInstantiation,
>> +     MatchesInstantiationOfClassTemplateNestedInNonTemplate) {
>> +  EXPECT_TRUE(matches(
>> +      "class A {};"
>> +      "class X {"
>> +      "  template <typename U> class Y { U u; };"
>> +      "  Y<A> y;"
>> +      "};",
>> +      record(hasName("::X::Y"), isTemplateInstantiation())));
>> +}
>> +
>> +TEST(IsTemplateInstantiation,
>> DoesNotMatchInstantiationsInsideOfInstantiation) {
>> +  // FIXME: Figure out whether this makes sense. It doesn't affect the
>> +  // normal use case as long as the uppermost instantiation always is
>> marked
>> +  // as template instantiation, but it might be confusing as a predicate.
>> +  EXPECT_TRUE(matches(
>> +      "class A {};"
>> +      "template <typename T> class X {"
>> +      "  template <typename U> class Y { U u; };"
>> +      "  Y<T> y;"
>> +      "}; X<A> x;",
>> +      record(hasName("::X<A>::Y"), unless(isTemplateInstantiation()))));
>> +}
>> +
>> +TEST(IsTemplateInstantiation,
>> DoesNotMatchExplicitClassTemplateSpecialization) {
>> +  EXPECT_TRUE(notMatches(
>> +      "template <typename T> class X {}; class A {};"
>> +      "template <> class X<A> {}; X<A> x;",
>> +      record(hasName("::X"), isTemplateInstantiation())));
>> +}
>> +
>> +TEST(IsTemplateInstantiation, DoesNotMatchNonTemplate) {
>> +  EXPECT_TRUE(notMatches(
>> +      "class A {}; class Y { A a; };",
>> +      record(isTemplateInstantiation())));
>> +}
>> +
>> +} // end namespace ast_matchers
>> +} // end namespace clang
>>
>> Added: cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.h?rev=159805&view=auto
>>
>> ==============================================================================
>> --- cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.h (added)
>> +++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.h Fri Jul  6 00:48:52
>> 2012
>> @@ -0,0 +1,128 @@
>> +//===- unittest/Tooling/ASTMatchersTest.h - Matcher tests helpers
>> ------===//
>> +//
>> +//                     The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLVM_CLANG_UNITTESTS_AST_MATCHERS_AST_MATCHERS_TEST_H
>> +#define LLVM_CLANG_UNITTESTS_AST_MATCHERS_AST_MATCHERS_TEST_H
>> +
>> +#include "clang/ASTMatchers/ASTMatchFinder.h"
>> +#include "clang/Tooling/Tooling.h"
>> +#include "gtest/gtest.h"
>> +
>> +namespace clang {
>> +namespace ast_matchers {
>> +
>> +using clang::tooling::newFrontendActionFactory;
>> +using clang::tooling::runToolOnCode;
>> +using clang::tooling::FrontendActionFactory;
>> +
>> +class BoundNodesCallback {
>> +public:
>> +  virtual ~BoundNodesCallback() {}
>> +  virtual bool run(const BoundNodes *BoundNodes) = 0;
>> +};
>> +
>> +// If 'FindResultVerifier' is not NULL, sets *Verified to the result of
>> +// running 'FindResultVerifier' with the bound nodes as argument.
>> +// If 'FindResultVerifier' is NULL, sets *Verified to true when Run is
>> called.
>> +class VerifyMatch : public MatchFinder::MatchCallback {
>> +public:
>> +  VerifyMatch(BoundNodesCallback *FindResultVerifier, bool *Verified)
>> +      : Verified(Verified), FindResultReviewer(FindResultVerifier) {}
>> +
>> +  virtual void run(const MatchFinder::MatchResult &Result) {
>> +    if (FindResultReviewer != NULL) {
>> +      *Verified = FindResultReviewer->run(&Result.Nodes);
>> +    } else {
>> +      *Verified = true;
>> +    }
>> +  }
>> +
>> +private:
>> +  bool *const Verified;
>> +  BoundNodesCallback *const FindResultReviewer;
>> +};
>> +
>> +template <typename T>
>> +testing::AssertionResult matchesConditionally(const std::string &Code,
>> +                                              const T &AMatcher,
>> +                                              bool ExpectMatch) {
>> +  bool Found = false;
>> +  MatchFinder Finder;
>> +  Finder.addMatcher(AMatcher, new VerifyMatch(0, &Found));
>> +  OwningPtr<FrontendActionFactory>
>> Factory(newFrontendActionFactory(&Finder));
>> +  if (!runToolOnCode(Factory->create(), Code)) {
>> +    return testing::AssertionFailure() << "Parsing error in \"" << Code
>> << "\"";
>> +  }
>> +  if (!Found && ExpectMatch) {
>> +    return testing::AssertionFailure()
>> +      << "Could not find match in \"" << Code << "\"";
>> +  } else if (Found && !ExpectMatch) {
>> +    return testing::AssertionFailure()
>> +      << "Found unexpected match in \"" << Code << "\"";
>> +  }
>> +  return testing::AssertionSuccess();
>> +}
>> +
>> +template <typename T>
>> +testing::AssertionResult matches(const std::string &Code, const T
>> &AMatcher) {
>> +  return matchesConditionally(Code, AMatcher, true);
>> +}
>> +
>> +template <typename T>
>> +testing::AssertionResult notMatches(const std::string &Code,
>> +                                    const T &AMatcher) {
>> +  return matchesConditionally(Code, AMatcher, false);
>> +}
>> +
>> +template <typename T>
>> +testing::AssertionResult
>> +matchAndVerifyResultConditionally(const std::string &Code, const T
>> &AMatcher,
>> +                                  BoundNodesCallback *FindResultVerifier,
>> +                                  bool ExpectResult) {
>> +  llvm::OwningPtr<BoundNodesCallback> ScopedVerifier(FindResultVerifier);
>> +  bool VerifiedResult = false;
>> +  MatchFinder Finder;
>> +  Finder.addMatcher(
>> +      AMatcher, new VerifyMatch(FindResultVerifier, &VerifiedResult));
>> +  OwningPtr<FrontendActionFactory>
>> Factory(newFrontendActionFactory(&Finder));
>> +  if (!runToolOnCode(Factory->create(), Code)) {
>> +    return testing::AssertionFailure() << "Parsing error in \"" << Code
>> << "\"";
>> +  }
>> +  if (!VerifiedResult && ExpectResult) {
>> +    return testing::AssertionFailure()
>> +      << "Could not verify result in \"" << Code << "\"";
>> +  } else if (VerifiedResult && !ExpectResult) {
>> +    return testing::AssertionFailure()
>> +      << "Verified unexpected result in \"" << Code << "\"";
>> +  }
>> +  return testing::AssertionSuccess();
>> +}
>> +
>> +// FIXME: Find better names for these functions (or document what they
>> +// do more precisely).
>> +template <typename T>
>> +testing::AssertionResult
>> +matchAndVerifyResultTrue(const std::string &Code, const T &AMatcher,
>> +                         BoundNodesCallback *FindResultVerifier) {
>> +  return matchAndVerifyResultConditionally(
>> +      Code, AMatcher, FindResultVerifier, true);
>> +}
>> +
>> +template <typename T>
>> +testing::AssertionResult
>> +matchAndVerifyResultFalse(const std::string &Code, const T &AMatcher,
>> +                          BoundNodesCallback *FindResultVerifier) {
>> +  return matchAndVerifyResultConditionally(
>> +      Code, AMatcher, FindResultVerifier, false);
>> +}
>> +
>> +} // end namespace ast_matchers
>> +} // end namespace clang
>> +
>> +#endif  // LLVM_CLANG_UNITTESTS_AST_MATCHERS_AST_MATCHERS_TEST_H
>>
>> Added: cfe/trunk/unittests/ASTMatchers/CMakeLists.txt
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/CMakeLists.txt?rev=159805&view=auto
>>
>> ==============================================================================
>> --- cfe/trunk/unittests/ASTMatchers/CMakeLists.txt (added)
>> +++ cfe/trunk/unittests/ASTMatchers/CMakeLists.txt Fri Jul  6 00:48:52
>> 2012
>> @@ -0,0 +1,5 @@
>> +add_clang_unittest(ASTMatchersTests
>> +  ASTMatchersTest.cpp)
>> +
>> +target_link_libraries(ASTMatchersTests
>> +  gtest gtest_main clangASTMatchers clangTooling)
>>
>> Added: cfe/trunk/unittests/ASTMatchers/Makefile
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Makefile?rev=159805&view=auto
>>
>> ==============================================================================
>> --- cfe/trunk/unittests/ASTMatchers/Makefile (added)
>> +++ cfe/trunk/unittests/ASTMatchers/Makefile Fri Jul  6 00:48:52 2012
>> @@ -0,0 +1,19 @@
>> +##===- unittests/ASTMatchers/Makefile ----------------------*- Makefile
>> -*-===##
>> +#
>> +#                     The LLVM Compiler Infrastructure
>> +#
>> +# This file is distributed under the University of Illinois Open Source
>> +# License. See LICENSE.TXT for details.
>> +#
>>
>> +##===----------------------------------------------------------------------===##
>> +
>> +CLANG_LEVEL = ../..
>> +PARALLEL_DIRS = Dynamic
>> +
>> +TESTNAME = ASTMatchers
>> +LINK_COMPONENTS := support mc
>> +USEDLIBS = clangEdit.a clangTooling.a clangFrontend.a
>> clangSerialization.a clangDriver.a \
>> +           clangRewrite.a clangParse.a clangSema.a clangAnalysis.a \
>> +                                        clangAST.a clangASTMatchers.a
>> clangLex.a clangBasic.a
>> +
>> +include $(CLANG_LEVEL)/unittests/Makefile
>>
>> Modified: cfe/trunk/unittests/CMakeLists.txt
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/CMakeLists.txt?rev=159805&r1=159804&r2=159805&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/unittests/CMakeLists.txt (original)
>> +++ cfe/trunk/unittests/CMakeLists.txt Fri Jul  6 00:48:52 2012
>> @@ -9,6 +9,7 @@
>>    add_unittest(ClangUnitTests ${test_dirname} ${ARGN})
>>  endfunction()
>>
>> +add_subdirectory(ASTMatchers)
>>  add_subdirectory(Basic)
>>  add_subdirectory(Lex)
>>  add_subdirectory(Frontend)
>>
>> Modified: cfe/trunk/unittests/Makefile
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Makefile?rev=159805&r1=159804&r2=159805&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/unittests/Makefile (original)
>> +++ cfe/trunk/unittests/Makefile Fri Jul  6 00:48:52 2012
>> @@ -14,7 +14,7 @@
>>
>>  IS_UNITTEST_LEVEL := 1
>>  CLANG_LEVEL := ..
>> -PARALLEL_DIRS = Basic AST Frontend Lex Tooling
>> +PARALLEL_DIRS = ASTMatchers Basic AST Frontend Lex Tooling
>>
>>  endif  # CLANG_LEVEL
>>
>>
>>
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
>



More information about the cfe-commits mailing list