[llvm-branch-commits] [cfe-branch] r146652 - in /cfe/branches/tooling: examples/ include/clang/ASTMatchers/ include/clang/Tooling/ lib/ lib/ASTMatchers/ lib/Tooling/ test/ test/Tooling/ tools/ tools/clang-check/ tools/remove-cstr-calls/ unittests/ unittests/ASTMatchers/ unittests/Tooling/

Chandler Carruth chandlerc at gmail.com
Thu Dec 15 03:51:05 PST 2011


Author: chandlerc
Date: Thu Dec 15 05:51:04 2011
New Revision: 146652

URL: http://llvm.org/viewvc/llvm-project?rev=146652&view=rev
Log:
Code drop of the current state of the tooling and AST matcher work at Google.
Most of this code is authored by Manuel Klimek, some of the early code was
originally authored by Zhanyong Wan, and only style tweaks and build system
munging from me.

All of this is slated for incremental review and migration to the primary Clang
codebase in one form or another. We're putting the code here early so that
others can see it and gain some context on what we're doing.

To use any of this, you need both the JSONParser that is currently in review
and the VariadicFunction that is currently in review. Both of those are slated
for going into LLVM, not Clang.

Added:
    cfe/branches/tooling/include/clang/ASTMatchers/
    cfe/branches/tooling/include/clang/ASTMatchers/ASTMatchFinder.h
    cfe/branches/tooling/include/clang/ASTMatchers/ASTMatchers.h
    cfe/branches/tooling/include/clang/ASTMatchers/ASTMatchersInternal.h
    cfe/branches/tooling/include/clang/ASTMatchers/ASTMatchersMacros.h
    cfe/branches/tooling/include/clang/Tooling/
    cfe/branches/tooling/include/clang/Tooling/Refactoring.h
    cfe/branches/tooling/include/clang/Tooling/Tooling.h
    cfe/branches/tooling/lib/ASTMatchers/
    cfe/branches/tooling/lib/ASTMatchers/ASTMatchFinder.cpp
    cfe/branches/tooling/lib/ASTMatchers/ASTMatchersInternal.cpp
    cfe/branches/tooling/lib/ASTMatchers/CMakeLists.txt
    cfe/branches/tooling/lib/ASTMatchers/Makefile
    cfe/branches/tooling/lib/Tooling/
    cfe/branches/tooling/lib/Tooling/CMakeLists.txt
    cfe/branches/tooling/lib/Tooling/Makefile
    cfe/branches/tooling/lib/Tooling/Refactoring.cpp
    cfe/branches/tooling/lib/Tooling/Tooling.cpp
    cfe/branches/tooling/test/Tooling/remove-cstr-calls.cpp
    cfe/branches/tooling/tools/clang-check/
    cfe/branches/tooling/tools/clang-check/CMakeLists.txt
    cfe/branches/tooling/tools/clang-check/ClangCheck.cpp
    cfe/branches/tooling/tools/clang-check/Makefile
    cfe/branches/tooling/tools/remove-cstr-calls/
    cfe/branches/tooling/tools/remove-cstr-calls/CMakeLists.txt
    cfe/branches/tooling/tools/remove-cstr-calls/Makefile
    cfe/branches/tooling/tools/remove-cstr-calls/RemoveCStrCalls.cpp
    cfe/branches/tooling/unittests/ASTMatchers/
    cfe/branches/tooling/unittests/ASTMatchers/ASTMatchersTest.cpp
    cfe/branches/tooling/unittests/ASTMatchers/Makefile
    cfe/branches/tooling/unittests/Tooling/
    cfe/branches/tooling/unittests/Tooling/Makefile
    cfe/branches/tooling/unittests/Tooling/RefactoringTest.cpp
    cfe/branches/tooling/unittests/Tooling/ToolingTest.cpp
Modified:
    cfe/branches/tooling/examples/CMakeLists.txt
    cfe/branches/tooling/lib/CMakeLists.txt
    cfe/branches/tooling/lib/Makefile
    cfe/branches/tooling/test/CMakeLists.txt
    cfe/branches/tooling/tools/CMakeLists.txt
    cfe/branches/tooling/tools/Makefile
    cfe/branches/tooling/unittests/CMakeLists.txt
    cfe/branches/tooling/unittests/Makefile

Modified: cfe/branches/tooling/examples/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/examples/CMakeLists.txt?rev=146652&r1=146651&r2=146652&view=diff
==============================================================================
--- cfe/branches/tooling/examples/CMakeLists.txt (original)
+++ cfe/branches/tooling/examples/CMakeLists.txt Thu Dec 15 05:51:04 2011
@@ -1,2 +1,3 @@
 add_subdirectory(clang-interpreter)
 add_subdirectory(PrintFunctionNames)
+add_subdirectory(Tooling)

Added: cfe/branches/tooling/include/clang/ASTMatchers/ASTMatchFinder.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/include/clang/ASTMatchers/ASTMatchFinder.h?rev=146652&view=auto
==============================================================================
--- cfe/branches/tooling/include/clang/ASTMatchers/ASTMatchFinder.h (added)
+++ cfe/branches/tooling/include/clang/ASTMatchers/ASTMatchFinder.h Thu Dec 15 05:51:04 2011
@@ -0,0 +1,133 @@
+//===--- 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 a FrontendAction 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 clang::tooling::MatchFinder::MatchCallback {
+//  public:
+//    virtual void Run(const clang::tooling::MatchFinder::MatchResult &Result) {
+//      const clang::CXXRecordDecl *Class =
+//          Result.Nodes.GetDeclAs<clang::CXXRecordDecl>("id");
+//      ...
+//    }
+//  };
+//
+//  int main(int argc, char **argv) {
+//    ClangTool Tool(argc, argv);
+//    MatchFinder finder;
+//    finder.AddMatcher(Id("id", Class(HasName("::a_namespace::AClass"))),
+//                      new HandleMatch);
+//    return Tool.Run(finder.NewFrontendActionFactory());
+//  }
+//
+//===----------------------------------------------------------------------===//
+
+#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 {
+
+class FrontendAction;
+
+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, NewFrontendAction() returns a FrontendAction
+/// 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:
+  struct MatchResult {
+    MatchResult(const BoundNodes &Nodes, clang::ASTContext *Context,
+                clang::SourceManager *SourceManager);
+
+    const BoundNodes Nodes;
+
+    ///@{
+    /// Utilities for interpreting the matched AST structures.
+    clang::ASTContext * const Context;
+    clang::SourceManager * const SourceManager;
+    ///@}
+  };
+
+  /// 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;
+  };
+
+  /// Called when parsing is finished. Intended for testing only.
+  class ParsingDoneTestCallback {
+  public:
+    virtual ~ParsingDoneTestCallback();
+    virtual void Run() = 0;
+  };
+
+  MatchFinder();
+  ~MatchFinder();
+
+  /// Adds a NodeMatcher to match 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.
+  /// @{
+  void AddMatcher(const DeclarationMatcher &NodeMatch,
+                  MatchCallback *Action);
+  void AddMatcher(const TypeMatcher &NodeMatch,
+                  MatchCallback *Action);
+  void AddMatcher(const StatementMatcher &NodeMatch,
+                  MatchCallback *Action);
+  /// @}
+
+  /// Creates a clang FrontendAction that finds all matches.
+  FrontendAction *NewFrontendAction();
+
+  /// 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:
+  /// The MatchCallback*'s will be called every time the UntypedBaseMatcher
+  /// matches on the AST.
+  std::vector< std::pair<
+    const internal::UntypedBaseMatcher*,
+    MatchCallback*> > Triggers;
+
+  /// Called when parsing is done.
+  ParsingDoneTestCallback *ParsingDone;
+
+  friend class MatchFinderFrontendActionFactory;
+};
+
+} // end namespace ast_matchers
+} // end namespace clang
+
+#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H

Added: cfe/branches/tooling/include/clang/ASTMatchers/ASTMatchers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/include/clang/ASTMatchers/ASTMatchers.h?rev=146652&view=auto
==============================================================================
--- cfe/branches/tooling/include/clang/ASTMatchers/ASTMatchers.h (added)
+++ cfe/branches/tooling/include/clang/ASTMatchers/ASTMatchers.h Thu Dec 15 05:51:04 2011
@@ -0,0 +1,1398 @@
+//===--- 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:
+//    Class(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
+//  which you want to access.
+//
+//  For example, when we're interested in child classes of a certain class, we
+//  would write:
+//    Class(HasName("MyClass"), HasChild(Id("child", Class())))
+//  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.
+//
+//===----------------------------------------------------------------------===//
+
+#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 when 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(const std::string &ID) const {
+    return GetNodeAs<T>(DeclBindings, ID);
+  }
+  template <typename T>
+  const T *GetStmtAs(const std::string &ID) const {
+    return GetNodeAs<T>(StmtBindings, ID);
+  }
+  /// @}
+
+private:
+  /// 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, const std::string &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;
+/// @}
+
+/// 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(True()) matches all declarations, e.g.,
+/// "int* p" and "void f()" in
+///   int* p;
+///   void f();
+inline internal::PolymorphicMatcherWithParam0<internal::TrueMatcher> True() {
+  return internal::PolymorphicMatcherWithParam0<internal::TrueMatcher>();
+}
+
+/// 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;
+
+/// Matches C++ class declarations.
+///
+/// Example matches X, Z
+///   class X;
+///   template<class T> class Z {};
+const internal::VariadicDynCastAllOfMatcher<
+  clang::Decl,
+  clang::CXXRecordDecl> Class;
+
+/// 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;
+
+/// Matches method declarations.
+///
+/// Example matches y
+///   class X { void y() };
+const internal::VariadicDynCastAllOfMatcher<
+  clang::Decl,
+  clang::CXXMethodDecl> Method;
+
+/// 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;
+
+/// Matches field declarations.
+///
+/// Given
+///   class X { int m; };
+/// Field()
+///   matches 'm'.
+const internal::VariadicDynCastAllOfMatcher<
+  clang::Decl,
+  clang::FieldDecl> Field;
+
+/// Matches function declarations.
+///
+/// Example matches f
+///   void f();
+const internal::VariadicDynCastAllOfMatcher<
+  clang::Decl,
+  clang::FunctionDecl> Function;
+
+
+/// Matches statements.
+///
+/// Given
+///   { ++a; }
+/// Statement()
+///   matches both the compound statement '{ ++a; }' and '++a'.
+const internal::VariadicDynCastAllOfMatcher<clang::Stmt, clang::Stmt> Statement;
+
+/// Matches declaration statements.
+///
+/// Given
+///   int a;
+/// DeclarationStatement()
+///   matches 'int a'.
+const internal::VariadicDynCastAllOfMatcher<
+  clang::Stmt,
+  clang::DeclStmt> DeclarationStatement;
+
+/// 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;
+
+/// Matches call expressions.
+///
+/// Example matches x.y()
+///   X x;
+///   x.y();
+const internal::VariadicDynCastAllOfMatcher<clang::Stmt, clang::CallExpr> Call;
+
+/// 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;
+
+/// Matches nodes where temporaries are created.
+///
+/// Example matches FunctionTakesString(GetStringByValue())
+///     (matcher = BindTemporaryExpr())
+///   FunctionTakesString(GetStringByValue());
+///   FunctionTakesStringByPointer(GetStringPointer());
+const internal::VariadicDynCastAllOfMatcher<
+  clang::Stmt,
+  clang::CXXBindTemporaryExpr> BindTemporaryExpression;
+
+/// Matches new expressions.
+///
+/// Given
+///   new X;
+/// NewExpression()
+///   matches 'new X'.
+const internal::VariadicDynCastAllOfMatcher<
+  clang::Stmt,
+  clang::CXXNewExpr> NewExpression;
+
+/// 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;
+
+/// 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;
+
+/// Matches expressions.
+///
+/// Example matches x()
+///   void f() { x(); }
+const internal::VariadicDynCastAllOfMatcher<
+  clang::Stmt,
+  clang::Expr> Expression;
+
+/// Matches expressions that refer to declarations.
+///
+/// Example matches x in if (x)
+///   bool x;
+///   if (x) {}
+const internal::VariadicDynCastAllOfMatcher<
+  clang::Stmt,
+  clang::DeclRefExpr> DeclarationReference;
+
+/// Matches if statements.
+///
+/// Example matches 'if (x) {}'
+///   if (x) {}
+const internal::VariadicDynCastAllOfMatcher<clang::Stmt, clang::IfStmt> If;
+
+/// Matches for statements.
+///
+/// Example matches 'for (;;) {}'
+///   for (;;) {}
+const internal::VariadicDynCastAllOfMatcher<clang::Stmt, clang::ForStmt> For;
+
+/// Matches while statements.
+///
+/// Given
+///   while (true) {}
+/// While()
+///   matches 'while (true) {}'.
+const internal::VariadicDynCastAllOfMatcher<
+  clang::Stmt,
+  clang::WhileStmt> While;
+
+/// Matches do statements.
+///
+/// Given
+///   do {} while (true);
+/// Do()
+///   matches 'do {} while(true)'
+const internal::VariadicDynCastAllOfMatcher<clang::Stmt, clang::DoStmt> Do;
+
+/// 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;
+
+/// Matches compound statements.
+///
+/// Example matches '{}' and '{{}}'in 'for (;;) {{}}'
+///   for (;;) {{}}
+const internal::VariadicDynCastAllOfMatcher<
+  clang::Stmt,
+  clang::CompoundStmt> CompoundStatement;
+
+/// Matches bool literals.
+///
+/// Example matches true
+///   true
+const internal::VariadicDynCastAllOfMatcher<
+  clang::Expr,
+  clang::CXXBoolLiteralExpr> BoolLiteral;
+
+/// 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;
+
+/// 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;
+
+/// 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;
+
+/// Matches binary operator expressions.
+///
+/// Example matches a || b
+///   !(a || b)
+const internal::VariadicDynCastAllOfMatcher<
+  clang::Stmt,
+  clang::BinaryOperator> BinaryOperator;
+
+/// Matches unary operator expressions.
+///
+/// Example matches !a
+///   !a || b
+const internal::VariadicDynCastAllOfMatcher<
+  clang::Stmt,
+  clang::UnaryOperator> UnaryOperator;
+
+/// Matches conditional operator expressions.
+///
+/// Example matches a ? b : c
+///   (a ? b : c) + 42
+const internal::VariadicDynCastAllOfMatcher<
+  clang::Stmt,
+  clang::ConditionalOperator> ConditionalOperator;
+
+/// 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;
+
+/// 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;
+
+/// 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;
+
+/// 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;
+
+/// 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 also: 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;
+
+/// 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;
+
+/// 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));
+}
+/// @}
+
+/// 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());
+  }
+}
+
+/// Matches overloaded operator name given 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;
+}
+
+/// 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);
+}
+
+/// Matches AST nodes that have child AST nodes that match the provided matcher.
+///
+/// Example matches X, Y (matcher = Class(Has(Class(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);
+}
+
+/// Matches AST nodes that have descendant AST nodes that match the provided
+/// matcher.
+///
+/// Example matches X, Y, Z
+///     (matcher = Class(HasDescendant(Class(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);
+}
+
+
+/// Matches AST nodes that have child AST nodes that match the provided matcher.
+///
+/// Example matches X, Y (matcher = Class(ForEach(Class(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);
+}
+
+/// Matches AST nodes that have descendant AST nodes that match the provided
+/// matcher.
+///
+/// Example matches X, A, B, C
+///     (matcher = Class(ForEachDescendant(Class(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:
+///   Class(ForEachDescendant(Class(ForEachDescendant(Class()))))
+/// 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);
+}
+
+/// Matches if the provided matcher does not match.
+///
+/// Example matches Y (matcher = Class(Not(HasName("X"))))
+///   class X {};
+///   class Y {};
+template <typename M>
+internal::PolymorphicMatcherWithParam1<internal::NotMatcher, M> Not(const M &InnerMatcher) {
+  return internal::PolymorphicMatcherWithParam1<
+    internal::NotMatcher, M>(InnerMatcher);
+}
+
+/// 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);
+}
+
+/// Matches on the implicit object argument of a member call expression.
+///
+/// Example matches y.x() (matcher = Call(On(HasType(Class(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));
+}
+
+/// 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));
+}
+
+/// 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));
+}
+
+/// Matches if the expression's or declaration's type matches a type matcher.
+///
+/// Example matches x (matcher = Expression(HasType(
+///                        HasDeclaration(Class(HasName("X"))))))
+///             and z (matcher = Variable(HasType(
+///                        HasDeclaration(Class(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);
+}
+
+/// 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;", Class(HasName("X")) matches the declaration of X,
+/// while Variable(HasType(Class(HasName("X")))) matches the declaration
+/// of x."
+///
+/// Example matches x (matcher = Expression(HasType(Class(HasName("X")))))
+///             and z (matcher = Variable(HasType(Class(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)));
+}
+
+/// 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(Class(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));
+}
+
+/// 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)));
+}
+
+/// 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(Class(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));
+}
+
+/// 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));
+}
+
+/// 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))));
+}
+
+/// 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))));
+}
+
+/// 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));
+}
+
+/// 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));
+}
+
+/// 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;
+}
+
+/// Checks that a new expression has a specific number of constructor
+/// arguments (including absent default arguments).
+///
+/// Given
+///   new X(1, 2);
+/// NewExpression(ConstructorArgumentCountIs(2))
+///   matches 'new X(1, 2)'.
+AST_MATCHER_P(clang::CXXNewExpr, ConstructorArgumentCountIs, unsigned, N) {
+  return Node.getNumConstructorArgs() == N;
+}
+
+/// 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));
+}
+
+/// Matches the n'th constructor argument of new expression.
+///
+/// Given
+///   int x;
+///   new X(1, y);
+/// NewExpression(HasConstructorArgument(1, DeclarationReference()))
+///   matches 'new X(1, y)',
+/// with DeclarationReference()
+///   matching 'y'.
+AST_MATCHER_P2(
+    clang::CXXNewExpr, HasConstructorArgument, unsigned, N,
+    internal::Matcher<clang::Expr>, InnerMatcher) {
+  return (N < Node.getNumConstructorArgs() &&
+          InnerMatcher.Matches(
+              *Node.getConstructorArg(N)->IgnoreParenImpCasts(),
+              Finder, Builder));
+}
+
+/// Matches a constructor initializer.
+///
+/// Given
+///   struct Foo {
+///     Foo() : foo_(1) { }
+///     int foo_;
+///   };
+/// Class(Has(Constructor(HasAnyConstructorInitializer(True()))))
+///   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;
+}
+
+/// Matches the field declaration of a constructor initializer.
+///
+/// Given
+///   struct Foo {
+///     Foo() : foo_(1) { }
+///     int foo_;
+///   };
+/// Class(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));
+}
+
+/// Matches the initializer expression of a constructor initializer.
+///
+/// Given
+///   struct Foo {
+///     Foo() : foo_(1) { }
+///     int foo_;
+///   };
+/// Class(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));
+}
+
+/// 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();
+}
+
+/// 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();
+}
+
+/// 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;
+}
+
+/// 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));
+}
+
+/// 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;
+}
+
+/// 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));
+}
+
+/// 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);
+}
+
+/// 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));
+}
+
+/// 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;
+}
+
+/// 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;
+}
+
+/// 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);
+}
+
+/// 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());
+}
+
+/// 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));
+}
+
+/// 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));
+}
+
+/// 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));
+}
+
+/// 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));
+}
+
+/// 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);
+}
+
+/// 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);
+}
+
+/// 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));
+}
+
+/// 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));
+}
+
+/// 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>();
+}
+
+/// Matches the class declaration that the given method declaration belongs to.
+/// TODO(qrczak): 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));
+}
+
+/// 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());
+}
+
+/// 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());
+}
+
+/// 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);
+}
+
+/// 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(Class(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);
+}
+
+/// 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>;
+/// Class(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;
+/// Class(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/branches/tooling/include/clang/ASTMatchers/ASTMatchersInternal.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/include/clang/ASTMatchers/ASTMatchersInternal.h?rev=146652&view=auto
==============================================================================
--- cfe/branches/tooling/include/clang/ASTMatchers/ASTMatchersInternal.h (added)
+++ cfe/branches/tooling/include/clang/ASTMatchers/ASTMatchersInternal.h Thu Dec 15 05:51:04 2011
@@ -0,0 +1,871 @@
+//===--- 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:
+  /// A visitor interface to visit all BoundNodes results for a BoundNodesTree.
+  class Visitor {
+  public:
+    virtual ~Visitor() {}
+
+    /// 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();
+
+  /// 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);
+
+  /// Adds all bound nodes to bound_nodes_builder.
+  void CopyTo(BoundNodesTreeBuilder* Builder) const;
+
+  /// Visits all matches that this BoundNodesTree represents.
+  /// The ownership of 'visitor' 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();
+
+  /// 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);
+  /// @}
+
+  /// Adds a branch in the tree.
+  void AddMatch(const BoundNodesTree& Bindings);
+
+  /// 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:
+  /// Takes ownership of the provided implementation pointer.
+  explicit Matcher(MatcherInterface<T> *Implementation)
+      : Implementation(Implementation) {}
+
+  /// 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);
+  }
+
+  /// 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));
+  }
+
+  /// 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:
+  /// 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
+
+/// 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);
+}
+
+/// 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:
+  /// 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);
+  }
+
+  /// 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);
+  }
+
+  /// 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);
+  }
+
+  /// Extracts the Decl of the constructor ran by the new expression and
+  /// returns whether the inner matcher matches on it.
+  bool MatchesSpecialized(const clang::CXXNewExpr& 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;
+};
+
+/// 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);
+};
+template <typename T>
+const bool IsBaseType<T>::value;
+
+/// Interface that can match any AST base node type and contains default
+/// implementations returning false.
+class UntypedBaseMatcher {
+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;
+  }
+
+  /// Returns a unique ID for the matcher.
+  virtual uint64_t GetID() const = 0;
+};
+
+/// 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;
+  /// 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);
+  }
+
+  /// Implements UntypedBaseMatcher::GetID.
+  virtual uint64_t GetID() const {
+    return InnerMatcher.GetID();
+  }
+
+private:
+  Matcher<T> InnerMatcher;
+};
+
+/// FIXME: Find a better name.
+///
+/// Interface that allows matchers to traverse the AST.
+/// 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:
+  /// 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
+  };
+
+  /// 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() {}
+
+  /// 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,
+                                  const std::string &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;
+};
+
+/// 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;
+};
+
+/// 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;
+};
+
+/// 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: True().
+///
+/// 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:
+///   Class()
+/// and
+///   Class(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;
+  }
+};
+
+/// 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;
+};
+
+/// 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));
+}
+
+/// 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:
+  /// Creates an IdMatcher that binds to 'ID' if 'InnerMatcher' matches the
+  /// node.
+  IdMatcher(const std::string &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;
+};
+
+/// 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;
+};
+
+/// 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;
+};
+
+/// 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;
+};
+
+/// 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;
+};
+
+/// 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(
+    const Matcher<InnerT> *const InnerMatchers[], int Count) {
+  if (Count == 0) {
+    return ArgumentAdaptingMatcher<DynCastMatcher, InnerT>(
+        MakeMatcher(new TrueMatcher<InnerT>));
+  }
+  Matcher<InnerT> InnerMatcher = *InnerMatchers[Count-1];
+  for (int I = Count-2; I >= 0; --I) {
+    InnerMatcher = MakeMatcher(
+        new AllOfMatcher<InnerT, Matcher<InnerT>, Matcher<InnerT> >(
+            *InnerMatchers[I], InnerMatcher));
+  }
+  return ArgumentAdaptingMatcher<DynCastMatcher, InnerT>(InnerMatcher);
+}
+
+/// 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;
+};
+
+/// 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();
+  }
+};
+
+/// 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();
+  }
+};
+
+/// 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> Class;
+/// Creates a functor Class(...) 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/branches/tooling/include/clang/ASTMatchers/ASTMatchersMacros.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/include/clang/ASTMatchers/ASTMatchersMacros.h?rev=146652&view=auto
==============================================================================
--- cfe/branches/tooling/include/clang/ASTMatchers/ASTMatchersMacros.h (added)
+++ cfe/branches/tooling/include/clang/ASTMatchers/ASTMatchersMacros.h Thu Dec 15 05:51:04 2011
@@ -0,0 +1,210 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
+#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
+
+/// 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
+
+/// 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
+
+/// 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
+
+/// 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
+
+/// 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/branches/tooling/include/clang/Tooling/Refactoring.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/include/clang/Tooling/Refactoring.h?rev=146652&view=auto
==============================================================================
--- cfe/branches/tooling/include/clang/Tooling/Refactoring.h (added)
+++ cfe/branches/tooling/include/clang/Tooling/Refactoring.h Thu Dec 15 05:51:04 2011
@@ -0,0 +1,138 @@
+//===--- Refactoring.h - Framework for clang refactoring tools --*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  Interfaces supporting refactorings that span multiple translation units.
+//  While single translation unit refactorings are supported via the Rewriter,
+//  when refactoring multiple translation units changes must be stored in a
+//  SourceManager independent form, duplicate changes need to be removed, and
+//  all changes must be applied at once at the end of the refactoring so that
+//  the code is always parseable.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/StringRef.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Tooling/Tooling.h"
+#include <set>
+#include <string>
+
+namespace clang {
+
+class Rewriter;
+class SourceLocation;
+
+namespace tooling {
+
+/// \brief A text replacement.
+///
+/// Represents a SourceManager independent replacement of a range of text in a
+/// specific file.
+class Replacement {
+public:
+  /// \brief Creates a replacement of the range [Offset, Offset+Length) in
+  /// FilePath with ReplacementText.
+  ///
+  /// \param FilePath A source file accessible via a SourceManager.
+  /// \param Offset The byte offset of the start of the range in the file.
+  /// \param Length The length of the range in bytes.
+  Replacement(llvm::StringRef FilePath, unsigned Offset,
+              unsigned Length, llvm::StringRef ReplacementText);
+
+  /// \brief Creates a Replacement of the range [Start, Start+Length) with
+  /// ReplacementText.
+  Replacement(SourceManager &Sources, SourceLocation Start, unsigned Length,
+              llvm::StringRef ReplacementText);
+
+  /// \brief Creates a Replacement of the given range with ReplacementText.
+  Replacement(SourceManager &Sources, const CharSourceRange &Range,
+              llvm::StringRef ReplacementText);
+
+  /// \brief Creates a Replacement of the node with ReplacementText.
+  template <typename Node>
+  Replacement(SourceManager &Sources, const Node &NodeToReplace,
+              llvm::StringRef ReplacementText);
+
+  /// \brief Applies the replacement on the Rewriter.
+  bool Apply(Rewriter &Rewrite) const;
+
+  /// \brief Comparator to be able to use Replacement in std::set for uniquing.
+  class Less {
+  public:
+    bool operator()(const Replacement &R1, const Replacement &R2) const;
+  };
+
+ private:
+  void SetFromSourceLocation(SourceManager &Sources, SourceLocation Start, 
+                             unsigned Length, llvm::StringRef ReplacementText);
+  void SetFromSourceRange(SourceManager &Sources, const CharSourceRange &Range,
+                          llvm::StringRef ReplacementText);
+
+  std::string FilePath;
+  unsigned Offset;
+  unsigned Length;
+  std::string ReplacementText;
+};
+
+/// \brief A set of Replacements.
+/// FIXME: Change to a vector and deduplicate in the RefactoringTool.
+typedef std::set<Replacement, Replacement::Less> Replacements;
+
+/// \brief Apply all replacements on the Rewriter.
+///
+/// If at least one Apply returns false, ApplyAll returns false. Every
+/// Apply will be executed independently of the result of the result of
+/// other Apply operations.
+bool ApplyAllReplacements(Replacements &Replaces, Rewriter &Rewrite);
+
+/// \brief Saves all changed files in the Rewriter to disk.
+///
+/// \returns True On Success.
+/// FIXME: Put into Rewriter.
+bool SaveRewrittenFiles(Rewriter &Rewrite);
+
+/// \brief A tool to run refactorings.
+///
+/// This is a refactoring specific version of \see ClangTool.
+/// All text replacements added to GetReplacements() during the run of the
+/// tool will be applied and saved after all translation units have been
+/// processed.
+/// FIXME: Figure out the correct relationship to ClangTool.
+class RefactoringTool {
+public:
+  /// \see ClangTool::ClangTool.
+  RefactoringTool(int argc, char **argv);
+
+  /// \brief Returns a set of replacements. All replacements added during the
+  /// run of the tool will be applied after all translation units have been
+  /// processed.
+  Replacements &GetReplacements();
+
+  /// \see ClangTool::Run.
+  int Run(FrontendActionFactory *ActionFactory);
+
+private:
+  ClangTool Tool;
+  Replacements Replace;
+};
+
+/// \brief Returns the length of the given range.
+///
+/// FIXME: Put into  SourceManager.
+int getRangeSize(SourceManager &Sources, const CharSourceRange &Range);
+
+template <typename Node>
+Replacement::Replacement(SourceManager &Sources, const Node &NodeToReplace,
+                         llvm::StringRef ReplacementText) {
+  const CharSourceRange Range =
+      CharSourceRange::getTokenRange(NodeToReplace->getSourceRange());
+  SetFromSourceRange(Sources, Range, ReplacementText);
+}
+
+} // end namespace tooling
+} // end namespace clang

Added: cfe/branches/tooling/include/clang/Tooling/Tooling.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/include/clang/Tooling/Tooling.h?rev=146652&view=auto
==============================================================================
--- cfe/branches/tooling/include/clang/Tooling/Tooling.h (added)
+++ cfe/branches/tooling/include/clang/Tooling/Tooling.h Thu Dec 15 05:51:04 2011
@@ -0,0 +1,272 @@
+//===--- Tooling.h - Framework for standalone Clang tools -------*- 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 functions to run clang tools standalone instead
+//  of running them as a plugin.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_TOOLING_H
+#define LLVM_CLANG_TOOLING_TOOLING_H
+
+#include "clang/Basic/FileManager.h"
+#include "clang/Driver/Util.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include <map>
+#include <string>
+#include <vector>
+
+namespace clang {
+
+namespace driver {
+class Compilation;
+} // end namespace driver
+
+class CompilerInvocation;
+class SourceManager;
+class FrontendAction;
+
+namespace tooling {
+
+/// Interface to generate clang::FrontendActions.
+class FrontendActionFactory {
+public:
+  virtual ~FrontendActionFactory();
+
+  /// Returns a new clang::FrontendAction. The caller takes ownership of the
+  /// returned action.
+  virtual clang::FrontendAction *New() = 0;
+};
+
+/// \brief Returns a new FrontendActionFactory for a given type.
+///
+/// T must extend clang::FrontendAction.
+///
+/// Example:
+/// FrontendActionFactory *Factory =
+///   NewFrontendActionFactor<clang::SyntaxOnlyAction>();
+template <typename T>
+FrontendActionFactory *NewFrontendActionFactory();
+
+/// \brief Returns a new FrontendActionFactory any type that provides an
+/// implementation of NewFrontendAction().
+///
+/// FactoryT must implement: FrontendAction *NewFrontendAction().
+///
+/// Example:
+/// struct ProvidesFrontendActions {
+///   FrontendActionFactory *NewFrontendAction();
+/// } Factory;
+/// FrontendActionFactory *FactoryAdapter =
+///   NewFrontendActionFactor(&Factory);
+template <typename FactoryT>
+FrontendActionFactory *NewFrontendActionFactory(FactoryT *ActionFactory);
+
+/// \brief Runs (and deletes) the tool on 'Code' with the -fsynatx-only flag.
+///
+/// \param ToolAction The action to run over the code.
+/// \param Code C++ code.
+///
+/// \return - True if 'ToolAction' was successfully executed.
+bool RunSyntaxOnlyToolOnCode(
+    clang::FrontendAction *ToolAction, llvm::StringRef Code);
+
+/// \brief Converts a vector<string> into a vector<char*> suitable to pass
+/// to main-style functions taking (int Argc, char *Argv[]).
+std::vector<char*> CommandLineToArgv(const std::vector<std::string> *Command);
+
+/// \brief Specifies the working directory and command of a compilation.
+struct CompileCommand {
+  /// \brief The working directory the command was executed from.
+  std::string Directory;
+
+  /// \brief The command line that was executed.
+  std::vector<std::string> CommandLine;
+};
+
+/// \brief Converts a JSON escaped command line to a vector of arguments.
+///
+/// \param JsonEscapedCommandLine The escaped command line as a string. This
+/// is assumed to be escaped as a JSON string (e.g. " and \ are escaped).
+/// In addition, any arguments containing spaces are assumed to be \-escaped.
+///
+/// For example, the input (|| denoting non C-escaped strings):
+///   |./call  a  \"b \\\" c \\\\ \"  d|
+/// would yield:
+///   [ |./call|, |a|, |b " c \ |, |d| ].
+std::vector<std::string> UnescapeJsonCommandLine(
+    llvm::StringRef JsonEscapedCommandLine);
+
+/// \brief Looks up the compile command for 'FileName' in 'JsonDatabase'.
+///
+/// \param FileName The path to an input file for which we want the compile
+/// command line. If the 'JsonDatabase' was created by CMake, this must be
+/// an absolute path inside the CMake source directory which does not have
+/// symlinks resolved.
+///
+/// \param JsonDatabase A JSON formatted list of compile commands. This lookup
+/// command supports only a subset of the JSON standard as written by CMake.
+///
+/// \param ErrorMessage If non-empty, an error occurred and 'ErrorMessage' will
+/// be set to contain the error message. In this case CompileCommand will
+/// contain an empty directory and command line.
+///
+/// \see JsonCompileCommandLineDatabase
+CompileCommand FindCompileArgsInJsonDatabase(
+    llvm::StringRef FileName, llvm::StringRef JsonDatabase,
+    std::string &ErrorMessage);
+
+/// \brief Utility to run a FrontendAction in a single clang invocation.
+class ToolInvocation {
+ public:
+  /// \brief Create a tool invocation.
+  ///
+  /// \param CommandLine The command line arguments to clang.
+  /// \param ToolAction The action to be executed. Class takes ownership.
+  /// \param Files The FileManager used for the execution. Class does not take
+  /// ownership.
+  ToolInvocation(
+      llvm::ArrayRef<std::string> CommandLine, FrontendAction *ToolAction,
+      FileManager *Files);
+
+  /// \brief Map virtual files to be used while running the tool.
+  ///
+  /// \param FileContents A map from file names to the file content of the
+  /// mapped virtual files.
+  void MapVirtualFiles(const std::map<std::string, std::string> &FileContents);
+
+  /// \brief Run the clang invocation.
+  ///
+  /// \returns True if there were no errors during execution.
+  bool Run();
+
+ private:
+  void AddFileMappingsTo(SourceManager &SourceManager);
+
+  bool RunInvocation(
+      const char *BinaryName,
+      clang::driver::Compilation *Compilation,
+      clang::CompilerInvocation *Invocation,
+      const clang::driver::ArgStringList &CC1Args,
+      clang::FrontendAction *ToolAction);
+
+  std::vector<std::string> CommandLine;
+  llvm::OwningPtr<FrontendAction> ToolAction;
+  FileManager *Files;
+  // Maps <file name> -> <file content>.
+  std::map<std::string, std::string> MappedFileContents;
+};
+
+/// \brief Utility to run a FrontendAction over a set of files.
+///
+/// This class is written to be usable for command line utilities.
+class ClangTool {
+ public:
+  /// \brief Construct a clang tool from a command line.
+  ///
+  /// This will parse the command line parameters and print an error message
+  /// and exit the program if the command line does not specify the required
+  /// parameters.
+  ///
+  /// Usage:
+  /// $ tool-name <cmake-output-dir> <file1> <file2> ...
+  ///
+  /// where <cmake-output-dir> is a CMake build directory in which a file named
+  /// compile_commands.json exists (enable -DCMAKE_EXPORT_COMPILE_COMMANDS in
+  /// CMake to get this output).
+  ///
+  /// <file1> ... specify the paths of files in the CMake source tree. This
+  /// path is looked up in the compile command database. If the path of a file
+  /// is absolute, it needs to point into CMake's source tree. If the path is
+  /// relative, the current working directory needs to be in the CMake source
+  /// tree and the file must be in a subdirectory of the current working
+  /// directory. "./" prefixes in the relative files will be automatically
+  /// removed, but the rest of a relative path must be a suffix of a path in
+  /// the compile command line database.
+  ///
+  /// For example, to use a tool on all files in a subtree of the source
+  /// tree, use:
+  ///
+  ///   /path/in/subtree $ find . -name '*.cpp' |
+  ///       xargs tool-name /path/to/source
+  ///
+  /// \param argc The argc argument from main.
+  /// \param argv The argv argument from main.
+  ClangTool(int argc, char **argv);
+
+  /// \brief Map virtual files to be used while running the tool.
+  ///
+  /// \param FileContents A map from file names to the file content of the
+  /// mapped virtual files.
+  void MapVirtualFiles(const std::map<std::string, std::string> &FileContents);
+
+  /// Runs a frontend action over all files specified in the command line.
+  ///
+  /// \param ActionFactory Factory generating the frontend actions. The function
+  /// takes ownership of this parameter. A new action is generated for every
+  /// processed translation unit.
+  int Run(FrontendActionFactory *ActionFactory);
+
+  /// \brief Returns the file manager used in the tool.
+  ///
+  /// The file manager is shared between all translation units.
+  FileManager &GetFiles() { return Files; }
+
+ private:
+  /// \brief Add translation units to run the tool over.
+  ///
+  /// Translation units not found in JsonDatabaseDirectory (see constructore)
+  /// will be skipped.
+  void AddTranslationUnits(
+      llvm::StringRef JsonDatabaseDirectory,
+      llvm::ArrayRef<std::string> TranslationUnits);
+
+  // We store command lines as pair (file name, command line).
+  typedef std::pair< std::string, std::vector<std::string> > CommandLine;
+  std::vector<CommandLine> CommandLines;
+
+  FileManager Files;
+  // Maps <file name> -> <file content>.
+  std::map<std::string, std::string> MappedFileContents;
+};
+
+template <typename T>
+FrontendActionFactory *NewFrontendActionFactory() {
+  class SimpleFrontendActionFactory : public FrontendActionFactory {
+  public:
+    virtual clang::FrontendAction *New() { return new T; }
+  };
+
+  return new SimpleFrontendActionFactory;
+}
+
+template <typename FactoryT>
+FrontendActionFactory *NewFrontendActionFactory(FactoryT *ActionFactory) {
+  class FrontendActionFactoryAdapter : public FrontendActionFactory {
+  public:
+    explicit FrontendActionFactoryAdapter(FactoryT *ActionFactory)
+      : ActionFactory(ActionFactory) {}
+
+    virtual clang::FrontendAction *New() {
+      return ActionFactory->NewFrontendAction();
+    }
+
+  private:
+    FactoryT *ActionFactory;
+  };
+
+  return new FrontendActionFactoryAdapter(ActionFactory);
+}
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_TOOLING_H
+

Added: cfe/branches/tooling/lib/ASTMatchers/ASTMatchFinder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/ASTMatchers/ASTMatchFinder.cpp?rev=146652&view=auto
==============================================================================
--- cfe/branches/tooling/lib/ASTMatchers/ASTMatchFinder.cpp (added)
+++ cfe/branches/tooling/lib/ASTMatchers/ASTMatchFinder.cpp Thu Dec 15 05:51:04 2011
@@ -0,0 +1,594 @@
+//===--- 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/RecursiveASTVisitor.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendAction.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; }
+
+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,
+                  clang::SourceManager *VisitorSourceManager,
+                  clang::LangOptions *LanguageOptions)
+     : Triggers(Triggers),
+       VisitorSourceManager(VisitorSourceManager),
+       LanguageOptions(LanguageOptions),
+       ActiveASTContext(NULL) {
+    assert(VisitorSourceManager != NULL);
+    assert(LanguageOptions != NULL);
+    // FIXME: add rewriter_(*source_manager, *language_options)
+  }
+
+  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,
+                                  const std::string &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; }
+
+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,
+                 clang::SourceManager* Sources,
+                 MatchFinder::MatchCallback* Callback)
+      : Context(Context), Sources(Sources),
+        Callback(Callback) {}
+
+    virtual void VisitMatch(const BoundNodes& BoundNodesView) {
+      Callback->Run(MatchFinder::MatchResult(BoundNodesView, Context, Sources));
+    }
+
+  private:
+    clang::ASTContext* Context;
+    clang::SourceManager* Sources;
+    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,
+                    const std::string &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, VisitorSourceManager,
+                             It->second);
+        BoundNodes.VisitMatches(&Visitor);
+      }
+    }
+  }
+
+  std::vector< std::pair<const UntypedBaseMatcher*,
+               MatchFinder::MatchCallback*> > *const Triggers;
+  clang::SourceManager *const VisitorSourceManager;
+  clang::LangOptions *const LanguageOptions;
+  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,
+                                    const std::string &BaseName) const {
+  if (std::string(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,
+                   clang::SourceManager *ConsumerSourceManager,
+                   clang::LangOptions *LanaguageOptions)
+      : Visitor(Triggers, ConsumerSourceManager, LanaguageOptions),
+        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;
+};
+
+class MatchASTAction : public clang::ASTFrontendAction {
+ public:
+  explicit MatchASTAction(
+      std::vector< std::pair<const UntypedBaseMatcher*,
+                   MatchFinder::MatchCallback*> > *Triggers,
+      MatchFinder::ParsingDoneTestCallback *ParsingDone)
+      : Triggers(Triggers),
+        ParsingDone(ParsingDone) {}
+
+ private:
+  clang::ASTConsumer *CreateASTConsumer(
+      clang::CompilerInstance &Compiler,
+      llvm::StringRef) {
+    return new MatchASTConsumer(Triggers,
+                                ParsingDone,
+                                &Compiler.getSourceManager(),
+                                &Compiler.getLangOpts());
+  }
+
+  std::vector< std::pair<const UntypedBaseMatcher*,
+               MatchFinder::MatchCallback*> > *const Triggers;
+  MatchFinder::ParsingDoneTestCallback *ParsingDone;
+};
+
+} // end namespace
+} // end namespace internal
+
+MatchFinder::MatchResult::MatchResult(const BoundNodes &Nodes,
+                                      clang::ASTContext *Context,
+                                      clang::SourceManager *SourceManager)
+  : Nodes(Nodes), Context(Context), SourceManager(SourceManager) {}
+
+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;
+    delete It->second;
+  }
+}
+
+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::FrontendAction *MatchFinder::NewFrontendAction() {
+  return new internal::MatchASTAction(&Triggers, ParsingDone);
+}
+
+void MatchFinder::RegisterTestCallbackAfterParsing(
+    MatchFinder::ParsingDoneTestCallback *NewParsingDone) {
+  ParsingDone = NewParsingDone;
+}
+
+} // end namespace ast_matchers
+} // end namespace clang

Added: cfe/branches/tooling/lib/ASTMatchers/ASTMatchersInternal.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/ASTMatchers/ASTMatchersInternal.cpp?rev=146652&view=auto
==============================================================================
--- cfe/branches/tooling/lib/ASTMatchers/ASTMatchersInternal.cpp (added)
+++ cfe/branches/tooling/lib/ASTMatchers/ASTMatchersInternal.cpp Thu Dec 15 05:51:04 2011
@@ -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/branches/tooling/lib/ASTMatchers/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/ASTMatchers/CMakeLists.txt?rev=146652&view=auto
==============================================================================
--- cfe/branches/tooling/lib/ASTMatchers/CMakeLists.txt (added)
+++ cfe/branches/tooling/lib/ASTMatchers/CMakeLists.txt Thu Dec 15 05:51:04 2011
@@ -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/branches/tooling/lib/ASTMatchers/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/ASTMatchers/Makefile?rev=146652&view=auto
==============================================================================
--- cfe/branches/tooling/lib/ASTMatchers/Makefile (added)
+++ cfe/branches/tooling/lib/ASTMatchers/Makefile Thu Dec 15 05:51:04 2011
@@ -0,0 +1,13 @@
+##===- 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
+
+include $(CLANG_LEVEL)/Makefile

Modified: cfe/branches/tooling/lib/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/CMakeLists.txt?rev=146652&r1=146651&r2=146652&view=diff
==============================================================================
--- cfe/branches/tooling/lib/CMakeLists.txt (original)
+++ cfe/branches/tooling/lib/CMakeLists.txt Thu Dec 15 05:51:04 2011
@@ -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)
@@ -12,5 +13,6 @@
 add_subdirectory(Serialization)
 add_subdirectory(Frontend)
 add_subdirectory(FrontendTool)
+add_subdirectory(Tooling)
 add_subdirectory(Index)
 add_subdirectory(StaticAnalyzer)

Modified: cfe/branches/tooling/lib/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Makefile?rev=146652&r1=146651&r2=146652&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Makefile (original)
+++ cfe/branches/tooling/lib/Makefile Thu Dec 15 05:51:04 2011
@@ -8,9 +8,9 @@
 ##===----------------------------------------------------------------------===##
 CLANG_LEVEL := ..
 
-PARALLEL_DIRS = Headers Basic Lex Parse AST Sema CodeGen Analysis \
+PARALLEL_DIRS = Headers Basic Lex Parse AST ASTMatchers Sema CodeGen Analysis \
                 StaticAnalyzer Rewrite ARCMigrate Serialization Frontend \
-                FrontendTool Index Driver
+                FrontendTool Tooling Index Driver
 
 include $(CLANG_LEVEL)/Makefile
 

Added: cfe/branches/tooling/lib/Tooling/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Tooling/CMakeLists.txt?rev=146652&view=auto
==============================================================================
--- cfe/branches/tooling/lib/Tooling/CMakeLists.txt (added)
+++ cfe/branches/tooling/lib/Tooling/CMakeLists.txt Thu Dec 15 05:51:04 2011
@@ -0,0 +1,8 @@
+set(LLVM_LINK_COMPONENTS support)
+SET(LLVM_USED_LIBS clangBasic clangFrontend clangAST clangASTMatchers
+                   clangRewrite)
+
+add_clang_library(clangTooling
+  Refactoring.cpp
+  Tooling.cpp
+  )

Added: cfe/branches/tooling/lib/Tooling/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Tooling/Makefile?rev=146652&view=auto
==============================================================================
--- cfe/branches/tooling/lib/Tooling/Makefile (added)
+++ cfe/branches/tooling/lib/Tooling/Makefile Thu Dec 15 05:51:04 2011
@@ -0,0 +1,13 @@
+##===- clang/lib/Tooling/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 := clangTooling
+
+include $(CLANG_LEVEL)/Makefile

Added: cfe/branches/tooling/lib/Tooling/Refactoring.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Tooling/Refactoring.cpp?rev=146652&view=auto
==============================================================================
--- cfe/branches/tooling/lib/Tooling/Refactoring.cpp (added)
+++ cfe/branches/tooling/lib/Tooling/Refactoring.cpp Thu Dec 15 05:51:04 2011
@@ -0,0 +1,162 @@
+//===--- Refactoring.cpp - Framework for clang refactoring tools ----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  Implements tools to support refactorings.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/DiagnosticOptions.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Rewrite/Rewriter.h"
+#include "clang/Tooling/Refactoring.h"
+#include "llvm/Support/raw_os_ostream.h"
+
+namespace clang {
+namespace tooling {
+
+Replacement::Replacement(llvm::StringRef FilePath, unsigned Offset,
+                         unsigned Length, llvm::StringRef ReplacementText)
+    : FilePath(FilePath), Offset(Offset),
+      Length(Length), ReplacementText(ReplacementText) {}
+
+Replacement::Replacement(SourceManager &Sources, SourceLocation Start,
+                         unsigned Length, llvm::StringRef ReplacementText) {
+  SetFromSourceLocation(Sources, Start, Length, ReplacementText);
+}
+
+Replacement::Replacement(SourceManager &Sources, const CharSourceRange &Range,
+                         llvm::StringRef ReplacementText) {
+  SetFromSourceRange(Sources, Range, ReplacementText);
+}
+
+bool Replacement::Apply(Rewriter &Rewrite) const {
+  SourceManager &SM = Rewrite.getSourceMgr();
+  const FileEntry *Entry = SM.getFileManager().getFile(FilePath);
+  if (Entry == NULL)
+    return false;
+  FileID ID;
+  // FIXME: Use SM.translateFile directly.
+  SourceLocation Location = SM.translateFileLineCol(Entry, 1, 1);
+  ID = Location.isValid() ?
+    SM.getFileID(Location) :
+    SM.createFileID(Entry, SourceLocation(), SrcMgr::C_User);
+  // FIXME: We cannot check whether Offset + Length is in the file, as
+  // the remapping API is not public in the RewriteBuffer.
+  const SourceLocation Start =
+    SM.getLocForStartOfFile(ID).
+    getLocWithOffset(Offset);
+  // ReplaceText returns false on success.
+  // ReplaceText only fails if the source location is not a file location, in
+  // which case we already returned false earlier.
+  bool RewriteSucceeded = !Rewrite.ReplaceText(Start, Length, ReplacementText);
+  assert(RewriteSucceeded);
+  return RewriteSucceeded;
+}
+
+bool Replacement::Less::operator()(const Replacement &R1,
+                                   const Replacement &R2) const {
+  if (R1.FilePath != R2.FilePath) return R1.FilePath < R2.FilePath;
+  if (R1.Offset != R2.Offset) return R1.Offset < R2.Offset;
+  if (R1.Length != R2.Length) return R1.Length < R2.Length;
+  return R1.ReplacementText < R2.ReplacementText;
+}
+
+void Replacement::SetFromSourceLocation(SourceManager &Sources,
+                                        SourceLocation Start, unsigned Length,
+                                        llvm::StringRef ReplacementText) {
+  const std::pair<FileID, unsigned> DecomposedLocation =
+      Sources.getDecomposedLoc(Start);
+  const FileEntry *Entry = Sources.getFileEntryForID(DecomposedLocation.first);
+  this->FilePath = Entry != NULL ? Entry->getName() : "invalid-location";
+  this->Offset = DecomposedLocation.second;
+  this->Length = Length;
+  this->ReplacementText = ReplacementText;
+}
+
+void Replacement::SetFromSourceRange(SourceManager &Sources,
+                                     const CharSourceRange &Range,
+                                     llvm::StringRef ReplacementText) {
+  SetFromSourceLocation(Sources, Range.getBegin(),
+                        getRangeSize(Sources, Range), ReplacementText);
+}
+
+bool ApplyAllReplacements(Replacements &Replaces, Rewriter &Rewrite) {
+  bool Result = true;
+  for (Replacements::const_iterator I = Replaces.begin(),
+                                    E = Replaces.end();
+       I != E; ++I) {
+    Result = I->Apply(Rewrite) && Result;
+  }
+  return Result;
+}
+
+bool SaveRewrittenFiles(Rewriter &Rewrite) {
+  for (Rewriter::buffer_iterator I = Rewrite.buffer_begin(),
+                                 E = Rewrite.buffer_end();
+       I != E; ++I) {
+    // FIXME: This code is copied from the FixItRewriter.cpp - I think it should
+    // go into directly into Rewriter (there we also have the Diagnostics to
+    // handle the error cases better).
+    const FileEntry *Entry =
+        Rewrite.getSourceMgr().getFileEntryForID(I->first);
+    std::string ErrorInfo;
+    llvm::raw_fd_ostream FileStream(
+        Entry->getName(), ErrorInfo, llvm::raw_fd_ostream::F_Binary);
+    if (!ErrorInfo.empty())
+      return false;
+    I->second.write(FileStream);
+    FileStream.flush();
+  }
+  return true;
+}
+
+int getRangeSize(SourceManager &Sources, const CharSourceRange &Range) {
+  std::pair<FileID, unsigned> Start =
+      Sources.getDecomposedLoc(Range.getBegin());
+  std::pair<FileID, unsigned> End =
+      Sources.getDecomposedLoc(Range.getEnd());
+  if (Start.first != End.first) return -1;
+  if (Range.isTokenRange())
+    // FIXME: Bring in the correct LangOptions.
+    End.second += Lexer::MeasureTokenLength(Range.getEnd(), Sources,
+                                            LangOptions());
+  return End.second - Start.second;
+}
+
+RefactoringTool::RefactoringTool(int argc, char **argv) : Tool(argc, argv) {}
+
+Replacements &RefactoringTool::GetReplacements() { return Replace; }
+
+int RefactoringTool::Run(FrontendActionFactory *ActionFactory) {
+  int Result = Tool.Run(ActionFactory);
+  LangOptions DefaultLangOptions;
+  DiagnosticOptions DefaultDiagnosticOptions;
+  TextDiagnosticPrinter DiagnosticPrinter(llvm::errs(),
+                                          DefaultDiagnosticOptions);
+  DiagnosticsEngine Diagnostics(
+      llvm::IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()),
+      &DiagnosticPrinter, false);
+  SourceManager Sources(Diagnostics, Tool.GetFiles());
+  Rewriter Rewrite(Sources, DefaultLangOptions);
+  if (!ApplyAllReplacements(Replace, Rewrite)) {
+    llvm::errs() << "Could not apply replacements.\n";
+    return 1;
+  }
+  if (!SaveRewrittenFiles(Rewrite)) {
+    llvm::errs() << "Could not save rewritten files.\n";
+    return 1;
+  }
+  return Result;
+}
+
+} // end namespace tooling
+} // end namespace clang

Added: cfe/branches/tooling/lib/Tooling/Tooling.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Tooling/Tooling.cpp?rev=146652&view=auto
==============================================================================
--- cfe/branches/tooling/lib/Tooling/Tooling.cpp (added)
+++ cfe/branches/tooling/lib/Tooling/Tooling.cpp Thu Dec 15 05:51:04 2011
@@ -0,0 +1,481 @@
+//===--- Tooling.cpp - Running clang standalone tools ---------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements functions to run clang tools standalone instead
+//  of running them as a plugin.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/JSONParser.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/system_error.h"
+#include "clang/Basic/DiagnosticIDs.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/Tool.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include <map>
+#include <cstdio>
+
+namespace clang {
+namespace tooling {
+
+FrontendActionFactory::~FrontendActionFactory() {}
+
+// FIXME: This file contains structural duplication with other parts of the
+// code that sets up a compiler to run tools on it, and we should refactor
+// it to be based on the same framework.
+
+// Exists solely for the purpose of lookup of the main executable.
+static int StaticSymbol;
+
+/// \brief Builds a clang driver initialized for running clang tools.
+static clang::driver::Driver *NewDriver(clang::DiagnosticsEngine *Diagnostics,
+                                        const char *BinaryName) {
+  // This just needs to be some symbol in the binary.
+  void *const SymbolAddr = &StaticSymbol;
+  const llvm::sys::Path ExePath =
+      llvm::sys::Path::GetMainExecutable(BinaryName, SymbolAddr);
+
+  const std::string DefaultOutputName = "a.out";
+  clang::driver::Driver *CompilerDriver = new clang::driver::Driver(
+      ExePath.str(), llvm::sys::getDefaultTargetTriple(),
+      DefaultOutputName, false, *Diagnostics);
+  CompilerDriver->setTitle("clang_based_tool");
+  return CompilerDriver;
+}
+
+/// \brief Retrieves the clang CC1 specific flags out of the compilation's jobs.
+/// Returns NULL on error.
+static const clang::driver::ArgStringList *GetCC1Arguments(
+    clang::DiagnosticsEngine *Diagnostics,
+    clang::driver::Compilation *Compilation) {
+  // We expect to get back exactly one Command job, if we didn't something
+  // failed. Extract that job from the Compilation.
+  const clang::driver::JobList &Jobs = Compilation->getJobs();
+  if (Jobs.size() != 1 || !isa<clang::driver::Command>(*Jobs.begin())) {
+    llvm::SmallString<256> error_msg;
+    llvm::raw_svector_ostream error_stream(error_msg);
+    Compilation->PrintJob(error_stream, Compilation->getJobs(), "; ", true);
+    Diagnostics->Report(clang::diag::err_fe_expected_compiler_job)
+        << error_stream.str();
+    return NULL;
+  }
+
+  // The one job we find should be to invoke clang again.
+  const clang::driver::Command *Cmd =
+      cast<clang::driver::Command>(*Jobs.begin());
+  if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") {
+    Diagnostics->Report(clang::diag::err_fe_expected_clang_command);
+    return NULL;
+  }
+
+  return &Cmd->getArguments();
+}
+
+/// \brief Returns a clang build invocation initialized from the CC1 flags.
+static clang::CompilerInvocation *NewInvocation(
+    clang::DiagnosticsEngine *Diagnostics,
+    const clang::driver::ArgStringList &CC1Args) {
+  clang::CompilerInvocation *Invocation = new clang::CompilerInvocation;
+  clang::CompilerInvocation::CreateFromArgs(
+      *Invocation, CC1Args.data() + 1, CC1Args.data() + CC1Args.size(),
+      *Diagnostics);
+  Invocation->getFrontendOpts().DisableFree = false;
+  return Invocation;
+}
+
+/// \brief Converts a string vector representing a Command line into a C
+/// string vector representing the Argv (including the trailing NULL).
+std::vector<char*> CommandLineToArgv(const std::vector<std::string> *Command) {
+  std::vector<char*> Result(Command->size() + 1);
+  for (std::vector<char*>::size_type I = 0; I < Command->size(); ++I) {
+    Result[I] = const_cast<char*>((*Command)[I].c_str());
+  }
+  Result[Command->size()] = NULL;
+  return Result;
+}
+
+bool RunSyntaxOnlyToolOnCode(
+    clang::FrontendAction *ToolAction, llvm::StringRef Code) {
+  const char *const FileName = "input.cc";
+  const char *const CommandLine[] = {
+      "clang-tool", "-fsyntax-only", FileName
+  };
+  std::map<std::string, std::string> FileContents;
+  FileContents[FileName] = Code;
+
+  FileManager Files((FileSystemOptions()));
+  ToolInvocation Invocation(
+      std::vector<std::string>(
+          CommandLine,
+          CommandLine + sizeof(CommandLine)/sizeof(CommandLine[0])),
+      ToolAction, &Files);
+  Invocation.MapVirtualFiles(FileContents);
+  return Invocation.Run();
+}
+
+namespace {
+
+// A parser for JSON escaped strings of command line arguments with \-escaping
+// for quoted arguments (see the documentation of UnescapeJsonCommandLine(...)).
+class CommandLineArgumentParser {
+ public:
+  CommandLineArgumentParser(llvm::StringRef CommandLine)
+      : Input(CommandLine), Position(Input.begin()-1) {}
+
+  std::vector<std::string> Parse() {
+    bool HasMoreInput = true;
+    while (HasMoreInput && nextNonWhitespace()) {
+      std::string Argument;
+      HasMoreInput = ParseStringInto(Argument);
+      CommandLine.push_back(Argument);
+    }
+    return CommandLine;
+  }
+
+ private:
+  // All private methods return true if there is more input available.
+
+  bool ParseStringInto(std::string &String) {
+    do {
+      if (*Position == '"') {
+        if (!ParseQuotedStringInto(String)) return false;
+      } else {
+        if (!ParseFreeStringInto(String)) return false;
+      }
+    } while (*Position != ' ');
+    return true;
+  }
+
+  bool ParseQuotedStringInto(std::string &String) {
+    if (!Next()) return false;
+    while (*Position != '"') {
+      if (!SkipEscapeCharacter()) return false;
+      String.push_back(*Position);
+      if (!Next()) return false;
+    }
+    return Next();
+  }
+
+  bool ParseFreeStringInto(std::string &String) {
+    do {
+      if (!SkipEscapeCharacter()) return false;
+      String.push_back(*Position);
+      if (!Next()) return false;
+    } while (*Position != ' ' && *Position != '"');
+    return true;
+  }
+
+  bool SkipEscapeCharacter() {
+    if (*Position == '\\') {
+      return Next();
+    }
+    return true;
+  }
+
+  bool nextNonWhitespace() {
+    do {
+      if (!Next()) return false;
+    } while (*Position == ' ');
+    return true;
+  }
+
+  bool Next() {
+    ++Position;
+    if (Position == Input.end()) return false;
+    // Remove the JSON escaping first. This is done unconditionally.
+    if (*Position == '\\') ++Position;
+    return Position != Input.end();
+  }
+
+  const llvm::StringRef Input;
+  llvm::StringRef::iterator Position;
+  std::vector<std::string> CommandLine;
+};
+
+} // end namespace
+
+std::vector<std::string> UnescapeJsonCommandLine(
+    llvm::StringRef JsonEscapedCommandLine) {
+  CommandLineArgumentParser parser(JsonEscapedCommandLine);
+  return parser.Parse();
+}
+
+CompileCommand FindCompileArgsInJsonDatabase(
+    llvm::StringRef FileName, llvm::StringRef JsonDatabase,
+    std::string &ErrorMessage) {
+  llvm::JSONParser Parser(JsonDatabase);
+  llvm::JSONValue *Root = Parser.parseRoot();
+  if (Root == NULL) {
+    ErrorMessage = Parser.getErrorMessage();
+    return CompileCommand();
+  }
+  llvm::JSONArray *Array = llvm::dyn_cast<llvm::JSONArray>(Root);
+  if (Array == NULL) {
+    ErrorMessage = "Expected array.";
+    return CompileCommand();
+  }
+  for (llvm::JSONArray::const_iterator AI = Array->begin(), AE = Array->end();
+       AI != AE; ++AI) {
+    const llvm::JSONObject *Object = llvm::dyn_cast<llvm::JSONObject>(*AI);
+    if (Object == NULL) {
+      ErrorMessage = "Expected object.";
+      return CompileCommand();
+    }
+    llvm::StringRef EntryDirectory;
+    llvm::StringRef EntryFile;
+    llvm::StringRef EntryCommand;
+    for (llvm::JSONObject::const_iterator KVI = Object->begin(),
+                                          KVE = Object->end();
+         KVI != KVE; ++KVI) {
+      const llvm::JSONValue *Value = (*KVI)->Value;
+      if (Value == NULL) {
+        ErrorMessage = "Expected value.";
+        return CompileCommand();
+      }
+      const llvm::JSONString *ValueString =
+        llvm::dyn_cast<llvm::JSONString>(Value);
+      if (ValueString == NULL) {
+        ErrorMessage = "Expected string as value.";
+        return CompileCommand();
+      }
+      if ((*KVI)->Key->getRawText() == "directory") {
+        EntryDirectory = ValueString->getRawText();
+      } else if ((*KVI)->Key->getRawText() == "file") {
+        EntryFile = ValueString->getRawText();
+      } else if ((*KVI)->Key->getRawText() == "command") {
+        EntryCommand = ValueString->getRawText();
+      } else {
+        ErrorMessage = (llvm::Twine("Unknown key: \"") +
+                        (*KVI)->Key->getRawText() + "\"").str();
+        return CompileCommand();
+      }
+    }
+    if (EntryFile == FileName) {
+      CompileCommand Result;
+      Result.Directory = EntryDirectory;
+      Result.CommandLine = UnescapeJsonCommandLine(EntryCommand);
+      return Result;
+    }
+  }
+  ErrorMessage = "ERROR: No matching command found.";
+  return CompileCommand();
+}
+
+/// \brief Returns the absolute path of 'File', by prepending it with
+/// 'BaseDirectory' if 'File' is not absolute. Otherwise returns 'File'.
+/// If 'File' starts with "./", the returned path will not contain the "./".
+/// Otherwise, the returned path will contain the literal path-concatenation of
+/// 'BaseDirectory' and 'File'.
+///
+/// \param File Either an absolute or relative path.
+/// \param BaseDirectory An absolute path.
+static std::string GetAbsolutePath(
+    llvm::StringRef File, llvm::StringRef BaseDirectory) {
+  assert(llvm::sys::path::is_absolute(BaseDirectory));
+  if (llvm::sys::path::is_absolute(File)) {
+    return File;
+  }
+  llvm::StringRef RelativePath(File);
+  if (RelativePath.startswith("./")) {
+    RelativePath = RelativePath.substr(strlen("./"));
+  }
+  llvm::SmallString<1024> AbsolutePath(BaseDirectory);
+  llvm::sys::path::append(AbsolutePath, RelativePath);
+  return AbsolutePath.str();
+}
+
+ToolInvocation::ToolInvocation(
+    llvm::ArrayRef<std::string> CommandLine, FrontendAction *ToolAction,
+    FileManager *Files)
+    : CommandLine(CommandLine.vec()), ToolAction(ToolAction), Files(Files) {
+}
+
+void ToolInvocation::MapVirtualFiles(
+    const std::map<std::string, std::string> &FileContents) {
+  MappedFileContents.insert(FileContents.begin(), FileContents.end());
+}
+
+bool ToolInvocation::Run() {
+  const std::vector<char*> Argv = CommandLineToArgv(&CommandLine);
+  const char *const BinaryName = Argv[0];
+  DiagnosticOptions DefaultDiagnosticOptions;
+  TextDiagnosticPrinter DiagnosticPrinter(
+      llvm::errs(), DefaultDiagnosticOptions);
+  DiagnosticsEngine Diagnostics(llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs>(
+      new DiagnosticIDs()), &DiagnosticPrinter, false);
+
+  const llvm::OwningPtr<clang::driver::Driver> Driver(
+      NewDriver(&Diagnostics, BinaryName));
+  // Since the input might only be virtual, don't check whether it exists.
+  Driver->setCheckInputsExist(false);
+  const llvm::OwningPtr<clang::driver::Compilation> Compilation(
+      Driver->BuildCompilation(llvm::ArrayRef<const char*>(
+          &Argv[0], Argv.size() - 1)));
+  const clang::driver::ArgStringList *const CC1Args = GetCC1Arguments(
+      &Diagnostics, Compilation.get());
+  if (CC1Args == NULL) {
+    return false;
+  }
+  llvm::OwningPtr<clang::CompilerInvocation> Invocation(
+      NewInvocation(&Diagnostics, *CC1Args));
+  return RunInvocation(BinaryName, Compilation.get(),
+                       Invocation.take(), *CC1Args, ToolAction.take());
+}
+
+bool ToolInvocation::RunInvocation(
+    const char *BinaryName,
+    clang::driver::Compilation *Compilation,
+    clang::CompilerInvocation *Invocation,
+    const clang::driver::ArgStringList &CC1Args,
+    clang::FrontendAction *ToolAction) {
+  llvm::OwningPtr<clang::FrontendAction> ScopedToolAction(ToolAction);
+  // Show the invocation, with -v.
+  if (Invocation->getHeaderSearchOpts().Verbose) {
+    llvm::errs() << "clang Invocation:\n";
+    Compilation->PrintJob(llvm::errs(), Compilation->getJobs(), "\n", true);
+    llvm::errs() << "\n";
+  }
+
+  // Create a compiler instance to handle the actual work.
+  clang::CompilerInstance Compiler;
+  Compiler.setInvocation(Invocation);
+  Compiler.setFileManager(Files);
+  // FIXME: What about LangOpts?
+
+  // Create the compilers actual diagnostics engine.
+  Compiler.createDiagnostics(CC1Args.size(),
+                             const_cast<char**>(CC1Args.data()));
+  if (!Compiler.hasDiagnostics())
+    return false;
+
+  Compiler.createSourceManager(*Files);
+  AddFileMappingsTo(Compiler.getSourceManager());
+
+  // Infer the builtin include path if unspecified.
+  if (Compiler.getHeaderSearchOpts().UseBuiltinIncludes &&
+      Compiler.getHeaderSearchOpts().ResourceDir.empty()) {
+    // This just needs to be some symbol in the binary.
+    void *const SymbolAddr = &StaticSymbol;
+    Compiler.getHeaderSearchOpts().ResourceDir =
+        clang::CompilerInvocation::GetResourcesPath(BinaryName, SymbolAddr);
+  }
+
+  const bool Success = Compiler.ExecuteAction(*ToolAction);
+
+  Compiler.resetAndLeakFileManager();
+  return Success;
+}
+
+void ToolInvocation::AddFileMappingsTo(SourceManager &Sources) {
+  for (std::map<std::string, std::string>::const_iterator
+           It = MappedFileContents.begin(), End = MappedFileContents.end();
+       It != End; ++It) {
+    // Inject the code as the given file name into the preprocessor options.
+    const llvm::MemoryBuffer *Input =
+        llvm::MemoryBuffer::getMemBuffer(It->second.c_str());
+    // FIXME: figure out what '0' stands for.
+    const FileEntry *FromFile = Files->getVirtualFile(
+        It->first, Input->getBufferSize(), 0);
+    // FIXME: figure out memory management ('true').
+    Sources.overrideFileContents(FromFile, Input, true);
+  }
+}
+
+ClangTool::ClangTool(int argc, char **argv)
+    : Files((FileSystemOptions())) {
+  if (argc < 3) {
+    llvm::outs() << "Usage: " << argv[0] << " <cmake-output-dir> "
+                 << "<file1> <file2> ...\n";
+    exit(1);
+  }
+  AddTranslationUnits(argv[1], std::vector<std::string>(argv + 2, argv + argc));
+}
+
+void ClangTool::AddTranslationUnits(
+    llvm::StringRef JsonDatabaseDirectory,
+    llvm::ArrayRef<std::string> TranslationUnits) {
+  llvm::SmallString<1024> JsonDatabasePath(JsonDatabaseDirectory);
+  llvm::sys::path::append(JsonDatabasePath, "compile_commands.json");
+  llvm::OwningPtr<llvm::MemoryBuffer> JsonDatabase;
+  llvm::error_code Result =
+      llvm::MemoryBuffer::getFile(JsonDatabasePath, JsonDatabase);
+  if (Result != 0) {
+    llvm::outs() << "Error while opening JSON database: " << Result.message()
+                 << "\n";
+    exit(1);
+  }
+  llvm::StringRef BaseDirectory(::getenv("PWD"));
+  for (unsigned I = 0; I < TranslationUnits.size(); ++I) {
+    llvm::SmallString<1024> File(GetAbsolutePath(
+        TranslationUnits[I], BaseDirectory));
+    std::string ErrorMessage;
+    clang::tooling::CompileCommand LookupResult =
+        clang::tooling::FindCompileArgsInJsonDatabase(
+            File.str(), JsonDatabase->getBuffer(), ErrorMessage);
+    if (!ErrorMessage.empty()) {
+      llvm::outs() << "Error while parsing JSON database: " << ErrorMessage
+                   << "\n";
+      exit(1);
+    }
+    if (!LookupResult.CommandLine.empty()) {
+      if (!LookupResult.Directory.empty()) {
+        // FIXME: What should happen if CommandLine includes -working-directory
+        // as well?
+        LookupResult.CommandLine.push_back(
+            "-working-directory=" + LookupResult.Directory);
+      }
+      CommandLines.push_back(make_pair(File.str(), LookupResult.CommandLine));
+    } else {
+      // FIXME: There are two use cases here: doing a fuzzy
+      // "find . -name '*.cc' |xargs tool" match, where as a user I don't care
+      // about the .cc files that were not found, and the use case where I
+      // specify all files I want to run over explicitly, where this should
+      // be an error. We'll want to add an option for this.
+      llvm::outs() << "Skipping " << File << ". Command line not found.\n";
+    }
+  }
+}
+
+void ClangTool::MapVirtualFiles(
+    const std::map<std::string, std::string> &FileContents) {
+  MappedFileContents.insert(FileContents.begin(), FileContents.end());
+}
+
+int ClangTool::Run(FrontendActionFactory *ActionFactory) {
+  bool ProcessingFailed = false;
+  for (unsigned I = 0; I < CommandLines.size(); ++I) {
+    std::string File = CommandLines[I].first;
+    std::vector<std::string> &CommandLine = CommandLines[I].second;
+    llvm::outs() << "Processing: " << File << ".\n";
+    ToolInvocation Invocation(CommandLine, ActionFactory->New(), &Files);
+    Invocation.MapVirtualFiles(MappedFileContents);
+    if (!Invocation.Run()) {
+      llvm::outs() << "Error while processing " << File << ".\n";
+      ProcessingFailed = true;
+    }
+  }
+  return ProcessingFailed ? 1 : 0;
+}
+
+} // end namespace tooling
+} // end namespace clang

Modified: cfe/branches/tooling/test/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/test/CMakeLists.txt?rev=146652&r1=146651&r2=146652&view=diff
==============================================================================
--- cfe/branches/tooling/test/CMakeLists.txt (original)
+++ cfe/branches/tooling/test/CMakeLists.txt Thu Dec 15 05:51:04 2011
@@ -112,7 +112,8 @@
 
   add_dependencies(clang-test clang-test.deps)
   add_dependencies(clang-test.deps
-                 clang clang-headers c-index-test diagtool arcmt-test c-arcmt-test
+                 clang clang-headers c-index-test diagtool
+                 arcmt-test c-arcmt-test remove-cstr-calls
                  )
 
 endif()

Added: cfe/branches/tooling/test/Tooling/remove-cstr-calls.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/test/Tooling/remove-cstr-calls.cpp?rev=146652&view=auto
==============================================================================
--- cfe/branches/tooling/test/Tooling/remove-cstr-calls.cpp (added)
+++ cfe/branches/tooling/test/Tooling/remove-cstr-calls.cpp Thu Dec 15 05:51:04 2011
@@ -0,0 +1,38 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo '[{"directory":".","command":"clang++ -c %t/test.cpp","file":"%t/test.cpp"}]' > %t/compile_commands.json
+// RUN: cp "%s" "%t/test.cpp"
+// RUN: remove-cstr-calls "%t" "%t/test.cpp"
+// RUN: cat "%t/test.cpp" | FileCheck %s
+// FIXME: implement a mode for refactoring tools that takes input from stdin
+// and writes output to stdout for easier testing of tools. 
+
+namespace std {
+template<typename T> class allocator {};
+template<typename T> class char_traits {};
+template<typename C, typename T, typename A> struct basic_string {
+  basic_string();
+  basic_string(const C *p, const A& a = A());
+  const C *c_str() const;
+};
+typedef basic_string<char, std::char_traits<char>, std::allocator<char> > string;
+}
+namespace llvm { struct StringRef { StringRef(const char *p); }; }
+
+void f1(const std::string &s) {
+  f1(s.c_str());
+  // CHECK: void f1
+  // CHECK-NEXT: f1(s)
+}
+void f2(const llvm::StringRef r) {
+  std::string s;
+  f2(s.c_str());
+  // CHECK: std::string s; 
+  // CHECK-NEXT: f2(s)
+}
+void f3(const llvm::StringRef &r) {
+  std::string s;
+  f3(s.c_str());
+  // CHECK: std::string s;
+  // CHECK: f3(s)
+}

Modified: cfe/branches/tooling/tools/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/tools/CMakeLists.txt?rev=146652&r1=146651&r2=146652&view=diff
==============================================================================
--- cfe/branches/tooling/tools/CMakeLists.txt (original)
+++ cfe/branches/tooling/tools/CMakeLists.txt Thu Dec 15 05:51:04 2011
@@ -4,3 +4,5 @@
 add_subdirectory(c-arcmt-test)
 add_subdirectory(diagtool)
 add_subdirectory(driver)
+add_subdirectory(clang-check)
+add_subdirectory(remove-cstr-calls)

Modified: cfe/branches/tooling/tools/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/tools/Makefile?rev=146652&r1=146651&r2=146652&view=diff
==============================================================================
--- cfe/branches/tooling/tools/Makefile (original)
+++ cfe/branches/tooling/tools/Makefile Thu Dec 15 05:51:04 2011
@@ -8,7 +8,8 @@
 ##===----------------------------------------------------------------------===##
 
 CLANG_LEVEL := ..
-DIRS := driver libclang c-index-test arcmt-test c-arcmt-test diagtool
+DIRS := driver libclang c-index-test arcmt-test c-arcmt-test diagtool \
+        clang-check remove-cstr-calls
 
 include $(CLANG_LEVEL)/../../Makefile.config
 

Added: cfe/branches/tooling/tools/clang-check/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/tools/clang-check/CMakeLists.txt?rev=146652&view=auto
==============================================================================
--- cfe/branches/tooling/tools/clang-check/CMakeLists.txt (added)
+++ cfe/branches/tooling/tools/clang-check/CMakeLists.txt Thu Dec 15 05:51:04 2011
@@ -0,0 +1,5 @@
+set(LLVM_USED_LIBS clangTooling clangBasic)
+
+add_clang_executable(clang-check
+  ClangCheck.cpp
+  )

Added: cfe/branches/tooling/tools/clang-check/ClangCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/tools/clang-check/ClangCheck.cpp?rev=146652&view=auto
==============================================================================
--- cfe/branches/tooling/tools/clang-check/ClangCheck.cpp (added)
+++ cfe/branches/tooling/tools/clang-check/ClangCheck.cpp Thu Dec 15 05:51:04 2011
@@ -0,0 +1,45 @@
+//===- examples/Tooling/ClangCheck.cpp - Clang check tool -----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements a clang-check tool that runs the
+//  clang::SyntaxOnlyAction over a number of translation units.
+//
+//  Usage:
+//  clang-check <cmake-output-dir> <file1> <file2> ...
+//
+//  Where <cmake-output-dir> is a CMake build directory in which a file named
+//  compile_commands.json exists (enable -DCMAKE_EXPORT_COMPILE_COMMANDS in
+//  CMake to get this output).
+//
+//  <file1> ... specify the paths of files in the CMake source tree. This  path
+//  is looked up in the compile command database. If the path of a file is
+//  absolute, it needs to point into CMake's source tree. If the path is
+//  relative, the current working directory needs to be in the CMake source
+//  tree and the file must be in a subdirectory of the current working
+//  directory. "./" prefixes in the relative files will be automatically
+//  removed, but the rest of a relative path must be a suffix of a path in
+//  the compile command line database.
+//
+//  For example, to use clang-check on all files in a subtree of the source
+//  tree, use:
+//
+//    /path/in/subtree $ find . -name '*.cpp'| xargs clang-check /path/to/source
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Tooling/Tooling.h"
+
+using clang::tooling::ClangTool;
+using clang::tooling::NewFrontendActionFactory;
+
+int main(int argc, char **argv) {
+  ClangTool Tool(argc, argv);
+  return Tool.Run(NewFrontendActionFactory<clang::SyntaxOnlyAction>());
+}

Added: cfe/branches/tooling/tools/clang-check/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/tools/clang-check/Makefile?rev=146652&view=auto
==============================================================================
--- cfe/branches/tooling/tools/clang-check/Makefile (added)
+++ cfe/branches/tooling/tools/clang-check/Makefile Thu Dec 15 05:51:04 2011
@@ -0,0 +1,24 @@
+##===- tools/clang-check/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 := ../..
+
+TOOLNAME = clang-check
+NO_INSTALL = 1
+
+# No plugins, optimize startup time.
+TOOL_NO_EXPORTS = 1
+
+LINK_COMPONENTS := support mc
+USEDLIBS = clangFrontend.a clangSerialization.a clangDriver.a \
+           clangTooling.a clangParse.a clangSema.a clangAnalysis.a \
+           clangAST.a clangLex.a clangBasic.a
+
+include $(CLANG_LEVEL)/Makefile
+

Added: cfe/branches/tooling/tools/remove-cstr-calls/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/tools/remove-cstr-calls/CMakeLists.txt?rev=146652&view=auto
==============================================================================
--- cfe/branches/tooling/tools/remove-cstr-calls/CMakeLists.txt (added)
+++ cfe/branches/tooling/tools/remove-cstr-calls/CMakeLists.txt Thu Dec 15 05:51:04 2011
@@ -0,0 +1,5 @@
+set(LLVM_USED_LIBS clangTooling clangBasic clangAST)
+
+add_clang_executable(remove-cstr-calls
+  RemoveCStrCalls.cpp
+  )

Added: cfe/branches/tooling/tools/remove-cstr-calls/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/tools/remove-cstr-calls/Makefile?rev=146652&view=auto
==============================================================================
--- cfe/branches/tooling/tools/remove-cstr-calls/Makefile (added)
+++ cfe/branches/tooling/tools/remove-cstr-calls/Makefile Thu Dec 15 05:51:04 2011
@@ -0,0 +1,23 @@
+##===- tools/remove-cstr-calls/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 := ../..
+
+TOOLNAME = remove-cstr-calls
+NO_INSTALL = 1
+
+# No plugins, optimize startup time.
+TOOL_NO_EXPORTS = 1
+
+LINK_COMPONENTS := support mc
+USEDLIBS = 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)/Makefile

Added: cfe/branches/tooling/tools/remove-cstr-calls/RemoveCStrCalls.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/tools/remove-cstr-calls/RemoveCStrCalls.cpp?rev=146652&view=auto
==============================================================================
--- cfe/branches/tooling/tools/remove-cstr-calls/RemoveCStrCalls.cpp (added)
+++ cfe/branches/tooling/tools/remove-cstr-calls/RemoveCStrCalls.cpp Thu Dec 15 05:51:04 2011
@@ -0,0 +1,213 @@
+//===- examples/Tooling/RemoveCStrCalls.cpp - Redundant c_str call removal ===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements a tool that prints replacements that remove redundant
+//  calls of c_str() on strings.
+//
+//  Usage:
+//  remove-cstr-calls <cmake-output-dir> <file1> <file2> ...
+//
+//  Where <cmake-output-dir> is a CMake build directory in which a file named
+//  compile_commands.json exists (enable -DCMAKE_EXPORT_COMPILE_COMMANDS in
+//  CMake to get this output).
+//
+//  <file1> ... specify the paths of files in the CMake source tree. This path
+//  is looked up in the compile command database. If the path of a file is
+//  absolute, it needs to point into CMake's source tree. If the path is
+//  relative, the current working directory needs to be in the CMake source
+//  tree and the file must be in a subdirectory of the current working
+//  directory. "./" prefixes in the relative files will be automatically
+//  removed, but the rest of a relative path must be a suffix of a path in
+//  the compile command line database.
+//
+//  For example, to use remove-cstr-calls on all files in a subtree of the
+//  source tree, use:
+//
+//    /path/in/subtree $ find . -name '*.cpp'|
+//        xargs remove-cstr-calls /path/to/build
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/system_error.h"
+
+using namespace clang;
+using namespace clang::ast_matchers;
+using clang::tooling::NewFrontendActionFactory;
+using clang::tooling::Replacement;
+
+// FIXME: Pull out helper methods in here into more fitting places.
+
+// Returns the text that makes up 'node' in the source.
+// Returns an empty string if the text cannot be found.
+template <typename T>
+static std::string GetText(const SourceManager &SourceManager, const T &Node) {
+  SourceLocation StartSpellingLocatino =
+      SourceManager.getSpellingLoc(Node.getLocStart());
+  SourceLocation EndSpellingLocation =
+      SourceManager.getSpellingLoc(Node.getLocEnd());
+  if (!StartSpellingLocatino.isValid() || !EndSpellingLocation.isValid()) {
+    return std::string();
+  }
+  bool Invalid = true;
+  const char *Text =
+      SourceManager.getCharacterData(StartSpellingLocatino, &Invalid);
+  if (Invalid) {
+    return std::string();
+  }
+  std::pair<FileID, unsigned> Start =
+      SourceManager.getDecomposedLoc(StartSpellingLocatino);
+  std::pair<FileID, unsigned> End =
+      SourceManager.getDecomposedLoc(Lexer::getLocForEndOfToken(
+          EndSpellingLocation, 0, SourceManager, LangOptions()));
+  if (Start.first != End.first) {
+    // Start and end are in different files.
+    return std::string();
+  }
+  if (End.second < Start.second) {
+    // Shuffling text with macros may cause this.
+    return std::string();
+  }
+  return std::string(Text, End.second - Start.second);
+}
+
+// Return true if expr needs to be put in parens when it is an
+// argument of a prefix unary operator, e.g. when it is a binary or
+// ternary operator syntactically.
+static bool NeedParensAfterUnaryOperator(const Expr &ExprNode) {
+  if (dyn_cast<clang::BinaryOperator>(&ExprNode) ||
+      dyn_cast<clang::ConditionalOperator>(&ExprNode)) {
+    return true;
+  }
+  if (const CXXOperatorCallExpr *op =
+      dyn_cast<CXXOperatorCallExpr>(&ExprNode)) {
+    return op->getNumArgs() == 2 &&
+        op->getOperator() != OO_PlusPlus &&
+        op->getOperator() != OO_MinusMinus &&
+        op->getOperator() != OO_Call &&
+        op->getOperator() != OO_Subscript;
+  }
+  return false;
+}
+
+// Format a pointer to an expression: prefix with '*' but simplify
+// when it already begins with '&'.  Return empty string on failure.
+static std::string FormatDereference(const SourceManager &SourceManager,
+                              const Expr &ExprNode) {
+  if (const clang::UnaryOperator *Op =
+      dyn_cast<clang::UnaryOperator>(&ExprNode)) {
+    if (Op->getOpcode() == UO_AddrOf) {
+      // Strip leading '&'.
+      return GetText(SourceManager, *Op->getSubExpr()->IgnoreParens());
+    }
+  }
+  const std::string Text = GetText(SourceManager, ExprNode);
+  if (Text.empty()) return std::string();
+  // Add leading '*'.
+  if (NeedParensAfterUnaryOperator(ExprNode)) {
+    return std::string("*(") + Text + ")";
+  }
+  return std::string("*") + Text;
+}
+
+namespace {
+class FixCStrCall : public ast_matchers::MatchFinder::MatchCallback {
+ public:
+  FixCStrCall(tooling::Replacements *Replace)
+      : Replace(Replace) {}
+
+  virtual void Run(const ast_matchers::MatchFinder::MatchResult &Result) {
+    const CallExpr *Call =
+        Result.Nodes.GetStmtAs<CallExpr>("call");
+    const Expr *Arg =
+        Result.Nodes.GetStmtAs<Expr>("arg");
+    const bool Arrow =
+        Result.Nodes.GetStmtAs<MemberExpr>("member")->isArrow();
+    // Replace the "call" node with the "arg" node, prefixed with '*'
+    // if the call was using '->' rather than '.'.
+    const std::string ArgText = Arrow ?
+        FormatDereference(*Result.SourceManager, *Arg) :
+        GetText(*Result.SourceManager, *Arg);
+    if (ArgText.empty()) return;
+
+    Replace->insert(Replacement(*Result.SourceManager, Call, ArgText));
+  }
+
+ private:
+  tooling::Replacements *Replace;
+};
+} // end namespace
+
+const char *StringConstructor =
+    "::std::basic_string<char, std::char_traits<char>, std::allocator<char> >"
+    "::basic_string";
+
+const char *StringCStrMethod =
+    "::std::basic_string<char, std::char_traits<char>, std::allocator<char> >"
+    "::c_str";
+
+int main(int argc, char **argv) {
+  tooling::RefactoringTool Tool(argc, argv);
+  ast_matchers::MatchFinder Finder;
+  Finder.AddMatcher(
+      ConstructorCall(
+          HasDeclaration(Method(HasName(StringConstructor))),
+          ArgumentCountIs(2),
+          // The first argument must have the form x.c_str() or p->c_str()
+          // where the method is string::c_str().  We can use the copy
+          // constructor of string instead (or the compiler might share
+          // the string object).
+          HasArgument(
+              0,
+              Id("call", Call(
+                  Callee(Id("member", MemberExpression())),
+                  Callee(Method(HasName(StringCStrMethod))),
+                  On(Id("arg", Expression()))))),
+          // The second argument is the alloc object which must not be
+          // present explicitly.
+          HasArgument(
+              1,
+              DefaultArgument())),
+      new FixCStrCall(&Tool.GetReplacements()));
+  Finder.AddMatcher(
+      ConstructorCall(
+          // Implicit constructors of these classes are overloaded
+          // wrt. string types and they internally make a StringRef
+          // referring to the argument.  Passing a string directly to
+          // them is preferred to passing a char pointer.
+          HasDeclaration(Method(AnyOf(
+              HasName("::llvm::StringRef::StringRef"),
+              HasName("::llvm::Twine::Twine")))),
+          ArgumentCountIs(1),
+          // The only argument must have the form x.c_str() or p->c_str()
+          // where the method is string::c_str().  StringRef also has
+          // a constructor from string which is more efficient (avoids
+          // strlen), so we can construct StringRef from the string
+          // directly.
+          HasArgument(
+              0,
+              Id("call", Call(
+                  Callee(Id("member", MemberExpression())),
+                  Callee(Method(HasName(StringCStrMethod))),
+                  On(Id("arg", Expression())))))),
+      new FixCStrCall(&Tool.GetReplacements()));
+  return Tool.Run(NewFrontendActionFactory(&Finder));
+}
+

Added: cfe/branches/tooling/unittests/ASTMatchers/ASTMatchersTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/unittests/ASTMatchers/ASTMatchersTest.cpp?rev=146652&view=auto
==============================================================================
--- cfe/branches/tooling/unittests/ASTMatchers/ASTMatchersTest.cpp (added)
+++ cfe/branches/tooling/unittests/ASTMatchers/ASTMatchersTest.cpp Thu Dec 15 05:51:04 2011
@@ -0,0 +1,2081 @@
+//===- 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 "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/Tooling.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace ast_matchers {
+
+using clang::tooling::RunSyntaxOnlyToolOnCode;
+
+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));
+  if (!RunSyntaxOnlyToolOnCode(Finder.NewFrontendAction(), 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));
+  if (!RunSyntaxOnlyToolOnCode(Finder.NewFrontendAction(), 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);
+}
+
+TEST(HasNameDeathTest, DiesOnEmptyName) {
+  ASSERT_DEBUG_DEATH({
+    DeclarationMatcher HasEmptyName = Class(HasName(""));
+    EXPECT_TRUE(NotMatches("class X {};", HasEmptyName));
+  }, "");
+}
+
+TEST(IsDerivedFromDeathTest, DiesOnEmptyBaseName) {
+  ASSERT_DEBUG_DEATH({
+    DeclarationMatcher IsDerivedFromEmpty = Class(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(Class());
+  // Even for an empty string there are classes in the AST.
+  EXPECT_TRUE(Matches("", ClassMatcher));
+
+  DeclarationMatcher ClassX = Class(Class(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 = Class(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 =
+      Class(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(Class(IsDerivedFrom("Base1")))))));
+  EXPECT_TRUE(NotMatches(
+      RecursiveTemplateOneParameter,
+      Variable(
+          HasName("z_float"),
+          HasInitializer(HasType(Class(IsDerivedFrom("Base2")))))));
+  EXPECT_TRUE(Matches(
+      RecursiveTemplateOneParameter,
+      Variable(
+          HasName("z_char"),
+          HasInitializer(HasType(Class(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(Class(IsDerivedFrom("Base1")))))));
+  EXPECT_TRUE(NotMatches(
+      RecursiveTemplateTwoParameters,
+      Variable(
+          HasName("z_float"),
+          HasInitializer(HasType(Class(IsDerivedFrom("Base2")))))));
+  EXPECT_TRUE(Matches(
+      RecursiveTemplateTwoParameters,
+      Variable(
+          HasName("z_char"),
+          HasInitializer(HasType(Class(IsDerivedFrom("Base1"),
+                                       IsDerivedFrom("Base2")))))));
+}
+
+TEST(DeclarationMatcher, MatchAnyOf) {
+  DeclarationMatcher YOrZDerivedFromX =
+      Class(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 =
+      Class(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 = Class(Has(Class(HasName("X"))));
+
+  EXPECT_TRUE(Matches("class Y { class X {}; };", HasClassX));
+  EXPECT_TRUE(Matches("class X {};", HasClassX));
+
+  DeclarationMatcher YHasClassX =
+      Class(HasName("Y"), Has(Class(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 =
+    Class(
+      Has(Class(
+        Has(Class(HasName("X"))),
+        Has(Class(HasName("Y"))),
+        HasName("Z"))),
+      Has(Class(
+        Has(Class(HasName("A"))),
+        Has(Class(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 =
+      Class(
+          AnyOf(
+              Has(Class(
+                  AnyOf(
+                      Has(Class(
+                          HasName("X"))),
+                      Has(Class(
+                          HasName("Y"))),
+                      HasName("Z")))),
+              Has(Class(
+                  AnyOf(
+                      HasName("C"),
+                      Has(Class(
+                          HasName("A"))),
+                      Has(Class(
+                          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 =
+      Class(
+          IsDerivedFrom("Y"),
+          Not(HasName("Y")),
+          Not(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 =
+      Class(
+          HasName("X"),
+          Has(Class(HasName("Z"))),
+          Not(
+              Has(Class(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 =
+      Class(
+          HasDescendant(Class(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 =
+      Class(
+          HasDescendant(Class(Has(Class(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 =
+      Class(
+          HasDescendant(Class(HasDescendant(Class(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(Class(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(Class(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(Class(HasName("A")));
+
+  EXPECT_TRUE(Matches("class A { public: A *a; };", TypeA));
+  EXPECT_TRUE(NotMatches("class A {};", TypeA));
+
+  TypeMatcher TypeDerivedFromA = HasDeclaration(Class(IsDerivedFrom("A")));
+
+  EXPECT_TRUE(Matches("class A {}; class B : public A { public: B *b; };",
+              TypeDerivedFromA));
+  EXPECT_TRUE(NotMatches("class A {};", TypeA));
+
+  TypeMatcher TypeAHasClassB = HasDeclaration(
+      Class(HasName("A"), Has(Class(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", Class(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(
+      Class(HasName("A"), Has(Id("b", Class(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(Class(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(Class(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 = Class(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 = Class(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(Class(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(Class(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(Class(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(Class(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(Class(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(Class(HasName("X")))))));
+  EXPECT_TRUE(NotMatches("class X { void x(const X &x) {} };",
+      Method(HasParameter(0, HasType(Class(HasName("X")))))));
+  EXPECT_TRUE(Matches("class X { void x(const X *x) {} };",
+      Method(HasParameter(0, HasType(PointsTo(Class(HasName("X"))))))));
+  EXPECT_TRUE(Matches("class X { void x(const X &x) {} };",
+      Method(HasParameter(0, HasType(References(Class(HasName("X"))))))));
+}
+
+TEST(HasAnyParameter, MatchesIndependentlyOfPosition) {
+  EXPECT_TRUE(Matches("class Y {}; class X { void x(X x, Y y) {} };",
+      Method(HasAnyParameter(HasType(Class(HasName("X")))))));
+  EXPECT_TRUE(Matches("class Y {}; class X { void x(Y y, X x) {} };",
+      Method(HasAnyParameter(HasType(Class(HasName("X")))))));
+}
+
+TEST(HasAnyParameter, DoesntMatchIfInnerMatcherDoesntMatch) {
+  EXPECT_TRUE(NotMatches("class Y {}; class X { void x(int) {} };",
+      Method(HasAnyParameter(HasType(Class(HasName("X")))))));
+}
+
+TEST(HasAnyParameter, DoesNotMatchThisPointer) {
+  EXPECT_TRUE(NotMatches("class Y {}; class X { void x() {} };",
+      Method(HasAnyParameter(HasType(PointsTo(Class(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(Not(IsImplicit()))));
+}
+
+TEST(HasAnyConstructorInitializer, SimpleCase) {
+  EXPECT_TRUE(NotMatches(
+      "class Foo { Foo() { } };",
+      Constructor(HasAnyConstructorInitializer(True()))));
+  EXPECT_TRUE(Matches(
+      "class Foo {"
+      "  Foo() : foo_() { }"
+      "  int foo_;"
+      "};",
+      Constructor(HasAnyConstructorInitializer(True()))));
+}
+
+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(Class(HasName("Baz"))))))));
+  EXPECT_TRUE(Matches(Code, Constructor(HasAnyConstructorInitializer(
+      ForField(HasName("foo_"))))));
+  EXPECT_TRUE(NotMatches(Code, Constructor(HasAnyConstructorInitializer(
+      ForField(HasType(Class(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_")), Not(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(NewExpression(
+      HasConstructorArgument(
+          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(NewExpression(
+      HasConstructorArgument(
+          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 = Expression(NewExpression(
+      ConstructorArgumentCountIs(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 = If(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; } }",
+              Class(HasName("a::b::C"))));
+  EXPECT_TRUE(Matches("namespace a { namespace b { class C; } }",
+              Class(HasName("::a::b::C"))));
+  EXPECT_TRUE(Matches("namespace a { namespace b { class C; } }",
+              Class(HasName("b::C"))));
+  EXPECT_TRUE(Matches("namespace a { namespace b { class C; } }",
+              Class(HasName("C"))));
+  EXPECT_TRUE(NotMatches("namespace a { namespace b { class C; } }",
+              Class(HasName("c::b::C"))));
+  EXPECT_TRUE(NotMatches("namespace a { namespace b { class C; } }",
+              Class(HasName("a::c::C"))));
+  EXPECT_TRUE(NotMatches("namespace a { namespace b { class C; } }",
+              Class(HasName("a::b::A"))));
+  EXPECT_TRUE(NotMatches("namespace a { namespace b { class C; } }",
+              Class(HasName("::C"))));
+  EXPECT_TRUE(NotMatches("namespace a { namespace b { class C; } }",
+              Class(HasName("::b::C"))));
+  EXPECT_TRUE(NotMatches("namespace a { namespace b { class C; } }",
+              Class(HasName("z::a::b::C"))));
+  EXPECT_TRUE(NotMatches("namespace a { namespace b { class C; } }",
+              Class(HasName("a+b::C"))));
+  EXPECT_TRUE(NotMatches("namespace a { namespace b { class AC; } }",
+              Class(HasName("C"))));
+}
+
+TEST(Matcher, HasNameSupportsOuterClasses) {
+  EXPECT_TRUE(
+      Matches("class A { class B { class C; }; };", Class(HasName("A::B::C"))));
+  EXPECT_TRUE(
+      Matches("class A { class B { class C; }; };",
+              Class(HasName("::A::B::C"))));
+  EXPECT_TRUE(
+      Matches("class A { class B { class C; }; };", Class(HasName("B::C"))));
+  EXPECT_TRUE(
+      Matches("class A { class B { class C; }; };", Class(HasName("C"))));
+  EXPECT_TRUE(
+      NotMatches("class A { class B { class C; }; };",
+                 Class(HasName("c::B::C"))));
+  EXPECT_TRUE(
+      NotMatches("class A { class B { class C; }; };",
+                 Class(HasName("A::c::C"))));
+  EXPECT_TRUE(
+      NotMatches("class A { class B { class C; }; };",
+                 Class(HasName("A::B::A"))));
+  EXPECT_TRUE(
+      NotMatches("class A { class B { class C; }; };", Class(HasName("::C"))));
+  EXPECT_TRUE(
+      NotMatches("class A { class B { class C; }; };",
+                 Class(HasName("::B::C"))));
+  EXPECT_TRUE(NotMatches("class A { class B { class C; }; };",
+              Class(HasName("z::A::B::C"))));
+  EXPECT_TRUE(
+      NotMatches("class A { class B { class C; }; };",
+                 Class(HasName("A+B::C"))));
+}
+
+TEST(Matcher, IsDefinition) {
+  DeclarationMatcher DefinitionOfClassA =
+      Class(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();"
+      "}", Class(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", Class(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", Class(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(Class(HasName("B")));
+
+  EXPECT_TRUE(Matches("void x() { class B {}; }", StatementHasClassB));
+}
+
+TEST(For, FindsForLoops) {
+  EXPECT_TRUE(Matches("void f() { for(;;); }", For()));
+  EXPECT_TRUE(Matches("void f() { if(true) for(;;); }", For()));
+}
+
+TEST(For, ReportsNoFalsePositives) {
+  EXPECT_TRUE(NotMatches("void f() { ; }", For()));
+  EXPECT_TRUE(NotMatches("void f() { if(true); }", For()));
+}
+
+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 =
+      For(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(For()))));
+}
+
+TEST(HasAnySubstatement, IsNotRecursive) {
+  // It's really "has any immediate substatement".
+  EXPECT_TRUE(NotMatches("void f() { if (true) for (;;); }",
+              CompoundStatement(HasAnySubstatement(For()))));
+}
+
+TEST(HasAnySubstatement, MatchesInNestedCompoundStatements) {
+  EXPECT_TRUE(Matches("void f() { if (true) { for (;;); } }",
+              CompoundStatement(HasAnySubstatement(For()))));
+}
+
+TEST(HasAnySubstatement, FindsSubstatementBetweenOthers) {
+  EXPECT_TRUE(Matches("void f() { 1; 2; 3; for (;;); 4; 5; 6; }",
+              CompoundStatement(HasAnySubstatement(For()))));
+}
+
+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(Class(HasName("X")))))));
+}
+
+TEST(HasObjectExpression, MatchesBaseOfVariable) {
+  EXPECT_TRUE(Matches(
+      "struct X { int m; }; void f(X x) { x.m; }",
+      MemberExpression(HasObjectExpression(HasType(Class(HasName("X")))))));
+  EXPECT_TRUE(Matches(
+      "struct X { int m; }; void f(X* x) { x->m; }",
+      MemberExpression(HasObjectExpression(
+          HasType(PointsTo(Class(HasName("X"))))))));
+}
+
+TEST(HasObjectExpression,
+     MatchesObjectExpressionOfImplicitlyFormedMemberExpression) {
+  EXPECT_TRUE(Matches(
+      "class X {}; struct S { X m; void f() { this->m; } };",
+      MemberExpression(HasObjectExpression(
+          HasType(PointsTo(Class(HasName("S"))))))));
+  EXPECT_TRUE(Matches(
+      "class X {}; struct S { X m; void f() { m; } };",
+      MemberExpression(HasObjectExpression(
+          HasType(PointsTo(Class(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(True())))))));
+}
+
+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() {}", While()));
+  EXPECT_TRUE(Matches("void x() { while(true); }", While()));
+  EXPECT_TRUE(NotMatches("void x() { do {} while(true); }", While()));
+}
+
+TEST(Do, MatchesDoLoops) {
+  EXPECT_TRUE(Matches("void x() { do {} while(true); }", Do()));
+  EXPECT_TRUE(Matches("void x() { do ; while(false); }", Do()));
+}
+
+TEST(Do, DoesNotMatchWhileLoops) {
+  EXPECT_TRUE(NotMatches("void x() { while(true) {} }", Do()));
+}
+
+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) {} }",
+      If(HasConditionVariableStatement(DeclarationStatement()))));
+  EXPECT_TRUE(NotMatches(
+      "void x() { int x; if((x = 42)) {} }",
+      If(HasConditionVariableStatement(DeclarationStatement()))));
+}
+
+TEST(HasConditionVariableStatement, MatchesConditionVariables) {
+  EXPECT_TRUE(Matches(
+      "void x() { if(int* a = 0) {} }",
+      If(HasConditionVariableStatement(DeclarationStatement()))));
+}
+
+TEST(ForEach, BindsOneNode) {
+  EXPECT_TRUE(MatchAndVerifyResultTrue("class C { int x; };",
+      Class(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; };",
+      Class(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; }; };",
+      Class(HasName("C"), ForEach(Class(ForEach(Id("f", Field()))))),
+      new VerifyIdIsBoundToDecl<clang::FieldDecl>("f", 4)));
+}
+
+TEST(ForEachDescendant, BindsOneNode) {
+  EXPECT_TRUE(MatchAndVerifyResultTrue("class C { class D { int x; }; };",
+      Class(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; }; }; };",
+      Class(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; }; }; }; }; };",
+      Class(HasName("C"), ForEachDescendant(Class(
+          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;",
+      Class(HasName("::X"), IsTemplateInstantiation())));
+
+  EXPECT_TRUE(Matches(
+      "template <typename T> class X { T t; }; class A {}; X<A> x;",
+      Class(IsTemplateInstantiation(), HasDescendant(
+          Field(HasType(Class(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(Class(HasName("A")))),
+               IsTemplateInstantiation())));
+}
+
+TEST(IsTemplateInstantiation, MatchesExplicitClassTemplateInstantiation) {
+  EXPECT_TRUE(Matches(
+      "template <typename T> class X { T t; }; class A {};"
+      "template class X<A>;",
+      Class(IsTemplateInstantiation(), HasDescendant(
+          Field(HasType(Class(HasName("A"))))))));
+}
+
+TEST(IsTemplateInstantiation,
+     MatchesInstantiationOfPartiallySpecializedClassTemplate) {
+  EXPECT_TRUE(Matches(
+      "template <typename T> class X {};"
+      "template <typename T> class X<T*> {}; class A {}; X<A*> x;",
+      Class(HasName("::X"), IsTemplateInstantiation())));
+}
+
+TEST(IsTemplateInstantiation,
+     MatchesInstantiationOfClassTemplateNestedInNonTemplate) {
+  EXPECT_TRUE(Matches(
+      "class A {};"
+      "class X {"
+      "  template <typename U> class Y { U u; };"
+      "  Y<A> y;"
+      "};",
+      Class(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;",
+      Class(HasName("::X<A>::Y"), Not(IsTemplateInstantiation()))));
+}
+
+TEST(IsTemplateInstantiation, DoesNotMatchExplicitClassTemplateSpecialization) {
+  EXPECT_TRUE(NotMatches(
+      "template <typename T> class X {}; class A {};"
+      "template <> class X<A> {}; X<A> x;",
+      Class(HasName("::X"), IsTemplateInstantiation())));
+}
+
+TEST(IsTemplateInstantiation, DoesNotMatchNonTemplate) {
+  EXPECT_TRUE(NotMatches(
+      "class A {}; class Y { A a; };",
+      Class(IsTemplateInstantiation())));
+}
+
+} // end namespace tooling
+} // end namespace clang

Added: cfe/branches/tooling/unittests/ASTMatchers/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/unittests/ASTMatchers/Makefile?rev=146652&view=auto
==============================================================================
--- cfe/branches/tooling/unittests/ASTMatchers/Makefile (added)
+++ cfe/branches/tooling/unittests/ASTMatchers/Makefile Thu Dec 15 05:51:04 2011
@@ -0,0 +1,17 @@
+##===- 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 = ../..
+TESTNAME = ASTMatchers
+LINK_COMPONENTS := support mc
+USEDLIBS = 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/branches/tooling/unittests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/unittests/CMakeLists.txt?rev=146652&r1=146651&r2=146652&view=diff
==============================================================================
--- cfe/branches/tooling/unittests/CMakeLists.txt (original)
+++ cfe/branches/tooling/unittests/CMakeLists.txt Thu Dec 15 05:51:04 2011
@@ -55,6 +55,11 @@
   USED_LIBS gtest gtest_main clangAST
  )
 
+add_clang_unittest(ASTMatchers
+  ASTMatchers/ASTMatchersTest.cpp
+  USED_LIBS gtest gtest_main clangASTMatchers clangTooling
+ )
+
 add_clang_unittest(Basic
   Basic/FileManagerTest.cpp
   USED_LIBS gtest gtest_main clangBasic
@@ -64,3 +69,9 @@
   Frontend/FrontendActionTest.cpp
   USED_LIBS gtest gtest_main clangFrontend
  )
+
+add_clang_unittest(Tooling
+  Tooling/ToolingTest.cpp
+  Tooling/RefactoringTest.cpp
+  USED_LIBS gtest gtest_main clangTooling
+ )

Modified: cfe/branches/tooling/unittests/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/unittests/Makefile?rev=146652&r1=146651&r2=146652&view=diff
==============================================================================
--- cfe/branches/tooling/unittests/Makefile (original)
+++ cfe/branches/tooling/unittests/Makefile Thu Dec 15 05:51:04 2011
@@ -14,7 +14,7 @@
 
 IS_UNITTEST_LEVEL := 1
 CLANG_LEVEL := ..
-PARALLEL_DIRS = AST Basic Frontend
+PARALLEL_DIRS = AST ASTMatchers Basic Frontend Tooling
 
 endif  # CLANG_LEVEL
 

Added: cfe/branches/tooling/unittests/Tooling/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/unittests/Tooling/Makefile?rev=146652&view=auto
==============================================================================
--- cfe/branches/tooling/unittests/Tooling/Makefile (added)
+++ cfe/branches/tooling/unittests/Tooling/Makefile Thu Dec 15 05:51:04 2011
@@ -0,0 +1,17 @@
+##===- unittests/Tooling/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 = ../..
+TESTNAME = Tooling
+LINK_COMPONENTS := support mc
+USEDLIBS = clangTooling.a clangFrontend.a clangSerialization.a clangDriver.a \
+           clangRewrite.a clangParse.a clangSema.a clangAnalysis.a \
+					 clangAST.a clangLex.a clangBasic.a
+
+include $(CLANG_LEVEL)/unittests/Makefile

Added: cfe/branches/tooling/unittests/Tooling/RefactoringTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/unittests/Tooling/RefactoringTest.cpp?rev=146652&view=auto
==============================================================================
--- cfe/branches/tooling/unittests/Tooling/RefactoringTest.cpp (added)
+++ cfe/branches/tooling/unittests/Tooling/RefactoringTest.cpp Thu Dec 15 05:51:04 2011
@@ -0,0 +1,231 @@
+//===- unittest/Tooling/RefactoringTest.cpp - Refactoring unit tests ------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/Refactoring.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/DiagnosticOptions.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Rewrite/Rewriter.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_os_ostream.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace tooling {
+
+class RewriterTestContext {
+ public:
+  RewriterTestContext()
+      : Diagnostics(llvm::IntrusiveRefCntPtr<DiagnosticIDs>()),
+        DiagnosticPrinter(llvm::outs(), DiagnosticOptions()),
+        Files((FileSystemOptions())),
+        Sources(Diagnostics, Files),
+        Rewrite(Sources, Options) {
+    Diagnostics.setClient(&DiagnosticPrinter, false);
+  }
+
+  FileID CreateInMemoryFile(llvm::StringRef Name, llvm::StringRef Content) {
+    const llvm::MemoryBuffer *Source =
+      llvm::MemoryBuffer::getMemBuffer(Content);
+    const FileEntry *Entry =
+      Files.getVirtualFile(Name, Source->getBufferSize(), 0);
+    Sources.overrideFileContents(Entry, Source, true);
+    assert(Entry != NULL);
+    return Sources.createFileID(Entry, SourceLocation(), SrcMgr::C_User);
+  }
+
+  SourceLocation GetLocation(FileID ID, unsigned Line, unsigned Column) {
+    SourceLocation Result = Sources.translateFileLineCol(
+        Sources.getFileEntryForID(ID), Line, Column);
+    assert(Result.isValid());
+    return Result;
+  }
+
+  std::string GetRewrittenText(FileID ID) {
+    std::string Result;
+    llvm::raw_string_ostream OS(Result);
+    Rewrite.getEditBuffer(ID).write(OS);
+    return Result;
+  }
+
+  Replacement CreateReplacement(SourceLocation Start, unsigned Length,
+                                llvm::StringRef ReplacementText) {
+    return Replacement(Sources, Start, Length, ReplacementText);
+  }
+
+  DiagnosticsEngine Diagnostics;
+  TextDiagnosticPrinter DiagnosticPrinter;
+  FileManager Files;
+  SourceManager Sources;
+  LangOptions Options;
+  Rewriter Rewrite;
+};
+
+class ReplacementTest : public ::testing::Test {
+ protected:
+  RewriterTestContext Context;
+};
+
+TEST_F(ReplacementTest, CanDeleteAllText) {
+  FileID ID = Context.CreateInMemoryFile("input.cpp", "text");
+  SourceLocation Location = Context.GetLocation(ID, 1, 1);
+  Replacement Replace(Context.CreateReplacement(Location, 4, ""));
+  EXPECT_TRUE(Replace.Apply(Context.Rewrite));
+  EXPECT_EQ("", Context.GetRewrittenText(ID));
+}
+
+TEST_F(ReplacementTest, CanDeleteAllTextInTextWithNewlines) {
+  FileID ID = Context.CreateInMemoryFile("input.cpp", "line1\nline2\nline3");
+  SourceLocation Location = Context.GetLocation(ID, 1, 1);
+  Replacement Replace(Context.CreateReplacement(Location, 17, ""));
+  EXPECT_TRUE(Replace.Apply(Context.Rewrite));
+  EXPECT_EQ("", Context.GetRewrittenText(ID));
+}
+
+TEST_F(ReplacementTest, CanAddText) {
+  FileID ID = Context.CreateInMemoryFile("input.cpp", "");
+  SourceLocation Location = Context.GetLocation(ID, 1, 1);
+  Replacement Replace(Context.CreateReplacement(Location, 0, "result"));
+  EXPECT_TRUE(Replace.Apply(Context.Rewrite));
+  EXPECT_EQ("result", Context.GetRewrittenText(ID));
+}
+
+TEST_F(ReplacementTest, CanReplaceTextAtPosition) {
+  FileID ID = Context.CreateInMemoryFile("input.cpp",
+		                         "line1\nline2\nline3\nline4");
+  SourceLocation Location = Context.GetLocation(ID, 2, 3);
+  Replacement Replace(Context.CreateReplacement(Location, 12, "x"));
+  EXPECT_TRUE(Replace.Apply(Context.Rewrite));
+  EXPECT_EQ("line1\nlixne4", Context.GetRewrittenText(ID));
+}
+
+TEST_F(ReplacementTest, CanReplaceTextAtPositionMultipleTimes) {
+  FileID ID = Context.CreateInMemoryFile("input.cpp",
+                                         "line1\nline2\nline3\nline4");
+  SourceLocation Location1 = Context.GetLocation(ID, 2, 3);
+  Replacement Replace1(Context.CreateReplacement(Location1, 12, "x\ny\n"));
+  EXPECT_TRUE(Replace1.Apply(Context.Rewrite));
+  EXPECT_EQ("line1\nlix\ny\nne4", Context.GetRewrittenText(ID));
+
+  // Since the original source has not been modified, the (4, 4) points to the
+  // 'e' in the original content.
+  SourceLocation Location2 = Context.GetLocation(ID, 4, 4);
+  Replacement Replace2(Context.CreateReplacement(Location2, 1, "f"));
+  EXPECT_TRUE(Replace2.Apply(Context.Rewrite));
+  EXPECT_EQ("line1\nlix\ny\nnf4", Context.GetRewrittenText(ID));
+}
+
+TEST_F(ReplacementTest, ApplyFailsForNonExistentLocation) {
+  Replacement Replace("nonexistent-file.cpp", 0, 1, "");
+  EXPECT_FALSE(Replace.Apply(Context.Rewrite));
+}
+
+TEST_F(ReplacementTest, CanApplyReplacements) {
+  FileID ID = Context.CreateInMemoryFile("input.cpp",
+                                         "line1\nline2\nline3\nline4");
+  Replacements Replaces;
+  Replaces.insert(Replacement(Context.Sources, Context.GetLocation(ID, 2, 1),
+                              5, "replaced"));
+  Replaces.insert(Replacement(Context.Sources, Context.GetLocation(ID, 3, 1),
+                              5, "other"));
+  EXPECT_TRUE(ApplyAllReplacements(Replaces, Context.Rewrite));
+  EXPECT_EQ("line1\nreplaced\nother\nline4", Context.GetRewrittenText(ID));
+}
+
+TEST_F(ReplacementTest, SkipsDuplicateReplacements) {
+  FileID ID = Context.CreateInMemoryFile("input.cpp",
+                                         "line1\nline2\nline3\nline4");
+  Replacements Replaces;
+  Replaces.insert(Replacement(Context.Sources, Context.GetLocation(ID, 2, 1),
+                              5, "replaced"));
+  Replaces.insert(Replacement(Context.Sources, Context.GetLocation(ID, 2, 1),
+                              5, "replaced"));
+  Replaces.insert(Replacement(Context.Sources, Context.GetLocation(ID, 2, 1),
+                              5, "replaced"));
+  EXPECT_TRUE(ApplyAllReplacements(Replaces, Context.Rewrite));
+  EXPECT_EQ("line1\nreplaced\nline3\nline4", Context.GetRewrittenText(ID));
+}
+
+TEST_F(ReplacementTest, ApplyAllFailsIfOneApplyFails) {
+  // This test depends on the value of the file name of an invalid source
+  // location being in the range ]a, z[.
+  FileID IDa = Context.CreateInMemoryFile("a.cpp", "text");
+  FileID IDz = Context.CreateInMemoryFile("z.cpp", "text");
+  Replacements Replaces;
+  Replaces.insert(Replacement(Context.Sources, Context.GetLocation(IDa, 1, 1),
+                              4, "a"));
+  Replaces.insert(Replacement(Context.Sources, SourceLocation(),
+                              5, "2"));
+  Replaces.insert(Replacement(Context.Sources, Context.GetLocation(IDz, 1, 1),
+                              4, "z"));
+  EXPECT_FALSE(ApplyAllReplacements(Replaces, Context.Rewrite));
+  EXPECT_EQ("a", Context.GetRewrittenText(IDa));
+  EXPECT_EQ("z", Context.GetRewrittenText(IDz));
+}
+
+class FlushRewrittenFilesTest : public ::testing::Test {
+ public:
+  FlushRewrittenFilesTest() {
+    std::string ErrorInfo;
+    TemporaryDirectory = llvm::sys::Path::GetTemporaryDirectory(&ErrorInfo);
+    assert(ErrorInfo.empty());
+  }
+
+  ~FlushRewrittenFilesTest() {
+    std::string ErrorInfo;
+    TemporaryDirectory.eraseFromDisk(true, &ErrorInfo);
+    assert(ErrorInfo.empty());
+  }
+
+  FileID CreateFile(llvm::StringRef Name, llvm::StringRef Content) {
+    llvm::SmallString<1024> Path(TemporaryDirectory.str());
+    llvm::sys::path::append(Path, Name);
+    std::string ErrorInfo;
+    llvm::raw_fd_ostream OutStream(Path.c_str(),
+                                   ErrorInfo, llvm::raw_fd_ostream::F_Binary);
+    assert(ErrorInfo.empty());
+    OutStream << Content;
+    OutStream.close();
+    const FileEntry *File = Context.Files.getFile(Path);
+    assert(File != NULL);
+    return Context.Sources.createFileID(File, SourceLocation(), SrcMgr::C_User);
+  }
+
+  std::string GetFileContentFromDisk(llvm::StringRef Name) {
+    llvm::SmallString<1024> Path(TemporaryDirectory.str());
+    llvm::sys::path::append(Path, Name);
+    // We need to read directly from the FileManager without relaying through
+    // a FileEntry, as otherwise we'd read through an already opened file
+    // descriptor, which might not see the changes made.
+    // FIXME: Figure out whether there is a way to get the SourceManger to
+    // reopen the file.
+    return Context.Files.getBufferForFile(Path, NULL)->getBuffer();
+  }
+
+  llvm::sys::Path TemporaryDirectory;
+  RewriterTestContext Context;
+};
+
+TEST_F(FlushRewrittenFilesTest, StoresChangesOnDisk) {
+  FileID ID = CreateFile("input.cpp", "line1\nline2\nline3\nline4");
+  Replacements Replaces;
+  Replaces.insert(Replacement(Context.Sources, Context.GetLocation(ID, 2, 1),
+                              5, "replaced"));
+  EXPECT_TRUE(ApplyAllReplacements(Replaces, Context.Rewrite));
+  EXPECT_TRUE(SaveRewrittenFiles(Context.Rewrite));
+  EXPECT_EQ("line1\nreplaced\nline3\nline4",
+            GetFileContentFromDisk("input.cpp"));
+}
+
+} // end namespace tooling
+} // end namespace clang

Added: cfe/branches/tooling/unittests/Tooling/ToolingTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/unittests/Tooling/ToolingTest.cpp?rev=146652&view=auto
==============================================================================
--- cfe/branches/tooling/unittests/Tooling/ToolingTest.cpp (added)
+++ cfe/branches/tooling/unittests/Tooling/ToolingTest.cpp Thu Dec 15 05:51:04 2011
@@ -0,0 +1,269 @@
+//===- unittest/Tooling/ToolingTest.cpp - Tooling unit tests --------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/Twine.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclGroup.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/Tooling/Tooling.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace tooling {
+
+namespace {
+/// Takes an ast consumer and returns it from CreateASTConsumer. This only
+/// works with single translation unit compilations.
+class TestAction : public clang::ASTFrontendAction {
+ public:
+  /// Takes ownership of TestConsumer.
+  explicit TestAction(clang::ASTConsumer *TestConsumer)
+      : TestConsumer(TestConsumer) {}
+
+ protected:
+  virtual clang::ASTConsumer* CreateASTConsumer(
+      clang::CompilerInstance& compiler, llvm::StringRef dummy) {
+    /// TestConsumer will be deleted by the framework calling us.
+    return TestConsumer;
+  }
+
+ private:
+  clang::ASTConsumer * const TestConsumer;
+};
+
+class FindTopLevelDeclConsumer : public clang::ASTConsumer {
+ public:
+  explicit FindTopLevelDeclConsumer(bool *FoundTopLevelDecl)
+      : FoundTopLevelDecl(FoundTopLevelDecl) {}
+  virtual bool HandleTopLevelDecl(clang::DeclGroupRef DeclGroup) {
+    *FoundTopLevelDecl = true;
+    return true;
+  }
+ private:
+  bool * const FoundTopLevelDecl;
+};
+} // end namespace
+
+TEST(RunSyntaxOnlyToolOnCode, FindsTopLevelDeclOnEmptyCode) {
+  bool FoundTopLevelDecl = false;
+  EXPECT_TRUE(RunSyntaxOnlyToolOnCode(
+      new TestAction(new FindTopLevelDeclConsumer(&FoundTopLevelDecl)), ""));
+  EXPECT_TRUE(FoundTopLevelDecl);
+}
+
+namespace {
+class FindClassDeclXConsumer : public clang::ASTConsumer {
+ public:
+  FindClassDeclXConsumer(bool *FoundClassDeclX)
+      : FoundClassDeclX(FoundClassDeclX) {}
+  virtual bool HandleTopLevelDecl(clang::DeclGroupRef GroupRef) {
+    if (CXXRecordDecl* Record = llvm::dyn_cast<clang::CXXRecordDecl>(
+            *GroupRef.begin())) {
+      if (Record->getName() == "X") {
+        *FoundClassDeclX = true;
+      }
+    }
+    return true;
+  }
+ private:
+  bool *FoundClassDeclX;
+};
+} // end namespace
+
+TEST(RunSyntaxOnlyToolOnCode, FindsClassDecl) {
+  bool FoundClassDeclX = false;
+  EXPECT_TRUE(RunSyntaxOnlyToolOnCode(new TestAction(
+      new FindClassDeclXConsumer(&FoundClassDeclX)), "class X;"));
+  EXPECT_TRUE(FoundClassDeclX);
+
+  FoundClassDeclX = false;
+  EXPECT_TRUE(RunSyntaxOnlyToolOnCode(new TestAction(
+      new FindClassDeclXConsumer(&FoundClassDeclX)), "class Y;"));
+  EXPECT_FALSE(FoundClassDeclX);
+}
+
+TEST(FindCompileArgsInJsonDatabase, FindsNothingIfEmpty) {
+  std::string ErrorMessage;
+  CompileCommand NotFound = FindCompileArgsInJsonDatabase(
+      "a-file.cpp", "", ErrorMessage);
+  EXPECT_TRUE(NotFound.CommandLine.empty()) << ErrorMessage;
+  EXPECT_TRUE(NotFound.Directory.empty()) << ErrorMessage;
+}
+
+TEST(FindCompileArgsInJsonDatabase, ReadsSingleEntry) {
+  llvm::StringRef Directory("/some/directory");
+  llvm::StringRef FileName("/path/to/a-file.cpp");
+  llvm::StringRef Command("/path/to/compiler and some arguments");
+  std::string ErrorMessage;
+  CompileCommand FoundCommand = FindCompileArgsInJsonDatabase(
+      FileName,
+      (llvm::Twine("[{\"directory\":\"") + Directory + "\"," +
+                     "\"command\":\"" + Command + "\","
+                     "\"file\":\"" + FileName + "\"}]").str(), ErrorMessage);
+  EXPECT_EQ(Directory, FoundCommand.Directory) << ErrorMessage;
+  ASSERT_EQ(4u, FoundCommand.CommandLine.size()) << ErrorMessage;
+  EXPECT_EQ("/path/to/compiler", FoundCommand.CommandLine[0]) << ErrorMessage;
+  EXPECT_EQ("and", FoundCommand.CommandLine[1]) << ErrorMessage;
+  EXPECT_EQ("some", FoundCommand.CommandLine[2]) << ErrorMessage;
+  EXPECT_EQ("arguments", FoundCommand.CommandLine[3]) << ErrorMessage;
+
+  CompileCommand NotFound = FindCompileArgsInJsonDatabase(
+      "a-file.cpp",
+      (llvm::Twine("[{\"directory\":\"") + Directory + "\"," +
+                     "\"command\":\"" + Command + "\","
+                     "\"file\":\"" + FileName + "\"}]").str(), ErrorMessage);
+  EXPECT_TRUE(NotFound.Directory.empty()) << ErrorMessage;
+  EXPECT_TRUE(NotFound.CommandLine.empty()) << ErrorMessage;
+}
+
+TEST(FindCompileArgsInJsonDatabase, ReadsCompileCommandLinesWithSpaces) {
+  llvm::StringRef Directory("/some/directory");
+  llvm::StringRef FileName("/path/to/a-file.cpp");
+  llvm::StringRef Command("\\\"/path to compiler\\\" \\\"and an argument\\\"");
+  std::string ErrorMessage;
+  CompileCommand FoundCommand = FindCompileArgsInJsonDatabase(
+      FileName,
+      (llvm::Twine("[{\"directory\":\"") + Directory + "\"," +
+                     "\"command\":\"" + Command + "\","
+                     "\"file\":\"" + FileName + "\"}]").str(), ErrorMessage);
+  ASSERT_EQ(2u, FoundCommand.CommandLine.size());
+  EXPECT_EQ("/path to compiler", FoundCommand.CommandLine[0]) << ErrorMessage;
+  EXPECT_EQ("and an argument", FoundCommand.CommandLine[1]) << ErrorMessage;
+}
+
+TEST(FindCompileArgsInJsonDatabase, ReadsDirectoryWithSpaces) {
+  llvm::StringRef Directory("/some directory / with spaces");
+  llvm::StringRef FileName("/path/to/a-file.cpp");
+  llvm::StringRef Command("a command");
+  std::string ErrorMessage;
+  CompileCommand FoundCommand = FindCompileArgsInJsonDatabase(
+      FileName,
+      (llvm::Twine("[{\"directory\":\"") + Directory + "\"," +
+                     "\"command\":\"" + Command + "\","
+                     "\"file\":\"" + FileName + "\"}]").str(), ErrorMessage);
+  EXPECT_EQ(Directory, FoundCommand.Directory) << ErrorMessage;
+}
+
+TEST(FindCompileArgsInJsonDatabase, FindsEntry) {
+  llvm::StringRef Directory("directory");
+  llvm::StringRef FileName("file");
+  llvm::StringRef Command("command");
+  std::string JsonDatabase = "[";
+  for (int I = 0; I < 10; ++I) {
+    if (I > 0) JsonDatabase += ",";
+    JsonDatabase += (llvm::Twine(
+        "{\"directory\":\"") + Directory + llvm::Twine(I) + "\"," +
+         "\"command\":\"" + Command + llvm::Twine(I) + "\","
+         "\"file\":\"" + FileName + llvm::Twine(I) + "\"}").str();
+  }
+  JsonDatabase += "]";
+  std::string ErrorMessage;
+  CompileCommand FoundCommand = FindCompileArgsInJsonDatabase(
+      "file4", JsonDatabase, ErrorMessage);
+  EXPECT_EQ("directory4", FoundCommand.Directory) << ErrorMessage;
+  ASSERT_EQ(1u, FoundCommand.CommandLine.size()) << ErrorMessage;
+  EXPECT_EQ("command4", FoundCommand.CommandLine[0]) << ErrorMessage;
+}
+
+TEST(UnescapeJsonCommandLine, ReturnsEmptyArrayOnEmptyString) {
+  std::vector<std::string> Result = UnescapeJsonCommandLine("");
+  EXPECT_TRUE(Result.empty());
+}
+
+TEST(UnescapeJsonCommandLine, SplitsOnSpaces) {
+  std::vector<std::string> Result = UnescapeJsonCommandLine("a b c");
+  ASSERT_EQ(3ul, Result.size());
+  EXPECT_EQ("a", Result[0]);
+  EXPECT_EQ("b", Result[1]);
+  EXPECT_EQ("c", Result[2]);
+}
+
+TEST(UnescapeJsonCommandLine, MungesMultipleSpaces) {
+  std::vector<std::string> Result = UnescapeJsonCommandLine("   a   b   ");
+  ASSERT_EQ(2ul, Result.size());
+  EXPECT_EQ("a", Result[0]);
+  EXPECT_EQ("b", Result[1]);
+}
+
+TEST(UnescapeJsonCommandLine, UnescapesBackslashCharacters) {
+  std::vector<std::string> Backslash = UnescapeJsonCommandLine("a\\\\\\\\");
+  ASSERT_EQ(1ul, Backslash.size());
+  EXPECT_EQ("a\\", Backslash[0]);
+  std::vector<std::string> Quote = UnescapeJsonCommandLine("a\\\\\\\"");
+  ASSERT_EQ(1ul, Quote.size());
+  EXPECT_EQ("a\"", Quote[0]);
+}
+
+TEST(UnescapeJsonCommandLine, DoesNotMungeSpacesBetweenQuotes) {
+  std::vector<std::string> Result = UnescapeJsonCommandLine("\\\"  a  b  \\\"");
+  ASSERT_EQ(1ul, Result.size());
+  EXPECT_EQ("  a  b  ", Result[0]);
+}
+
+TEST(UnescapeJsonCommandLine, AllowsMultipleQuotedArguments) {
+  std::vector<std::string> Result = UnescapeJsonCommandLine(
+      "  \\\" a \\\"  \\\" b \\\"  ");
+  ASSERT_EQ(2ul, Result.size());
+  EXPECT_EQ(" a ", Result[0]);
+  EXPECT_EQ(" b ", Result[1]);
+}
+
+TEST(UnescapeJsonCommandLine, AllowsEmptyArgumentsInQuotes) {
+  std::vector<std::string> Result = UnescapeJsonCommandLine(
+      "\\\"\\\"\\\"\\\"");
+  ASSERT_EQ(1ul, Result.size());
+  EXPECT_TRUE(Result[0].empty()) << Result[0];
+}
+
+TEST(UnescapeJsonCommandLine, ParsesEscapedQuotesInQuotedStrings) {
+  std::vector<std::string> Result = UnescapeJsonCommandLine(
+      "\\\"\\\\\\\"\\\"");
+  ASSERT_EQ(1ul, Result.size());
+  EXPECT_EQ("\"", Result[0]);
+}
+
+TEST(UnescapeJsonCommandLine, ParsesMultipleArgumentsWithEscapedCharacters) {
+  std::vector<std::string> Result = UnescapeJsonCommandLine(
+      "  \\\\\\\"  \\\"a \\\\\\\" b \\\"     \\\"and\\\\\\\\c\\\"   \\\\\\\"");
+  ASSERT_EQ(4ul, Result.size());
+  EXPECT_EQ("\"", Result[0]);
+  EXPECT_EQ("a \" b ", Result[1]);
+  EXPECT_EQ("and\\c", Result[2]);
+  EXPECT_EQ("\"", Result[3]);
+}
+
+TEST(UnescapeJsonCommandLine, ParsesStringsWithoutSpacesIntoSingleArgument) {
+  std::vector<std::string> QuotedNoSpaces = UnescapeJsonCommandLine(
+      "\\\"a\\\"\\\"b\\\"");
+  ASSERT_EQ(1ul, QuotedNoSpaces.size());
+  EXPECT_EQ("ab", QuotedNoSpaces[0]);
+
+  std::vector<std::string> MixedNoSpaces = UnescapeJsonCommandLine(
+      "\\\"a\\\"bcd\\\"ef\\\"\\\"\\\"\\\"g\\\"");
+  ASSERT_EQ(1ul, MixedNoSpaces.size());
+  EXPECT_EQ("abcdefg", MixedNoSpaces[0]);
+}
+
+TEST(UnescapeJsonCommandLine, ParsesQuotedStringWithoutClosingQuote) {
+  std::vector<std::string> Unclosed = UnescapeJsonCommandLine("\"abc");
+  ASSERT_EQ(1ul, Unclosed.size());
+  EXPECT_EQ("abc", Unclosed[0]);
+
+  std::vector<std::string> EndsInBackslash = UnescapeJsonCommandLine("\"a\\");
+  ASSERT_EQ(1ul, EndsInBackslash.size());
+  EXPECT_EQ("a", EndsInBackslash[0]);
+
+  std::vector<std::string> Empty = UnescapeJsonCommandLine("\"");
+  ASSERT_EQ(1ul, Empty.size());
+  EXPECT_EQ("", Empty[0]);
+}
+
+} // end namespace tooling
+} // end namespace clang





More information about the llvm-branch-commits mailing list