r181768 - First revision of the dynamic ASTMatcher library.

Reid Kleckner rnk at google.com
Tue May 14 13:46:01 PDT 2013


No worries, it was easy, so fixed in r181826.


On Tue, May 14, 2013 at 4:37 PM, Manuel Klimek <klimek at google.com> wrote:

> +sam
> On May 14, 2013 10:25 PM, "Reid Kleckner" <rnk at google.com> wrote:
>
>> This doesn't compile with MSVC 2012?
>>
>> http://bb.pgr.jp/builders/ninja-clang-i686-msc17-R/builds/1350/steps/build_clang/logs/stdio
>>
>> I get this locally:
>>
>> ..\tools\clang\include\clang/ASTMatchers/Dynamic/VariantValue.h(88) :
>> error C2872: 'DynTypedMatcher' : ambiguous symbol
>>         could be
>> '..\tools\clang\include\clang/ASTMatchers/Dynamic/VariantValue.h(29) :
>> clang::ast_matchers::internal::DynTypedMatcher
>> clang::ast_matchers::dynamic::DynTypedMatcher'
>>         or
>> '..\tools\clang\include\clang/ASTMatchers/ASTMatchersInternal.h(233) :
>> clang::ast_matchers::internal::DynTypedMatcher'
>>
>> ..\tools\clang\include\clang/ASTMatchers/Dynamic/VariantValue.h(77) : see
>> reference to class template instantiation
>> 'clang::ast_matchers::dynamic::VariantValue::DerivedTypeMatcher<T>' being
>> compiled
>>         with
>>         [
>>             T=clang::Decl
>>         ]
>>
>> ..\tools\clang\unittests\ASTMatchers\Dynamic\VariantValueTest.cpp(79) : see
>> reference to function template instantiation
>> 'clang::ast_matchers::internal::Matcher<T>
>> clang::ast_matchers::dynamic::VariantValue::getTypedMatcher<clang::Decl>(void)
>> const' being compiled
>>         with
>>         [
>>             T=clang::Decl
>>         ]
>> ..\tools\clang\include\clang/ASTMatchers/Dynamic/VariantValue.h(101) :
>> error C2872: 'DynTypedMatcher' : ambiguous symbol
>>         could be
>> '..\tools\clang\include\clang/ASTMatchers/Dynamic/VariantValue.h(29) :
>> clang::ast_matchers::internal::DynTypedMatcher
>> clang::ast_matchers::dynamic::DynTypedMatcher'
>>         or
>> '..\tools\clang\include\clang/ASTMatchers/ASTMatchersInternal.h(233) :
>> clang::ast_matchers::internal::DynTypedMatcher'
>>
>> I'll attempt to fix, but I may give up and revert.
>>
>>
>> On Tue, May 14, 2013 at 5:13 AM, Manuel Klimek <klimek at google.com> wrote:
>>
>>> Author: klimek
>>> Date: Tue May 14 04:13:00 2013
>>> New Revision: 181768
>>>
>>> URL: http://llvm.org/viewvc/llvm-project?rev=181768&view=rev
>>> Log:
>>> First revision of the dynamic ASTMatcher library.
>>>
>>> This library supports all the features of the compile-time based
>>> ASTMatcher
>>> library, but allows the user to specify and construct the matchers at
>>> runtime.
>>> It contains the following modules:
>>>  - A variant type, to be used by the matcher factory.
>>>  - A registry, where the matchers are indexed by name and have a factory
>>> method
>>>    with a generic signature.
>>>  - A simple matcher expression parser, that can be used to convert a
>>> matcher
>>>    expression string into actual matchers that can be used with the AST
>>> at
>>>    runtime.
>>>
>>> Many features where omitted from this first revision to simplify this
>>> code
>>> review. The main ideas are still represented in this change and it
>>> already has
>>> support working use cases.
>>> Things that are missing:
>>>  - Support for polymorphic matchers. These requires supporting code in
>>> the
>>>    registry, the marshallers and the variant type.
>>>  - Support for numbers, char and bool arguments to the matchers. This
>>> requires
>>>    supporting code in the parser and the variant type.
>>>  - A command line program putting everything together and providing an
>>> already
>>>    functional tool.
>>>
>>> Patch by Samuel Benzaquen.
>>>
>>> Added:
>>>     cfe/trunk/include/clang/ASTMatchers/Dynamic/
>>>     cfe/trunk/include/clang/ASTMatchers/Dynamic/Diagnostics.h
>>>     cfe/trunk/include/clang/ASTMatchers/Dynamic/Parser.h
>>>     cfe/trunk/include/clang/ASTMatchers/Dynamic/Registry.h
>>>     cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h
>>>     cfe/trunk/lib/ASTMatchers/Dynamic/
>>>     cfe/trunk/lib/ASTMatchers/Dynamic/CMakeLists.txt
>>>     cfe/trunk/lib/ASTMatchers/Dynamic/Diagnostics.cpp
>>>     cfe/trunk/lib/ASTMatchers/Dynamic/Makefile
>>>       - copied, changed from r181767, cfe/trunk/lib/ASTMatchers/Makefile
>>>     cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h
>>>     cfe/trunk/lib/ASTMatchers/Dynamic/Parser.cpp
>>>     cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
>>>     cfe/trunk/lib/ASTMatchers/Dynamic/VariantValue.cpp
>>>     cfe/trunk/unittests/ASTMatchers/Dynamic/
>>>     cfe/trunk/unittests/ASTMatchers/Dynamic/CMakeLists.txt
>>>     cfe/trunk/unittests/ASTMatchers/Dynamic/Makefile
>>>     cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp
>>>     cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
>>>     cfe/trunk/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp
>>> Modified:
>>>     cfe/trunk/include/clang/ASTMatchers/ASTMatchFinder.h
>>>     cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h
>>>     cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp
>>>     cfe/trunk/lib/ASTMatchers/CMakeLists.txt
>>>     cfe/trunk/lib/ASTMatchers/Makefile
>>>     cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.h
>>>     cfe/trunk/unittests/ASTMatchers/CMakeLists.txt
>>>     cfe/trunk/unittests/ASTMatchers/Makefile
>>>
>>> Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchFinder.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchFinder.h?rev=181768&r1=181767&r2=181768&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/include/clang/ASTMatchers/ASTMatchFinder.h (original)
>>> +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchFinder.h Tue May 14
>>> 04:13:00 2013
>>> @@ -131,6 +131,17 @@ public:
>>>                    MatchCallback *Action);
>>>    /// @}
>>>
>>> +  /// \brief Adds a matcher to execute when running over the AST.
>>> +  ///
>>> +  /// This is similar to \c addMatcher(), but it uses the dynamic
>>> interface. It
>>> +  /// is more flexible, but the lost type information enables a caller
>>> to pass
>>> +  /// a matcher that cannot match anything.
>>> +  ///
>>> +  /// \returns \c true if the matcher is a valid top-level matcher, \c
>>> false
>>> +  ///   otherwise.
>>> +  bool addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
>>> +                         MatchCallback *Action);
>>> +
>>>    /// \brief Creates a clang ASTConsumer that finds all matches.
>>>    clang::ASTConsumer *newASTConsumer();
>>>
>>>
>>> Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h?rev=181768&r1=181767&r2=181768&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h (original)
>>> +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h Tue May 14
>>> 04:13:00 2013
>>> @@ -239,6 +239,9 @@ public:
>>>                         ASTMatchFinder *Finder,
>>>                         BoundNodesTreeBuilder *Builder) const = 0;
>>>
>>> +  /// \brief Makes a copy of this matcher object.
>>> +  virtual DynTypedMatcher *clone() const = 0;
>>> +
>>>    /// \brief Returns a unique ID for the matcher.
>>>    virtual uint64_t getID() const = 0;
>>>  };
>>> @@ -301,6 +304,9 @@ public:
>>>      return matches(*Node, Finder, Builder);
>>>    }
>>>
>>> +  /// \brief Makes a copy of this matcher object.
>>> +  virtual Matcher<T> *clone() const { return new Matcher<T>(*this); }
>>> +
>>>    /// \brief Allows the conversion of a \c Matcher<Type> to a \c
>>>    /// Matcher<QualType>.
>>>    ///
>>>
>>> Added: cfe/trunk/include/clang/ASTMatchers/Dynamic/Diagnostics.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/Dynamic/Diagnostics.h?rev=181768&view=auto
>>>
>>> ==============================================================================
>>> --- cfe/trunk/include/clang/ASTMatchers/Dynamic/Diagnostics.h (added)
>>> +++ cfe/trunk/include/clang/ASTMatchers/Dynamic/Diagnostics.h Tue May 14
>>> 04:13:00 2013
>>> @@ -0,0 +1,109 @@
>>> +//===--- Diagnostics.h - Helper class for error diagnostics -----*- C++
>>> -*-===//
>>> +//
>>> +//                     The LLVM Compiler Infrastructure
>>> +//
>>> +// This file is distributed under the University of Illinois Open Source
>>> +// License. See LICENSE.TXT for details.
>>> +//
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +///
>>> +/// \file
>>> +/// \brief Diagnostics class to manage error messages.
>>> +///
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +
>>> +#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H
>>> +#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H
>>> +
>>> +#include <string>
>>> +#include <vector>
>>> +
>>> +#include "clang/ASTMatchers/Dynamic/VariantValue.h"
>>> +#include "clang/Basic/LLVM.h"
>>> +#include "llvm/ADT/ArrayRef.h"
>>> +#include "llvm/ADT/StringRef.h"
>>> +#include "llvm/ADT/Twine.h"
>>> +
>>> +namespace clang {
>>> +namespace ast_matchers {
>>> +namespace dynamic {
>>> +
>>> +struct SourceLocation {
>>> +  SourceLocation() : Line(), Column() {}
>>> +  unsigned Line;
>>> +  unsigned Column;
>>> +};
>>> +
>>> +struct SourceRange {
>>> +  SourceLocation Start;
>>> +  SourceLocation End;
>>> +};
>>> +
>>> +/// \brief A VariantValue instance annotated with its parser context.
>>> +struct ParserValue {
>>> +  ParserValue() : Text(), Range(), Value() {}
>>> +  StringRef Text;
>>> +  SourceRange Range;
>>> +  VariantValue Value;
>>> +};
>>> +
>>> +/// \brief Helper class to manage error messages.
>>> +class Diagnostics {
>>> + public:
>>> +  /// \brief All errors from the system.
>>> +  enum ErrorType {
>>> +    ET_None = 0,
>>> +
>>> +    ET_RegistryNotFound = 1,
>>> +    ET_RegistryWrongArgCount = 2,
>>> +    ET_RegistryWrongArgType = 3,
>>> +
>>> +    ET_ParserStringError = 100,
>>> +    ET_ParserMatcherArgFailure = 101,
>>> +    ET_ParserMatcherFailure = 102,
>>> +    ET_ParserNoOpenParen = 103,
>>> +    ET_ParserNoCloseParen = 104,
>>> +    ET_ParserNoComma = 105,
>>> +    ET_ParserNoCode = 106,
>>> +    ET_ParserNotAMatcher = 107,
>>> +    ET_ParserInvalidToken = 108
>>> +  };
>>> +
>>> +  /// \brief Helper stream class.
>>> +  struct ArgStream {
>>> +    template <class T> ArgStream &operator<<(const T &Arg) {
>>> +      return operator<<(Twine(Arg));
>>> +    }
>>> +    ArgStream &operator<<(const Twine &Arg);
>>> +    std::vector<std::string> *Out;
>>> +  };
>>> +
>>> +  /// \brief Push a frame to the beginning of the list
>>> +  ///
>>> +  /// Returns a helper class to allow the caller to pass the arguments
>>> for the
>>> +  /// error message, using the << operator.
>>> +  ArgStream pushErrorFrame(const SourceRange &Range, ErrorType Error);
>>> +
>>> +  struct ErrorFrame {
>>> +    SourceRange Range;
>>> +    ErrorType Type;
>>> +    std::vector<std::string> Args;
>>> +
>>> +    std::string ToString() const;
>>> +  };
>>> +  ArrayRef<ErrorFrame> frames() const { return Frames; }
>>> +
>>> +  /// \brief Returns a string representation of the last frame.
>>> +  std::string ToString() const;
>>> +  /// \brief Returns a string representation of the whole frame stack.
>>> +  std::string ToStringFull() const;
>>> +
>>> + private:
>>> +   std::vector<ErrorFrame> Frames;
>>> +};
>>> +
>>> +}  // namespace dynamic
>>> +}  // namespace ast_matchers
>>> +}  // namespace clang
>>> +
>>> +#endif  // LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H
>>>
>>> Added: cfe/trunk/include/clang/ASTMatchers/Dynamic/Parser.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/Dynamic/Parser.h?rev=181768&view=auto
>>>
>>> ==============================================================================
>>> --- cfe/trunk/include/clang/ASTMatchers/Dynamic/Parser.h (added)
>>> +++ cfe/trunk/include/clang/ASTMatchers/Dynamic/Parser.h Tue May 14
>>> 04:13:00 2013
>>> @@ -0,0 +1,143 @@
>>> +//===--- 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.
>>> +//
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +///
>>> +/// \file
>>> +/// \brief Simple matcher expression parser.
>>> +///
>>> +/// The parser understands matcher expressions of the form:
>>> +///   MatcherName(Arg0, Arg1, ..., ArgN)
>>> +/// as well as simple types like strings.
>>> +/// The parser does not know how to process the matchers. It delegates
>>> this task
>>> +/// to a Sema object received as an argument.
>>> +///
>>> +/// \code
>>> +/// Grammar for the expressions supported:
>>> +/// <Expression>        := <StringLiteral> | <MatcherExpression>
>>> +/// <StringLiteral>     := "quoted string"
>>> +/// <MatcherExpression> := <MatcherName>(<ArgumentList>)
>>> +/// <MatcherName>       := [a-zA-Z]+
>>> +/// <ArgumentList>      := <Expression> | <Expression>,<ArgumentList>
>>> +/// \endcode
>>> +///
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +
>>> +#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H
>>> +#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H
>>> +
>>> +#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
>>> +#include "clang/ASTMatchers/Dynamic/VariantValue.h"
>>> +#include "clang/Basic/LLVM.h"
>>> +#include "llvm/ADT/ArrayRef.h"
>>> +#include "llvm/ADT/StringRef.h"
>>> +
>>> +namespace clang {
>>> +namespace ast_matchers {
>>> +namespace dynamic {
>>> +
>>> +/// \brief Matcher expression parser.
>>> +class Parser {
>>> +public:
>>> +  /// \brief Interface to connect the parser with the registry and more.
>>> +  ///
>>> +  /// The parser uses the Sema instance passed into
>>> +  /// parseMatcherExpression() to handle all matcher tokens. The
>>> simplest
>>> +  /// processor implementation would simply call into the registry to
>>> create
>>> +  /// the matchers.
>>> +  /// However, a more complex processor might decide to intercept the
>>> matcher
>>> +  /// creation and do some extra work. For example, it could apply some
>>> +  /// transformation to the matcher by adding some id() nodes, or could
>>> detect
>>> +  /// specific matcher nodes for more efficient lookup.
>>> +  class Sema {
>>> +  public:
>>> +    virtual ~Sema();
>>> +
>>> +    /// \brief Process a matcher expression.
>>> +    ///
>>> +    /// All the arguments passed here have already been processed.
>>> +    ///
>>> +    /// \param MatcherName The matcher name found by the parser.
>>> +    ///
>>> +    /// \param NameRange The location of the name in the matcher source.
>>> +    ///   Useful for error reporting.
>>> +    ///
>>> +    /// \param Args The argument list for the matcher.
>>> +    ///
>>> +    /// \return The matcher object constructed by the processor, or NULL
>>> +    ///   if an error occurred. In that case, \c Error will contain a
>>> +    ///   description of the error.
>>> +    ///   The caller takes ownership of the DynTypedMatcher object
>>> returned.
>>> +    virtual DynTypedMatcher *
>>> +    actOnMatcherExpression(StringRef MatcherName, const SourceRange
>>> &NameRange,
>>> +                           ArrayRef<ParserValue> Args, Diagnostics
>>> *Error) = 0;
>>> +  };
>>> +
>>> +  /// \brief Parse a matcher expression, creating matchers from the
>>> registry.
>>> +  ///
>>> +  /// This overload creates matchers calling directly into the
>>> registry. If the
>>> +  /// caller needs more control over how the matchers are created, then
>>> it can
>>> +  /// use the overload below that takes a Sema.
>>> +  ///
>>> +  /// \param MatcherCode The matcher expression to parse.
>>> +  ///
>>> +  /// \return The matcher object constructed, or NULL if an error
>>> occurred.
>>> +  //    In that case, \c Error will contain a description of the error.
>>> +  ///   The caller takes ownership of the DynTypedMatcher object
>>> returned.
>>> +  static DynTypedMatcher *parseMatcherExpression(StringRef MatcherCode,
>>> +                                                 Diagnostics *Error);
>>> +
>>> +  /// \brief Parse a matcher expression.
>>> +  ///
>>> +  /// \param MatcherCode The matcher expression to parse.
>>> +  ///
>>> +  /// \param S The Sema instance that will help the parser
>>> +  ///   construct the matchers.
>>> +  /// \return The matcher object constructed by the processor, or NULL
>>> +  ///   if an error occurred. In that case, \c Error will contain a
>>> +  ///   description of the error.
>>> +  ///   The caller takes ownership of the DynTypedMatcher object
>>> returned.
>>> +  static DynTypedMatcher *parseMatcherExpression(StringRef MatcherCode,
>>> +                                                 Sema *S,
>>> +                                                 Diagnostics *Error);
>>> +
>>> +  /// \brief Parse an expression, creating matchers from the registry.
>>> +  ///
>>> +  /// Parses any expression supported by this parser. In general, the
>>> +  /// \c parseMatcherExpression function is a better approach to get a
>>> matcher
>>> +  /// object.
>>> +  static bool parseExpression(StringRef Code, VariantValue *Value,
>>> +                              Diagnostics *Error);
>>> +
>>> +  /// \brief Parse an expression.
>>> +  ///
>>> +  /// Parses any expression supported by this parser. In general, the
>>> +  /// \c parseMatcherExpression function is a better approach to get a
>>> matcher
>>> +  /// object.
>>> +  static bool parseExpression(StringRef Code, Sema *S,
>>> +                              VariantValue *Value, Diagnostics *Error);
>>> +
>>> +private:
>>> +  class CodeTokenizer;
>>> +  struct TokenInfo;
>>> +
>>> +  Parser(CodeTokenizer *Tokenizer, Sema *S,
>>> +         Diagnostics *Error);
>>> +
>>> +  bool parseExpressionImpl(VariantValue *Value);
>>> +  bool parseMatcherExpressionImpl(VariantValue *Value);
>>> +
>>> +  CodeTokenizer *const Tokenizer;
>>> +  Sema *const S;
>>> +  Diagnostics *const Error;
>>> +};
>>> +
>>> +}  // namespace dynamic
>>> +}  // namespace ast_matchers
>>> +}  // namespace clang
>>> +
>>> +#endif  // LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H
>>>
>>> Added: cfe/trunk/include/clang/ASTMatchers/Dynamic/Registry.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/Dynamic/Registry.h?rev=181768&view=auto
>>>
>>> ==============================================================================
>>> --- cfe/trunk/include/clang/ASTMatchers/Dynamic/Registry.h (added)
>>> +++ cfe/trunk/include/clang/ASTMatchers/Dynamic/Registry.h Tue May 14
>>> 04:13:00 2013
>>> @@ -0,0 +1,63 @@
>>> +//===--- 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.
>>> +//
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +///
>>> +/// \file
>>> +/// \brief 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 "clang/ASTMatchers/Dynamic/Diagnostics.h"
>>> +#include "clang/ASTMatchers/Dynamic/VariantValue.h"
>>> +#include "clang/Basic/LLVM.h"
>>> +#include "llvm/ADT/ArrayRef.h"
>>> +#include "llvm/ADT/StringRef.h"
>>> +
>>> +namespace clang {
>>> +namespace ast_matchers {
>>> +namespace dynamic {
>>> +
>>> +class Registry {
>>> +public:
>>> +  /// \brief Construct a matcher from the registry by name.
>>> +  ///
>>> +  /// Consult the registry of known matchers and construct the
>>> appropriate
>>> +  /// matcher by name.
>>> +  ///
>>> +  /// \param MatcherName The name of the matcher to instantiate.
>>> +  ///
>>> +  /// \param NameRange The location of the name in the matcher source.
>>> +  ///   Useful for error reporting.
>>> +  ///
>>> +  /// \param Args The argument list for the matcher. The number and
>>> types of the
>>> +  ///   values must be valid for the matcher requested. Otherwise, the
>>> function
>>> +  ///   will return an error.
>>> +  ///
>>> +  /// \return The matcher if no error was found. NULL if the matcher is
>>> not
>>> +  //    found, or if the number of arguments or argument types do not
>>> +  ///   match the signature. In that case \c Error will contain the
>>> description
>>> +  ///   of the error.
>>> +  static DynTypedMatcher *constructMatcher(StringRef MatcherName,
>>> +                                           const SourceRange &NameRange,
>>> +                                           ArrayRef<ParserValue> Args,
>>> +                                           Diagnostics *Error);
>>> +
>>> +private:
>>> +  Registry() LLVM_DELETED_FUNCTION;
>>> +};
>>> +
>>> +}  // namespace dynamic
>>> +}  // namespace ast_matchers
>>> +}  // namespace clang
>>> +
>>> +#endif  // LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H
>>>
>>> Added: cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h?rev=181768&view=auto
>>>
>>> ==============================================================================
>>> --- cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h (added)
>>> +++ cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h Tue May
>>> 14 04:13:00 2013
>>> @@ -0,0 +1,125 @@
>>> +//===--- VariantValue.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.
>>> +//
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +///
>>> +/// \file
>>> +/// \brief Polymorphic value type.
>>> +///
>>> +/// 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_VARIANT_VALUE_H
>>> +#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
>>> +
>>> +#include "clang/ASTMatchers/ASTMatchers.h"
>>> +#include "clang/ASTMatchers/ASTMatchersInternal.h"
>>> +#include "llvm/ADT/Twine.h"
>>> +#include "llvm/Support/type_traits.h"
>>> +
>>> +namespace clang {
>>> +namespace ast_matchers {
>>> +namespace dynamic {
>>> +
>>> +typedef ast_matchers::internal::DynTypedMatcher DynTypedMatcher;
>>> +
>>> +/// \brief Variant value class.
>>> +///
>>> +/// Basically, a tagged union with value type semantics.
>>> +/// It is used by the registry as the return value and argument type
>>> for the
>>> +/// matcher factory methods.
>>> +/// It can be constructed from any of the supported types. It supports
>>> +/// copy/assignment.
>>> +///
>>> +/// Supported types:
>>> +///  - \c std::string
>>> +///  - \c DynTypedMatcher, and any \c Matcher<T>
>>> +class VariantValue {
>>> +public:
>>> +  VariantValue() : Type(VT_Nothing) {}
>>> +
>>> +  VariantValue(const VariantValue &Other);
>>> +  ~VariantValue();
>>> +  VariantValue &operator=(const VariantValue &Other);
>>> +
>>> +  /// \brief Specific constructors for each supported type.
>>> +  VariantValue(const std::string &String);
>>> +  VariantValue(const DynTypedMatcher &Matcher);
>>> +
>>> +  /// \brief String value functions.
>>> +  bool isString() const;
>>> +  const std::string &getString() const;
>>> +  void setString(const std::string &String);
>>> +
>>> +  /// \brief Matcher value functions.
>>> +  bool isMatcher() const;
>>> +  const DynTypedMatcher &getMatcher() const;
>>> +  void setMatcher(const DynTypedMatcher &Matcher);
>>> +  /// \brief Set the value to be \c Matcher by taking ownership of the
>>> object.
>>> +  void takeMatcher(DynTypedMatcher *Matcher);
>>> +
>>> +  /// \brief Specialized Matcher<T> is/get functions.
>>> +  template <class T>
>>> +  bool isTypedMatcher() const {
>>> +    // TODO: Add some logic to test if T is actually valid for the
>>> underlying
>>> +    // type of the matcher.
>>> +    return isMatcher();
>>> +  }
>>> +
>>> +  template <class T>
>>> +  ast_matchers::internal::Matcher<T> getTypedMatcher() const {
>>> +    return ast_matchers::internal::makeMatcher(
>>> +        new DerivedTypeMatcher<T>(getMatcher()));
>>> +  }
>>> +
>>> +private:
>>> +  void reset();
>>> +
>>> +  /// \brief Matcher bridge between a Matcher<T> and a generic
>>> DynTypedMatcher.
>>> +  template <class T>
>>> +  class DerivedTypeMatcher :
>>> +      public ast_matchers::internal::MatcherInterface<T> {
>>> +  public:
>>> +    explicit DerivedTypeMatcher(const DynTypedMatcher &DynMatcher)
>>> +        : DynMatcher(DynMatcher.clone()) {}
>>> +    virtual ~DerivedTypeMatcher() {}
>>> +
>>> +    typedef ast_matchers::internal::ASTMatchFinder ASTMatchFinder;
>>> +    typedef ast_matchers::internal::BoundNodesTreeBuilder
>>> BoundNodesTreeBuilder;
>>> +    bool matches(const T &Node, ASTMatchFinder *Finder,
>>> +                 BoundNodesTreeBuilder *Builder) const {
>>> +      return
>>> DynMatcher->matches(ast_type_traits::DynTypedNode::create(Node),
>>> +                                 Finder, Builder);
>>> +    }
>>> +
>>> +  private:
>>> +    const OwningPtr<DynTypedMatcher> DynMatcher;
>>> +  };
>>> +
>>> +  /// \brief All supported value types.
>>> +  enum ValueType {
>>> +    VT_Nothing,
>>> +    VT_String,
>>> +    VT_Matcher
>>> +  };
>>> +
>>> +  /// \brief All supported value types.
>>> +  union AllValues {
>>> +    std::string *String;
>>> +    DynTypedMatcher *Matcher;
>>> +  };
>>> +
>>> +  ValueType Type;
>>> +  AllValues Value;
>>> +};
>>> +
>>> +} // end namespace dynamic
>>> +} // end namespace ast_matchers
>>> +} // end namespace clang
>>> +
>>> +#endif  // LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
>>>
>>> Modified: cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp?rev=181768&r1=181767&r2=181768&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp (original)
>>> +++ cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp Tue May 14 04:13:00 2013
>>> @@ -744,6 +744,14 @@ void MatchFinder::addMatcher(const TypeL
>>>      new TypeLocMatcher(NodeMatch), Action));
>>>  }
>>>
>>> +bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher
>>> &NodeMatch,
>>> +                                    MatchCallback *Action) {
>>> +  MatcherCallbackPairs.push_back(std::make_pair(NodeMatch.clone(),
>>> Action));
>>> +  // TODO: Do runtime type checking to make sure the matcher is one of
>>> the valid
>>> +  // top-level matchers.
>>> +  return true;
>>> +}
>>> +
>>>  ASTConsumer *MatchFinder::newASTConsumer() {
>>>    return new internal::MatchASTConsumer(&MatcherCallbackPairs,
>>> ParsingDone);
>>>  }
>>>
>>> Modified: cfe/trunk/lib/ASTMatchers/CMakeLists.txt
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/CMakeLists.txt?rev=181768&r1=181767&r2=181768&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/ASTMatchers/CMakeLists.txt (original)
>>> +++ cfe/trunk/lib/ASTMatchers/CMakeLists.txt Tue May 14 04:13:00 2013
>>> @@ -1,3 +1,5 @@
>>> +add_subdirectory(Dynamic)
>>> +
>>>  set(LLVM_LINK_COMPONENTS support)
>>>
>>>  add_clang_library(clangASTMatchers
>>>
>>> Added: cfe/trunk/lib/ASTMatchers/Dynamic/CMakeLists.txt
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/CMakeLists.txt?rev=181768&view=auto
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/ASTMatchers/Dynamic/CMakeLists.txt (added)
>>> +++ cfe/trunk/lib/ASTMatchers/Dynamic/CMakeLists.txt Tue May 14 04:13:00
>>> 2013
>>> @@ -0,0 +1,12 @@
>>> +set(LLVM_LINK_COMPONENTS support)
>>> +
>>> +add_clang_library(clangDynamicASTMatchers
>>> +  Diagnostics.cpp
>>> +  VariantValue.cpp
>>> +  Parser.cpp
>>> +  Registry.cpp
>>> +  )
>>> +
>>> +add_dependencies(clangDynamicASTMatchers
>>> +  clangASTMatchers
>>> +  )
>>>
>>> Added: cfe/trunk/lib/ASTMatchers/Dynamic/Diagnostics.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Diagnostics.cpp?rev=181768&view=auto
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/ASTMatchers/Dynamic/Diagnostics.cpp (added)
>>> +++ cfe/trunk/lib/ASTMatchers/Dynamic/Diagnostics.cpp Tue May 14
>>> 04:13:00 2013
>>> @@ -0,0 +1,113 @@
>>> +//===--- Diagnostics.cpp - Helper class for error diagnostics -----*-
>>> C++ -*-===//
>>> +//
>>> +//                     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/Diagnostics.h"
>>> +
>>> +namespace clang {
>>> +namespace ast_matchers {
>>> +namespace dynamic {
>>> +
>>> +Diagnostics::ArgStream &
>>> +Diagnostics::ArgStream::operator<<(const Twine &Arg) {
>>> +  Out->push_back(Arg.str());
>>> +  return *this;
>>> +}
>>> +
>>> +Diagnostics::ArgStream Diagnostics::pushErrorFrame(const SourceRange
>>> &Range,
>>> +                                                   ErrorType Error) {
>>> +  Frames.insert(Frames.begin(), ErrorFrame());
>>> +  ErrorFrame &Last = Frames.front();
>>> +  Last.Range = Range;
>>> +  Last.Type = Error;
>>> +  ArgStream Out = { &Last.Args };
>>> +  return Out;
>>> +}
>>> +
>>> +StringRef ErrorTypeToString(Diagnostics::ErrorType Type) {
>>> +  switch (Type) {
>>> +  case Diagnostics::ET_RegistryNotFound:
>>> +    return "Matcher not found: $0";
>>> +  case Diagnostics::ET_RegistryWrongArgCount:
>>> +    return "Incorrect argument count. (Expected = $0) != (Actual = $1)";
>>> +  case Diagnostics::ET_RegistryWrongArgType:
>>> +    return "Incorrect type on function $0 for arg $1.";
>>> +
>>> +  case Diagnostics::ET_ParserStringError:
>>> +    return "Error parsing string token: <$0>";
>>> +  case Diagnostics::ET_ParserMatcherArgFailure:
>>> +    return "Error parsing argument $0 for matcher $1.";
>>> +  case Diagnostics::ET_ParserMatcherFailure:
>>> +    return "Error building matcher $0.";
>>> +  case Diagnostics::ET_ParserNoOpenParen:
>>> +    return "Error parsing matcher. Found token <$0> while looking for
>>> '('.";
>>> +  case Diagnostics::ET_ParserNoCloseParen:
>>> +    return "Error parsing matcher. Found end-of-code while looking for
>>> ')'.";
>>> +  case Diagnostics::ET_ParserNoComma:
>>> +    return "Error parsing matcher. Found token <$0> while looking for
>>> ','.";
>>> +  case Diagnostics::ET_ParserNoCode:
>>> +    return "End of code found while looking for token.";
>>> +  case Diagnostics::ET_ParserNotAMatcher:
>>> +    return "Input value is not a matcher expression.";
>>> +  case Diagnostics::ET_ParserInvalidToken:
>>> +    return "Invalid token <$0> found when looking for a value.";
>>> +
>>> +  case Diagnostics::ET_None:
>>> +    return "<N/A>";
>>> +  }
>>> +  llvm_unreachable("Unknown ErrorType value.");
>>> +}
>>> +
>>> +std::string FormatErrorString(StringRef FormatString,
>>> +                              ArrayRef<std::string> Args) {
>>> +  std::string Out;
>>> +  while (!FormatString.empty()) {
>>> +    std::pair<StringRef, StringRef> Pieces = FormatString.split("$");
>>> +    Out += Pieces.first.str();
>>> +    if (Pieces.second.empty()) break;
>>> +
>>> +    const char Next = Pieces.second.front();
>>> +    FormatString = Pieces.second.drop_front();
>>> +    if (Next >= '0' && Next <= '9') {
>>> +      const unsigned Index = Next - '0';
>>> +      if (Index < Args.size()) {
>>> +        Out += Args[Index];
>>> +      } else {
>>> +        Out += "<Argument_Not_Provided>";
>>> +      }
>>> +    }
>>> +  }
>>> +  return Out;
>>> +}
>>> +
>>> +std::string Diagnostics::ErrorFrame::ToString() const {
>>> +  StringRef FormatString = ErrorTypeToString(Type);
>>> +  std::string ErrorOut = FormatErrorString(FormatString, Args);
>>> +  if (Range.Start.Line > 0 && Range.Start.Column > 0)
>>> +    return (Twine(Range.Start.Line) + ":" + Twine(Range.Start.Column) +
>>> ": " +
>>> +            ErrorOut).str();
>>> +  return ErrorOut;
>>> +}
>>> +
>>> +std::string Diagnostics::ToString() const {
>>> +  if (Frames.empty()) return "";
>>> +  return Frames[Frames.size() - 1].ToString();
>>> +}
>>> +
>>> +std::string Diagnostics::ToStringFull() const {
>>> +  std::string Result;
>>> +  for (size_t i = 0, end = Frames.size(); i != end; ++i) {
>>> +    if (i > 0) Result += "\n";
>>> +    Result += Frames[i].ToString();
>>> +  }
>>> +  return Result;
>>> +}
>>> +
>>> +}  // namespace dynamic
>>> +}  // namespace ast_matchers
>>> +}  // namespace clang
>>>
>>> Copied: cfe/trunk/lib/ASTMatchers/Dynamic/Makefile (from r181767,
>>> cfe/trunk/lib/ASTMatchers/Makefile)
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Makefile?p2=cfe/trunk/lib/ASTMatchers/Dynamic/Makefile&p1=cfe/trunk/lib/ASTMatchers/Makefile&r1=181767&r2=181768&rev=181768&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/ASTMatchers/Makefile (original)
>>> +++ cfe/trunk/lib/ASTMatchers/Dynamic/Makefile Tue May 14 04:13:00 2013
>>> @@ -1,4 +1,4 @@
>>> -##===- clang/lib/ASTMatchers/Makefile ----------------------*- Makefile
>>> -*-===##
>>> +##===- clang/lib/ASTMatchers/Dynamic/Makefile --------------*- Makefile
>>> -*-===##
>>>  #
>>>  #                     The LLVM Compiler Infrastructure
>>>  #
>>> @@ -7,7 +7,7 @@
>>>  #
>>>
>>>  ##===----------------------------------------------------------------------===##
>>>
>>> -CLANG_LEVEL := ../..
>>> -LIBRARYNAME := clangASTMatchers
>>> +CLANG_LEVEL := ../../..
>>> +LIBRARYNAME := clangDynamicASTMatchers
>>>
>>>  include $(CLANG_LEVEL)/Makefile
>>>
>>> Added: cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h?rev=181768&view=auto
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h (added)
>>> +++ cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h Tue May 14 04:13:00
>>> 2013
>>> @@ -0,0 +1,223 @@
>>> +//===--- 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.
>>> +//
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +///
>>> +/// \file
>>> +/// \brief Functions templates and classes to wrap matcher construct
>>> functions.
>>> +///
>>> +/// 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/Diagnostics.h"
>>> +#include "clang/ASTMatchers/Dynamic/VariantValue.h"
>>> +#include "clang/Basic/LLVM.h"
>>> +#include "llvm/Support/type_traits.h"
>>> +
>>> +namespace clang {
>>> +namespace ast_matchers {
>>> +namespace dynamic {
>>> +
>>> +namespace internal {
>>> +
>>> +/// \brief Helper template class to just from argument type to the
>>> right is/get
>>> +///   functions in VariantValue.
>>> +/// Used to verify and extract the matcher arguments below.
>>> +template <class T> struct ArgTypeTraits;
>>> +template <class T> struct ArgTypeTraits<const T &> : public
>>> ArgTypeTraits<T> {
>>> +};
>>> +
>>> +template <> struct ArgTypeTraits<std::string> {
>>> +  static bool is(const VariantValue &Value) { return Value.isString(); }
>>> +  static const std::string &get(const VariantValue &Value) {
>>> +    return Value.getString();
>>> +  }
>>> +};
>>> +
>>> +template <class T> struct
>>> ArgTypeTraits<ast_matchers::internal::Matcher<T> > {
>>> +  static bool is(const VariantValue &Value) { return Value.isMatcher();
>>> }
>>> +  static ast_matchers::internal::Matcher<T> get(const VariantValue
>>> &Value) {
>>> +    return Value.getTypedMatcher<T>();
>>> +  }
>>> +
>>> +};
>>> +
>>> +/// \brief Generic MatcherCreate interface.
>>> +///
>>> +/// Provides a \c run() method that constructs the matcher from the
>>> provided
>>> +/// arguments.
>>> +class MatcherCreateCallback {
>>> +public:
>>> +  virtual ~MatcherCreateCallback() {}
>>> +  virtual DynTypedMatcher *run(const SourceRange &NameRange,
>>> +                               ArrayRef<ParserValue> Args,
>>> +                               Diagnostics *Error) const = 0;
>>> +};
>>> +
>>> +/// \brief Simple callback implementation. Marshaller and function are
>>> provided.
>>> +///
>>> +/// \param Marshaller Function to unpack the arguments and call \c Func
>>> +/// \param Func Matcher construct function. This is the function that
>>> +///   compile-time matcher expressions would use to create the matcher.
>>> +template <typename MarshallerType, typename FuncType>
>>> +class FixedArgCountMatcherCreateCallback : public MatcherCreateCallback
>>> {
>>> +public:
>>> +  FixedArgCountMatcherCreateCallback(MarshallerType Marshaller,
>>> FuncType Func,
>>> +                                     StringRef MatcherName)
>>> +      : Marshaller(Marshaller), Func(Func),
>>> MatcherName(MatcherName.str()) {}
>>> +
>>> +  DynTypedMatcher *run(const SourceRange &NameRange,
>>> +                       ArrayRef<ParserValue> Args, Diagnostics *Error)
>>> const {
>>> +    return Marshaller(Func, MatcherName, NameRange, Args, Error);
>>> +  }
>>> +
>>> +private:
>>> +  const MarshallerType Marshaller;
>>> +  const FuncType Func;
>>> +  const std::string MatcherName;
>>> +};
>>> +
>>> +/// \brief Helper function to do template argument deduction.
>>> +template <typename MarshallerType, typename FuncType>
>>> +MatcherCreateCallback *
>>> +createMarshallerCallback(MarshallerType Marshaller, FuncType Func,
>>> +                         StringRef MatcherName) {
>>> +  return new FixedArgCountMatcherCreateCallback<MarshallerType,
>>> FuncType>(
>>> +      Marshaller, Func, MatcherName);
>>> +}
>>> +
>>> +/// \brief Helper macros to check the arguments on all marshaller
>>> functions.
>>> +#define CHECK_ARG_COUNT(count)
>>>         \
>>> +  if (Args.size() != count) {
>>>        \
>>> +    Error->pushErrorFrame(NameRange, Error->ET_RegistryWrongArgCount)
>>>        \
>>> +        << count << Args.size();
>>>         \
>>> +    return NULL;
>>>         \
>>> +  }
>>> +
>>> +#define CHECK_ARG_TYPE(index, type)
>>>        \
>>> +  if (!ArgTypeTraits<type>::is(Args[index].Value)) {
>>>         \
>>> +    Error->pushErrorFrame(Args[index].Range,
>>> Error->ET_RegistryWrongArgType)   \
>>> +        << MatcherName << (index + 1);
>>>         \
>>> +    return NULL;
>>>         \
>>> +  }
>>> +
>>> +/// \brief Metafunction to normalize argument types.
>>> +///
>>> +/// We need to remove the const& out of the function parameters to be
>>> able to
>>> +/// find values on VariantValue.
>>> +template <typename T>
>>> +struct remove_const_ref :
>>> +    public llvm::remove_const<typename llvm::remove_reference<T>::type>
>>> {
>>> +};
>>> +
>>> +/// \brief 0-arg marshaller function.
>>> +template <typename ReturnType>
>>> +DynTypedMatcher *matcherMarshall0(ReturnType (*Func)(), StringRef
>>> MatcherName,
>>> +                                  const SourceRange &NameRange,
>>> +                                  ArrayRef<ParserValue> Args,
>>> +                                  Diagnostics *Error) {
>>> +  CHECK_ARG_COUNT(0);
>>> +  return Func().clone();
>>> +}
>>> +
>>> +/// \brief 1-arg marshaller function.
>>> +template <typename ReturnType, typename InArgType1>
>>> +DynTypedMatcher *matcherMarshall1(ReturnType (*Func)(InArgType1),
>>> +                                  StringRef MatcherName,
>>> +                                  const SourceRange &NameRange,
>>> +                                  ArrayRef<ParserValue> Args,
>>> +                                  Diagnostics *Error) {
>>> +  typedef typename remove_const_ref<InArgType1>::type ArgType1;
>>> +  CHECK_ARG_COUNT(1);
>>> +  CHECK_ARG_TYPE(0, ArgType1);
>>> +  return Func(ArgTypeTraits<ArgType1>::get(Args[0].Value)).clone();
>>> +}
>>> +
>>> +/// \brief Variadic marshaller function.
>>> +template <typename BaseType, typename DerivedType>
>>> +class VariadicMatcherCreateCallback : public MatcherCreateCallback {
>>> +public:
>>> +  explicit VariadicMatcherCreateCallback(StringRef MatcherName)
>>> +      : MatcherName(MatcherName.str()) {}
>>> +
>>> +  typedef ast_matchers::internal::Matcher<DerivedType>
>>> DerivedMatcherType;
>>> +
>>> +  DynTypedMatcher *run(const SourceRange &NameRange,
>>> ArrayRef<ParserValue> Args,
>>> +                       Diagnostics *Error) const {
>>> +    std::list<DerivedMatcherType> References;
>>> +    std::vector<const DerivedMatcherType *> InnerArgs(Args.size());
>>> +    for (size_t i = 0, e = Args.size(); i != e; ++i) {
>>> +      CHECK_ARG_TYPE(i, DerivedMatcherType);
>>> +      References.push_back(
>>> +          ArgTypeTraits<DerivedMatcherType>::get(Args[i].Value));
>>> +      InnerArgs[i] = &References.back();
>>> +    }
>>> +    return ast_matchers::internal::makeDynCastAllOfComposite<BaseType>(
>>> +        ArrayRef<const DerivedMatcherType *>(InnerArgs)).clone();
>>> +  }
>>> +
>>> +private:
>>> +  const std::string MatcherName;
>>> +};
>>> +
>>> +#undef CHECK_ARG_COUNT
>>> +#undef CHECK_ARG_TYPE
>>> +
>>> +/// Helper functions to select the appropriate marshaller functions.
>>> +/// They detects the number of arguments, arguments types and return
>>> type.
>>> +
>>> +/// \brief 0-arg overload
>>> +template <typename ReturnType>
>>> +MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(),
>>> +                                               StringRef MatcherName) {
>>> +  return createMarshallerCallback(matcherMarshall0<ReturnType>, Func,
>>> +                                  MatcherName);
>>> +}
>>> +
>>> +/// \brief 1-arg overload
>>> +template <typename ReturnType, typename ArgType1>
>>> +MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType
>>> (*Func)(ArgType1),
>>> +                                               StringRef MatcherName) {
>>> +  return createMarshallerCallback(matcherMarshall1<ReturnType,
>>> ArgType1>, Func,
>>> +                                  MatcherName);
>>> +}
>>> +
>>> +/// \brief Variadic overload.
>>> +template <typename MatcherType>
>>> +MatcherCreateCallback *makeMatcherAutoMarshall(
>>> +    ast_matchers::internal::VariadicAllOfMatcher<MatcherType> Func,
>>> +    StringRef MatcherName) {
>>> +  return new VariadicMatcherCreateCallback<MatcherType, MatcherType>(
>>> +      MatcherName);
>>> +}
>>> +
>>> +template <typename BaseType, typename MatcherType>
>>> +MatcherCreateCallback *
>>>
>>> +makeMatcherAutoMarshall(ast_matchers::internal::VariadicDynCastAllOfMatcher<
>>> +                            BaseType, MatcherType> Func,
>>> +                        StringRef MatcherName) {
>>> +  return new VariadicMatcherCreateCallback<BaseType,
>>> MatcherType>(MatcherName);
>>> +}
>>> +
>>> +}  // namespace internal
>>> +}  // namespace dynamic
>>> +}  // namespace ast_matchers
>>> +}  // namespace clang
>>> +
>>> +#endif  // LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H
>>>
>>> Added: cfe/trunk/lib/ASTMatchers/Dynamic/Parser.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Parser.cpp?rev=181768&view=auto
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/ASTMatchers/Dynamic/Parser.cpp (added)
>>> +++ cfe/trunk/lib/ASTMatchers/Dynamic/Parser.cpp Tue May 14 04:13:00 2013
>>> @@ -0,0 +1,332 @@
>>> +//===--- 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.
>>> +//
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +///
>>> +/// \file
>>> +/// \brief Recursive parser implementation for the matcher expression
>>> grammar.
>>> +///
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +
>>> +#include <string>
>>> +#include <vector>
>>> +
>>> +#include "clang/ASTMatchers/Dynamic/Parser.h"
>>> +#include "clang/ASTMatchers/Dynamic/Registry.h"
>>> +#include "clang/Basic/CharInfo.h"
>>> +#include "llvm/ADT/Twine.h"
>>> +
>>> +namespace clang {
>>> +namespace ast_matchers {
>>> +namespace dynamic {
>>> +
>>> +/// \brief Simple structure to hold information for one token from the
>>> parser.
>>> +struct Parser::TokenInfo {
>>> +  /// \brief Different possible tokens.
>>> +  enum TokenKind {
>>> +    TK_Eof = 0,
>>> +    TK_OpenParen = 1,
>>> +    TK_CloseParen = 2,
>>> +    TK_Comma = 3,
>>> +    TK_Literal = 4,
>>> +    TK_Ident = 5,
>>> +    TK_InvalidChar = 6,
>>> +    TK_Error = 7
>>> +  };
>>> +
>>> +  TokenInfo() : Text(), Kind(TK_Eof), Range(), Value() {}
>>> +
>>> +  StringRef Text;
>>> +  TokenKind Kind;
>>> +  SourceRange Range;
>>> +  VariantValue Value;
>>> +};
>>> +
>>> +/// \brief Simple tokenizer for the parser.
>>> +class Parser::CodeTokenizer {
>>> +public:
>>> +  explicit CodeTokenizer(StringRef MatcherCode, Diagnostics *Error)
>>> +      : Code(MatcherCode), StartOfLine(MatcherCode), Line(1),
>>> Error(Error) {
>>> +    NextToken = getNextToken();
>>> +  }
>>> +
>>> +  /// \brief Returns but doesn't consume the next token.
>>> +  const TokenInfo &peekNextToken() const { return NextToken; }
>>> +
>>> +  /// \brief Consumes and returns the next token.
>>> +  TokenInfo consumeNextToken() {
>>> +    TokenInfo ThisToken = NextToken;
>>> +    NextToken = getNextToken();
>>> +    return ThisToken;
>>> +  }
>>> +
>>> +  TokenInfo::TokenKind nextTokenKind() const { return NextToken.Kind; }
>>> +
>>> +private:
>>> +  TokenInfo getNextToken() {
>>> +    consumeWhitespace();
>>> +    TokenInfo Result;
>>> +    Result.Range.Start = currentLocation();
>>> +
>>> +    if (Code.empty()) {
>>> +      Result.Kind = TokenInfo::TK_Eof;
>>> +      Result.Text = "";
>>> +      return Result;
>>> +    }
>>> +
>>> +    switch (Code[0]) {
>>> +    case ',':
>>> +      Result.Kind = TokenInfo::TK_Comma;
>>> +      Result.Text = Code.substr(0, 1);
>>> +      Code = Code.drop_front();
>>> +      break;
>>> +    case '(':
>>> +      Result.Kind = TokenInfo::TK_OpenParen;
>>> +      Result.Text = Code.substr(0, 1);
>>> +      Code = Code.drop_front();
>>> +      break;
>>> +    case ')':
>>> +      Result.Kind = TokenInfo::TK_CloseParen;
>>> +      Result.Text = Code.substr(0, 1);
>>> +      Code = Code.drop_front();
>>> +      break;
>>> +
>>> +    case '"':
>>> +    case '\'':
>>> +      // Parse a string literal.
>>> +      consumeStringLiteral(&Result);
>>> +      break;
>>> +
>>> +    default:
>>> +      if (isAlphanumeric(Code[0])) {
>>> +        // Parse an identifier
>>> +        size_t TokenLength = 1;
>>> +        while (TokenLength < Code.size() &&
>>> isAlphanumeric(Code[TokenLength]))
>>> +          ++TokenLength;
>>> +        Result.Kind = TokenInfo::TK_Ident;
>>> +        Result.Text = Code.substr(0, TokenLength);
>>> +        Code = Code.drop_front(TokenLength);
>>> +      } else {
>>> +        Result.Kind = TokenInfo::TK_InvalidChar;
>>> +        Result.Text = Code.substr(0, 1);
>>> +        Code = Code.drop_front(1);
>>> +      }
>>> +      break;
>>> +    }
>>> +
>>> +    Result.Range.End = currentLocation();
>>> +    return Result;
>>> +  }
>>> +
>>> +  /// \brief Consume a string literal.
>>> +  ///
>>> +  /// \c Code must be positioned at the start of the literal (the
>>> opening
>>> +  /// quote). Consumed until it finds the same closing quote character.
>>> +  void consumeStringLiteral(TokenInfo *Result) {
>>> +    bool InEscape = false;
>>> +    const char Marker = Code[0];
>>> +    for (size_t Length = 1, Size = Code.size(); Length != Size;
>>> ++Length) {
>>> +      if (InEscape) {
>>> +        InEscape = false;
>>> +        continue;
>>> +      }
>>> +      if (Code[Length] == '\\') {
>>> +        InEscape = true;
>>> +        continue;
>>> +      }
>>> +      if (Code[Length] == Marker) {
>>> +        Result->Kind = TokenInfo::TK_Literal;
>>> +        Result->Text = Code.substr(0, Length + 1);
>>> +        Result->Value = Code.substr(1, Length - 1).str();
>>> +        Code = Code.drop_front(Length + 1);
>>> +        return;
>>> +      }
>>> +    }
>>> +
>>> +    StringRef ErrorText = Code;
>>> +    Code = Code.drop_front(Code.size());
>>> +    SourceRange Range;
>>> +    Range.Start = Result->Range.Start;
>>> +    Range.End = currentLocation();
>>> +    Error->pushErrorFrame(Range, Error->ET_ParserStringError)
>>> +        << ErrorText;
>>> +    Result->Kind = TokenInfo::TK_Error;
>>> +  }
>>> +
>>> +  /// \brief Consume all leading whitespace from \c Code.
>>> +  void consumeWhitespace() {
>>> +    while (!Code.empty() && isWhitespace(Code[0])) {
>>> +      if (Code[0] == '\n') {
>>> +        ++Line;
>>> +        StartOfLine = Code.drop_front();
>>> +      }
>>> +      Code = Code.drop_front();
>>> +    }
>>> +  }
>>> +
>>> +  SourceLocation currentLocation() {
>>> +    SourceLocation Location;
>>> +    Location.Line = Line;
>>> +    Location.Column = Code.data() - StartOfLine.data() + 1;
>>> +    return Location;
>>> +  }
>>> +
>>> +  StringRef Code;
>>> +  StringRef StartOfLine;
>>> +  unsigned Line;
>>> +  Diagnostics *Error;
>>> +  TokenInfo NextToken;
>>> +};
>>> +
>>> +Parser::Sema::~Sema() {}
>>> +
>>> +/// \brief Parse and validate a matcher expression.
>>> +/// \return \c true on success, in which case \c Value has the matcher
>>> parsed.
>>> +///   If the input is malformed, or some argument has an error, it
>>> +///   returns \c false.
>>> +bool Parser::parseMatcherExpressionImpl(VariantValue *Value) {
>>> +  const TokenInfo NameToken = Tokenizer->consumeNextToken();
>>> +  assert(NameToken.Kind == TokenInfo::TK_Ident);
>>> +  const TokenInfo OpenToken = Tokenizer->consumeNextToken();
>>> +  if (OpenToken.Kind != TokenInfo::TK_OpenParen) {
>>> +    Error->pushErrorFrame(OpenToken.Range, Error->ET_ParserNoOpenParen)
>>> +        << OpenToken.Text;
>>> +    return false;
>>> +  }
>>> +
>>> +  std::vector<ParserValue> Args;
>>> +  TokenInfo EndToken;
>>> +  while (Tokenizer->nextTokenKind() != TokenInfo::TK_Eof) {
>>> +    if (Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen) {
>>> +      // End of args.
>>> +      EndToken = Tokenizer->consumeNextToken();
>>> +      break;
>>> +    }
>>> +    if (Args.size() > 0) {
>>> +      // We must find a , token to continue.
>>> +      const TokenInfo CommaToken = Tokenizer->consumeNextToken();
>>> +      if (CommaToken.Kind != TokenInfo::TK_Comma) {
>>> +        Error->pushErrorFrame(CommaToken.Range, Error->ET_ParserNoComma)
>>> +            << CommaToken.Text;
>>> +        return false;
>>> +      }
>>> +    }
>>> +
>>> +    ParserValue ArgValue;
>>> +    ArgValue.Text = Tokenizer->peekNextToken().Text;
>>> +    ArgValue.Range = Tokenizer->peekNextToken().Range;
>>> +    if (!parseExpressionImpl(&ArgValue.Value)) {
>>> +      Error->pushErrorFrame(NameToken.Range,
>>> +                            Error->ET_ParserMatcherArgFailure)
>>> +          << (Args.size() + 1) << NameToken.Text;
>>> +      return false;
>>> +    }
>>> +
>>> +    Args.push_back(ArgValue);
>>> +  }
>>> +
>>> +  if (EndToken.Kind == TokenInfo::TK_Eof) {
>>> +    Error->pushErrorFrame(OpenToken.Range,
>>> Error->ET_ParserNoCloseParen);
>>> +    return false;
>>> +  }
>>> +
>>> +  // Merge the start and end infos.
>>> +  SourceRange MatcherRange = NameToken.Range;
>>> +  MatcherRange.End = EndToken.Range.End;
>>> +  DynTypedMatcher *Result =
>>> +      S->actOnMatcherExpression(NameToken.Text, MatcherRange, Args,
>>> Error);
>>> +  if (Result == NULL) {
>>> +    Error->pushErrorFrame(NameToken.Range,
>>> Error->ET_ParserMatcherFailure)
>>> +        << NameToken.Text;
>>> +    return false;
>>> +  }
>>> +
>>> +  Value->takeMatcher(Result);
>>> +  return true;
>>> +}
>>> +
>>> +/// \brief Parse an <Expresssion>
>>> +bool Parser::parseExpressionImpl(VariantValue *Value) {
>>> +  switch (Tokenizer->nextTokenKind()) {
>>> +  case TokenInfo::TK_Literal:
>>> +    *Value = Tokenizer->consumeNextToken().Value;
>>> +    return true;
>>> +
>>> +  case TokenInfo::TK_Ident:
>>> +    return parseMatcherExpressionImpl(Value);
>>> +
>>> +  case TokenInfo::TK_Eof:
>>> +    Error->pushErrorFrame(Tokenizer->consumeNextToken().Range,
>>> +                          Error->ET_ParserNoCode);
>>> +    return false;
>>> +
>>> +  case TokenInfo::TK_Error:
>>> +    // This error was already reported by the tokenizer.
>>> +    return false;
>>> +
>>> +  case TokenInfo::TK_OpenParen:
>>> +  case TokenInfo::TK_CloseParen:
>>> +  case TokenInfo::TK_Comma:
>>> +  case TokenInfo::TK_InvalidChar:
>>> +    const TokenInfo Token = Tokenizer->consumeNextToken();
>>> +    Error->pushErrorFrame(Token.Range, Error->ET_ParserInvalidToken)
>>> +        << Token.Text;
>>> +    return false;
>>> +  }
>>> +
>>> +  llvm_unreachable("Unknown token kind.");
>>> +}
>>> +
>>> +Parser::Parser(CodeTokenizer *Tokenizer, Sema *S,
>>> +               Diagnostics *Error)
>>> +    : Tokenizer(Tokenizer), S(S), Error(Error) {}
>>> +
>>> +class RegistrySema : public Parser::Sema {
>>> +public:
>>> +  virtual ~RegistrySema() {}
>>> +  DynTypedMatcher *actOnMatcherExpression(StringRef MatcherName,
>>> +                                          const SourceRange &NameRange,
>>> +                                          ArrayRef<ParserValue> Args,
>>> +                                          Diagnostics *Error) {
>>> +    return Registry::constructMatcher(MatcherName, NameRange, Args,
>>> Error);
>>> +  }
>>> +};
>>> +
>>> +bool Parser::parseExpression(StringRef Code, VariantValue *Value,
>>> +                             Diagnostics *Error) {
>>> +  RegistrySema S;
>>> +  return parseExpression(Code, &S, Value, Error);
>>> +}
>>> +
>>> +bool Parser::parseExpression(StringRef Code, Sema *S,
>>> +                             VariantValue *Value, Diagnostics *Error) {
>>> +  CodeTokenizer Tokenizer(Code, Error);
>>> +  return Parser(&Tokenizer, S, Error).parseExpressionImpl(Value);
>>> +}
>>> +
>>> +DynTypedMatcher *Parser::parseMatcherExpression(StringRef Code,
>>> +                                                Diagnostics *Error) {
>>> +  RegistrySema S;
>>> +  return parseMatcherExpression(Code, &S, Error);
>>> +}
>>> +
>>> +DynTypedMatcher *Parser::parseMatcherExpression(StringRef Code,
>>> +                                                Parser::Sema *S,
>>> +                                                Diagnostics *Error) {
>>> +  VariantValue Value;
>>> +  if (!parseExpression(Code, S, &Value, Error))
>>> +    return NULL;
>>> +  if (!Value.isMatcher()) {
>>> +    Error->pushErrorFrame(SourceRange(), Error->ET_ParserNotAMatcher);
>>> +    return NULL;
>>> +  }
>>> +  return Value.getMatcher().clone();
>>> +}
>>> +
>>> +}  // namespace dynamic
>>> +}  // namespace ast_matchers
>>> +}  // namespace clang
>>>
>>> Added: cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp?rev=181768&view=auto
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp (added)
>>> +++ cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp Tue May 14 04:13:00
>>> 2013
>>> @@ -0,0 +1,153 @@
>>> +//===--- 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.
>>> +//
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +///
>>> +/// \file
>>> +/// \brief Registry map populated at static initialization time.
>>> +///
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +
>>> +#include "clang/ASTMatchers/Dynamic/Registry.h"
>>> +
>>> +#include <utility>
>>> +
>>> +#include "Marshallers.h"
>>> +#include "clang/ASTMatchers/ASTMatchers.h"
>>> +#include "llvm/ADT/StringMap.h"
>>> +#include "llvm/ADT/StringRef.h"
>>> +#include "llvm/Support/ManagedStatic.h"
>>> +
>>> +namespace clang {
>>> +namespace ast_matchers {
>>> +namespace dynamic {
>>> +namespace {
>>> +
>>> +using internal::MatcherCreateCallback;
>>> +
>>> +typedef llvm::StringMap<const MatcherCreateCallback *> ConstructorMap;
>>> +class RegistryMaps {
>>> +public:
>>> +  RegistryMaps();
>>> +  ~RegistryMaps();
>>> +
>>> +  const ConstructorMap &constructors() const { return Constructors; }
>>> +
>>> +private:
>>> +  void registerMatcher(StringRef MatcherName, MatcherCreateCallback
>>> *Callback);
>>> +  ConstructorMap Constructors;
>>> +};
>>> +
>>> +void RegistryMaps::registerMatcher(StringRef MatcherName,
>>> +                                   MatcherCreateCallback *Callback) {
>>> +  Constructors[MatcherName] = Callback;
>>> +}
>>> +
>>> +#define REGISTER_MATCHER(name)
>>>         \
>>> +  registerMatcher(#name, internal::makeMatcherAutoMarshall(
>>>        \
>>> +                             ::clang::ast_matchers::name, #name));
>>> +
>>> +/// \brief Generate a registry map with all the known matchers.
>>> +RegistryMaps::RegistryMaps() {
>>> +  // TODO: This list is not complete. It only has non-overloaded
>>> matchers,
>>> +  // which are the simplest to add to the system. Overloaded matchers
>>> require
>>> +  // more supporting code that was omitted from the first revision for
>>> +  // simplicitly of code review.
>>> +
>>> +  REGISTER_MATCHER(binaryOperator);
>>> +  REGISTER_MATCHER(bindTemporaryExpr);
>>> +  REGISTER_MATCHER(boolLiteral);
>>> +  REGISTER_MATCHER(callExpr);
>>> +  REGISTER_MATCHER(characterLiteral);
>>> +  REGISTER_MATCHER(compoundStmt);
>>> +  REGISTER_MATCHER(conditionalOperator);
>>> +  REGISTER_MATCHER(constCastExpr);
>>> +  REGISTER_MATCHER(constructExpr);
>>> +  REGISTER_MATCHER(constructorDecl);
>>> +  REGISTER_MATCHER(declRefExpr);
>>> +  REGISTER_MATCHER(declStmt);
>>> +  REGISTER_MATCHER(defaultArgExpr);
>>> +  REGISTER_MATCHER(doStmt);
>>> +  REGISTER_MATCHER(dynamicCastExpr);
>>> +  REGISTER_MATCHER(explicitCastExpr);
>>> +  REGISTER_MATCHER(expr);
>>> +  REGISTER_MATCHER(fieldDecl);
>>> +  REGISTER_MATCHER(forStmt);
>>> +  REGISTER_MATCHER(functionDecl);
>>> +  REGISTER_MATCHER(hasAnyParameter);
>>> +  REGISTER_MATCHER(hasAnySubstatement);
>>> +  REGISTER_MATCHER(hasConditionVariableStatement);
>>> +  REGISTER_MATCHER(hasDestinationType);
>>> +  REGISTER_MATCHER(hasEitherOperand);
>>> +  REGISTER_MATCHER(hasFalseExpression);
>>> +  REGISTER_MATCHER(hasImplicitDestinationType);
>>> +  REGISTER_MATCHER(hasInitializer);
>>> +  REGISTER_MATCHER(hasLHS);
>>> +  REGISTER_MATCHER(hasName);
>>> +  REGISTER_MATCHER(hasObjectExpression);
>>> +  REGISTER_MATCHER(hasRHS);
>>> +  REGISTER_MATCHER(hasSourceExpression);
>>> +  REGISTER_MATCHER(hasTrueExpression);
>>> +  REGISTER_MATCHER(hasUnaryOperand);
>>> +  REGISTER_MATCHER(ifStmt);
>>> +  REGISTER_MATCHER(implicitCastExpr);
>>> +  REGISTER_MATCHER(integerLiteral);
>>> +  REGISTER_MATCHER(isArrow);
>>> +  REGISTER_MATCHER(isConstQualified);
>>> +  REGISTER_MATCHER(isImplicit);
>>> +  REGISTER_MATCHER(member);
>>> +  REGISTER_MATCHER(memberExpr);
>>> +  REGISTER_MATCHER(methodDecl);
>>> +  REGISTER_MATCHER(namedDecl);
>>> +  REGISTER_MATCHER(newExpr);
>>> +  REGISTER_MATCHER(ofClass);
>>> +  REGISTER_MATCHER(on);
>>> +  REGISTER_MATCHER(onImplicitObjectArgument);
>>> +  REGISTER_MATCHER(operatorCallExpr);
>>> +  REGISTER_MATCHER(recordDecl);
>>> +  REGISTER_MATCHER(reinterpretCastExpr);
>>> +  REGISTER_MATCHER(staticCastExpr);
>>> +  REGISTER_MATCHER(stmt);
>>> +  REGISTER_MATCHER(stringLiteral);
>>> +  REGISTER_MATCHER(switchCase);
>>> +  REGISTER_MATCHER(to);
>>> +  REGISTER_MATCHER(unaryOperator);
>>> +  REGISTER_MATCHER(varDecl);
>>> +  REGISTER_MATCHER(whileStmt);
>>> +}
>>> +
>>> +RegistryMaps::~RegistryMaps() {
>>> +  for (ConstructorMap::iterator it = Constructors.begin(),
>>> +                                end = Constructors.end();
>>> +       it != end; ++it) {
>>> +    delete it->second;
>>> +  }
>>> +}
>>> +
>>> +static llvm::ManagedStatic<RegistryMaps> RegistryData;
>>> +
>>> +} // anonymous namespace
>>> +
>>> +// static
>>> +DynTypedMatcher *Registry::constructMatcher(StringRef MatcherName,
>>> +                                            const SourceRange
>>> &NameRange,
>>> +                                            ArrayRef<ParserValue> Args,
>>> +                                            Diagnostics *Error) {
>>> +  ConstructorMap::const_iterator it =
>>> +      RegistryData->constructors().find(MatcherName);
>>> +  if (it == RegistryData->constructors().end()) {
>>> +    Error->pushErrorFrame(NameRange, Error->ET_RegistryNotFound)
>>> +        << MatcherName;
>>> +    return NULL;
>>> +  }
>>> +
>>> +  return it->second->run(NameRange, Args, Error);
>>> +}
>>> +
>>> +}  // namespace dynamic
>>> +}  // namespace ast_matchers
>>> +}  // namespace clang
>>>
>>> Added: cfe/trunk/lib/ASTMatchers/Dynamic/VariantValue.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/VariantValue.cpp?rev=181768&view=auto
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/ASTMatchers/Dynamic/VariantValue.cpp (added)
>>> +++ cfe/trunk/lib/ASTMatchers/Dynamic/VariantValue.cpp Tue May 14
>>> 04:13:00 2013
>>> @@ -0,0 +1,105 @@
>>> +//===--- VariantValue.cpp - 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.
>>> +//
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +///
>>> +/// \file
>>> +/// \brief Polymorphic value type.
>>> +///
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +
>>> +#include "clang/ASTMatchers/Dynamic/VariantValue.h"
>>> +
>>> +namespace clang {
>>> +namespace ast_matchers {
>>> +namespace dynamic {
>>> +
>>> +VariantValue::VariantValue(const VariantValue &Other) :
>>> Type(VT_Nothing) {
>>> +  *this = Other;
>>> +}
>>> +
>>> +VariantValue::VariantValue(const DynTypedMatcher &Matcher) :
>>> Type(VT_Nothing) {
>>> +  setMatcher(Matcher);
>>> +}
>>> +
>>> +VariantValue::VariantValue(const std::string &String) :
>>> Type(VT_Nothing) {
>>> +  setString(String);
>>> +}
>>> +
>>> +VariantValue::~VariantValue() { reset(); }
>>> +
>>> +VariantValue &VariantValue::operator=(const VariantValue &Other) {
>>> +  if (this == &Other) return *this;
>>> +  reset();
>>> +  switch (Other.Type) {
>>> +  case VT_String:
>>> +    setString(Other.getString());
>>> +    break;
>>> +  case VT_Matcher:
>>> +    setMatcher(Other.getMatcher());
>>> +    break;
>>> +  case VT_Nothing:
>>> +    Type = VT_Nothing;
>>> +    break;
>>> +  }
>>> +  return *this;
>>> +}
>>> +
>>> +void VariantValue::reset() {
>>> +  switch (Type) {
>>> +  case VT_String:
>>> +    delete Value.String;
>>> +    break;
>>> +  case VT_Matcher:
>>> +    delete Value.Matcher;
>>> +    break;
>>> +  // Cases that do nothing.
>>> +  case VT_Nothing:
>>> +    break;
>>> +  }
>>> +  Type = VT_Nothing;
>>> +}
>>> +
>>> +bool VariantValue::isString() const {
>>> +  return Type == VT_String;
>>> +}
>>> +
>>> +const std::string &VariantValue::getString() const {
>>> +  assert(isString());
>>> +  return *Value.String;
>>> +}
>>> +
>>> +void VariantValue::setString(const std::string &NewValue) {
>>> +  reset();
>>> +  Type = VT_String;
>>> +  Value.String = new std::string(NewValue);
>>> +}
>>> +
>>> +bool VariantValue::isMatcher() const {
>>> +  return Type == VT_Matcher;
>>> +}
>>> +
>>> +const DynTypedMatcher &VariantValue::getMatcher() const {
>>> +  assert(isMatcher());
>>> +  return *Value.Matcher;
>>> +}
>>> +
>>> +void VariantValue::setMatcher(const DynTypedMatcher &NewValue) {
>>> +  reset();
>>> +  Type = VT_Matcher;
>>> +  Value.Matcher = NewValue.clone();
>>> +}
>>> +
>>> +void VariantValue::takeMatcher(DynTypedMatcher *NewValue) {
>>> +  reset();
>>> +  Type = VT_Matcher;
>>> +  Value.Matcher = NewValue;
>>> +}
>>> +
>>> +} // end namespace dynamic
>>> +} // end namespace ast_matchers
>>> +} // end namespace clang
>>>
>>> Modified: cfe/trunk/lib/ASTMatchers/Makefile
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Makefile?rev=181768&r1=181767&r2=181768&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/ASTMatchers/Makefile (original)
>>> +++ cfe/trunk/lib/ASTMatchers/Makefile Tue May 14 04:13:00 2013
>>> @@ -10,4 +10,6 @@
>>>  CLANG_LEVEL := ../..
>>>  LIBRARYNAME := clangASTMatchers
>>>
>>> +PARALLEL_DIRS = Dynamic
>>> +
>>>  include $(CLANG_LEVEL)/Makefile
>>>
>>> Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.h?rev=181768&r1=181767&r2=181768&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.h (original)
>>> +++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.h Tue May 14
>>> 04:13:00 2013
>>> @@ -84,6 +84,41 @@ testing::AssertionResult notMatches(cons
>>>    return matchesConditionally(Code, AMatcher, false, "-std=c++11");
>>>  }
>>>
>>> +inline testing::AssertionResult
>>> +matchesConditionallyDynamic(const std::string &Code,
>>> +                            const internal::DynTypedMatcher &AMatcher,
>>> +                            bool ExpectMatch, llvm::StringRef
>>> CompileArg) {
>>> +  bool Found = false;
>>> +  MatchFinder Finder;
>>> +  Finder.addDynamicMatcher(AMatcher, new VerifyMatch(0, &Found));
>>> +  OwningPtr<FrontendActionFactory>
>>> Factory(newFrontendActionFactory(&Finder));
>>> +  // Some tests use typeof, which is a gnu extension.
>>> +  std::vector<std::string> Args(1, CompileArg);
>>> +  if (!runToolOnCodeWithArgs(Factory->create(), Code, Args)) {
>>> +    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();
>>> +}
>>> +
>>> +inline testing::AssertionResult
>>> +matchesDynamic(const std::string &Code,
>>> +               const internal::DynTypedMatcher &AMatcher) {
>>> +  return matchesConditionallyDynamic(Code, AMatcher, true,
>>> "-std=c++11");
>>> +}
>>> +
>>> +inline testing::AssertionResult
>>> +notMatchesDynamic(const std::string &Code,
>>> +                  const internal::DynTypedMatcher &AMatcher) {
>>> +  return matchesConditionallyDynamic(Code, AMatcher, false,
>>> "-std=c++11");
>>> +}
>>> +
>>>  template <typename T>
>>>  testing::AssertionResult
>>>  matchAndVerifyResultConditionally(const std::string &Code, const T
>>> &AMatcher,
>>>
>>> Modified: cfe/trunk/unittests/ASTMatchers/CMakeLists.txt
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/CMakeLists.txt?rev=181768&r1=181767&r2=181768&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/unittests/ASTMatchers/CMakeLists.txt (original)
>>> +++ cfe/trunk/unittests/ASTMatchers/CMakeLists.txt Tue May 14 04:13:00
>>> 2013
>>> @@ -11,3 +11,5 @@ add_clang_unittest(ASTMatchersTests
>>>
>>>  target_link_libraries(ASTMatchersTests
>>>    gtest gtest_main clangASTMatchers clangTooling)
>>> +
>>> +add_subdirectory(Dynamic)
>>>
>>> Added: cfe/trunk/unittests/ASTMatchers/Dynamic/CMakeLists.txt
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/CMakeLists.txt?rev=181768&view=auto
>>>
>>> ==============================================================================
>>> --- cfe/trunk/unittests/ASTMatchers/Dynamic/CMakeLists.txt (added)
>>> +++ cfe/trunk/unittests/ASTMatchers/Dynamic/CMakeLists.txt Tue May 14
>>> 04:13:00 2013
>>> @@ -0,0 +1,7 @@
>>> +add_clang_unittest(DynamicASTMatchersTests
>>> +  VariantValueTest.cpp
>>> +  ParserTest.cpp
>>> +  RegistryTest.cpp)
>>> +
>>> +target_link_libraries(DynamicASTMatchersTests
>>> +  gtest gtest_main clangASTMatchers clangDynamicASTMatchers
>>> clangTooling)
>>>
>>> Added: cfe/trunk/unittests/ASTMatchers/Dynamic/Makefile
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/Makefile?rev=181768&view=auto
>>>
>>> ==============================================================================
>>> --- cfe/trunk/unittests/ASTMatchers/Dynamic/Makefile (added)
>>> +++ cfe/trunk/unittests/ASTMatchers/Dynamic/Makefile Tue May 14 04:13:00
>>> 2013
>>> @@ -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 = clangEdit.a clangTooling.a clangFrontend.a
>>> clangSerialization.a clangDriver.a \
>>> +           clangRewrite.a clangParse.a clangSema.a clangAnalysis.a \
>>> +           clangAST.a clangASTMatchers.a clangLex.a clangBasic.a \
>>> +           clangDynamicASTMatchers.a
>>> +
>>> +include $(CLANG_LEVEL)/unittests/Makefile
>>>
>>> Added: cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp?rev=181768&view=auto
>>>
>>> ==============================================================================
>>> --- cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp (added)
>>> +++ cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp Tue May 14
>>> 04:13:00 2013
>>> @@ -0,0 +1,194 @@
>>> +//===- 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"
>>> +#include "llvm/ADT/StringMap.h"
>>> +
>>> +namespace clang {
>>> +namespace ast_matchers {
>>> +namespace dynamic {
>>> +namespace {
>>> +
>>> +class DummyDynTypedMatcher : public DynTypedMatcher {
>>> +public:
>>> +  DummyDynTypedMatcher(uint64_t ID) : ID(ID) {}
>>> +
>>> +  typedef ast_matchers::internal::ASTMatchFinder ASTMatchFinder;
>>> +  typedef ast_matchers::internal::BoundNodesTreeBuilder
>>> BoundNodesTreeBuilder;
>>> +  virtual bool matches(const ast_type_traits::DynTypedNode DynNode,
>>> +                       ASTMatchFinder *Finder,
>>> +                       BoundNodesTreeBuilder *Builder) const {
>>> +    return false;
>>> +  }
>>> +
>>> +  /// \brief Makes a copy of this matcher object.
>>> +  virtual DynTypedMatcher *clone() const {
>>> +    return new DummyDynTypedMatcher(ID);
>>> +  }
>>> +
>>> +  /// \brief Returns a unique ID for the matcher.
>>> +  virtual uint64_t getID() const { return ID; }
>>> +
>>> +private:
>>> +  uint64_t ID;
>>> +};
>>> +
>>> +class MockSema : public Parser::Sema {
>>> +public:
>>> +  virtual ~MockSema() {}
>>> +
>>> +  uint64_t expectMatcher(StringRef MatcherName) {
>>> +    uint64_t ID = ExpectedMatchers.size() + 1;
>>> +    ExpectedMatchers[MatcherName] = ID;
>>> +    return ID;
>>> +  }
>>> +
>>> +  void parse(StringRef Code) {
>>> +    Diagnostics Error;
>>> +    VariantValue Value;
>>> +    Parser::parseExpression(Code, this, &Value, &Error);
>>> +    Values.push_back(Value);
>>> +    Errors.push_back(Error.ToStringFull());
>>> +  }
>>> +
>>> +  DynTypedMatcher *actOnMatcherExpression(StringRef MatcherName,
>>> +                                          const SourceRange &NameRange,
>>> +                                          ArrayRef<ParserValue> Args,
>>> +                                          Diagnostics *Error) {
>>> +    MatcherInfo ToStore = { MatcherName, NameRange, Args };
>>> +    Matchers.push_back(ToStore);
>>> +    return new DummyDynTypedMatcher(ExpectedMatchers[MatcherName]);
>>> +  }
>>> +
>>> +  struct MatcherInfo {
>>> +    StringRef MatcherName;
>>> +    SourceRange NameRange;
>>> +    std::vector<ParserValue> Args;
>>> +  };
>>> +
>>> +  std::vector<std::string> Errors;
>>> +  std::vector<VariantValue> Values;
>>> +  std::vector<MatcherInfo> Matchers;
>>> +  llvm::StringMap<uint64_t> ExpectedMatchers;
>>> +};
>>> +
>>> +TEST(ParserTest, ParseString) {
>>> +  MockSema Sema;
>>> +  Sema.parse("\"Foo\"");
>>> +  Sema.parse("\"\"");
>>> +  Sema.parse("\"Baz");
>>> +  EXPECT_EQ(3ULL, Sema.Values.size());
>>> +  EXPECT_EQ("Foo", Sema.Values[0].getString());
>>> +  EXPECT_EQ("", Sema.Values[1].getString());
>>> +  EXPECT_EQ("1:1: Error parsing string token: <\"Baz>", Sema.Errors[2]);
>>> +}
>>> +
>>> +bool matchesRange(const SourceRange &Range, unsigned StartLine,
>>> +                  unsigned EndLine, unsigned StartColumn, unsigned
>>> EndColumn) {
>>> +  EXPECT_EQ(StartLine, Range.Start.Line);
>>> +  EXPECT_EQ(EndLine, Range.End.Line);
>>> +  EXPECT_EQ(StartColumn, Range.Start.Column);
>>> +  EXPECT_EQ(EndColumn, Range.End.Column);
>>> +  return Range.Start.Line == StartLine && Range.End.Line == EndLine &&
>>> +         Range.Start.Column == StartColumn && Range.End.Column ==
>>> EndColumn;
>>> +}
>>> +
>>> +TEST(ParserTest, ParseMatcher) {
>>> +  MockSema Sema;
>>> +  const uint64_t ExpectedFoo = Sema.expectMatcher("Foo");
>>> +  const uint64_t ExpectedBar = Sema.expectMatcher("Bar");
>>> +  const uint64_t ExpectedBaz = Sema.expectMatcher("Baz");
>>> +  Sema.parse(" Foo ( Bar (), Baz( \n \"B A,Z\") )  ");
>>> +  for (size_t i = 0, e = Sema.Errors.size(); i != e; ++i) {
>>> +    EXPECT_EQ("", Sema.Errors[i]);
>>> +  }
>>> +
>>> +  EXPECT_EQ(1ULL, Sema.Values.size());
>>> +  EXPECT_EQ(ExpectedFoo, Sema.Values[0].getMatcher().getID());
>>> +
>>> +  EXPECT_EQ(3ULL, Sema.Matchers.size());
>>> +  const MockSema::MatcherInfo Bar = Sema.Matchers[0];
>>> +  EXPECT_EQ("Bar", Bar.MatcherName);
>>> +  EXPECT_TRUE(matchesRange(Bar.NameRange, 1, 1, 8, 14));
>>> +  EXPECT_EQ(0ULL, Bar.Args.size());
>>> +
>>> +  const MockSema::MatcherInfo Baz = Sema.Matchers[1];
>>> +  EXPECT_EQ("Baz", Baz.MatcherName);
>>> +  EXPECT_TRUE(matchesRange(Baz.NameRange, 1, 2, 16, 10));
>>> +  EXPECT_EQ(1ULL, Baz.Args.size());
>>> +  EXPECT_EQ("B A,Z", Baz.Args[0].Value.getString());
>>> +
>>> +  const MockSema::MatcherInfo Foo = Sema.Matchers[2];
>>> +  EXPECT_EQ("Foo", Foo.MatcherName);
>>> +  EXPECT_TRUE(matchesRange(Foo.NameRange, 1, 2, 2, 12));
>>> +  EXPECT_EQ(2ULL, Foo.Args.size());
>>> +  EXPECT_EQ(ExpectedBar, Foo.Args[0].Value.getMatcher().getID());
>>> +  EXPECT_EQ(ExpectedBaz, Foo.Args[1].Value.getMatcher().getID());
>>> +}
>>> +
>>> +using ast_matchers::internal::Matcher;
>>> +
>>> +TEST(ParserTest, FullParserTest) {
>>> +  OwningPtr<DynTypedMatcher> Matcher(Parser::parseMatcherExpression(
>>> +      "hasInitializer(binaryOperator(hasLHS(integerLiteral())))",
>>> NULL));
>>> +  EXPECT_TRUE(matchesDynamic("int x = 1 + false;", *Matcher));
>>> +  EXPECT_FALSE(matchesDynamic("int x = true + 1;", *Matcher));
>>> +
>>> +  Diagnostics Error;
>>> +  EXPECT_TRUE(Parser::parseMatcherExpression(
>>> +      "hasInitializer(\n    binaryOperator(hasLHS(\"A\")))", &Error) ==
>>> NULL);
>>> +  EXPECT_EQ("1:1: Error parsing argument 1 for matcher
>>> hasInitializer.\n"
>>> +            "2:5: Error parsing argument 1 for matcher
>>> binaryOperator.\n"
>>> +            "2:20: Error building matcher hasLHS.\n"
>>> +            "2:27: Incorrect type on function hasLHS for arg 1.",
>>> +            Error.ToStringFull());
>>> +}
>>> +
>>> +std::string ParseWithError(StringRef Code) {
>>> +  Diagnostics Error;
>>> +  VariantValue Value;
>>> +  Parser::parseExpression(Code, &Value, &Error);
>>> +  return Error.ToStringFull();
>>> +}
>>> +
>>> +std::string ParseMatcherWithError(StringRef Code) {
>>> +  Diagnostics Error;
>>> +  Parser::parseMatcherExpression(Code, &Error);
>>> +  return Error.ToStringFull();
>>> +}
>>> +
>>> +TEST(ParserTest, Errors) {
>>> +  EXPECT_EQ(
>>> +      "1:5: Error parsing matcher. Found token <123> while looking for
>>> '('.",
>>> +      ParseWithError("Foo 123"));
>>> +  EXPECT_EQ(
>>> +      "1:9: Error parsing matcher. Found token <123> while looking for
>>> ','.",
>>> +      ParseWithError("Foo(\"A\" 123)"));
>>> +  EXPECT_EQ(
>>> +      "1:4: Error parsing matcher. Found end-of-code while looking for
>>> ')'.",
>>> +      ParseWithError("Foo("));
>>> +  EXPECT_EQ("1:1: End of code found while looking for token.",
>>> +            ParseWithError(""));
>>> +  EXPECT_EQ("Input value is not a matcher expression.",
>>> +            ParseMatcherWithError("\"A\""));
>>> +  EXPECT_EQ("1:1: Error parsing argument 1 for matcher Foo.\n"
>>> +            "1:5: Invalid token <(> found when looking for a value.",
>>> +            ParseWithError("Foo(("));
>>> +}
>>> +
>>> +}  // end anonymous namespace
>>> +}  // end namespace dynamic
>>> +}  // end namespace ast_matchers
>>> +}  // end namespace clang
>>>
>>> Added: cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp?rev=181768&view=auto
>>>
>>> ==============================================================================
>>> --- cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp (added)
>>> +++ cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp Tue May 14
>>> 04:13:00 2013
>>> @@ -0,0 +1,112 @@
>>> +//===- 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 {
>>> +
>>> +using ast_matchers::internal::Matcher;
>>> +
>>> +DynTypedMatcher *constructMatcher(StringRef MatcherName, Diagnostics
>>> *Error) {
>>> +  const std::vector<ParserValue> Args;
>>> +  return Registry::constructMatcher(MatcherName, SourceRange(), Args,
>>> Error);
>>> +}
>>> +
>>> +DynTypedMatcher *constructMatcher(StringRef MatcherName,
>>> +                                  const VariantValue &Arg1,
>>> +                                  Diagnostics *Error) {
>>> +  std::vector<ParserValue> Args(1);
>>> +  Args[0].Value = Arg1;
>>> +  return Registry::constructMatcher(MatcherName, SourceRange(), Args,
>>> Error);
>>> +}
>>> +
>>> +DynTypedMatcher *constructMatcher(StringRef MatcherName,
>>> +                                  const VariantValue &Arg1,
>>> +                                  const VariantValue &Arg2,
>>> +                                  Diagnostics *Error) {
>>> +  std::vector<ParserValue> Args(2);
>>> +  Args[0].Value = Arg1;
>>> +  Args[1].Value = Arg2;
>>> +  return Registry::constructMatcher(MatcherName, SourceRange(), Args,
>>> Error);
>>> +}
>>> +
>>> +TEST(RegistryTest, CanConstructNoArgs) {
>>> +  OwningPtr<DynTypedMatcher> IsArrowValue(constructMatcher("isArrow",
>>> NULL));
>>> +  OwningPtr<DynTypedMatcher> BoolValue(constructMatcher("boolLiteral",
>>> NULL));
>>> +
>>> +  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(matchesDynamic(ClassSnippet, *IsArrowValue));
>>> +  EXPECT_TRUE(matchesDynamic(BoolSnippet, *BoolValue));
>>> +  EXPECT_FALSE(matchesDynamic(ClassSnippet, *BoolValue));
>>> +  EXPECT_FALSE(matchesDynamic(BoolSnippet, *IsArrowValue));
>>> +}
>>> +
>>> +TEST(RegistryTest, ConstructWithSimpleArgs) {
>>> +  OwningPtr<DynTypedMatcher> Value(
>>> +      constructMatcher("hasName", std::string("X"), NULL));
>>> +  EXPECT_TRUE(matchesDynamic("class X {};", *Value));
>>> +  EXPECT_FALSE(matchesDynamic("int x;", *Value));
>>> +}
>>> +
>>> +TEST(RegistryTest, ConstructWithMatcherArgs) {
>>> +  OwningPtr<DynTypedMatcher> HasInitializerSimple(
>>> +      constructMatcher("hasInitializer", stmt(), NULL));
>>> +  OwningPtr<DynTypedMatcher> HasInitializerComplex(
>>> +      constructMatcher("hasInitializer", callExpr(), NULL));
>>> +
>>> +  std::string code = "int i;";
>>> +  EXPECT_FALSE(matchesDynamic(code, *HasInitializerSimple));
>>> +  EXPECT_FALSE(matchesDynamic(code, *HasInitializerComplex));
>>> +
>>> +  code = "int i = 1;";
>>> +  EXPECT_TRUE(matchesDynamic(code, *HasInitializerSimple));
>>> +  EXPECT_FALSE(matchesDynamic(code, *HasInitializerComplex));
>>> +
>>> +  code = "int y(); int i = y();";
>>> +  EXPECT_TRUE(matchesDynamic(code, *HasInitializerSimple));
>>> +  EXPECT_TRUE(matchesDynamic(code, *HasInitializerComplex));
>>> +}
>>> +
>>> +TEST(RegistryTest, Errors) {
>>> +  // Incorrect argument count.
>>> +  OwningPtr<Diagnostics> Error(new Diagnostics());
>>> +  EXPECT_TRUE(NULL == constructMatcher("hasInitializer", Error.get()));
>>> +  EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)",
>>> +            Error->ToString());
>>> +  Error.reset(new Diagnostics());
>>> +  EXPECT_TRUE(NULL == constructMatcher("isArrow", std::string(),
>>> Error.get()));
>>> +  EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)",
>>> +            Error->ToString());
>>> +
>>> +  // Bad argument type
>>> +  Error.reset(new Diagnostics());
>>> +  EXPECT_TRUE(NULL == constructMatcher("ofClass", std::string(),
>>> Error.get()));
>>> +  EXPECT_EQ("Incorrect type on function ofClass for arg 1.",
>>> Error->ToString());
>>> +  Error.reset(new Diagnostics());
>>> +  EXPECT_TRUE(NULL == constructMatcher("recordDecl", recordDecl(),
>>> +                                       ::std::string(), Error.get()));
>>> +  EXPECT_EQ("Incorrect type on function recordDecl for arg 2.",
>>> +            Error->ToString());
>>> +}
>>> +
>>> +} // end anonymous namespace
>>> +} // end namespace dynamic
>>> +} // end namespace ast_matchers
>>> +} // end namespace clang
>>>
>>> Added: cfe/trunk/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp?rev=181768&view=auto
>>>
>>> ==============================================================================
>>> --- cfe/trunk/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp (added)
>>> +++ cfe/trunk/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp Tue May
>>> 14 04:13:00 2013
>>> @@ -0,0 +1,97 @@
>>> +//===- unittest/ASTMatchers/Dynamic/VariantValueTest.cpp - VariantValue
>>> 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/VariantValue.h"
>>> +#include "gtest/gtest.h"
>>> +
>>> +namespace clang {
>>> +namespace ast_matchers {
>>> +namespace dynamic {
>>> +namespace {
>>> +
>>> +using ast_matchers::internal::DynTypedMatcher;
>>> +using ast_matchers::internal::Matcher;
>>> +
>>> +TEST(VariantValueTest, String) {
>>> +  const ::std::string kString = "string";
>>> +  VariantValue Value = kString;
>>> +
>>> +  EXPECT_TRUE(Value.isString());
>>> +  EXPECT_EQ(kString, Value.getString());
>>> +
>>> +  EXPECT_FALSE(Value.isMatcher());
>>> +  EXPECT_FALSE(Value.isTypedMatcher<clang::Decl>());
>>> +  EXPECT_FALSE(Value.isTypedMatcher<clang::UnaryOperator>());
>>> +}
>>> +
>>> +TEST(VariantValueTest, DynTypedMatcher) {
>>> +  VariantValue Value = stmt();
>>> +
>>> +  EXPECT_FALSE(Value.isString());
>>> +
>>> +  EXPECT_TRUE(Value.isMatcher());
>>> +  EXPECT_TRUE(Value.isTypedMatcher<clang::Decl>());
>>> +  EXPECT_TRUE(Value.isTypedMatcher<clang::UnaryOperator>());
>>> +
>>> +  // Conversion to any type of matcher works.
>>> +  // If they are not compatible it would just return a matcher that
>>> matches
>>> +  // nothing. We test this below.
>>> +  Value = recordDecl();
>>> +  EXPECT_TRUE(Value.isMatcher());
>>> +  EXPECT_TRUE(Value.isTypedMatcher<clang::Decl>());
>>> +  EXPECT_TRUE(Value.isTypedMatcher<clang::UnaryOperator>());
>>> +
>>> +  Value = unaryOperator();
>>> +  EXPECT_TRUE(Value.isMatcher());
>>> +  EXPECT_TRUE(Value.isTypedMatcher<clang::Decl>());
>>> +  EXPECT_TRUE(Value.isTypedMatcher<clang::Stmt>());
>>> +  EXPECT_TRUE(Value.isTypedMatcher<clang::UnaryOperator>());
>>> +}
>>> +
>>> +TEST(VariantValueTest, Assignment) {
>>> +  VariantValue Value = std::string("A");
>>> +  EXPECT_TRUE(Value.isString());
>>> +  EXPECT_EQ("A", Value.getString());
>>> +  EXPECT_FALSE(Value.isMatcher());
>>> +
>>> +  Value = recordDecl();
>>> +  EXPECT_FALSE(Value.isString());
>>> +  EXPECT_TRUE(Value.isMatcher());
>>> +  EXPECT_TRUE(Value.isTypedMatcher<clang::Decl>());
>>> +  EXPECT_TRUE(Value.isTypedMatcher<clang::UnaryOperator>());
>>> +
>>> +  Value = VariantValue();
>>> +  EXPECT_FALSE(Value.isString());
>>> +  EXPECT_FALSE(Value.isMatcher());
>>> +}
>>> +
>>> +TEST(GeneicValueTest, Matcher) {
>>> +  EXPECT_TRUE(matchesDynamic(
>>> +      "class X {};",
>>> VariantValue(recordDecl(hasName("X"))).getMatcher()));
>>> +  EXPECT_TRUE(matchesDynamic(
>>> +      "int x;",
>>> VariantValue(varDecl()).getTypedMatcher<clang::Decl>()));
>>> +  EXPECT_TRUE(matchesDynamic("int foo() { return 1 + 1; }",
>>> +
>>> VariantValue(functionDecl()).getMatcher()));
>>> +  // Going through the wrong Matcher<T> will fail to match, even if the
>>> +  // underlying matcher is correct.
>>> +  EXPECT_FALSE(matchesDynamic(
>>> +      "int x;",
>>> VariantValue(varDecl()).getTypedMatcher<clang::Stmt>()));
>>> +
>>> +  EXPECT_FALSE(
>>> +      matchesDynamic("int x;",
>>> VariantValue(functionDecl()).getMatcher()));
>>> +  EXPECT_FALSE(matchesDynamic(
>>> +      "int foo() { return 1 + 1; }",
>>> +
>>>  VariantValue(declRefExpr()).getTypedMatcher<clang::DeclRefExpr>()));
>>> +}
>>> +
>>> +} // end anonymous namespace
>>> +} // end namespace dynamic
>>> +} // end namespace ast_matchers
>>> +} // end namespace clang
>>>
>>> Modified: cfe/trunk/unittests/ASTMatchers/Makefile
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Makefile?rev=181768&r1=181767&r2=181768&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/unittests/ASTMatchers/Makefile (original)
>>> +++ cfe/trunk/unittests/ASTMatchers/Makefile Tue May 14 04:13:00 2013
>>> @@ -9,6 +9,8 @@
>>>
>>>  CLANG_LEVEL = ../..
>>>
>>> +PARALLEL_DIRS = Dynamic
>>> +
>>>  TESTNAME = ASTMatchers
>>>  include $(CLANG_LEVEL)/../../Makefile.config
>>>  LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc
>>>
>>>
>>> _______________________________________________
>>> cfe-commits mailing list
>>> cfe-commits at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>>>
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130514/1f45157c/attachment.html>


More information about the cfe-commits mailing list