[llvm-branch-commits] [cfe-branch] r157622 - in /cfe/branches/tooling: include/clang/ASTMatchers/ include/clang/ASTMatchers/Dynamic/ lib/ASTMatchers/ lib/ASTMatchers/Dynamic/ tools/ tools/ast-query/ unittests/ unittests/ASTMatchers/ unittests/ASTMatchers/Dynamic/

Manuel Klimek klimek at google.com
Tue May 29 07:10:54 PDT 2012


Author: klimek
Date: Tue May 29 09:10:54 2012
New Revision: 157622

URL: http://llvm.org/viewvc/llvm-project?rev=157622&view=rev
Log:
Adds dynamic matcher interface contributed by Samuel Benzaquen.


Added:
    cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/
    cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/GenericMatcher.h   (with props)
    cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/GenericValue.h   (with props)
    cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/NumberHolder.h   (with props)
    cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/Parser.h   (with props)
    cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/Registry.h   (with props)
    cfe/branches/tooling/lib/ASTMatchers/Dynamic/
    cfe/branches/tooling/lib/ASTMatchers/Dynamic/CMakeLists.txt   (with props)
    cfe/branches/tooling/lib/ASTMatchers/Dynamic/Makefile   (with props)
    cfe/branches/tooling/lib/ASTMatchers/Dynamic/Marshallers.h   (with props)
    cfe/branches/tooling/lib/ASTMatchers/Dynamic/Parser.cpp   (with props)
    cfe/branches/tooling/lib/ASTMatchers/Dynamic/Registry.cpp   (with props)
    cfe/branches/tooling/tools/ast-query/
    cfe/branches/tooling/tools/ast-query/ASTQuery.cpp   (with props)
    cfe/branches/tooling/tools/ast-query/CMakeLists.txt   (with props)
    cfe/branches/tooling/tools/ast-query/Makefile   (with props)
    cfe/branches/tooling/unittests/ASTMatchers/ASTMatchersTest.h   (with props)
    cfe/branches/tooling/unittests/ASTMatchers/Dynamic/
    cfe/branches/tooling/unittests/ASTMatchers/Dynamic/GenericMatcherTest.cpp   (with props)
    cfe/branches/tooling/unittests/ASTMatchers/Dynamic/GenericValueTest.cpp   (with props)
    cfe/branches/tooling/unittests/ASTMatchers/Dynamic/Makefile   (with props)
    cfe/branches/tooling/unittests/ASTMatchers/Dynamic/NumberHolderTest.cpp   (with props)
    cfe/branches/tooling/unittests/ASTMatchers/Dynamic/ParserTest.cpp   (with props)
    cfe/branches/tooling/unittests/ASTMatchers/Dynamic/RegistryTest.cpp   (with props)
Modified:
    cfe/branches/tooling/include/clang/ASTMatchers/ASTMatchersInternal.h
    cfe/branches/tooling/lib/ASTMatchers/CMakeLists.txt
    cfe/branches/tooling/lib/ASTMatchers/Makefile
    cfe/branches/tooling/tools/CMakeLists.txt
    cfe/branches/tooling/tools/Makefile
    cfe/branches/tooling/unittests/ASTMatchers/ASTMatchersTest.cpp
    cfe/branches/tooling/unittests/ASTMatchers/Makefile
    cfe/branches/tooling/unittests/CMakeLists.txt

Modified: cfe/branches/tooling/include/clang/ASTMatchers/ASTMatchersInternal.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/include/clang/ASTMatchers/ASTMatchersInternal.h?rev=157622&r1=157621&r2=157622&view=diff
==============================================================================
--- cfe/branches/tooling/include/clang/ASTMatchers/ASTMatchersInternal.h (original)
+++ cfe/branches/tooling/include/clang/ASTMatchers/ASTMatchersInternal.h Tue May 29 09:10:54 2012
@@ -311,16 +311,18 @@
 /// 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);
+  static const bool value =
+      (llvm::is_same<T, clang::Decl>::value ||
+       llvm::is_same<T, clang::Stmt>::value ||
+       llvm::is_same<T, clang::QualType>::value ||
+       llvm::is_same<T, clang::CXXCtorInitializer>::value);
 };
 template <typename T>
 const bool IsBaseType<T>::value;
 
 /// \brief Interface that can match any AST base node type and contains default
 /// implementations returning false.
-class UntypedBaseMatcher {
+class UntypedBaseMatcher : public llvm::RefCountedBaseVPTR {
 public:
   virtual ~UntypedBaseMatcher() {}
 
@@ -336,6 +338,11 @@
                        BoundNodesTreeBuilder *Builder) const {
     return false;
   }
+  virtual bool matches(const clang::CXXCtorInitializer &CtorInitNode,
+                       ASTMatchFinder *Finder,
+                       BoundNodesTreeBuilder *Builder) const {
+    return false;
+  }
 
   /// \brief Returns a unique ID for the matcher.
   virtual uint64_t getID() const = 0;

Added: cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/GenericMatcher.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/GenericMatcher.h?rev=157622&view=auto
==============================================================================
--- cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/GenericMatcher.h (added)
+++ cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/GenericMatcher.h Tue May 29 09:10:54 2012
@@ -0,0 +1,198 @@
+//===--- GenericMatcher.h - Polymorphic matcher type -*- C++ -*-===/
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  A simple wrapper class that can impersonate any matcher type.
+//  It provides appropriate conversion of matchers. An invalid conversion will
+//  succeed, but return a matcher that won't match anything.
+//  Eg. Converting a Matcher<Stmt> to Matcher<Decl>.
+//  Used as the underlying matcher value on GenericValue.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_GENERIC_MATCHER_H
+#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_GENERIC_MATCHER_H
+
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/ASTMatchersInternal.h"
+#include "llvm/ADT/OwningPtr.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+using ast_matchers::internal::Matcher;
+using ast_matchers::internal::UntypedBaseMatcher;
+using ast_matchers::internal::TypedBaseMatcher;
+using ast_matchers::internal::ASTMatchFinder;
+using ast_matchers::internal::BoundNodesTreeBuilder;
+
+namespace internal {
+
+
+}  // namespace internal
+
+class GenericMatcher {
+  // Gives the base types for Decl/Expr and T for everything else.
+  // Callers to the GenericMatcher will use the derived classes when
+  // setting/getting the contents. This struct helps on the conversion.
+  template <typename T>
+  struct DerivedTypeHelper {
+    typedef typename llvm::conditional<llvm::is_base_of<clang::Decl, T>::value,
+            clang::Decl, T>::type Decl_type;
+    typedef typename llvm::conditional<llvm::is_base_of<clang::Stmt, T>::value,
+            clang::Stmt, Decl_type>::type Type;
+  };
+
+ public:
+  template <typename T>
+  GenericMatcher(Matcher<T> Inner)
+      : Untyped(makeUntyped(Inner)) { }
+
+  template <typename T>
+  Matcher<T> getAs() const {
+    return ast_matchers::internal::MakeMatcher(new UntypedWrapper<T>(Untyped));
+  }
+
+  static GenericMatcher anyOf(const GenericMatcher& First,
+                              const GenericMatcher& Second) {
+    return GenericMatcher(new AnyOfUntypedMatcher(
+        First.Untyped, Second.Untyped));
+  }
+
+  static GenericMatcher allOf(const GenericMatcher& First,
+                              const GenericMatcher& Second) {
+    return GenericMatcher(new AllOfUntypedMatcher(
+        First.Untyped, Second.Untyped));
+  }
+
+ private:
+  // Takes ownership.
+  explicit GenericMatcher(UntypedBaseMatcher* Inner) : Untyped(Inner) { }
+
+  typedef llvm::IntrusiveRefCntPtr<const UntypedBaseMatcher> UntypedMatcherPtr;
+
+  template <typename T>
+  static UntypedMatcherPtr makeUntyped(Matcher<T> Inner) {
+    typedef typename DerivedTypeHelper<T>::Type BaseType;
+    return new TypedBaseMatcher<BaseType>(
+        maybeMakeDynCastMatcher(Inner, static_cast<BaseType*>(NULL)));
+  }
+
+  // Use DynCastMatcher when From and To are different types.
+  // This allows skipping DynCastMatcher for QualType and CXXCtorInitializer
+  // that do not support it.
+  template <typename From, typename To>
+  static Matcher<From> maybeMakeDynCastMatcher(const Matcher<To>& BaseMatcher,
+                                               const From* dummy) {
+    return MakeMatcher(
+        new ast_matchers::internal::DynCastMatcher<From, To>(BaseMatcher));
+  }
+  template <typename T>
+  static Matcher<T> maybeMakeDynCastMatcher(const Matcher<T>& BaseMatcher,
+                                            const T* dummy) {
+    return BaseMatcher;
+  }
+
+  template <typename T>
+  class UntypedWrapper : public ast_matchers::internal::MatcherInterface<T> {
+   public:
+    explicit UntypedWrapper(const UntypedMatcherPtr& Inner) : Untyped(Inner) { }
+    virtual ~UntypedWrapper() { }
+    bool matches(const T& Node, ASTMatchFinder* Finder,
+                 BoundNodesTreeBuilder* Builder) const {
+      return Untyped->matches(Node, Finder, Builder);
+    }
+
+   private:
+    const UntypedMatcherPtr Untyped;
+  };
+
+  class AnyOfUntypedMatcher : public UntypedBaseMatcher {
+   public:
+    AnyOfUntypedMatcher(const UntypedMatcherPtr& FirstIn,
+                        const UntypedMatcherPtr& SecondIn)
+        : First(FirstIn), Second(SecondIn) { }
+    virtual ~AnyOfUntypedMatcher() {}
+
+    bool matches(const clang::Decl &DeclNode, ASTMatchFinder *Finder,
+                 BoundNodesTreeBuilder *Builder) const {
+      return First->matches(DeclNode, Finder, Builder) ||
+          Second->matches(DeclNode, Finder, Builder);
+    }
+    bool matches(const clang::QualType &TypeNode, ASTMatchFinder *Finder,
+                 BoundNodesTreeBuilder *Builder) const {
+      return First->matches(TypeNode, Finder, Builder) ||
+          Second->matches(TypeNode, Finder, Builder);
+    }
+    bool matches(const clang::Stmt &StmtNode, ASTMatchFinder *Finder,
+                 BoundNodesTreeBuilder *Builder) const {
+      return First->matches(StmtNode, Finder, Builder) ||
+          Second->matches(StmtNode, Finder, Builder);
+    }
+    bool matches(const clang::CXXCtorInitializer &CtorInitNode,
+                 ASTMatchFinder *Finder,
+                 BoundNodesTreeBuilder *Builder) const {
+      return First->matches(CtorInitNode, Finder, Builder) ||
+          Second->matches(CtorInitNode, Finder, Builder);
+    }
+
+    uint64_t getID() const {
+      return reinterpret_cast<uint64_t>(this);
+    }
+
+   private:
+    const UntypedMatcherPtr First;
+    const UntypedMatcherPtr Second;
+  };
+
+  class AllOfUntypedMatcher : public UntypedBaseMatcher {
+   public:
+    AllOfUntypedMatcher(const UntypedMatcherPtr& FirstIn,
+                        const UntypedMatcherPtr& SecondIn)
+        : First(FirstIn), Second(SecondIn) { }
+    virtual ~AllOfUntypedMatcher() {}
+
+    bool matches(const clang::Decl &DeclNode, ASTMatchFinder *Finder,
+                 BoundNodesTreeBuilder *Builder) const {
+      return First->matches(DeclNode, Finder, Builder) &&
+          Second->matches(DeclNode, Finder, Builder);
+    }
+    bool matches(const clang::QualType &TypeNode, ASTMatchFinder *Finder,
+                 BoundNodesTreeBuilder *Builder) const {
+      return First->matches(TypeNode, Finder, Builder) &&
+          Second->matches(TypeNode, Finder, Builder);
+    }
+    bool matches(const clang::Stmt &StmtNode, ASTMatchFinder *Finder,
+                 BoundNodesTreeBuilder *Builder) const {
+      return First->matches(StmtNode, Finder, Builder) &&
+          Second->matches(StmtNode, Finder, Builder);
+    }
+    bool matches(const clang::CXXCtorInitializer &CtorInitNode,
+                 ASTMatchFinder *Finder,
+                 BoundNodesTreeBuilder *Builder) const {
+      return First->matches(CtorInitNode, Finder, Builder) &&
+          Second->matches(CtorInitNode, Finder, Builder);
+    }
+
+    uint64_t getID() const {
+      return reinterpret_cast<uint64_t>(this);
+    }
+
+   private:
+    const UntypedMatcherPtr First;
+    const UntypedMatcherPtr Second;
+  };
+
+  UntypedMatcherPtr Untyped;
+};
+
+}  // end namespace dynamic
+}  // end namespace ast_matchers
+}  // end namespace clang
+
+#endif  // LLVM_CLANG_AST_MATCHERS_DYNAMIC_GENERIC_MATCHER_H

Propchange: cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/GenericMatcher.h
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/GenericValue.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/GenericValue.h?rev=157622&view=auto
==============================================================================
--- cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/GenericValue.h (added)
+++ cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/GenericValue.h Tue May 29 09:10:54 2012
@@ -0,0 +1,188 @@
+//===--- GenericValue.h - Polymorphic value type -*- C++ -*-===/
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  Polymorphic value type that supports all the types required for dynamic
+//  Matcher construction.
+//  Used by the registry to construct matchers in a generic way.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_GENERIC_VALUE_H
+#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_GENERIC_VALUE_H
+
+#include "GenericMatcher.h"
+#include "NumberHolder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+struct GenericError {
+  std::string Message;
+  GenericError() {}
+  explicit GenericError(const std::string& Message) : Message(Message) { }
+};
+
+class GenericValue {
+ public:
+  GenericValue() : Type(VT_Nothing) { }
+  template <typename T>
+  GenericValue(const T& Value) : Type(VT_Nothing) {
+    setImpl(Value);
+  }
+  GenericValue(const GenericValue& Other) : Type(VT_Nothing) {
+    *this = Other;
+  }
+
+  ~GenericValue() {
+    Reset();
+  }
+
+  GenericValue& operator=(const GenericValue& Other) {
+    Reset();
+    switch (Other.Type) {
+      case VT_String:  setImpl(Other.get<std::string>());    break;
+      case VT_Error:   setImpl(Other.get<GenericError>());   break;
+      case VT_Bool:    setImpl(Other.get<bool>());           break;
+      case VT_Matcher: setImpl(Other.get<GenericMatcher>()); break;
+      case VT_Number:  setImpl(Other.get<NumberHolder>());   break;
+      case VT_Nothing: Type = VT_Nothing;                    break;
+    }
+    return *this;
+  }
+
+  template <typename T>
+  bool is() const {
+    return isImpl(static_cast<T*>(NULL));
+  }
+
+  template <typename T>
+  T get() const {
+    assert(is<T>());
+    return getImpl(static_cast<T*>(NULL));
+  }
+
+ private:
+  void Reset() {
+    switch (Type) {
+      case VT_String:  delete Value.String;  break;
+      case VT_Error:   delete Value.Error;   break;
+      case VT_Matcher: delete Value.Matcher; break;
+      case VT_Number:  delete Value.Number;  break;
+      // Cases that do nothing.
+      case VT_Bool: break;
+      case VT_Nothing: break;
+    }
+    Type = VT_Nothing;
+  }
+
+  // std::string
+  bool isImpl(std::string* Dummy) const { return Type == VT_String; }
+  const std::string& getImpl(std::string* Dummy) const {
+    return *Value.String;
+  }
+  void setImpl(const std::string& NewValue) {
+    Type = VT_String;
+    Value.String = new std::string(NewValue);
+  }
+
+  // GenericError
+  bool isImpl(GenericError* Dummy) const { return Type == VT_Error; }
+  const GenericError& getImpl(GenericError* Dummy) const {
+    return *Value.Error;
+  }
+  void setImpl(const GenericError& NewValue) {
+    Type = VT_Error;
+    Value.Error = new GenericError(NewValue);
+  }
+
+  // bool
+  bool isImpl(bool* Dummy) const { return Type == VT_Bool; }
+  bool getImpl(bool* Dummy) const { return Value.Bool; }
+  void setImpl(bool NewValue) {
+    Type = VT_Bool;
+    Value.Bool = NewValue;
+  }
+
+  // GenericMatcher and Matcher<T>
+  bool isImpl(GenericMatcher* Dummy) const { return Type == VT_Matcher; }
+  const GenericMatcher& getImpl(GenericMatcher* Dummy) const {
+    return *Value.Matcher;
+  }
+  void setImpl(const GenericMatcher& NewValue) {
+    Type = VT_Matcher;
+    Value.Matcher = new GenericMatcher(NewValue);
+  }
+
+  template <typename T>
+  bool isImpl(Matcher<T>* Dummy) const { return Type == VT_Matcher; }
+  template <typename T>
+  Matcher<T> getImpl(Matcher<T>* Dummy) const {
+    return Value.Matcher->getAs<T>();
+  }
+  template <typename T>
+  void setImpl(const Matcher<T>& NewValue) {
+    Type = VT_Matcher;
+    Value.Matcher = new GenericMatcher(NewValue);
+  }
+
+  // All numbers.
+  bool isImpl(NumberHolder* Dummy) const { return Type == VT_Number; }
+  const NumberHolder& getImpl(NumberHolder* Dummy) const {
+    return *Value.Number;
+  }
+  void setImpl(const NumberHolder& NewValue) {
+    Type = VT_Number;
+    Value.Number = new NumberHolder(NewValue);
+  }
+
+  // For now, we assume any other type is a number.
+  // A compile time error should stop any other use since it will not be
+  // compatible with NumberHolder.
+  template <typename T>
+  bool isImpl(T* Dummy) const {
+    return Type == VT_Number && Value.Number->is<T>();
+  }
+  template <typename T>
+  T getImpl(T* Dummy) const {
+    return Value.Number->get<T>();
+  }
+  template <typename T>
+  void setImpl(const T& NewValue) {
+    Type = VT_Number;
+    Value.Number = new NumberHolder(NewValue);
+  }
+
+  enum ValueType {
+    VT_Nothing,
+    VT_Bool,
+    VT_String,
+    VT_Error,
+    VT_Matcher,
+    VT_Number
+  };
+
+  union AllValues {
+    std::string* String;
+    GenericError* Error;
+    bool Bool;
+    GenericMatcher* Matcher;
+    NumberHolder* Number;
+  };
+
+  ValueType Type;
+  AllValues Value;
+};
+
+}  // end namespace dynamic
+}  // end namespace ast_matchers
+}  // end namespace clang
+
+#endif  // LLVM_CLANG_AST_MATCHERS_DYNAMIC_GENERIC_VALUE_H

Propchange: cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/GenericValue.h
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/NumberHolder.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/NumberHolder.h?rev=157622&view=auto
==============================================================================
--- cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/NumberHolder.h (added)
+++ cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/NumberHolder.h Tue May 29 09:10:54 2012
@@ -0,0 +1,115 @@
+//===--- NumberHolder.h - Generic number type -*- C++ -*-===/
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  Implements a simple number type holder data structure.
+//  It provides the storage for the value plus templated conversion operators
+//  to any other numeric type.
+//  Used as the underlying number value on GenericValue.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_NUMBER_HOLDER_H
+#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_NUMBER_HOLDER_H
+
+#include <limits>
+
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/type_traits.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+class NumberHolder {
+ public:
+  template <typename T>
+  explicit NumberHolder(T Input) {
+    if (convertToImpl(Input, &Value.Unsigned64)) {
+      Type = NT_Unsigned64;
+    } else if (convertToImpl(Input, &Value.Signed64)) {
+      Type = NT_Signed64;
+    } else if (convertToImpl(Input, &Value.Double)) {
+      Type = NT_Double;
+    } else {
+      Type = NT_Nothing;
+    }
+  }
+
+  template <typename T>
+  bool is() const {
+    T Converted;
+    return convertTo(&Converted);
+  }
+  template <typename T>
+  T get() const {
+    T Converted;
+    convertTo(&Converted);
+    return Converted;
+  }
+
+ private:
+  template <typename DestType>
+  bool convertTo(DestType* Dest) const {
+    switch (Type) {
+      case NT_Unsigned64: return convertToImpl(Value.Unsigned64, Dest);
+      case NT_Signed64:   return convertToImpl(Value.Signed64, Dest);
+      case NT_Double:     return convertToImpl(Value.Double, Dest);
+      case NT_Nothing:    return false;
+    }
+    return false;
+  }
+
+  template <typename SourceType, typename DestType>
+  static bool convertToImpl(const SourceType Source, DestType* Dest) {
+    *Dest = Source;
+    // Try to convert back. This makes sure we didn't lose precision.
+    // Eg. Like converting 1.1 to int.
+    if (SourceType(*Dest) != Source) return false;
+    // Make sure that we didn't change the sign.
+    // Eg. Converting -1 to uint32_t.
+    if (isNegative(*Dest) ^ isNegative(Source))
+      return false;
+    return true;
+  }
+
+  template <typename ValueType>
+  struct CanBeNegative : public llvm::integral_constant<
+      bool, std::numeric_limits<ValueType>::is_signed> {};
+
+  template <typename ValueType>
+  static bool isNegative(ValueType Value, llvm::true_type CanBeNegative) {
+    return Value < 0;
+  }
+  template <typename ValueType>
+  static bool isNegative(ValueType Value, llvm::false_type CanBeNegative) {
+    return false;
+  }
+  template <typename ValueType>
+  static bool isNegative(ValueType Value) {
+    return isNegative(Value, CanBeNegative<ValueType>());
+  }
+
+  enum Type {
+    NT_Nothing,
+    NT_Unsigned64,
+    NT_Signed64,
+    NT_Double
+  };
+  Type Type;
+  union {
+    uint64_t Unsigned64;
+    int64_t Signed64;
+    double Double;
+  } Value;
+};
+
+}  // end namespace dynamic
+}  // end namespace ast_matchers
+}  // end namespace clang
+
+#endif  // LLVM_CLANG_AST_MATCHERS_DYNAMIC_NUMBER_HOLDER_H

Propchange: cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/NumberHolder.h
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/Parser.h?rev=157622&view=auto
==============================================================================
--- cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/Parser.h (added)
+++ cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/Parser.h Tue May 29 09:10:54 2012
@@ -0,0 +1,65 @@
+//===--- Parser.h - Matcher expression parser -----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Simple matcher expression parser.
+// The parser understand matcher expressions of the form:
+//   MatcherName(Arg0, Arg1, ..., ArgN)
+// as well as simple types like string, character, number and boolean literals.
+// The parser does not know how to process the matchers. It delegates this task
+// to a TokenProcessor object received as an argument.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H
+#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H
+
+#include <vector>
+
+#include "clang/ASTMatchers/Dynamic/GenericValue.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+class Parser {
+ public:
+  struct TokenInfo {
+    llvm::StringRef Token;
+    int StartLine;
+    int EndLine;
+    int StartColumn;
+    int EndColumn;
+  };
+
+  class TokenProcessor {
+   public:
+    virtual ~TokenProcessor(){}
+    virtual GenericValue processValueToken(const GenericValue& Value,
+                                           const TokenInfo& Info) {
+      return Value;
+    }
+    virtual GenericValue processMatcherToken(
+        llvm::StringRef MatcherName,
+        const std::vector<GenericValue>& Args,
+        const TokenInfo& Info) = 0;
+  };
+
+  static GenericValue parseMatcher(llvm::StringRef MatcherCode,
+                                   TokenProcessor* Processor);
+
+ private:
+  Parser();  // Declared, but not defined.
+};
+
+}  // namespace dynamic
+}  // namespace ast_matchers
+}  // namespace clang
+
+#endif  // LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H

Propchange: cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/Parser.h
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/Registry.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/Registry.h?rev=157622&view=auto
==============================================================================
--- cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/Registry.h (added)
+++ cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/Registry.h Tue May 29 09:10:54 2012
@@ -0,0 +1,47 @@
+//===--- Registry.h - Matcher registry -----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Registry of all known matchers.
+// The registry provides a generic interface to construct any matcher by name.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H
+#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H
+
+#include <string>
+#include <vector>
+
+#include "clang/ASTMatchers/Dynamic/GenericValue.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+class Registry {
+ public:
+  // Consult the registry of known matchers and construct the appropriate
+  // matcher by name.
+  // It will return GenericError if the matcher is not found, or if the
+  // number of arguments or argument types do not match the signature.
+  static GenericValue constructMatcher(const std::string& MatcherName,
+                                       const std::vector<GenericValue>& Args);
+
+  static const std::string* getTypeMatcherName(const std::string& TypeName);
+  static bool isKindName(const std::string& MatcherName);
+
+ private:
+  Registry();  // Declared, but not defined.
+};
+
+}  // namespace dynamic
+}  // namespace ast_matchers
+}  // namespace clang
+
+#endif  // LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H

Propchange: cfe/branches/tooling/include/clang/ASTMatchers/Dynamic/Registry.h
------------------------------------------------------------------------------
    svn:eol-style = LF

Modified: cfe/branches/tooling/lib/ASTMatchers/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/ASTMatchers/CMakeLists.txt?rev=157622&r1=157621&r2=157622&view=diff
==============================================================================
--- cfe/branches/tooling/lib/ASTMatchers/CMakeLists.txt (original)
+++ cfe/branches/tooling/lib/ASTMatchers/CMakeLists.txt Tue May 29 09:10:54 2012
@@ -1,3 +1,5 @@
+add_subdirectory(Dynamic)
+
 set(LLVM_LINK_COMPONENTS support)
 SET(LLVM_USED_LIBS clangBasic clangAST)
 

Added: cfe/branches/tooling/lib/ASTMatchers/Dynamic/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/ASTMatchers/Dynamic/CMakeLists.txt?rev=157622&view=auto
==============================================================================
--- cfe/branches/tooling/lib/ASTMatchers/Dynamic/CMakeLists.txt (added)
+++ cfe/branches/tooling/lib/ASTMatchers/Dynamic/CMakeLists.txt Tue May 29 09:10:54 2012
@@ -0,0 +1,7 @@
+set(LLVM_LINK_COMPONENTS support)
+SET(LLVM_USED_LIBS clangBasic clangAST clangASTMatchers)
+
+add_clang_library(clangDynamicASTMatchers
+  Parser.cpp
+  Registry.cpp
+  )

Propchange: cfe/branches/tooling/lib/ASTMatchers/Dynamic/CMakeLists.txt
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: cfe/branches/tooling/lib/ASTMatchers/Dynamic/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/ASTMatchers/Dynamic/Makefile?rev=157622&view=auto
==============================================================================
--- cfe/branches/tooling/lib/ASTMatchers/Dynamic/Makefile (added)
+++ cfe/branches/tooling/lib/ASTMatchers/Dynamic/Makefile Tue May 29 09:10:54 2012
@@ -0,0 +1,13 @@
+##===- clang/lib/ASTMatchers/Dynamic/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 := clangDynamicASTMatchers
+
+include $(CLANG_LEVEL)/Makefile

Propchange: cfe/branches/tooling/lib/ASTMatchers/Dynamic/Makefile
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: cfe/branches/tooling/lib/ASTMatchers/Dynamic/Marshallers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/ASTMatchers/Dynamic/Marshallers.h?rev=157622&view=auto
==============================================================================
--- cfe/branches/tooling/lib/ASTMatchers/Dynamic/Marshallers.h (added)
+++ cfe/branches/tooling/lib/ASTMatchers/Dynamic/Marshallers.h Tue May 29 09:10:54 2012
@@ -0,0 +1,276 @@
+//===--- Marshallers.h - Generic matcher function marshallers -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// A collection of template function and classes that provide a generic
+// marshalling layer on top of matcher construct functions.
+// These are used by the registry to export all marshaller constructors with
+// the same generic interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H
+#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H
+
+#include <list>
+#include <string>
+#include <vector>
+
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/Dynamic/GenericMatcher.h"
+#include "clang/ASTMatchers/Dynamic/GenericValue.h"
+#include "llvm/Support/type_traits.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+namespace internal {
+
+// Generic MatcherCreate interface.
+// Provides a run() method that constructs the matcher from the provided
+// arguments.
+class MatcherCreateCallback {
+ public:
+  virtual ~MatcherCreateCallback() { }
+  virtual GenericValue run(const std::vector<GenericValue>& Args) const = 0;
+};
+
+// Generic callback implementation.
+// The Marshaller function will unpack the arguments, call Func and repack the
+// return value.
+// It should also check that the arguments are valid for Func.
+template <typename MarshallerType, typename FuncType>
+class MatcherCreateCallbackImpl : public MatcherCreateCallback {
+ public:
+  MatcherCreateCallbackImpl(MarshallerType Marshaller,
+                            FuncType Func,
+                            const std::string& MatcherName)
+      : Marshaller(Marshaller), Func(Func), MatcherName(MatcherName) { }
+
+  GenericValue run(const std::vector<GenericValue>& Args) const {
+    return Marshaller(Func, MatcherName, Args);
+  }
+ private:
+  const MarshallerType Marshaller;
+  const FuncType Func;
+  const std::string MatcherName;
+};
+
+template <typename MarshallerType, typename FuncType>
+MatcherCreateCallback* CreateMarshallerCallback(
+    MarshallerType Marshaller,
+    FuncType Func,
+    const std::string& MatcherName) {
+  return new MatcherCreateCallbackImpl<MarshallerType, FuncType>(
+      Marshaller, Func, MatcherName);
+}
+
+#define CHECK_ARG_COUNT(count)                                        \
+    if (Args.size() != count) {                                       \
+      return GenericError(llvm::Twine(                                \
+          "Incorrect argument count on function " + MatcherName +     \
+          ". (Expected = " + llvm::Twine(count) +                     \
+          ") != (Actual = " + llvm::Twine(Args.size()) + ")").str()); \
+    }
+#define CHECK_ARG_TYPE(index, type)                                \
+    if (Args[index].is<GenericError>()) return Args[index];        \
+    if (!Args[index].is<type>()) {                                 \
+      return GenericError(llvm::Twine(                             \
+          "Incorrect type on function " + MatcherName +            \
+         " for arg " + llvm::Twine(index)).str());                 \
+    }
+
+// 0-arg marshaller function.
+template <typename FuncType, typename ReturnType>
+GenericValue MatcherMarshall0(FuncType Func,
+                              const std::string& MatcherName,
+                              const std::vector<GenericValue>& Args) {
+  CHECK_ARG_COUNT(0);
+  return GenericValue(ReturnType(Func()));
+}
+
+// 1-arg marshaller function.
+template <typename FuncType, typename ReturnType, typename ArgType1>
+GenericValue MatcherMarshall1(FuncType Func,
+                              const std::string& MatcherName,
+                              const std::vector<GenericValue>& Args) {
+  CHECK_ARG_COUNT(1);
+  CHECK_ARG_TYPE(0, ArgType1);
+  return GenericValue(ReturnType(Func(Args[0].get<ArgType1>())));
+}
+
+// 2-arg marshaller function.
+template <typename FuncType, typename ReturnType,
+          typename ArgType1, typename ArgType2>
+GenericValue MatcherMarshall2(FuncType Func,
+                              const std::string& MatcherName,
+                              const std::vector<GenericValue>& Args) {
+  CHECK_ARG_COUNT(2);
+  CHECK_ARG_TYPE(0, ArgType1);
+  CHECK_ARG_TYPE(1, ArgType2);
+  return GenericValue(ReturnType(Func(Args[0].get<ArgType1>(),
+                                      Args[1].get<ArgType2>())));
+}
+
+// Variadic marshaller function.
+template <typename BaseType, typename DerivedType>
+class MatcherMarshallVariadic : public MatcherCreateCallback {
+ public:
+  explicit MatcherMarshallVariadic(const std::string& MatcherName)
+      : MatcherName(MatcherName) { }
+
+  typedef Matcher<DerivedType> DerivedMatcherType;
+
+  GenericValue run(const std::vector<GenericValue>& Args) const {
+    std::list<DerivedMatcherType> References;
+    std::vector<const DerivedMatcherType*> InnerArgs(Args.size());
+    for (size_t i = 0; i < Args.size(); ++i) {
+      CHECK_ARG_TYPE(i, DerivedMatcherType);
+      References.push_back(Args[i].get<DerivedMatcherType>());
+      InnerArgs[i] = &References.back();
+    }
+    return GenericValue(
+        ast_matchers::internal::MakeDynCastAllOfComposite<BaseType>(
+            ArrayRef<const DerivedMatcherType*>(InnerArgs)));
+  }
+
+ private:
+  const std::string MatcherName;
+};
+
+#undef CHECK_ARG_COUNT
+#undef CHECK_ARG_TYPE
+
+// We need to remove the const& out of the function parameters to be able to
+// find values on GenericValue.
+template <typename T>
+struct remove_const_ref
+    : public llvm::remove_const<typename llvm::remove_reference<T>::type> {
+};
+
+// Helper functions to select the appropriate marshaller functions.
+// We have two names:
+//  - MakeMatcherAutoMarshall: Detects the number of arguments, arguments types
+//  and return types.
+//  - MakeMatcherAutoMarshallPoly: Same as MakeMatcherAutoMarshall, but allows
+//  passing the desired return type for polymorphic matchers.
+
+// 0-arg
+template <typename ReturnType, typename PolyReturnType>
+MatcherCreateCallback* MakeMatcherAutoMarshallPoly(
+    PolyReturnType (*Func)(),
+    const std::string& MatcherName) {
+  return CreateMarshallerCallback(
+      MatcherMarshall0<PolyReturnType(*)(), ReturnType>, Func, MatcherName);
+}
+template <typename ReturnType>
+MatcherCreateCallback* MakeMatcherAutoMarshall(
+    ReturnType (*Func)(),
+    const std::string& MatcherName) {
+  return MakeMatcherAutoMarshallPoly<ReturnType>(Func, MatcherName);
+}
+
+// 1-arg
+template <typename ReturnType, typename PolyReturnType, typename InArgType1>
+MatcherCreateCallback* MakeMatcherAutoMarshallPoly(
+    PolyReturnType (*Func)(InArgType1),
+    const std::string& MatcherName) {
+  typedef typename remove_const_ref<InArgType1>::type ArgType1;
+  return CreateMarshallerCallback(
+      MatcherMarshall1<PolyReturnType (*)(InArgType1), ReturnType, ArgType1>,
+      Func, MatcherName);
+}
+template <typename ReturnType, typename InArgType1>
+MatcherCreateCallback* MakeMatcherAutoMarshall(
+    ReturnType (*Func)(InArgType1),
+    const std::string& MatcherName) {
+  return MakeMatcherAutoMarshallPoly<ReturnType>(Func, MatcherName);
+}
+
+// 2-arg
+template <typename ReturnType, typename PolyReturnType,
+          typename InArgType1, typename InArgType2>
+MatcherCreateCallback* MakeMatcherAutoMarshallPoly(
+    PolyReturnType (*Func)(InArgType1, InArgType2),
+    const std::string& MatcherName) {
+  typedef typename remove_const_ref<InArgType1>::type ArgType1;
+  typedef typename remove_const_ref<InArgType2>::type ArgType2;
+  return CreateMarshallerCallback(
+      MatcherMarshall2<PolyReturnType (*)(InArgType1, InArgType2),
+                       ReturnType, ArgType1, ArgType2>,
+      Func, MatcherName);
+}
+template <typename ReturnType, typename InArgType1, typename InArgType2>
+MatcherCreateCallback* MakeMatcherAutoMarshall(
+    ReturnType (*Func)(InArgType1, InArgType2),
+    const std::string& MatcherName) {
+  return MakeMatcherAutoMarshallPoly<ReturnType>(Func, MatcherName);
+}
+
+// Variadic
+template <typename BaseType, typename MatcherType>
+MatcherCreateCallback* MakeMatcherAutoMarshall(
+    ast_matchers::internal::VariadicDynCastAllOfMatcher<
+        BaseType, MatcherType> Func,
+    const std::string& MatcherName) {
+  return new MatcherMarshallVariadic<BaseType, MatcherType>(MatcherName);
+}
+
+
+// Some basic functions that are easier to reimplement than reuse.
+class MatcherMarshallAnyOf : public MatcherCreateCallback {
+ public:
+  GenericValue run(const std::vector<GenericValue>& Args) const {
+    if (Args.empty())
+      return GenericError("anyOf() needs at least one argument!");
+
+    // Validate them
+    for (size_t i = 0; i < Args.size(); ++i) {
+      if (!Args[i].is<GenericMatcher>()) {
+        return GenericError(llvm::Twine("Argument " + llvm::Twine(i) +
+                                        " is not a matcher.").str());
+      }
+    }
+
+    GenericMatcher Matcher = Args[0].get<GenericMatcher>();
+    for (size_t i = 1; i < Args.size(); ++i) {
+      Matcher = GenericMatcher::anyOf(Matcher, Args[i].get<GenericMatcher>());
+    }
+    return Matcher;
+  }
+};
+
+class MatcherMarshallAllOf : public MatcherCreateCallback {
+ public:
+  GenericValue run(const std::vector<GenericValue>& Args) const {
+    if (Args.empty())
+      return GenericError("allOf() needs at least one argument!");
+
+    // Validate them
+    for (size_t i = 0; i < Args.size(); ++i) {
+      if (!Args[i].is<GenericMatcher>()) {
+        return GenericError(llvm::Twine("Argument " + llvm::Twine(i) +
+                                        " is not a matcher.").str());
+      }
+    }
+
+    GenericMatcher Matcher = Args[0].get<GenericMatcher>();
+    for (size_t i = 1; i < Args.size(); ++i) {
+      Matcher = GenericMatcher::allOf(Matcher, Args[i].get<GenericMatcher>());
+    }
+    return Matcher;
+  }
+};
+
+}  // namespace internal
+}  // namespace dynamic
+}  // namespace ast_matchers
+}  // namespace clang
+
+#endif  // LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H

Propchange: cfe/branches/tooling/lib/ASTMatchers/Dynamic/Marshallers.h
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: cfe/branches/tooling/lib/ASTMatchers/Dynamic/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/ASTMatchers/Dynamic/Parser.cpp?rev=157622&view=auto
==============================================================================
--- cfe/branches/tooling/lib/ASTMatchers/Dynamic/Parser.cpp (added)
+++ cfe/branches/tooling/lib/ASTMatchers/Dynamic/Parser.cpp Tue May 29 09:10:54 2012
@@ -0,0 +1,294 @@
+//===--- Parser.cpp - Matcher expression parser -----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Simple matcher expression parser.
+// The parser understand matcher expressions of the form:
+//   MatcherName(Arg0, Arg1, ..., ArgN)
+// as well as simple types like string, character, number and boolean literals.
+// The parser does not know how to process the matchers. It delegates this task
+// to a TokenProcessor object received as an argument.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string>
+#include <vector>
+
+#include "clang/ASTMatchers/Dynamic/Parser.h"
+#include "llvm/ADT/Twine.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+namespace {
+
+class CodeTokenizer {
+ public:
+  explicit CodeTokenizer(llvm::StringRef MatcherCode)
+      : Code(MatcherCode), StartOfLine(MatcherCode), Line(1) { }
+
+  Parser::TokenInfo getNextToken() {
+    consumeWhitespace();
+    Parser::TokenInfo Result;
+    Result.StartLine = Line;
+    Result.StartColumn = Column();
+
+    if (Code.empty()) {
+      // Nothing to do.
+    } else if (isSingleCharToken(Code[0])) {
+      Result.Token = Code.substr(0, 1);
+      Code = Code.drop_front();
+
+    } else if (Code[0] == '"' || Code[0] == '\'') {
+      // Parse a string literal.
+      Result.Token = consumeStringLiteral();
+      Code = Code.drop_front(Result.Token.size());
+
+    } else {
+      size_t TokenLength = 0;
+      while (TokenLength < Code.size() &&
+             !isspace(Code[TokenLength]) &&
+             !isSingleCharToken(Code[TokenLength]))
+        ++TokenLength;
+      Result.Token = Code.substr(0, TokenLength);
+      Code = Code.drop_front(TokenLength);
+    }
+
+    Result.EndLine = Line;
+    Result.EndColumn = Column() - 1;
+    return Result;
+  }
+
+  bool isDone() const { return Code.empty(); }
+
+ private:
+  llvm::StringRef consumeStringLiteral() const {
+    bool InEscape = false;
+    const char Marker = Code[0];
+    for (size_t Length = 1; Length < Code.size(); ++Length) {
+      if (InEscape) {
+        InEscape = false;
+        continue;
+      }
+      if (Code[Length] == '\\') {
+        InEscape = true;
+        continue;
+      }
+      if (Code[Length] == Marker) {
+        return Code.substr(0, Length + 1);
+      }
+    }
+    return Code;
+  }
+
+  void consumeWhitespace() {
+    while (!Code.empty() && isspace(Code[0])) {
+      if (Code[0] == '\n') {
+        ++Line;
+        StartOfLine = Code.drop_front();
+      }
+      Code = Code.drop_front();
+    }
+  }
+  static bool isSingleCharToken(const char Char) {
+    return Char == ',' || Char == '(' || Char == ')';
+  }
+
+  llvm::StringRef Code;
+  llvm::StringRef StartOfLine;
+  int Line;
+  int Column() const {
+    return Code.data() - StartOfLine.data() + 1;
+  }
+};
+
+char UnescapeCharSequence(llvm::StringRef* Escaped) {
+  if (Escaped->empty()) return 0;
+  char Char = (*Escaped)[0];
+  *Escaped = Escaped->drop_front();
+  if (Char != '\\') {
+    return Char;
+  }
+
+  if (Escaped->empty()) return 0;
+  Char = (*Escaped)[0];
+  *Escaped = Escaped->drop_front();
+  // TODO: Does not escape octal/hex sequences. Eg. "\123"
+  switch (Char) {
+    case 'a':  Char = '\a';  break;
+    case 'b':  Char = '\b';  break;
+    case 'f':  Char = '\f';  break;
+    case 'n':  Char = '\n';  break;
+    case 'r':  Char = '\r';  break;
+    case 't':  Char = '\t';  break;
+    case 'v':  Char = '\v';  break;
+    case '\\': Char = '\\';  break;
+    case '?':  Char = '\?';  break;
+    case '\'': Char = '\'';  break;
+    case '"':  Char = '\"';  break;
+  }
+  return Char;
+}
+
+GenericValue ParseString(const Parser::TokenInfo& Token,
+                         Parser::TokenProcessor* Processor) {
+  if (Token.Token.size() < 2 ||
+      !Token.Token.startswith("\"") || !Token.Token.endswith("\"")) {
+    return GenericError(
+        llvm::Twine("Error parsing string token: <" + Token.Token + ">").str());
+  }
+
+  llvm::StringRef Escaped = Token.Token.drop_front().drop_back();
+  std::string Unescaped;
+
+  while (!Escaped.empty()) {
+    Unescaped.push_back(UnescapeCharSequence(&Escaped));
+  }
+
+  GenericValue Value = Unescaped;
+  return Processor->processValueToken(Value, Token);
+}
+
+GenericValue ParseChar(const Parser::TokenInfo& Token,
+                       Parser::TokenProcessor* Processor) {
+  if (Token.Token.size() < 3 ||
+      !Token.Token.startswith("'") || !Token.Token.endswith("'")) {
+    return GenericError(
+        llvm::Twine("Error parsing char token: <" + Token.Token + ">").str());
+  }
+  llvm::StringRef Escaped = Token.Token.drop_front().drop_back();
+  const int Unescaped = UnescapeCharSequence(&Escaped);
+  if (!Escaped.empty()) {
+    return GenericError(
+        llvm::Twine("Error parsing char token: <" + Token.Token + ">").str());
+  }
+
+  GenericValue Value = Unescaped;
+  return Processor->processValueToken(Value, Token);
+}
+
+GenericValue ParseNumber(const Parser::TokenInfo& Token,
+                         Parser::TokenProcessor* Processor) {
+  long long SignedLong;
+  if (!Token.Token.getAsInteger(0, SignedLong)) {
+    return Processor->processValueToken(NumberHolder(SignedLong), Token);
+  }
+  unsigned long long UnsignedLong;
+  if (!Token.Token.getAsInteger(0, UnsignedLong)) {
+    return Processor->processValueToken(NumberHolder(UnsignedLong), Token);
+  }
+
+  // TODO: Figure out a way to do this without copying the token.
+  const std::string AsString = Token.Token;
+  char* endptr = NULL;
+  double Double = strtod(AsString.c_str(), &endptr);
+  if (endptr[0] == 0)
+    return Processor->processValueToken(NumberHolder(Double), Token);
+
+  return GenericError(
+      llvm::Twine("Error parsing number token: <" + Token.Token + ">").str());
+}
+
+GenericValue ParseToken(const Parser::TokenInfo& Token,
+                        CodeTokenizer* Tokenizer,
+                        Parser::TokenProcessor* Processor);
+
+GenericValue ParseMatcher(const Parser::TokenInfo& Token,
+                          CodeTokenizer* Tokenizer,
+                          Parser::TokenProcessor* Processor) {
+  const Parser::TokenInfo& OpenToken = Tokenizer->getNextToken();
+  if (OpenToken.Token != "(") {
+    return GenericError(
+        llvm::Twine("Error parsing matcher. Found token <" +
+                    OpenToken.Token + "> while looking for '('").str());
+  }
+
+  std::vector<GenericValue> Args;
+  Parser::TokenInfo EndToken;
+  while (!Tokenizer->isDone()) {
+    Parser::TokenInfo NextToken = Tokenizer->getNextToken();
+    if (NextToken.Token == ")") {
+      // End of args.
+      EndToken = NextToken;
+      break;
+    }
+    if (Args.size() > 0) {
+      // We must find a , token to continue.
+      if (NextToken.Token != ",") {
+        return GenericError(
+            llvm::Twine("Error parsing matcher. Found token <" +
+                        NextToken.Token + "> while looking for ','").str());
+      }
+      NextToken = Tokenizer->getNextToken();
+    }
+    const GenericValue Arg = ParseToken(NextToken, Tokenizer, Processor);
+    if (Arg.is<GenericError>()) {
+      return GenericError(
+          llvm::Twine("Error parsing argument " + llvm::Twine(Args.size()) +
+                      " for matcher " + Token.Token + ": " +
+                      Arg.get<GenericError>().Message).str());
+    }
+    Args.push_back(Arg);
+  }
+
+  if (EndToken.Token == "") {
+    return GenericError("Error parsing matcher. Found end-of-code while "
+                        "looking for ')'");
+  }
+
+  // Merge the start and end infos.
+  Parser::TokenInfo NewInfo = Token;
+  NewInfo.EndLine = EndToken.EndLine;
+  NewInfo.EndColumn = EndToken.EndColumn;
+  const GenericValue Result = Processor->processMatcherToken(
+      Token.Token, Args, NewInfo);
+  if (Result.is<GenericError>()) {
+    return GenericError(
+        llvm::Twine("Error building matcher " + Token.Token +
+                    ": " + Result.get<GenericError>().Message).str());
+  }
+
+  return Result;
+}
+
+GenericValue ParseToken(const Parser::TokenInfo& Token,
+                        CodeTokenizer* Tokenizer,
+                        Parser::TokenProcessor* Processor) {
+  if (Token.Token.empty()) {
+    return GenericError("End of code found while looking for token.");
+  }
+
+  if (Token.Token[0] == '"') return ParseString(Token, Processor);
+  if (Token.Token[0] == '\'') return ParseChar(Token, Processor);
+  if (isdigit(Token.Token[0]) ||
+      Token.Token[0] == '-' || Token.Token[0] == '+') {
+    return ParseNumber(Token, Processor);
+  }
+
+  // TODO: Do this better when we have more constants.
+  // TODO: Add more constants (like INT_MAX and stuff like that).
+  if (Token.Token == "true")
+    return Processor->processValueToken(true, Token);
+  if (Token.Token == "false")
+    return Processor->processValueToken(false, Token);
+
+  return ParseMatcher(Token, Tokenizer, Processor);
+}
+
+}  // anonymous namespace
+
+GenericValue Parser::parseMatcher(llvm::StringRef Code,
+                                  Parser::TokenProcessor* Processor) {
+  CodeTokenizer Tokenizer(Code);
+  return ParseToken(Tokenizer.getNextToken(), &Tokenizer, Processor);
+}
+
+}  // namespace dynamic
+}  // namespace ast_matchers
+}  // namespace clang

Propchange: cfe/branches/tooling/lib/ASTMatchers/Dynamic/Parser.cpp
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: cfe/branches/tooling/lib/ASTMatchers/Dynamic/Registry.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/ASTMatchers/Dynamic/Registry.cpp?rev=157622&view=auto
==============================================================================
--- cfe/branches/tooling/lib/ASTMatchers/Dynamic/Registry.cpp (added)
+++ cfe/branches/tooling/lib/ASTMatchers/Dynamic/Registry.cpp Tue May 29 09:10:54 2012
@@ -0,0 +1,371 @@
+//===--- Registry.cpp - Matcher registry ------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Registry of all known matchers.
+// The registry provides a generic interface to construct any matcher by name.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ASTMatchers/Dynamic/Registry.h"
+
+#include <map>
+#include <set>
+#include <utility>
+
+#include "Marshallers.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/Dynamic/GenericMatcher.h"
+#include "llvm/ADT/OwningPtr.h"
+
+namespace clang {
+
+// A utility function that returns that name of a type, for all the types
+// defined in the AST.
+#define DECL(DERIVED, BASE) \
+class DERIVED##Decl; \
+const char* GetRegistryTypeName(DERIVED##Decl* dummy) { return #DERIVED; }
+#include "clang/AST/DeclNodes.inc"
+#define STMT(CLASS, PARENT) \
+class CLASS; \
+const char* GetRegistryTypeName(CLASS* dummy) { return #CLASS; }
+#include "clang/AST/StmtNodes.inc"
+const char* GetRegistryTypeName(Stmt* dummy) { return "Stmt"; }
+
+namespace ast_matchers {
+
+// Create some functions to help disambiguate certain overloaded matchers.
+
+#define MAKE_HELPER_POLY_FUNCTION1(func, name, R) \
+template <typename P1> \
+R name(const P1& t1) { return func(t1); } \
+
+MAKE_HELPER_POLY_FUNCTION1(HasType, HasType_Expr,
+                           internal::Matcher<clang::Expr>)
+MAKE_HELPER_POLY_FUNCTION1(HasType, HasType_ValueDecl,
+                           internal::Matcher<clang::ValueDecl>)
+
+namespace dynamic {
+
+namespace {
+
+using internal::MatcherCreateCallback;
+
+typedef std::map<std::string, const MatcherCreateCallback*> ConstructorMap;
+typedef std::map<std::string, std::string> KindNameMap;
+typedef std::set<std::string> KindSet;
+struct RegistryMaps {
+  ConstructorMap Constructors;
+  KindNameMap KindNames;
+  KindSet AllKinds;
+};
+
+// If both input callbacks return a matcher, the output will be anyOf() of them.
+// If only one of them (any of them) returns a matcher, the output will be that
+// returned matcher.
+// If they both return an error, the output will be any of them.
+class MatcherCallbackUnion : public MatcherCreateCallback {
+ public:
+  MatcherCallbackUnion(const MatcherCreateCallback* Callback1,
+                       const MatcherCreateCallback* Callback2)
+      : Callback1(Callback1), Callback2(Callback2) { }
+
+  GenericValue run(const std::vector<GenericValue>& args) const {
+    // If they are both matchers, return the union of them.
+    // If only one is a matcher, return that one.
+    // Otherwise, return any of them, which should be an error.
+    const GenericValue Out1 = Callback1->run(args);
+    const GenericValue Out2 = Callback2->run(args);
+    if (!Out1.is<GenericMatcher>()) {
+      return Out2;
+    } else if (!Out2.is<GenericMatcher>()) {
+      return Out1;
+    } else {
+      return GenericMatcher::anyOf(Out1.get<GenericMatcher>(),
+                                   Out2.get<GenericMatcher>());
+    }
+  }
+
+ private:
+  const llvm::OwningPtr<const MatcherCreateCallback> Callback1;
+  const llvm::OwningPtr<const MatcherCreateCallback> Callback2;
+};
+
+void RegisterMatcher(const std::string& MatcherName,
+                     MatcherCreateCallback* Callback,
+                     RegistryMaps* Data) {
+  const MatcherCreateCallback** MapCallback = &Data->Constructors[MatcherName];
+  if (*MapCallback) {
+    Callback = new MatcherCallbackUnion(*MapCallback, Callback);
+  }
+  *MapCallback = Callback;
+}
+
+template <typename T>
+void RegisterKindName(const std::string& MatcherName, const T& t,
+                      RegistryMaps* Data) { }
+template <typename Base, typename Type>
+void RegisterKindName(
+    const std::string& MatcherName,
+    ast_matchers::internal::VariadicDynCastAllOfMatcher<Base, Type> Func,
+    RegistryMaps* Data) {
+  Data->KindNames[GetRegistryTypeName(static_cast<Type*>(NULL))] = MatcherName;
+  Data->AllKinds.insert(MatcherName);
+}
+
+#define MATCH_NS ::clang::ast_matchers
+
+#define REGISTER_NAMED_MATCHER_AUTO(name, func)                               \
+    RegisterMatcher(#name,                                                    \
+                    internal::MakeMatcherAutoMarshall(MATCH_NS::func, #name), \
+                    Data)
+
+#define REGISTER_MATCHER_AUTO(name)                                           \
+    REGISTER_NAMED_MATCHER_AUTO(name, name);                                  \
+    RegisterKindName(#name, MATCH_NS::name, Data)
+
+#define REGISTER_POLY_NAMED_MATCHER_AUTO(name, func, R)                       \
+    RegisterMatcher(#name,                                                    \
+                    internal::MakeMatcherAutoMarshallPoly<Matcher<R> >(       \
+                        MATCH_NS::func, #name), Data)
+
+#define REGISTER_POLY_MATCHER_AUTO(name, R)                                   \
+    REGISTER_POLY_NAMED_MATCHER_AUTO(name, name, R)
+
+#define REGISTER_MATCHER1(name, R, P1)                                        \
+    RegisterMatcher(#name, internal::MakeMatcherAutoMarshallPoly<R, R, P1>(   \
+        MATCH_NS::name, #name), Data)
+
+RegistryMaps* RegisterMatchers() {
+  RegistryMaps* Data = new RegistryMaps();
+
+  REGISTER_MATCHER_AUTO(BinaryOperator);
+  REGISTER_MATCHER_AUTO(BindTemporaryExpression);
+  REGISTER_MATCHER_AUTO(BoolLiteral);
+  REGISTER_MATCHER_AUTO(Call);
+  REGISTER_MATCHER_AUTO(CharacterLiteral);
+  REGISTER_MATCHER_AUTO(Class);
+  REGISTER_MATCHER_AUTO(CompoundStatement);
+  REGISTER_MATCHER_AUTO(ConditionalOperator);
+  REGISTER_MATCHER_AUTO(ConstCast);
+  REGISTER_MATCHER_AUTO(Constructor);
+  REGISTER_MATCHER_AUTO(ConstructorCall);
+  REGISTER_MATCHER_AUTO(DeclarationReference);
+  REGISTER_MATCHER_AUTO(DeclarationStatement);
+  REGISTER_MATCHER_AUTO(DefaultArgument);
+  REGISTER_MATCHER_AUTO(Do);
+  REGISTER_MATCHER_AUTO(DynamicCast);
+  REGISTER_MATCHER_AUTO(ExplicitCast);
+  REGISTER_MATCHER_AUTO(Expression);
+  REGISTER_MATCHER_AUTO(Field);
+  REGISTER_MATCHER_AUTO(For);
+  REGISTER_MATCHER_AUTO(ForField);
+  REGISTER_MATCHER_AUTO(Function);
+  REGISTER_MATCHER_AUTO(FunctionalCast);
+  REGISTER_MATCHER_AUTO(HasAnyConstructorInitializer);
+  REGISTER_MATCHER_AUTO(HasAnyConstructorInitializer);
+  REGISTER_MATCHER_AUTO(HasAnyParameter);
+  REGISTER_MATCHER_AUTO(HasAnySubstatement);
+  REGISTER_MATCHER_AUTO(HasBody);
+  REGISTER_MATCHER_AUTO(HasConditionVariableStatement);
+  REGISTER_MATCHER_AUTO(HasDestinationType);
+  REGISTER_MATCHER_AUTO(HasEitherOperand);
+  REGISTER_MATCHER_AUTO(HasFalseExpression);
+  REGISTER_MATCHER_AUTO(HasImplicitDestinationType);
+  REGISTER_MATCHER_AUTO(HasInitializer);
+  REGISTER_MATCHER_AUTO(HasLHS);
+  REGISTER_MATCHER_AUTO(HasName);
+  REGISTER_MATCHER_AUTO(HasObjectExpression);
+  REGISTER_MATCHER_AUTO(HasOverloadedOperatorName);
+  REGISTER_MATCHER_AUTO(HasParameter);
+  REGISTER_MATCHER_AUTO(HasRHS);
+  REGISTER_MATCHER_AUTO(HasSourceExpression);
+  REGISTER_MATCHER_AUTO(HasTrueExpression);
+  REGISTER_MATCHER_AUTO(HasUnaryOperand);
+  REGISTER_MATCHER_AUTO(If);
+  REGISTER_MATCHER_AUTO(ImplicitCast);
+  REGISTER_MATCHER_AUTO(IntegerLiteral);
+  REGISTER_MATCHER_AUTO(IsArrow);
+  REGISTER_MATCHER_AUTO(IsConstQualified);
+  REGISTER_MATCHER_AUTO(IsDerivedFrom);
+  REGISTER_MATCHER_AUTO(IsImplicit);
+  REGISTER_MATCHER_AUTO(IsWritten);
+  REGISTER_MATCHER_AUTO(Member);
+  REGISTER_MATCHER_AUTO(MemberExpression);
+  REGISTER_MATCHER_AUTO(Method);
+  REGISTER_MATCHER_AUTO(NameableDeclaration);
+  REGISTER_MATCHER_AUTO(NewExpression);
+  REGISTER_MATCHER_AUTO(OfClass);
+  REGISTER_MATCHER_AUTO(On);
+  REGISTER_MATCHER_AUTO(OnImplicitObjectArgument);
+  REGISTER_MATCHER_AUTO(OverloadedOperatorCall);
+  REGISTER_MATCHER_AUTO(ReinterpretCast);
+  REGISTER_MATCHER_AUTO(Statement);
+  REGISTER_MATCHER_AUTO(StatementCountIs);
+  REGISTER_MATCHER_AUTO(StaticCast);
+  REGISTER_MATCHER_AUTO(StringLiteral);
+  REGISTER_MATCHER_AUTO(SwitchCase);
+  REGISTER_MATCHER_AUTO(To);
+  REGISTER_MATCHER_AUTO(UnaryOperator);
+  REGISTER_MATCHER_AUTO(Variable);
+  REGISTER_MATCHER_AUTO(While);
+  REGISTER_MATCHER_AUTO(WithInitializer);
+
+  // HasType is very special. It is overloaded on parameter and return value.
+  REGISTER_NAMED_MATCHER_AUTO(HasType, HasType_Expr<Matcher<clang::QualType> >);
+  REGISTER_NAMED_MATCHER_AUTO(HasType, HasType_Expr<Matcher<clang::Decl> >);
+  REGISTER_NAMED_MATCHER_AUTO(HasType,
+                              HasType_ValueDecl<Matcher<clang::QualType> >);
+  REGISTER_NAMED_MATCHER_AUTO(HasType,
+                              HasType_ValueDecl<Matcher<clang::Decl> >);
+
+  // True
+  REGISTER_POLY_MATCHER_AUTO(True, clang::Stmt);
+  REGISTER_POLY_MATCHER_AUTO(True, clang::QualType);
+  REGISTER_POLY_MATCHER_AUTO(True, clang::Decl);
+  REGISTER_POLY_MATCHER_AUTO(True, clang::CXXCtorInitializer);
+
+  // HasAnyArgument
+  REGISTER_POLY_MATCHER_AUTO(HasAnyArgument, clang::CallExpr);
+  REGISTER_POLY_MATCHER_AUTO(HasAnyArgument, clang::CXXConstructExpr);
+
+  // HasDeclaration
+  REGISTER_POLY_MATCHER_AUTO(HasDeclaration, clang::QualType);
+  REGISTER_POLY_MATCHER_AUTO(HasDeclaration, clang::CallExpr);
+  REGISTER_POLY_MATCHER_AUTO(HasDeclaration, clang::CXXConstructExpr);
+
+  // HasArgument
+  REGISTER_POLY_MATCHER_AUTO(HasArgument, clang::CallExpr);
+  REGISTER_POLY_MATCHER_AUTO(HasArgument, clang::CXXConstructExpr);
+
+  // HasOperatorName
+  REGISTER_POLY_MATCHER_AUTO(HasOperatorName, clang::BinaryOperator);
+  REGISTER_POLY_MATCHER_AUTO(HasOperatorName, clang::UnaryOperator);
+
+  // IsDefinition
+  REGISTER_POLY_MATCHER_AUTO(IsDefinition, clang::TagDecl);
+  REGISTER_POLY_MATCHER_AUTO(IsDefinition, clang::VarDecl);
+  REGISTER_POLY_MATCHER_AUTO(IsDefinition, clang::FunctionDecl);
+
+  // IsTemplateInstantiation
+  REGISTER_POLY_MATCHER_AUTO(IsTemplateInstantiation, clang::FunctionDecl);
+  REGISTER_POLY_MATCHER_AUTO(IsTemplateInstantiation, clang::VarDecl);
+  REGISTER_POLY_MATCHER_AUTO(IsTemplateInstantiation, clang::CXXRecordDecl);
+
+  // ArgumentCountIs
+  REGISTER_POLY_MATCHER_AUTO(ArgumentCountIs, clang::CallExpr);
+  REGISTER_POLY_MATCHER_AUTO(ArgumentCountIs, clang::CXXConstructExpr);
+
+  // For if() and (?:)
+  REGISTER_POLY_MATCHER_AUTO(HasCondition, clang::IfStmt);
+  REGISTER_POLY_MATCHER_AUTO(HasCondition, clang::ConditionalOperator);
+
+  // Equals. TODO: Needs more.
+  REGISTER_POLY_NAMED_MATCHER_AUTO(Equals, Equals<bool>,
+                                   clang::CXXBoolLiteralExpr);
+  REGISTER_POLY_NAMED_MATCHER_AUTO(Equals, Equals<unsigned long long>,
+                                   clang::IntegerLiteral);
+  REGISTER_POLY_NAMED_MATCHER_AUTO(Equals, Equals<long long>,
+                                   clang::IntegerLiteral);
+  REGISTER_POLY_NAMED_MATCHER_AUTO(Equals, Equals<unsigned>,
+                                   clang::CharacterLiteral);
+
+  // Has/hasDescendant/forEach/forEachDescendant for Decl and Stmt
+  REGISTER_POLY_NAMED_MATCHER_AUTO(Has, has<clang::Decl>, clang::Decl);
+  REGISTER_POLY_NAMED_MATCHER_AUTO(Has, has<clang::Stmt>, clang::Stmt);
+  REGISTER_POLY_NAMED_MATCHER_AUTO(hasDescendant, hasDescendant<clang::Decl>,
+                                   clang::Decl);
+  REGISTER_POLY_NAMED_MATCHER_AUTO(hasDescendant, hasDescendant<clang::Stmt>,
+                                   clang::Stmt);
+  REGISTER_POLY_NAMED_MATCHER_AUTO(forEach, forEach<clang::Decl>, clang::Decl);
+  REGISTER_POLY_NAMED_MATCHER_AUTO(forEach, forEach<clang::Stmt>, clang::Stmt);
+  REGISTER_POLY_NAMED_MATCHER_AUTO(forEachDescendant,
+                                   forEachDescendant<clang::Decl>, clang::Decl);
+  REGISTER_POLY_NAMED_MATCHER_AUTO(forEachDescendant,
+                                   forEachDescendant<clang::Stmt>, clang::Stmt);
+
+
+  // Id
+  REGISTER_NAMED_MATCHER_AUTO(Id, Id<clang::Decl>);
+  REGISTER_NAMED_MATCHER_AUTO(Id, Id<clang::Stmt>);
+
+  // Not. One per basic type.
+  REGISTER_POLY_NAMED_MATCHER_AUTO(Not, Not<Matcher<clang::Decl> >,
+                                   clang::Decl);
+  REGISTER_POLY_NAMED_MATCHER_AUTO(Not, Not<Matcher<clang::Stmt> >,
+                                   clang::Stmt);
+  REGISTER_POLY_NAMED_MATCHER_AUTO(Not, Not<Matcher<clang::QualType> >,
+                                   clang::QualType);
+  REGISTER_POLY_NAMED_MATCHER_AUTO(Not,
+                                   Not<Matcher<clang::CXXCtorInitializer> >,
+                                   clang::CXXCtorInitializer);
+
+  // ThisPointerType is overloaded.
+  REGISTER_MATCHER1(ThisPointerType, Matcher<clang::CallExpr>,
+                    const Matcher<clang::QualType>&);
+  REGISTER_MATCHER1(ThisPointerType, Matcher<clang::CallExpr>,
+                    const Matcher<clang::Decl>&);
+
+  // Callee is overloaded.
+  REGISTER_MATCHER1(Callee, Matcher<clang::CallExpr>,
+                    const Matcher<clang::Stmt>&);
+  REGISTER_MATCHER1(Callee, Matcher<clang::CallExpr>,
+                    const Matcher<clang::Decl>&);
+
+  // PointsTo is overloaded.
+  REGISTER_MATCHER1(PointsTo, Matcher<clang::QualType>,
+                    const Matcher<clang::QualType>&);
+  REGISTER_MATCHER1(PointsTo, Matcher<clang::QualType>,
+                    const Matcher<clang::Decl>&);
+
+  // References is overloaded.
+  REGISTER_MATCHER1(References, Matcher<clang::QualType>,
+                    const Matcher<clang::QualType>&);
+  REGISTER_MATCHER1(References, Matcher<clang::QualType>,
+                    const Matcher<clang::Decl>&);
+
+  // Some hardcoded marshallers
+  RegisterMatcher("allOf", new internal::MatcherMarshallAllOf, Data);
+  RegisterMatcher("anyOf", new internal::MatcherMarshallAnyOf, Data);
+
+  return Data;
+}
+
+// The registry is const to make it thread-safe.
+static const RegistryMaps* const RegistryData = RegisterMatchers();
+
+}  // anonymous namespace
+
+// static
+GenericValue Registry::constructMatcher(
+    const std::string& MatcherName,
+    const std::vector<GenericValue>& Args) {
+  ConstructorMap::const_iterator it =
+      RegistryData->Constructors.find(MatcherName);
+  if (it == RegistryData->Constructors.end()) {
+    return GenericError("Not found: " + MatcherName);
+  }
+
+  return it->second->run(Args);
+}
+
+// static
+const std::string* Registry::getTypeMatcherName(const std::string& TypeName) {
+  KindNameMap::const_iterator it = RegistryData->KindNames.find(TypeName);
+  if (it == RegistryData->KindNames.end()) return NULL;
+  return &it->second;
+}
+
+// static
+bool Registry::isKindName(const std::string& MatcherName) {
+  return RegistryData->AllKinds.count(MatcherName);
+}
+
+}  // namespace dynamic
+}  // namespace ast_matchers
+}  // namespace clang

Propchange: cfe/branches/tooling/lib/ASTMatchers/Dynamic/Registry.cpp
------------------------------------------------------------------------------
    svn:eol-style = LF

Modified: cfe/branches/tooling/lib/ASTMatchers/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/ASTMatchers/Makefile?rev=157622&r1=157621&r2=157622&view=diff
==============================================================================
--- cfe/branches/tooling/lib/ASTMatchers/Makefile (original)
+++ cfe/branches/tooling/lib/ASTMatchers/Makefile Tue May 29 09:10:54 2012
@@ -10,4 +10,6 @@
 CLANG_LEVEL := ../..
 LIBRARYNAME := clangASTMatchers
 
+PARALLEL_DIRS = Dynamic
+
 include $(CLANG_LEVEL)/Makefile

Modified: cfe/branches/tooling/tools/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/tools/CMakeLists.txt?rev=157622&r1=157621&r2=157622&view=diff
==============================================================================
--- cfe/branches/tooling/tools/CMakeLists.txt (original)
+++ cfe/branches/tooling/tools/CMakeLists.txt Tue May 29 09:10:54 2012
@@ -5,6 +5,7 @@
 add_subdirectory(diagtool)
 add_subdirectory(driver)
 add_subdirectory(clang-check)
+add_subdirectory(ast-query)
 add_subdirectory(remove-cstr-calls)
 add_subdirectory(fix-llvm-style)
 add_subdirectory(rename)

Modified: cfe/branches/tooling/tools/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/tools/Makefile?rev=157622&r1=157621&r2=157622&view=diff
==============================================================================
--- cfe/branches/tooling/tools/Makefile (original)
+++ cfe/branches/tooling/tools/Makefile Tue May 29 09:10:54 2012
@@ -9,7 +9,7 @@
 
 CLANG_LEVEL := ..
 DIRS := driver libclang c-index-test arcmt-test c-arcmt-test diagtool \
-        clang-check remove-cstr-calls
+        clang-check remove-cstr-calls ast-query
 
 include $(CLANG_LEVEL)/../../Makefile.config
 

Added: cfe/branches/tooling/tools/ast-query/ASTQuery.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/tools/ast-query/ASTQuery.cpp?rev=157622&view=auto
==============================================================================
--- cfe/branches/tooling/tools/ast-query/ASTQuery.cpp (added)
+++ cfe/branches/tooling/tools/ast-query/ASTQuery.cpp Tue May 29 09:10:54 2012
@@ -0,0 +1,215 @@
+//===- tools/ast-query/ASTQuery.cpp - Command line tool to query the AST ===//
+//
+//                     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 to query the AST of a compilation unit by using
+//  the matcher syntax.
+//
+//  Usage:
+//  ast-query <matcher> <cmake-output-dir> <file1> <file2> ...
+//
+//  Where <matcher> is a string representing the AST Matcher that will be run
+//  over the compilation unit.
+//
+//  <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 find all calls to a function <func> on all files in a
+//  subtree of the source tree, use:
+//
+//    /path/in/subtree $ ast-query "Call(Callee(HasName(\"func\")))" \
+//                       /path/to/build $(find . -name '*.cpp')
+//
+//===----------------------------------------------------------------------===//
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include "llvm/Support/CommandLine.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/Dynamic/GenericMatcher.h"
+#include "clang/ASTMatchers/Dynamic/GenericValue.h"
+#include "clang/ASTMatchers/Dynamic/Parser.h"
+#include "clang/ASTMatchers/Dynamic/Registry.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/Tooling.h"
+
+using namespace clang;
+using namespace clang::ast_matchers;
+using namespace clang::tooling;
+using namespace llvm;
+
+namespace {
+
+template <typename T>
+std::string GetFilePath(const SourceManager& SourceManager,
+                        const T& Node) {
+  SourceLocation Location = Node.getLocStart();
+  static const char InvalidLocation[] = "<nofile>";
+  if (Location.isInvalid()) {
+    return InvalidLocation;
+  }
+
+  const FileEntry* Entry = SourceManager.getFileEntryForID(
+      SourceManager.getFileID(SourceManager.getSpellingLoc(Location)));
+  std::string FileName = Entry ? Entry->getName() : InvalidLocation;
+  return FileName + ":";
+}
+
+template <typename T>
+std::string GetPositionString(const SourceManager& SourceManager,
+                              const T& Node) {
+  SourceLocation StartLocation = Node.getLocStart();
+  StartLocation = StartLocation.isMacroID() ?
+      SourceManager.getExpansionLoc(StartLocation) :
+      SourceManager.getSpellingLoc(StartLocation);
+
+  if (!StartLocation.isValid()) return std::string();
+
+  PresumedLoc StartPresumed = SourceManager.getPresumedLoc(StartLocation);
+
+  return (llvm::Twine(StartPresumed.getLine()) + ":" +
+      llvm::Twine(StartPresumed.getColumn()) + ": ").str();
+}
+
+// Returns the text that makes up 'node' in the source.
+// Returns an empty string if the text cannot be found.
+template <typename T>
+std::string GetText(const SourceManager& SourceManager, const T& Node) {
+  SourceLocation StartSpellingLocation =
+      SourceManager.getSpellingLoc(Node.getLocStart());
+  SourceLocation EndSpellingLocation =
+      SourceManager.getSpellingLoc(Node.getLocEnd());
+  if (!StartSpellingLocation.isValid() || !EndSpellingLocation.isValid()) {
+    return std::string();
+  }
+  bool Invalid = true;
+  const char* Text =
+      SourceManager.getCharacterData(StartSpellingLocation, &Invalid);
+  if (Invalid) {
+    return std::string();
+  }
+  std::pair<FileID, unsigned> Start =
+      SourceManager.getDecomposedLoc(StartSpellingLocation);
+  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();
+  }
+  std::string Line = std::string(Text, End.second - Start.second);
+  const size_t EndOfLine = Line.find("\n");
+  if (EndOfLine != Line.npos) {
+    Line = Line.substr(0, EndOfLine);
+  }
+  return Line;
+}
+
+class RegistryProcessor : public dynamic::Parser::TokenProcessor {
+ public:
+  virtual ~RegistryProcessor() {}
+  dynamic::GenericValue processMatcherToken(
+      llvm::StringRef MatcherName,
+      const std::vector<dynamic::GenericValue>& Args,
+      const dynamic::Parser::TokenInfo& Info) {
+    return dynamic::Registry::constructMatcher(MatcherName, Args);
+  }
+};
+
+dynamic::GenericValue AddIdNode(const dynamic::GenericValue& Value) {
+  std::vector<dynamic::GenericValue> Args;
+  Args.push_back(std::string("__toplevel__"));
+  Args.push_back(Value);
+  return dynamic::Registry::constructMatcher("Id", Args);
+}
+
+class ReportTopLevel : public ast_matchers::MatchFinder::MatchCallback {
+ public:
+  virtual ~ReportTopLevel() {}
+  virtual void run(const MatchFinder::MatchResult& Result) {
+    if (const Decl* Node = Result.Nodes.getDeclAs<Decl>("__toplevel__")) {
+      ReportNode(*Result.SourceManager, *Node);
+    }
+    if (const Stmt* Node = Result.Nodes.getStmtAs<Stmt>("__toplevel__")) {
+      ReportNode(*Result.SourceManager, *Node);
+    }
+  }
+
+ private:
+  template <typename NodeType>
+  void ReportNode(const SourceManager& SourceManager, const NodeType& Node) {
+    std::cout << GetFilePath(SourceManager, Node)
+              << GetPositionString(SourceManager, Node)
+              << GetText(SourceManager, Node)
+              << std::endl;
+  }
+};
+
+}  // end anonymous namespace
+
+cl::opt<std::string> MatcherCode(
+  cl::Positional,
+  cl::desc("<matcher-code>"));
+
+cl::opt<std::string> BuildPath(
+  cl::Positional,
+  cl::desc("<build-path>"));
+
+cl::list<std::string> SourcePaths(
+  cl::Positional,
+  cl::desc("<source0> [... <sourceN>]"),
+  cl::OneOrMore);
+
+int main(int argc, const char **argv) {
+  llvm::OwningPtr<CompilationDatabase> Compilations(
+    FixedCompilationDatabase::loadFromCommandLine(argc, argv));
+  cl::ParseCommandLineOptions(argc, argv);
+  if (!Compilations) {
+    std::string ErrorMessage;
+    Compilations.reset(CompilationDatabase::loadFromDirectory(BuildPath,
+                                                              ErrorMessage));
+    if (!Compilations)
+      llvm::report_fatal_error(ErrorMessage);
+  }
+
+  RegistryProcessor Processor;
+  const dynamic::GenericValue Value = AddIdNode(
+      dynamic::Parser::parseMatcher(MatcherCode, &Processor));
+  if (Value.is<dynamic::GenericError>()) {
+    std::cerr << Value.get<dynamic::GenericError>().Message << std::endl;
+    return 1;
+  } else if (!Value.is<dynamic::GenericMatcher>()) {
+    std::cerr << "Invalid matcher code.";
+    return 1;
+  }
+
+  tooling::ClangTool Tool(*Compilations, SourcePaths);
+  ast_matchers::MatchFinder Finder;
+  Finder.addMatcher(Value.get<internal::Matcher<clang::Decl> >(),
+                    new ReportTopLevel());
+  Finder.addMatcher(Value.get<internal::Matcher<clang::Stmt> >(),
+                    new ReportTopLevel());
+  return Tool.run(newFrontendActionFactory(&Finder));
+}

Propchange: cfe/branches/tooling/tools/ast-query/ASTQuery.cpp
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: cfe/branches/tooling/tools/ast-query/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/tools/ast-query/CMakeLists.txt?rev=157622&view=auto
==============================================================================
--- cfe/branches/tooling/tools/ast-query/CMakeLists.txt (added)
+++ cfe/branches/tooling/tools/ast-query/CMakeLists.txt Tue May 29 09:10:54 2012
@@ -0,0 +1,6 @@
+set(LLVM_USED_LIBS clangTooling clangBasic clangAST clangASTMatchers
+    clangDynamicASTMatchers)
+
+add_clang_executable(ast-query
+  ASTQuery.cpp
+  )

Propchange: cfe/branches/tooling/tools/ast-query/CMakeLists.txt
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: cfe/branches/tooling/tools/ast-query/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/tools/ast-query/Makefile?rev=157622&view=auto
==============================================================================
--- cfe/branches/tooling/tools/ast-query/Makefile (added)
+++ cfe/branches/tooling/tools/ast-query/Makefile Tue May 29 09:10:54 2012
@@ -0,0 +1,24 @@
+##===- tools/ast-query/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 = ast-query
+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 clangDynamicASTMatchers.a \
+           clangLex.a clangBasic.a
+
+include $(CLANG_LEVEL)/Makefile

Propchange: cfe/branches/tooling/tools/ast-query/Makefile
------------------------------------------------------------------------------
    svn:eol-style = LF

Modified: cfe/branches/tooling/unittests/ASTMatchers/ASTMatchersTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/unittests/ASTMatchers/ASTMatchersTest.cpp?rev=157622&r1=157621&r2=157622&view=diff
==============================================================================
--- cfe/branches/tooling/unittests/ASTMatchers/ASTMatchersTest.cpp (original)
+++ cfe/branches/tooling/unittests/ASTMatchers/ASTMatchersTest.cpp Tue May 29 09:10:54 2012
@@ -7,6 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "ASTMatchersTest.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/Tooling/Tooling.h"
@@ -15,108 +16,6 @@
 namespace clang {
 namespace ast_matchers {
 
-using clang::tooling::runToolOnCode;
-
-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;
-  VerifyMatch Callback(0, &Found);
-  Finder.addMatcher(AMatcher, &Callback);
-  if (!runToolOnCode(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;
-  VerifyMatch Callback(FindResultVerifier, &VerifiedResult);
-  Finder.addMatcher(AMatcher, &Callback);
-  if (!runToolOnCode(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(""));
@@ -2077,5 +1976,5 @@
       Class(IsTemplateInstantiation())));
 }
 
-} // end namespace tooling
+} // end namespace ast_matchers
 } // end namespace clang

Added: cfe/branches/tooling/unittests/ASTMatchers/ASTMatchersTest.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/unittests/ASTMatchers/ASTMatchersTest.h?rev=157622&view=auto
==============================================================================
--- cfe/branches/tooling/unittests/ASTMatchers/ASTMatchersTest.h (added)
+++ cfe/branches/tooling/unittests/ASTMatchers/ASTMatchersTest.h Tue May 29 09:10:54 2012
@@ -0,0 +1,124 @@
+//===- unittest/Tooling/ASTMatchersTest.h - Matcher tests helpers ------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_UNITTESTS_AST_MATCHERS_AST_MATCHERS_TEST_H
+#define LLVM_CLANG_UNITTESTS_AST_MATCHERS_AST_MATCHERS_TEST_H
+
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/Tooling.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace ast_matchers {
+
+using clang::tooling::runToolOnCode;
+
+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 (!runToolOnCode(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 (!runToolOnCode(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);
+}
+
+} // end namespace ast_matchers
+} // end namespace clang
+
+#endif  // LLVM_CLANG_UNITTESTS_AST_MATCHERS_AST_MATCHERS_TEST_H

Propchange: cfe/branches/tooling/unittests/ASTMatchers/ASTMatchersTest.h
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: cfe/branches/tooling/unittests/ASTMatchers/Dynamic/GenericMatcherTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/unittests/ASTMatchers/Dynamic/GenericMatcherTest.cpp?rev=157622&view=auto
==============================================================================
--- cfe/branches/tooling/unittests/ASTMatchers/Dynamic/GenericMatcherTest.cpp (added)
+++ cfe/branches/tooling/unittests/ASTMatchers/Dynamic/GenericMatcherTest.cpp Tue May 29 09:10:54 2012
@@ -0,0 +1,108 @@
+//===- unittest/ASTMatchers/Dynamic/GenericMatcherTest.cpp - GenericMatcher unit tests -===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===-----------------------------------------------------------------------------===//
+
+#include "../ASTMatchersTest.h"
+#include "clang/ASTMatchers/Dynamic/GenericMatcher.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+namespace {
+
+testing::AssertionResult MatchesGeneric(const std::string& Code,
+                                        const GenericMatcher& Generic) {
+  if (matches(Code, Generic.getAs<clang::Decl>())) {
+    return testing::AssertionSuccess();
+  }
+  if (matches(Code, Generic.getAs<clang::Stmt>())) {
+    return testing::AssertionSuccess();
+  }
+  if (matches(Code, Generic.getAs<clang::QualType>())) {
+    return testing::AssertionSuccess();
+  }
+  return testing::AssertionFailure();
+}
+
+TEST(GeneicMatcherTest, SingleNode) {
+  EXPECT_TRUE(MatchesGeneric("class X {};",
+                             GenericMatcher(Class(HasName("X")))));
+  EXPECT_TRUE(MatchesGeneric("int x;", GenericMatcher(Variable())));
+  EXPECT_TRUE(MatchesGeneric("int foo() { return 1 + 1; }",
+                             GenericMatcher(Function())));
+
+  EXPECT_FALSE(MatchesGeneric("int x;", GenericMatcher(Function())));
+  EXPECT_FALSE(MatchesGeneric("int foo() { return 1 + 1; }",
+                              GenericMatcher(DeclarationReference())));
+}
+
+TEST(GeneicMatcherTest, AnyOf) {
+  GenericMatcher Generic(Class(HasName("X")));
+
+  EXPECT_TRUE(MatchesGeneric("class X {};", Generic));
+  EXPECT_FALSE(MatchesGeneric("int x;", Generic));
+  EXPECT_FALSE(MatchesGeneric("int foo() { return 1 + 1; }", Generic));
+
+  Generic = GenericMatcher::anyOf(Generic, Variable());
+
+  EXPECT_TRUE(MatchesGeneric("class X {};", Generic));
+  EXPECT_TRUE(MatchesGeneric("int x;", Generic));
+  EXPECT_FALSE(MatchesGeneric("int foo() { return 1 + 1; }", Generic));
+
+  // We can mix different types of matchers (statements and declarations)
+  Generic = GenericMatcher::anyOf(Generic,
+                                  BinaryOperator(HasOperatorName("+")));
+
+  EXPECT_TRUE(MatchesGeneric("class X {};", Generic));
+  EXPECT_TRUE(MatchesGeneric("int x;", Generic));
+  EXPECT_TRUE(MatchesGeneric("int foo() { return 1 + 1; }", Generic));
+}
+
+TEST(GeneicMatcherTest, AllOf) {
+  GenericMatcher Generic(BinaryOperator(HasOperatorName("+")));
+
+  EXPECT_TRUE(MatchesGeneric("int i = 1 + 1;", Generic));
+  EXPECT_TRUE(MatchesGeneric("int i = 2 + 1;", Generic));
+  EXPECT_TRUE(MatchesGeneric("int i = 1 + 3;", Generic));
+  EXPECT_FALSE(MatchesGeneric("void foo() { }", Generic));
+
+  Generic = GenericMatcher::allOf(
+      Generic,
+      BinaryOperator(HasLHS(IntegerLiteral(Equals(1)))));
+
+  EXPECT_TRUE( MatchesGeneric("int i = 1 + 1;", Generic));
+  EXPECT_FALSE(MatchesGeneric("int i = 2 + 1;", Generic));
+  EXPECT_TRUE( MatchesGeneric("int i = 1 + 3;", Generic));
+  EXPECT_FALSE(MatchesGeneric("void foo() { }", Generic));
+
+  Generic = GenericMatcher::allOf(
+      Generic,
+      BinaryOperator(HasRHS(IntegerLiteral(Equals(3)))));
+
+  EXPECT_FALSE(MatchesGeneric("int i = 1 + 1;", Generic));
+  EXPECT_FALSE(MatchesGeneric("int i = 2 + 1;", Generic));
+  EXPECT_TRUE( MatchesGeneric("int i = 1 + 3;", Generic));
+  EXPECT_FALSE(MatchesGeneric("void foo() { }", Generic));
+
+  Generic = GenericMatcher::allOf(Generic, Function());
+  // Now nothing matches. Not even the function one because it is an AllOf().
+
+  EXPECT_FALSE(MatchesGeneric("int i = 1 + 1;", Generic));
+  EXPECT_FALSE(MatchesGeneric("int i = 2 + 1;", Generic));
+  EXPECT_FALSE(MatchesGeneric("int i = 1 + 3;", Generic));
+  EXPECT_FALSE(MatchesGeneric("void foo() { }", Generic));
+
+  // Still no match, because it has to match all of it on the same node.
+  EXPECT_FALSE(MatchesGeneric("int foo() { return 1 + 3; }", Generic));
+}
+
+}  // end anonymous namespace
+}  // end namespace dynamic
+}  // end namespace ast_matchers
+}  // end namespace clang

Propchange: cfe/branches/tooling/unittests/ASTMatchers/Dynamic/GenericMatcherTest.cpp
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: cfe/branches/tooling/unittests/ASTMatchers/Dynamic/GenericValueTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/unittests/ASTMatchers/Dynamic/GenericValueTest.cpp?rev=157622&view=auto
==============================================================================
--- cfe/branches/tooling/unittests/ASTMatchers/Dynamic/GenericValueTest.cpp (added)
+++ cfe/branches/tooling/unittests/ASTMatchers/Dynamic/GenericValueTest.cpp Tue May 29 09:10:54 2012
@@ -0,0 +1,151 @@
+//===- unittest/ASTMatchers/Dynamic/GenericValueTest.cpp - GenericValue 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/Dynamic/GenericValue.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+namespace {
+
+TEST(GenericValueTest, String) {
+  const ::std::string kString = "string";
+  GenericValue Value = kString;
+
+  EXPECT_TRUE(Value.is< ::std::string>());
+  EXPECT_EQ(kString, Value.get< ::std::string>());
+
+  EXPECT_FALSE(Value.is<GenericError>());
+  EXPECT_FALSE(Value.is<bool>());
+  EXPECT_FALSE(Value.is<GenericMatcher>());
+  EXPECT_FALSE(Value.is<Matcher<clang::Decl> >());
+  EXPECT_FALSE(Value.is<Matcher<clang::UnaryOperator> >());
+  EXPECT_FALSE(Value.is<NumberHolder>());
+  EXPECT_FALSE(Value.is<int>());
+  EXPECT_FALSE(Value.is<double>());
+}
+
+TEST(GenericValueTest, GenericError) {
+  const ::std::string kString = "string";
+  GenericValue Value = GenericError(kString);
+
+  EXPECT_FALSE(Value.is< ::std::string>());
+
+  EXPECT_TRUE(Value.is<GenericError>());
+  EXPECT_EQ(kString, Value.get<GenericError>().Message);
+
+  EXPECT_FALSE(Value.is<bool>());
+  EXPECT_FALSE(Value.is<GenericMatcher>());
+  EXPECT_FALSE(Value.is<Matcher<clang::Decl> >());
+  EXPECT_FALSE(Value.is<Matcher<clang::UnaryOperator> >());
+  EXPECT_FALSE(Value.is<NumberHolder>());
+  EXPECT_FALSE(Value.is<int>());
+  EXPECT_FALSE(Value.is<double>());
+}
+
+TEST(GenericValueTest, Bool) {
+  GenericValue Value = true;
+
+  EXPECT_FALSE(Value.is< ::std::string>());
+  EXPECT_FALSE(Value.is<GenericError>());
+
+  EXPECT_TRUE(Value.is<bool>());
+  EXPECT_EQ(true, Value.get<bool>());
+
+  EXPECT_FALSE(Value.is<GenericMatcher>());
+  EXPECT_FALSE(Value.is<Matcher<clang::Decl> >());
+  EXPECT_FALSE(Value.is<Matcher<clang::UnaryOperator> >());
+  EXPECT_FALSE(Value.is<NumberHolder>());
+  EXPECT_FALSE(Value.is<int>());
+  EXPECT_FALSE(Value.is<double>());
+}
+
+TEST(GenericValueTest, GenericMatcher) {
+  GenericValue Value = Statement();
+
+  EXPECT_FALSE(Value.is< ::std::string>());
+  EXPECT_FALSE(Value.is<GenericError>());
+  EXPECT_FALSE(Value.is<bool>());
+
+  EXPECT_TRUE(Value.is<GenericMatcher>());
+  EXPECT_TRUE(Value.is<Matcher<clang::Decl> >());
+  EXPECT_TRUE(Value.is<Matcher<clang::UnaryOperator> >());
+
+  EXPECT_FALSE(Value.is<NumberHolder>());
+  EXPECT_FALSE(Value.is<int>());
+  EXPECT_FALSE(Value.is<double>());
+
+  // Conversion to any type of matcher works.
+  // If they are not compatible it would just return a matcher that matches
+  // nothing. That is tested in GenericMatcher's unittest.
+  Value = GenericMatcher(Class());
+  EXPECT_TRUE(Value.is<GenericMatcher>());
+  EXPECT_TRUE(Value.is<Matcher<clang::Decl> >());
+  EXPECT_TRUE(Value.is<Matcher<clang::UnaryOperator> >());
+
+  Value = GenericMatcher(UnaryOperator());
+  EXPECT_TRUE(Value.is<GenericMatcher>());
+  EXPECT_TRUE(Value.is<Matcher<clang::Decl> >());
+  EXPECT_TRUE(Value.is<Matcher<clang::Stmt> >());
+  EXPECT_TRUE(Value.is<Matcher<clang::UnaryOperator> >());
+}
+
+TEST(GenericValueTest, NumberHolder) {
+  GenericValue Value = NumberHolder(0);
+
+  EXPECT_FALSE(Value.is< ::std::string>());
+  EXPECT_FALSE(Value.is<GenericError>());
+  EXPECT_FALSE(Value.is<bool>());
+
+  EXPECT_FALSE(Value.is<GenericMatcher>());
+  EXPECT_FALSE(Value.is<Matcher<clang::Decl> >());
+  EXPECT_FALSE(Value.is<Matcher<clang::UnaryOperator> >());
+
+  EXPECT_TRUE(Value.is<NumberHolder>());
+  EXPECT_EQ(0, Value.get<NumberHolder>().get<int>());
+  EXPECT_TRUE(Value.is<int>());
+  EXPECT_EQ(0, Value.get<int>());
+  EXPECT_TRUE(Value.is<double>());
+  EXPECT_EQ(0.0, Value.get<double>());
+
+  // Conversions
+  Value = NumberHolder(1.1);
+  EXPECT_TRUE(Value.is<NumberHolder>());
+  EXPECT_EQ(1.1, Value.get<NumberHolder>().get<double>());
+  EXPECT_FALSE(Value.is<int>());
+  EXPECT_TRUE(Value.is<double>());
+  EXPECT_EQ(1.1, Value.get<double>());
+}
+
+TEST(GenericValueTest, Assignment) {
+  GenericValue Value = true;
+  EXPECT_TRUE(Value.is<bool>());
+  EXPECT_EQ(true, Value.get<bool>());
+  EXPECT_FALSE(Value.is<GenericMatcher>());
+  EXPECT_FALSE(Value.is<GenericError>());
+
+  Value = GenericError("foo");
+  EXPECT_FALSE(Value.is<bool>());
+  EXPECT_FALSE(Value.is<GenericMatcher>());
+  EXPECT_TRUE(Value.is<GenericError>());
+  EXPECT_EQ("foo", Value.get<GenericError>().Message);
+
+  Value = GenericMatcher(Class());
+  EXPECT_FALSE(Value.is<bool>());
+  EXPECT_TRUE(Value.is<GenericMatcher>());
+  EXPECT_TRUE(Value.is<Matcher<clang::Decl> >());
+  EXPECT_TRUE(Value.is<Matcher<clang::UnaryOperator> >());
+  EXPECT_FALSE(Value.is<GenericError>());
+}
+
+}  // end anonymous namespace
+}  // end namespace dynamic
+}  // end namespace ast_matchers
+}  // end namespace clang

Propchange: cfe/branches/tooling/unittests/ASTMatchers/Dynamic/GenericValueTest.cpp
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: cfe/branches/tooling/unittests/ASTMatchers/Dynamic/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/unittests/ASTMatchers/Dynamic/Makefile?rev=157622&view=auto
==============================================================================
--- cfe/branches/tooling/unittests/ASTMatchers/Dynamic/Makefile (added)
+++ cfe/branches/tooling/unittests/ASTMatchers/Dynamic/Makefile Tue May 29 09:10:54 2012
@@ -0,0 +1,18 @@
+##===- unittests/ASTMatchers/Dynamic/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 = DynamicASTMatchers
+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 \
+           clangDynamicASTMatchers.a
+
+include $(CLANG_LEVEL)/unittests/Makefile

Propchange: cfe/branches/tooling/unittests/ASTMatchers/Dynamic/Makefile
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: cfe/branches/tooling/unittests/ASTMatchers/Dynamic/NumberHolderTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/unittests/ASTMatchers/Dynamic/NumberHolderTest.cpp?rev=157622&view=auto
==============================================================================
--- cfe/branches/tooling/unittests/ASTMatchers/Dynamic/NumberHolderTest.cpp (added)
+++ cfe/branches/tooling/unittests/ASTMatchers/Dynamic/NumberHolderTest.cpp Tue May 29 09:10:54 2012
@@ -0,0 +1,222 @@
+//===- unittest/ASTMatchers/Dynamic/NumberHolderTest.cpp - NumberHolder 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/Dynamic/NumberHolder.h"
+
+#include <limits>
+
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+namespace {
+
+TEST(NumberHolderTest, CanCovertBetweenTypes) {
+  // Every type can represent 123.
+  const int32_t Expected = 123;
+  NumberHolder Holder(Expected);
+
+  EXPECT_TRUE(Holder.is<int8_t>());
+  EXPECT_EQ(Expected, Holder.get<int8_t>());
+
+  EXPECT_TRUE(Holder.is<int16_t>());
+  EXPECT_EQ(Expected, Holder.get<int16_t>());
+
+  EXPECT_TRUE(Holder.is<int32_t>());
+  EXPECT_EQ(Expected, Holder.get<int32_t>());
+
+  EXPECT_TRUE(Holder.is<int64_t>());
+  EXPECT_EQ(Expected, Holder.get<int64_t>());
+
+  EXPECT_TRUE(Holder.is<uint8_t>());
+  EXPECT_EQ(Expected, Holder.get<uint8_t>());
+
+  EXPECT_TRUE(Holder.is<uint16_t>());
+  EXPECT_EQ(Expected, Holder.get<uint16_t>());
+
+  EXPECT_TRUE(Holder.is<uint32_t>());
+  EXPECT_EQ(static_cast<uint32_t>(Expected), Holder.get<uint32_t>());
+
+  EXPECT_TRUE(Holder.is<uint64_t>());
+  EXPECT_EQ(static_cast<uint64_t>(Expected), Holder.get<uint64_t>());
+
+  EXPECT_TRUE(Holder.is<float>());
+  EXPECT_EQ(Expected, Holder.get<float>());
+
+  EXPECT_TRUE(Holder.is<double>());
+  EXPECT_EQ(Expected, Holder.get<double>());
+}
+
+TEST(NumberHolderTest, NegativeValues) {
+  // Only signed types can represent -123.
+  const int32_t Expected = -123;
+  NumberHolder Holder(Expected);
+
+  EXPECT_TRUE(Holder.is<int8_t>());
+  EXPECT_EQ(Expected, Holder.get<int8_t>());
+
+  EXPECT_TRUE(Holder.is<int16_t>());
+  EXPECT_EQ(Expected, Holder.get<int16_t>());
+
+  EXPECT_TRUE(Holder.is<int32_t>());
+  EXPECT_EQ(Expected, Holder.get<int32_t>());
+
+  EXPECT_TRUE(Holder.is<int64_t>());
+  EXPECT_EQ(Expected, Holder.get<int64_t>());
+
+  EXPECT_FALSE(Holder.is<uint8_t>());
+  EXPECT_FALSE(Holder.is<uint16_t>());
+  EXPECT_FALSE(Holder.is<uint32_t>());
+  EXPECT_FALSE(Holder.is<unsigned long>());
+  EXPECT_FALSE(Holder.is<uint64_t>());
+
+  EXPECT_TRUE(Holder.is<float>());
+  EXPECT_EQ(Expected, Holder.get<float>());
+
+  EXPECT_TRUE(Holder.is<double>());
+  EXPECT_EQ(Expected, Holder.get<double>());
+}
+
+TEST(NumberHolderTest, SignedOverflow) {
+  // Overflow int16_t. Value is still a valid uint16_t.
+  const uint64_t Expected = std::numeric_limits<int16_t>::max() + 1LL;
+  NumberHolder Holder(Expected);
+
+  EXPECT_FALSE(Holder.is<int8_t>());
+  EXPECT_FALSE(Holder.is<int16_t>());
+
+  EXPECT_TRUE(Holder.is<int32_t>());
+  EXPECT_EQ(static_cast<int32_t>(Expected), Holder.get<int32_t>());
+
+  EXPECT_TRUE(Holder.is<int64_t>());
+  EXPECT_EQ(static_cast<int64_t>(Expected), Holder.get<int64_t>());
+
+  EXPECT_FALSE(Holder.is<uint8_t>());
+
+  EXPECT_TRUE(Holder.is<uint16_t>());
+  EXPECT_EQ(Expected, Holder.get<uint16_t>());
+
+  EXPECT_TRUE(Holder.is<uint32_t>());
+  EXPECT_EQ(Expected, Holder.get<uint32_t>());
+
+  EXPECT_TRUE(Holder.is<uint64_t>());
+  EXPECT_EQ(Expected, Holder.get<uint64_t>());
+
+  EXPECT_TRUE(Holder.is<float>());
+  EXPECT_EQ(Expected, Holder.get<float>());
+
+  EXPECT_TRUE(Holder.is<double>());
+  EXPECT_EQ(Expected, Holder.get<double>());
+}
+
+TEST(NumberHolderTest, UnsignedOverflow) {
+  // Overflow everything up to uint32_t.
+  const uint64_t Expected = std::numeric_limits<uint32_t>::max() + 1LL;
+  NumberHolder Holder(Expected);
+
+  EXPECT_FALSE(Holder.is<int8_t>());
+  EXPECT_FALSE(Holder.is<int16_t>());
+  EXPECT_FALSE(Holder.is<int32_t>());
+
+  EXPECT_TRUE(Holder.is<int64_t>());
+  EXPECT_EQ(static_cast<int64_t>(Expected), Holder.get<int64_t>());
+
+  EXPECT_FALSE(Holder.is<uint8_t>());
+  EXPECT_FALSE(Holder.is<uint16_t>());
+  EXPECT_FALSE(Holder.is<uint32_t>());
+
+  EXPECT_TRUE(Holder.is<uint64_t>());
+  EXPECT_EQ(Expected, Holder.get<uint64_t>());
+
+  EXPECT_TRUE(Holder.is<float>());
+  EXPECT_EQ(Expected, Holder.get<float>());
+
+  EXPECT_TRUE(Holder.is<double>());
+  EXPECT_EQ(Expected, Holder.get<double>());
+}
+
+TEST(NumberHolderTest, DoubleOverflow) {
+  // Overflow a double using a very large integer.
+  const int64_t Expected = std::numeric_limits<int64_t>::max();
+  NumberHolder Holder(Expected);
+
+  EXPECT_FALSE(Holder.is<int8_t>());
+  EXPECT_FALSE(Holder.is<int16_t>());
+  EXPECT_FALSE(Holder.is<int32_t>());
+
+  EXPECT_TRUE(Holder.is<int64_t>());
+  EXPECT_EQ(Expected, Holder.get<int64_t>());
+
+  EXPECT_FALSE(Holder.is<uint8_t>());
+  EXPECT_FALSE(Holder.is<uint16_t>());
+  EXPECT_FALSE(Holder.is<uint32_t>());
+
+  EXPECT_TRUE(Holder.is<uint64_t>());
+  EXPECT_EQ(static_cast<uint64_t>(Expected), Holder.get<uint64_t>());
+
+  EXPECT_FALSE(Holder.is<float>());
+  EXPECT_FALSE(Holder.is<double>());
+}
+
+TEST(NumberHolderTest, FloatingPoint) {
+  // No integer should accept a floating point.
+  const double Expected = 1.5;
+  NumberHolder Holder(Expected);
+
+  EXPECT_FALSE(Holder.is<int8_t>());
+  EXPECT_FALSE(Holder.is<int16_t>());
+  EXPECT_FALSE(Holder.is<int32_t>());
+  EXPECT_FALSE(Holder.is<int64_t>());
+  EXPECT_FALSE(Holder.is<uint8_t>());
+  EXPECT_FALSE(Holder.is<uint16_t>());
+  EXPECT_FALSE(Holder.is<uint32_t>());
+  EXPECT_FALSE(Holder.is<uint64_t>());
+
+  EXPECT_TRUE(Holder.is<float>());
+  EXPECT_EQ(Expected, Holder.get<float>());
+
+  EXPECT_TRUE(Holder.is<double>());
+  EXPECT_EQ(Expected, Holder.get<double>());
+}
+
+TEST(NumberHolderTest, NotReallyFloatingPoint) {
+  // If the double is not really a floating point, then we accept it as ints.
+  const double Expected = 1234e5;
+  NumberHolder Holder(Expected);
+
+  EXPECT_FALSE(Holder.is<int8_t>());
+  EXPECT_FALSE(Holder.is<int16_t>());
+
+  EXPECT_TRUE(Holder.is<int32_t>());
+  EXPECT_EQ(Expected, Holder.get<int32_t>());
+
+  EXPECT_TRUE(Holder.is<int64_t>());
+  EXPECT_EQ(Expected, Holder.get<int64_t>());
+
+  EXPECT_FALSE(Holder.is<uint8_t>());
+  EXPECT_FALSE(Holder.is<uint16_t>());
+
+  EXPECT_TRUE(Holder.is<uint32_t>());
+  EXPECT_EQ(Expected, Holder.get<uint32_t>());
+
+  EXPECT_TRUE(Holder.is<uint64_t>());
+  EXPECT_EQ(Expected, Holder.get<uint64_t>());
+
+  EXPECT_TRUE(Holder.is<float>());
+  EXPECT_EQ(Expected, Holder.get<float>());
+
+  EXPECT_TRUE(Holder.is<double>());
+  EXPECT_EQ(Expected, Holder.get<double>());
+}
+
+}  // end anonymous namespace
+}  // end namespace dynamic
+}  // end namespace ast_matchers
+}  // end namespace clang

Propchange: cfe/branches/tooling/unittests/ASTMatchers/Dynamic/NumberHolderTest.cpp
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: cfe/branches/tooling/unittests/ASTMatchers/Dynamic/ParserTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/unittests/ASTMatchers/Dynamic/ParserTest.cpp?rev=157622&view=auto
==============================================================================
--- cfe/branches/tooling/unittests/ASTMatchers/Dynamic/ParserTest.cpp (added)
+++ cfe/branches/tooling/unittests/ASTMatchers/Dynamic/ParserTest.cpp Tue May 29 09:10:54 2012
@@ -0,0 +1,215 @@
+//===- unittest/ASTMatchers/Dynamic/ParserTest.cpp - Parser unit tests -===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===-------------------------------------------------------------------===//
+
+#include <string>
+#include <vector>
+
+#include "../ASTMatchersTest.h"
+#include "clang/ASTMatchers/Dynamic/Parser.h"
+#include "clang/ASTMatchers/Dynamic/Registry.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+namespace {
+
+class ValueProcessor : public Parser::TokenProcessor {
+ public:
+  virtual ~ValueProcessor() { }
+
+  void Parse(const std::string& Code) {
+    const GenericValue Value = Parser::parseMatcher(Code, this);
+    if (Value.is<GenericError>()) {
+      ValueInfo ToStore = { Value, Parser::TokenInfo() };
+      Values.push_back(ToStore);
+    }
+  }
+
+  GenericValue processValueToken(const GenericValue& Value,
+                                 const Parser::TokenInfo& Info) {
+    ValueInfo ToStore = { Value, Info };
+    Values.push_back(ToStore);
+    return Value;
+  }
+  GenericValue processMatcherToken(
+      llvm::StringRef MatcherName,
+      const std::vector<GenericValue>& Args,
+      const Parser::TokenInfo& Info) {
+    MatcherInfo ToStore = { MatcherName, Info, Args };
+    Matchers.push_back(ToStore);
+    // Return the matcher name with a special format to be able to EXPECT_EQ
+    // down there. No reason to actually create matchers here.
+    return GenericValue("__" + MatcherName.str() + "__");
+  }
+
+  struct ValueInfo {
+    GenericValue Value;
+    Parser::TokenInfo Info;
+  };
+  struct MatcherInfo {
+    std::string MatcherName;
+    Parser::TokenInfo Info;
+    std::vector<GenericValue> Args;
+  };
+
+  std::vector<ValueInfo> Values;
+  std::vector<MatcherInfo> Matchers;
+};
+
+TEST(ParserTest, ParseString) {
+  ValueProcessor Processor;
+  Processor.Parse("\"Foo\"");
+  Processor.Parse("\"F\\\"o o\\n\"");
+  Processor.Parse("\"\"");
+  Processor.Parse("\"Baz");
+  EXPECT_EQ(4ULL, Processor.Values.size());
+  EXPECT_EQ("Foo", Processor.Values[0].Value.get<std::string>());
+  EXPECT_EQ("F\"o o\n", Processor.Values[1].Value.get<std::string>());
+  EXPECT_EQ("", Processor.Values[2].Value.get<std::string>());
+  EXPECT_EQ("Error parsing string token: <\"Baz>",
+            Processor.Values[3].Value.get<GenericError>().Message);
+}
+
+TEST(ParserTest, ParseChar) {
+  ValueProcessor Processor;
+  Processor.Parse("'a'");
+  Processor.Parse("'^'");
+  Processor.Parse("'\\n'");
+  Processor.Parse("'aa'");
+  Processor.Parse("'6");
+  Processor.Parse("' '");
+  Processor.Parse("','");
+  EXPECT_EQ(7ULL, Processor.Values.size());
+  EXPECT_EQ('a', Processor.Values[0].Value.get<int>());
+  EXPECT_EQ('^', Processor.Values[1].Value.get<int>());
+  EXPECT_EQ('\n', Processor.Values[2].Value.get<int>());
+  EXPECT_EQ("Error parsing char token: <'aa'>",
+            Processor.Values[3].Value.get<GenericError>().Message);
+  EXPECT_EQ("Error parsing char token: <'6>",
+            Processor.Values[4].Value.get<GenericError>().Message);
+  EXPECT_EQ(' ', Processor.Values[5].Value.get<int>());
+  EXPECT_EQ(',', Processor.Values[6].Value.get<int>());
+}
+
+TEST(ParserTest, ParseNumber) {
+  ValueProcessor Processor;
+  Processor.Parse("123456789012345");
+  Processor.Parse("-1234567890123456");
+  Processor.Parse("1.23e5");
+  Processor.Parse("1.234e-5");
+  Processor.Parse("0x5");
+  Processor.Parse("0d3jg#");
+  EXPECT_EQ(6ULL, Processor.Values.size());
+  EXPECT_EQ(123456789012345ULL, Processor.Values[0].Value.get<uint64_t>());
+  EXPECT_EQ(-1234567890123456LL, Processor.Values[1].Value.get<int64_t>());
+  EXPECT_EQ(1.23e5, Processor.Values[2].Value.get<int>());
+  EXPECT_EQ(1.234e-5, Processor.Values[3].Value.get<double>());
+  EXPECT_EQ(0x5, Processor.Values[4].Value.get<char>());
+  EXPECT_EQ("Error parsing number token: <0d3jg#>",
+            Processor.Values[5].Value.get<GenericError>().Message);
+}
+
+TEST(ParserTest, ParseBool) {
+  ValueProcessor Processor;
+  Processor.Parse("true");
+  Processor.Parse("false");
+  EXPECT_EQ(2UL, Processor.Values.size());
+  EXPECT_EQ(true, Processor.Values[0].Value.get<bool>());
+  EXPECT_EQ(false, Processor.Values[1].Value.get<bool>());
+}
+
+bool MatchesInfo(const Parser::TokenInfo& Info,
+                 int StartLine, int EndLine, int StartColumn, int EndColumn) {
+  EXPECT_EQ(StartLine, Info.StartLine);
+  EXPECT_EQ(EndLine, Info.EndLine);
+  EXPECT_EQ(StartColumn, Info.StartColumn);
+  EXPECT_EQ(EndColumn, Info.EndColumn);
+  return Info.StartLine == StartLine && Info.EndLine == EndLine &&
+      Info.StartColumn == StartColumn && Info.EndColumn == EndColumn;
+}
+
+TEST(ParserTest, ParseMatcher) {
+  ValueProcessor Processor;
+  Processor.Parse(" Foo ( 1.2, Bar (), Baz( \n \"B \\nA,\\\"Z\"), \ntrue)  ");
+  for (size_t i = 0; i < Processor.Values.size(); ++i) {
+    EXPECT_FALSE(Processor.Values[i].Value.is<GenericError>())
+        << Processor.Values[i].Value.get<GenericError>().Message;
+  }
+
+  EXPECT_EQ(3ULL, Processor.Matchers.size());
+  const ValueProcessor::MatcherInfo Bar = Processor.Matchers[0];
+  EXPECT_EQ("Bar", Bar.MatcherName);
+  EXPECT_TRUE(MatchesInfo(Bar.Info, 1, 1, 13, 18));
+  EXPECT_EQ(0ULL, Bar.Args.size());
+
+  const ValueProcessor::MatcherInfo Baz = Processor.Matchers[1];
+  EXPECT_EQ("Baz", Baz.MatcherName);
+  EXPECT_TRUE(MatchesInfo(Baz.Info, 1, 2, 21, 13));
+  EXPECT_EQ(1ULL, Baz.Args.size());
+  EXPECT_EQ("B \nA,\"Z", Baz.Args[0].get<std::string>());
+
+  const ValueProcessor::MatcherInfo Foo = Processor.Matchers[2];
+  EXPECT_EQ("Foo", Foo.MatcherName);
+  EXPECT_TRUE(MatchesInfo(Foo.Info, 1, 3, 2, 5));
+  EXPECT_EQ(4ULL, Foo.Args.size());
+  EXPECT_EQ(1.2, Foo.Args[0].get<double>());
+  EXPECT_EQ("__Bar__", Foo.Args[1].get<std::string>());
+  EXPECT_EQ("__Baz__", Foo.Args[2].get<std::string>());
+  EXPECT_EQ(true, Foo.Args[3].get<bool>());
+}
+
+class RealProcessor : public Parser::TokenProcessor {
+ public:
+  virtual ~RealProcessor() {}
+  GenericValue processMatcherToken(llvm::StringRef MatcherName,
+                                   const std::vector<GenericValue>& Args,
+                                   const Parser::TokenInfo& Info) {
+    return Registry::constructMatcher(MatcherName, Args);
+  }
+};
+
+testing::AssertionResult MatchesGeneric(const std::string& Code,
+                                        const GenericValue& Value) {
+  if (!Value.is<GenericMatcher>())
+    return testing::AssertionFailure();
+  const GenericMatcher Matcher = Value.get<GenericMatcher>();
+  if (matches(Code, Matcher.getAs<clang::Decl>())) {
+    return testing::AssertionSuccess();
+  }
+  if (matches(Code, Matcher.getAs<clang::Stmt>())) {
+    return testing::AssertionSuccess();
+  }
+  if (matches(Code, Matcher.getAs<clang::QualType>())) {
+    return testing::AssertionSuccess();
+  }
+  return testing::AssertionFailure();
+}
+
+TEST(ParserTest, FullParserTest) {
+  RealProcessor Processor;
+  const GenericValue Value = Parser::parseMatcher(
+      "BinaryOperator( HasOperatorName(\"+\"),\n"
+      "               HasLHS(IntegerLiteral(Equals(1))))", &Processor);
+  EXPECT_TRUE(MatchesGeneric("int x = 1 + 1;", Value));
+  EXPECT_FALSE(MatchesGeneric("int x = 2 + 1;", Value));
+
+  const GenericValue Error = Parser::parseMatcher(
+      "BinaryOperator( HasOperatorName(6),\n"
+      "               HasLHS(IntegerLiteral(Equals(1))))", &Processor);
+  EXPECT_EQ("Error parsing argument 0 for matcher BinaryOperator: "
+            "Error building matcher HasOperatorName: "
+            "Incorrect type on function HasOperatorName for arg 0",
+            Error.get<GenericError>().Message);
+}
+
+}  // end anonymous namespace
+}  // end namespace dynamic
+}  // end namespace ast_matchers
+}  // end namespace clang

Propchange: cfe/branches/tooling/unittests/ASTMatchers/Dynamic/ParserTest.cpp
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: cfe/branches/tooling/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/unittests/ASTMatchers/Dynamic/RegistryTest.cpp?rev=157622&view=auto
==============================================================================
--- cfe/branches/tooling/unittests/ASTMatchers/Dynamic/RegistryTest.cpp (added)
+++ cfe/branches/tooling/unittests/ASTMatchers/Dynamic/RegistryTest.cpp Tue May 29 09:10:54 2012
@@ -0,0 +1,141 @@
+//===- unittest/ASTMatchers/Dynamic/RegistryTest.cpp - Registry unit tests -===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===-----------------------------------------------------------------------------===//
+
+#include <vector>
+
+#include "../ASTMatchersTest.h"
+#include "clang/ASTMatchers/Dynamic/Registry.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+namespace {
+
+testing::AssertionResult MatchesGeneric(const std::string& Code,
+                                        const GenericValue& Value) {
+  if (Value.is<GenericError>()) {
+    EXPECT_EQ("", Value.get<GenericError>().Message);
+    return testing::AssertionFailure();
+  }
+  const GenericMatcher Matcher = Value.get<GenericMatcher>();
+  if (matches(Code, Matcher.getAs<clang::Decl>())) {
+    return testing::AssertionSuccess();
+  }
+  if (matches(Code, Matcher.getAs<clang::Stmt>())) {
+    return testing::AssertionSuccess();
+  }
+  if (matches(Code, Matcher.getAs<clang::QualType>())) {
+    return testing::AssertionSuccess();
+  }
+  return testing::AssertionFailure();
+}
+
+GenericValue ConstructMatcher(const std::string& MatcherName) {
+  const std::vector<GenericValue> Args;
+  return Registry::constructMatcher(MatcherName, Args);
+}
+
+GenericValue ConstructMatcher(const std::string& MatcherName,
+                              const GenericValue Arg1) {
+  std::vector<GenericValue> Args;
+  Args.push_back(Arg1);
+  return Registry::constructMatcher(MatcherName, Args);
+}
+
+GenericValue ConstructMatcher(const std::string& MatcherName,
+                              const GenericValue Arg1,
+                              const GenericValue Arg2) {
+  std::vector<GenericValue> Args;
+  Args.push_back(Arg1);
+  Args.push_back(Arg2);
+  return Registry::constructMatcher(MatcherName, Args);
+}
+
+TEST(RegistryTest, CanConstructNoArgs) {
+  const GenericValue IsArrowValue = ConstructMatcher("IsArrow");
+  const GenericValue BoolValue = ConstructMatcher("BoolLiteral");
+
+  const std::string ClassSnippet =
+      "struct Foo { int x; };\n"
+      "Foo* foo = new Foo;\n"
+      "int i = foo->x;\n";
+  const std::string BoolSnippet = "bool Foo = true;\n";
+
+  EXPECT_TRUE(MatchesGeneric(ClassSnippet, IsArrowValue));
+  EXPECT_TRUE(MatchesGeneric(BoolSnippet, BoolValue));
+  EXPECT_FALSE(MatchesGeneric(ClassSnippet, BoolValue));
+  EXPECT_FALSE(MatchesGeneric(BoolSnippet, IsArrowValue));
+}
+
+TEST(RegistryTest, ConstructWithSimpleArgs) {
+  const GenericValue Value = ConstructMatcher("HasName", std::string("X"));
+  EXPECT_TRUE(MatchesGeneric("class X {};", Value));
+  EXPECT_FALSE(MatchesGeneric("int x;", Value));
+}
+
+TEST(RegistryTest, ContructWithMatcherArgs) {
+  const GenericValue OperatorPlus =
+      ConstructMatcher("HasOperatorName", std::string("+"));
+  const GenericValue OperatorMinus =
+      ConstructMatcher("HasOperatorName", std::string("-"));
+  const GenericValue One =
+      ConstructMatcher("IntegerLiteral", ConstructMatcher("Equals", 1));
+  const GenericValue HasLHSOne = ConstructMatcher("HasLHS", One);
+
+  const GenericValue OnePlus =
+      ConstructMatcher("BinaryOperator", OperatorPlus, HasLHSOne);
+  const GenericValue JustPlus =
+      ConstructMatcher("BinaryOperator", OperatorPlus);
+
+  const GenericValue OneMinus =
+      ConstructMatcher("BinaryOperator", OperatorMinus, HasLHSOne);
+  const GenericValue JustMinus =
+      ConstructMatcher("BinaryOperator", OperatorMinus);
+
+  EXPECT_TRUE( MatchesGeneric("int i = 1 + 1;", OnePlus));
+  EXPECT_TRUE( MatchesGeneric("int i = 1 + 1;", JustPlus));
+  EXPECT_FALSE(MatchesGeneric("int i = 1 + 1;", OneMinus));
+  EXPECT_FALSE(MatchesGeneric("int i = 1 + 1;", JustMinus));
+
+  EXPECT_FALSE(MatchesGeneric("int i = 1 - 1;", OnePlus));
+  EXPECT_FALSE(MatchesGeneric("int i = 1 - 1;", JustPlus));
+  EXPECT_TRUE( MatchesGeneric("int i = 1 - 1;", OneMinus));
+  EXPECT_TRUE( MatchesGeneric("int i = 1 - 1;", JustMinus));
+
+  EXPECT_FALSE(MatchesGeneric("int i = 2 + 1;", OnePlus));
+  EXPECT_TRUE( MatchesGeneric("int i = 2 + 1;", JustPlus));
+  EXPECT_FALSE(MatchesGeneric("int i = 2 + 1;", OneMinus));
+  EXPECT_FALSE(MatchesGeneric("int i = 2 + 1;", JustMinus));
+}
+
+TEST(RegistryTest, Errors) {
+  // Incorrect argument count.
+  GenericValue BadArgCount = ConstructMatcher("HasBody");
+  EXPECT_EQ("Incorrect argument count on function HasBody. "
+            "(Expected = 1) != (Actual = 0)",
+            BadArgCount.get<GenericError>().Message);
+  BadArgCount = ConstructMatcher("IsArrow", std::string());
+  EXPECT_EQ("Incorrect argument count on function IsArrow. "
+            "(Expected = 0) != (Actual = 1)",
+            BadArgCount.get<GenericError>().Message);
+
+  // Bad argument type
+  GenericValue BadArgType = ConstructMatcher("OfClass", true);
+  EXPECT_EQ("Incorrect type on function OfClass for arg 0",
+            BadArgType.get<GenericError>().Message);
+  BadArgType = ConstructMatcher("Class", Class(), 3);
+  EXPECT_EQ("Incorrect type on function Class for arg 1",
+            BadArgType.get<GenericError>().Message);
+}
+
+}  // end anonymous namespace
+}  // end namespace dynamic
+}  // end namespace ast_matchers
+}  // end namespace clang

Propchange: cfe/branches/tooling/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
------------------------------------------------------------------------------
    svn:eol-style = LF

Modified: cfe/branches/tooling/unittests/ASTMatchers/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/unittests/ASTMatchers/Makefile?rev=157622&r1=157621&r2=157622&view=diff
==============================================================================
--- cfe/branches/tooling/unittests/ASTMatchers/Makefile (original)
+++ cfe/branches/tooling/unittests/ASTMatchers/Makefile Tue May 29 09:10:54 2012
@@ -8,6 +8,8 @@
 ##===----------------------------------------------------------------------===##
 
 CLANG_LEVEL = ../..
+PARALLEL_DIRS = Dynamic
+
 TESTNAME = ASTMatchers
 LINK_COMPONENTS := support mc
 USEDLIBS = clangTooling.a clangFrontend.a clangSerialization.a clangDriver.a \

Modified: cfe/branches/tooling/unittests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/unittests/CMakeLists.txt?rev=157622&r1=157621&r2=157622&view=diff
==============================================================================
--- cfe/branches/tooling/unittests/CMakeLists.txt (original)
+++ cfe/branches/tooling/unittests/CMakeLists.txt Tue May 29 09:10:54 2012
@@ -55,6 +55,15 @@
   USED_LIBS gtest gtest_main clangASTMatchers clangTooling
  )
 
+add_clang_unittest(ASTMatchers/Dynamic
+  ASTMatchers/Dynamic/GenericMatcherTest.cpp
+  ASTMatchers/Dynamic/GenericValueTest.cpp
+  ASTMatchers/Dynamic/NumberHolderTest.cpp
+  ASTMatchers/Dynamic/ParserTest.cpp
+  ASTMatchers/Dynamic/RegistryTest.cpp
+  USED_LIBS gtest gtest_main clangASTMatchers clangDynamicASTMatchers clangTooling
+ )
+
 add_clang_unittest(Basic
   Basic/FileManagerTest.cpp
   Basic/SourceManagerTest.cpp





More information about the llvm-branch-commits mailing list