<div dir="ltr">No worries, it was easy, so fixed in r181826.</div><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, May 14, 2013 at 4:37 PM, Manuel Klimek <span dir="ltr"><<a href="mailto:klimek@google.com" target="_blank">klimek@google.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><p dir="ltr">+sam</p><div class="HOEnZb"><div class="h5">
<div class="gmail_quote">On May 14, 2013 10:25 PM, "Reid Kleckner" <<a href="mailto:rnk@google.com" target="_blank">rnk@google.com</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<div dir="ltr">This doesn't compile with MSVC 2012?<div><a href="http://bb.pgr.jp/builders/ninja-clang-i686-msc17-R/builds/1350/steps/build_clang/logs/stdio" target="_blank">http://bb.pgr.jp/builders/ninja-clang-i686-msc17-R/builds/1350/steps/build_clang/logs/stdio</a><br>


</div><div><br></div><div>I get this locally:</div><div><br></div><div><div>..\tools\clang\include\clang/ASTMatchers/Dynamic/VariantValue.h(88) : error C2872: 'DynTypedMatcher' : ambiguous symbol</div>
<div>        could be '..\tools\clang\include\clang/ASTMatchers/Dynamic/VariantValue.h(29) : clang::ast_matchers::internal::DynTypedMatcher clang::ast_matchers::dynamic::DynTypedMatcher'</div><div>        or       '..\tools\clang\include\clang/ASTMatchers/ASTMatchersInternal.h(233) : clang::ast_matchers::internal::DynTypedMatcher'</div>


<div>        ..\tools\clang\include\clang/ASTMatchers/Dynamic/VariantValue.h(77) : see reference to class template instantiation 'clang::ast_matchers::dynamic::VariantValue::DerivedTypeMatcher<T>' being compiled</div>


<div>        with</div><div>        [</div><div>            T=clang::Decl</div><div>        ]</div><div>        ..\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</div>


<div>        with</div><div>        [</div><div>            T=clang::Decl</div><div>        ]</div><div>..\tools\clang\include\clang/ASTMatchers/Dynamic/VariantValue.h(101) : error C2872: 'DynTypedMatcher' : ambiguous symbol</div>


<div>        could be '..\tools\clang\include\clang/ASTMatchers/Dynamic/VariantValue.h(29) : clang::ast_matchers::internal::DynTypedMatcher clang::ast_matchers::dynamic::DynTypedMatcher'</div><div>        or       '..\tools\clang\include\clang/ASTMatchers/ASTMatchersInternal.h(233) : clang::ast_matchers::internal::DynTypedMatcher'</div>


<div><br></div><div>I'll attempt to fix, but I may give up and revert.</div></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, May 14, 2013 at 5:13 AM, Manuel Klimek <span dir="ltr"><<a href="mailto:klimek@google.com" target="_blank">klimek@google.com</a>></span> wrote:<br>


<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: klimek<br>
Date: Tue May 14 04:13:00 2013<br>
New Revision: 181768<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=181768&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=181768&view=rev</a><br>
Log:<br>
First revision of the dynamic ASTMatcher library.<br>
<br>
This library supports all the features of the compile-time based ASTMatcher<br>
library, but allows the user to specify and construct the matchers at runtime.<br>
It contains the following modules:<br>
 - A variant type, to be used by the matcher factory.<br>
 - A registry, where the matchers are indexed by name and have a factory method<br>
   with a generic signature.<br>
 - A simple matcher expression parser, that can be used to convert a matcher<br>
   expression string into actual matchers that can be used with the AST at<br>
   runtime.<br>
<br>
Many features where omitted from this first revision to simplify this code<br>
review. The main ideas are still represented in this change and it already has<br>
support working use cases.<br>
Things that are missing:<br>
 - Support for polymorphic matchers. These requires supporting code in the<br>
   registry, the marshallers and the variant type.<br>
 - Support for numbers, char and bool arguments to the matchers. This requires<br>
   supporting code in the parser and the variant type.<br>
 - A command line program putting everything together and providing an already<br>
   functional tool.<br>
<br>
Patch by Samuel Benzaquen.<br>
<br>
Added:<br>
    cfe/trunk/include/clang/ASTMatchers/Dynamic/<br>
    cfe/trunk/include/clang/ASTMatchers/Dynamic/Diagnostics.h<br>
    cfe/trunk/include/clang/ASTMatchers/Dynamic/Parser.h<br>
    cfe/trunk/include/clang/ASTMatchers/Dynamic/Registry.h<br>
    cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h<br>
    cfe/trunk/lib/ASTMatchers/Dynamic/<br>
    cfe/trunk/lib/ASTMatchers/Dynamic/CMakeLists.txt<br>
    cfe/trunk/lib/ASTMatchers/Dynamic/Diagnostics.cpp<br>
    cfe/trunk/lib/ASTMatchers/Dynamic/Makefile<br>
      - copied, changed from r181767, cfe/trunk/lib/ASTMatchers/Makefile<br>
    cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h<br>
    cfe/trunk/lib/ASTMatchers/Dynamic/Parser.cpp<br>
    cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp<br>
    cfe/trunk/lib/ASTMatchers/Dynamic/VariantValue.cpp<br>
    cfe/trunk/unittests/ASTMatchers/Dynamic/<br>
    cfe/trunk/unittests/ASTMatchers/Dynamic/CMakeLists.txt<br>
    cfe/trunk/unittests/ASTMatchers/Dynamic/Makefile<br>
    cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp<br>
    cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp<br>
    cfe/trunk/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp<br>
Modified:<br>
    cfe/trunk/include/clang/ASTMatchers/ASTMatchFinder.h<br>
    cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h<br>
    cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp<br>
    cfe/trunk/lib/ASTMatchers/CMakeLists.txt<br>
    cfe/trunk/lib/ASTMatchers/Makefile<br>
    cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.h<br>
    cfe/trunk/unittests/ASTMatchers/CMakeLists.txt<br>
    cfe/trunk/unittests/ASTMatchers/Makefile<br>
<br>
Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchFinder.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchFinder.h?rev=181768&r1=181767&r2=181768&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchFinder.h?rev=181768&r1=181767&r2=181768&view=diff</a><br>



==============================================================================<br>
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchFinder.h (original)<br>
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchFinder.h Tue May 14 04:13:00 2013<br>
@@ -131,6 +131,17 @@ public:<br>
                   MatchCallback *Action);<br>
   /// @}<br>
<br>
+  /// \brief Adds a matcher to execute when running over the AST.<br>
+  ///<br>
+  /// This is similar to \c addMatcher(), but it uses the dynamic interface. It<br>
+  /// is more flexible, but the lost type information enables a caller to pass<br>
+  /// a matcher that cannot match anything.<br>
+  ///<br>
+  /// \returns \c true if the matcher is a valid top-level matcher, \c false<br>
+  ///   otherwise.<br>
+  bool addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,<br>
+                         MatchCallback *Action);<br>
+<br>
   /// \brief Creates a clang ASTConsumer that finds all matches.<br>
   clang::ASTConsumer *newASTConsumer();<br>
<br>
<br>
Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h?rev=181768&r1=181767&r2=181768&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h?rev=181768&r1=181767&r2=181768&view=diff</a><br>



==============================================================================<br>
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h (original)<br>
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h Tue May 14 04:13:00 2013<br>
@@ -239,6 +239,9 @@ public:<br>
                        ASTMatchFinder *Finder,<br>
                        BoundNodesTreeBuilder *Builder) const = 0;<br>
<br>
+  /// \brief Makes a copy of this matcher object.<br>
+  virtual DynTypedMatcher *clone() const = 0;<br>
+<br>
   /// \brief Returns a unique ID for the matcher.<br>
   virtual uint64_t getID() const = 0;<br>
 };<br>
@@ -301,6 +304,9 @@ public:<br>
     return matches(*Node, Finder, Builder);<br>
   }<br>
<br>
+  /// \brief Makes a copy of this matcher object.<br>
+  virtual Matcher<T> *clone() const { return new Matcher<T>(*this); }<br>
+<br>
   /// \brief Allows the conversion of a \c Matcher<Type> to a \c<br>
   /// Matcher<QualType>.<br>
   ///<br>
<br>
Added: cfe/trunk/include/clang/ASTMatchers/Dynamic/Diagnostics.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/Dynamic/Diagnostics.h?rev=181768&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/Dynamic/Diagnostics.h?rev=181768&view=auto</a><br>



==============================================================================<br>
--- cfe/trunk/include/clang/ASTMatchers/Dynamic/Diagnostics.h (added)<br>
+++ cfe/trunk/include/clang/ASTMatchers/Dynamic/Diagnostics.h Tue May 14 04:13:00 2013<br>
@@ -0,0 +1,109 @@<br>
+//===--- Diagnostics.h - Helper class for error diagnostics -----*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+///<br>
+/// \file<br>
+/// \brief Diagnostics class to manage error messages.<br>
+///<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H<br>
+#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H<br>
+<br>
+#include <string><br>
+#include <vector><br>
+<br>
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"<br>
+#include "clang/Basic/LLVM.h"<br>
+#include "llvm/ADT/ArrayRef.h"<br>
+#include "llvm/ADT/StringRef.h"<br>
+#include "llvm/ADT/Twine.h"<br>
+<br>
+namespace clang {<br>
+namespace ast_matchers {<br>
+namespace dynamic {<br>
+<br>
+struct SourceLocation {<br>
+  SourceLocation() : Line(), Column() {}<br>
+  unsigned Line;<br>
+  unsigned Column;<br>
+};<br>
+<br>
+struct SourceRange {<br>
+  SourceLocation Start;<br>
+  SourceLocation End;<br>
+};<br>
+<br>
+/// \brief A VariantValue instance annotated with its parser context.<br>
+struct ParserValue {<br>
+  ParserValue() : Text(), Range(), Value() {}<br>
+  StringRef Text;<br>
+  SourceRange Range;<br>
+  VariantValue Value;<br>
+};<br>
+<br>
+/// \brief Helper class to manage error messages.<br>
+class Diagnostics {<br>
+ public:<br>
+  /// \brief All errors from the system.<br>
+  enum ErrorType {<br>
+    ET_None = 0,<br>
+<br>
+    ET_RegistryNotFound = 1,<br>
+    ET_RegistryWrongArgCount = 2,<br>
+    ET_RegistryWrongArgType = 3,<br>
+<br>
+    ET_ParserStringError = 100,<br>
+    ET_ParserMatcherArgFailure = 101,<br>
+    ET_ParserMatcherFailure = 102,<br>
+    ET_ParserNoOpenParen = 103,<br>
+    ET_ParserNoCloseParen = 104,<br>
+    ET_ParserNoComma = 105,<br>
+    ET_ParserNoCode = 106,<br>
+    ET_ParserNotAMatcher = 107,<br>
+    ET_ParserInvalidToken = 108<br>
+  };<br>
+<br>
+  /// \brief Helper stream class.<br>
+  struct ArgStream {<br>
+    template <class T> ArgStream &operator<<(const T &Arg) {<br>
+      return operator<<(Twine(Arg));<br>
+    }<br>
+    ArgStream &operator<<(const Twine &Arg);<br>
+    std::vector<std::string> *Out;<br>
+  };<br>
+<br>
+  /// \brief Push a frame to the beginning of the list<br>
+  ///<br>
+  /// Returns a helper class to allow the caller to pass the arguments for the<br>
+  /// error message, using the << operator.<br>
+  ArgStream pushErrorFrame(const SourceRange &Range, ErrorType Error);<br>
+<br>
+  struct ErrorFrame {<br>
+    SourceRange Range;<br>
+    ErrorType Type;<br>
+    std::vector<std::string> Args;<br>
+<br>
+    std::string ToString() const;<br>
+  };<br>
+  ArrayRef<ErrorFrame> frames() const { return Frames; }<br>
+<br>
+  /// \brief Returns a string representation of the last frame.<br>
+  std::string ToString() const;<br>
+  /// \brief Returns a string representation of the whole frame stack.<br>
+  std::string ToStringFull() const;<br>
+<br>
+ private:<br>
+   std::vector<ErrorFrame> Frames;<br>
+};<br>
+<br>
+}  // namespace dynamic<br>
+}  // namespace ast_matchers<br>
+}  // namespace clang<br>
+<br>
+#endif  // LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H<br>
<br>
Added: cfe/trunk/include/clang/ASTMatchers/Dynamic/Parser.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/Dynamic/Parser.h?rev=181768&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/Dynamic/Parser.h?rev=181768&view=auto</a><br>



==============================================================================<br>
--- cfe/trunk/include/clang/ASTMatchers/Dynamic/Parser.h (added)<br>
+++ cfe/trunk/include/clang/ASTMatchers/Dynamic/Parser.h Tue May 14 04:13:00 2013<br>
@@ -0,0 +1,143 @@<br>
+//===--- Parser.h - Matcher expression parser -----*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+///<br>
+/// \file<br>
+/// \brief Simple matcher expression parser.<br>
+///<br>
+/// The parser understands matcher expressions of the form:<br>
+///   MatcherName(Arg0, Arg1, ..., ArgN)<br>
+/// as well as simple types like strings.<br>
+/// The parser does not know how to process the matchers. It delegates this task<br>
+/// to a Sema object received as an argument.<br>
+///<br>
+/// \code<br>
+/// Grammar for the expressions supported:<br>
+/// <Expression>        := <StringLiteral> | <MatcherExpression><br>
+/// <StringLiteral>     := "quoted string"<br>
+/// <MatcherExpression> := <MatcherName>(<ArgumentList>)<br>
+/// <MatcherName>       := [a-zA-Z]+<br>
+/// <ArgumentList>      := <Expression> | <Expression>,<ArgumentList><br>
+/// \endcode<br>
+///<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H<br>
+#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H<br>
+<br>
+#include "clang/ASTMatchers/Dynamic/Diagnostics.h"<br>
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"<br>
+#include "clang/Basic/LLVM.h"<br>
+#include "llvm/ADT/ArrayRef.h"<br>
+#include "llvm/ADT/StringRef.h"<br>
+<br>
+namespace clang {<br>
+namespace ast_matchers {<br>
+namespace dynamic {<br>
+<br>
+/// \brief Matcher expression parser.<br>
+class Parser {<br>
+public:<br>
+  /// \brief Interface to connect the parser with the registry and more.<br>
+  ///<br>
+  /// The parser uses the Sema instance passed into<br>
+  /// parseMatcherExpression() to handle all matcher tokens. The simplest<br>
+  /// processor implementation would simply call into the registry to create<br>
+  /// the matchers.<br>
+  /// However, a more complex processor might decide to intercept the matcher<br>
+  /// creation and do some extra work. For example, it could apply some<br>
+  /// transformation to the matcher by adding some id() nodes, or could detect<br>
+  /// specific matcher nodes for more efficient lookup.<br>
+  class Sema {<br>
+  public:<br>
+    virtual ~Sema();<br>
+<br>
+    /// \brief Process a matcher expression.<br>
+    ///<br>
+    /// All the arguments passed here have already been processed.<br>
+    ///<br>
+    /// \param MatcherName The matcher name found by the parser.<br>
+    ///<br>
+    /// \param NameRange The location of the name in the matcher source.<br>
+    ///   Useful for error reporting.<br>
+    ///<br>
+    /// \param Args The argument list for the matcher.<br>
+    ///<br>
+    /// \return The matcher object constructed by the processor, or NULL<br>
+    ///   if an error occurred. In that case, \c Error will contain a<br>
+    ///   description of the error.<br>
+    ///   The caller takes ownership of the DynTypedMatcher object returned.<br>
+    virtual DynTypedMatcher *<br>
+    actOnMatcherExpression(StringRef MatcherName, const SourceRange &NameRange,<br>
+                           ArrayRef<ParserValue> Args, Diagnostics *Error) = 0;<br>
+  };<br>
+<br>
+  /// \brief Parse a matcher expression, creating matchers from the registry.<br>
+  ///<br>
+  /// This overload creates matchers calling directly into the registry. If the<br>
+  /// caller needs more control over how the matchers are created, then it can<br>
+  /// use the overload below that takes a Sema.<br>
+  ///<br>
+  /// \param MatcherCode The matcher expression to parse.<br>
+  ///<br>
+  /// \return The matcher object constructed, or NULL if an error occurred.<br>
+  //    In that case, \c Error will contain a description of the error.<br>
+  ///   The caller takes ownership of the DynTypedMatcher object returned.<br>
+  static DynTypedMatcher *parseMatcherExpression(StringRef MatcherCode,<br>
+                                                 Diagnostics *Error);<br>
+<br>
+  /// \brief Parse a matcher expression.<br>
+  ///<br>
+  /// \param MatcherCode The matcher expression to parse.<br>
+  ///<br>
+  /// \param S The Sema instance that will help the parser<br>
+  ///   construct the matchers.<br>
+  /// \return The matcher object constructed by the processor, or NULL<br>
+  ///   if an error occurred. In that case, \c Error will contain a<br>
+  ///   description of the error.<br>
+  ///   The caller takes ownership of the DynTypedMatcher object returned.<br>
+  static DynTypedMatcher *parseMatcherExpression(StringRef MatcherCode,<br>
+                                                 Sema *S,<br>
+                                                 Diagnostics *Error);<br>
+<br>
+  /// \brief Parse an expression, creating matchers from the registry.<br>
+  ///<br>
+  /// Parses any expression supported by this parser. In general, the<br>
+  /// \c parseMatcherExpression function is a better approach to get a matcher<br>
+  /// object.<br>
+  static bool parseExpression(StringRef Code, VariantValue *Value,<br>
+                              Diagnostics *Error);<br>
+<br>
+  /// \brief Parse an expression.<br>
+  ///<br>
+  /// Parses any expression supported by this parser. In general, the<br>
+  /// \c parseMatcherExpression function is a better approach to get a matcher<br>
+  /// object.<br>
+  static bool parseExpression(StringRef Code, Sema *S,<br>
+                              VariantValue *Value, Diagnostics *Error);<br>
+<br>
+private:<br>
+  class CodeTokenizer;<br>
+  struct TokenInfo;<br>
+<br>
+  Parser(CodeTokenizer *Tokenizer, Sema *S,<br>
+         Diagnostics *Error);<br>
+<br>
+  bool parseExpressionImpl(VariantValue *Value);<br>
+  bool parseMatcherExpressionImpl(VariantValue *Value);<br>
+<br>
+  CodeTokenizer *const Tokenizer;<br>
+  Sema *const S;<br>
+  Diagnostics *const Error;<br>
+};<br>
+<br>
+}  // namespace dynamic<br>
+}  // namespace ast_matchers<br>
+}  // namespace clang<br>
+<br>
+#endif  // LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H<br>
<br>
Added: cfe/trunk/include/clang/ASTMatchers/Dynamic/Registry.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/Dynamic/Registry.h?rev=181768&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/Dynamic/Registry.h?rev=181768&view=auto</a><br>



==============================================================================<br>
--- cfe/trunk/include/clang/ASTMatchers/Dynamic/Registry.h (added)<br>
+++ cfe/trunk/include/clang/ASTMatchers/Dynamic/Registry.h Tue May 14 04:13:00 2013<br>
@@ -0,0 +1,63 @@<br>
+//===--- Registry.h - Matcher registry -----*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+///<br>
+/// \file<br>
+/// \brief Registry of all known matchers.<br>
+///<br>
+/// The registry provides a generic interface to construct any matcher by name.<br>
+///<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H<br>
+#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H<br>
+<br>
+#include "clang/ASTMatchers/Dynamic/Diagnostics.h"<br>
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"<br>
+#include "clang/Basic/LLVM.h"<br>
+#include "llvm/ADT/ArrayRef.h"<br>
+#include "llvm/ADT/StringRef.h"<br>
+<br>
+namespace clang {<br>
+namespace ast_matchers {<br>
+namespace dynamic {<br>
+<br>
+class Registry {<br>
+public:<br>
+  /// \brief Construct a matcher from the registry by name.<br>
+  ///<br>
+  /// Consult the registry of known matchers and construct the appropriate<br>
+  /// matcher by name.<br>
+  ///<br>
+  /// \param MatcherName The name of the matcher to instantiate.<br>
+  ///<br>
+  /// \param NameRange The location of the name in the matcher source.<br>
+  ///   Useful for error reporting.<br>
+  ///<br>
+  /// \param Args The argument list for the matcher. The number and types of the<br>
+  ///   values must be valid for the matcher requested. Otherwise, the function<br>
+  ///   will return an error.<br>
+  ///<br>
+  /// \return The matcher if no error was found. NULL if the matcher is not<br>
+  //    found, or if the number of arguments or argument types do not<br>
+  ///   match the signature. In that case \c Error will contain the description<br>
+  ///   of the error.<br>
+  static DynTypedMatcher *constructMatcher(StringRef MatcherName,<br>
+                                           const SourceRange &NameRange,<br>
+                                           ArrayRef<ParserValue> Args,<br>
+                                           Diagnostics *Error);<br>
+<br>
+private:<br>
+  Registry() LLVM_DELETED_FUNCTION;<br>
+};<br>
+<br>
+}  // namespace dynamic<br>
+}  // namespace ast_matchers<br>
+}  // namespace clang<br>
+<br>
+#endif  // LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H<br>
<br>
Added: cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h?rev=181768&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h?rev=181768&view=auto</a><br>



==============================================================================<br>
--- cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h (added)<br>
+++ cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h Tue May 14 04:13:00 2013<br>
@@ -0,0 +1,125 @@<br>
+//===--- VariantValue.h - Polymorphic value type -*- C++ -*-===/<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+///<br>
+/// \file<br>
+/// \brief Polymorphic value type.<br>
+///<br>
+/// Supports all the types required for dynamic Matcher construction.<br>
+///  Used by the registry to construct matchers in a generic way.<br>
+///<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H<br>
+#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H<br>
+<br>
+#include "clang/ASTMatchers/ASTMatchers.h"<br>
+#include "clang/ASTMatchers/ASTMatchersInternal.h"<br>
+#include "llvm/ADT/Twine.h"<br>
+#include "llvm/Support/type_traits.h"<br>
+<br>
+namespace clang {<br>
+namespace ast_matchers {<br>
+namespace dynamic {<br>
+<br>
+typedef ast_matchers::internal::DynTypedMatcher DynTypedMatcher;<br>
+<br>
+/// \brief Variant value class.<br>
+///<br>
+/// Basically, a tagged union with value type semantics.<br>
+/// It is used by the registry as the return value and argument type for the<br>
+/// matcher factory methods.<br>
+/// It can be constructed from any of the supported types. It supports<br>
+/// copy/assignment.<br>
+///<br>
+/// Supported types:<br>
+///  - \c std::string<br>
+///  - \c DynTypedMatcher, and any \c Matcher<T><br>
+class VariantValue {<br>
+public:<br>
+  VariantValue() : Type(VT_Nothing) {}<br>
+<br>
+  VariantValue(const VariantValue &Other);<br>
+  ~VariantValue();<br>
+  VariantValue &operator=(const VariantValue &Other);<br>
+<br>
+  /// \brief Specific constructors for each supported type.<br>
+  VariantValue(const std::string &String);<br>
+  VariantValue(const DynTypedMatcher &Matcher);<br>
+<br>
+  /// \brief String value functions.<br>
+  bool isString() const;<br>
+  const std::string &getString() const;<br>
+  void setString(const std::string &String);<br>
+<br>
+  /// \brief Matcher value functions.<br>
+  bool isMatcher() const;<br>
+  const DynTypedMatcher &getMatcher() const;<br>
+  void setMatcher(const DynTypedMatcher &Matcher);<br>
+  /// \brief Set the value to be \c Matcher by taking ownership of the object.<br>
+  void takeMatcher(DynTypedMatcher *Matcher);<br>
+<br>
+  /// \brief Specialized Matcher<T> is/get functions.<br>
+  template <class T><br>
+  bool isTypedMatcher() const {<br>
+    // TODO: Add some logic to test if T is actually valid for the underlying<br>
+    // type of the matcher.<br>
+    return isMatcher();<br>
+  }<br>
+<br>
+  template <class T><br>
+  ast_matchers::internal::Matcher<T> getTypedMatcher() const {<br>
+    return ast_matchers::internal::makeMatcher(<br>
+        new DerivedTypeMatcher<T>(getMatcher()));<br>
+  }<br>
+<br>
+private:<br>
+  void reset();<br>
+<br>
+  /// \brief Matcher bridge between a Matcher<T> and a generic DynTypedMatcher.<br>
+  template <class T><br>
+  class DerivedTypeMatcher :<br>
+      public ast_matchers::internal::MatcherInterface<T> {<br>
+  public:<br>
+    explicit DerivedTypeMatcher(const DynTypedMatcher &DynMatcher)<br>
+        : DynMatcher(DynMatcher.clone()) {}<br>
+    virtual ~DerivedTypeMatcher() {}<br>
+<br>
+    typedef ast_matchers::internal::ASTMatchFinder ASTMatchFinder;<br>
+    typedef ast_matchers::internal::BoundNodesTreeBuilder BoundNodesTreeBuilder;<br>
+    bool matches(const T &Node, ASTMatchFinder *Finder,<br>
+                 BoundNodesTreeBuilder *Builder) const {<br>
+      return DynMatcher->matches(ast_type_traits::DynTypedNode::create(Node),<br>
+                                 Finder, Builder);<br>
+    }<br>
+<br>
+  private:<br>
+    const OwningPtr<DynTypedMatcher> DynMatcher;<br>
+  };<br>
+<br>
+  /// \brief All supported value types.<br>
+  enum ValueType {<br>
+    VT_Nothing,<br>
+    VT_String,<br>
+    VT_Matcher<br>
+  };<br>
+<br>
+  /// \brief All supported value types.<br>
+  union AllValues {<br>
+    std::string *String;<br>
+    DynTypedMatcher *Matcher;<br>
+  };<br>
+<br>
+  ValueType Type;<br>
+  AllValues Value;<br>
+};<br>
+<br>
+} // end namespace dynamic<br>
+} // end namespace ast_matchers<br>
+} // end namespace clang<br>
+<br>
+#endif  // LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H<br>
<br>
Modified: cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp?rev=181768&r1=181767&r2=181768&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp?rev=181768&r1=181767&r2=181768&view=diff</a><br>



==============================================================================<br>
--- cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp (original)<br>
+++ cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp Tue May 14 04:13:00 2013<br>
@@ -744,6 +744,14 @@ void MatchFinder::addMatcher(const TypeL<br>
     new TypeLocMatcher(NodeMatch), Action));<br>
 }<br>
<br>
+bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,<br>
+                                    MatchCallback *Action) {<br>
+  MatcherCallbackPairs.push_back(std::make_pair(NodeMatch.clone(), Action));<br>
+  // TODO: Do runtime type checking to make sure the matcher is one of the valid<br>
+  // top-level matchers.<br>
+  return true;<br>
+}<br>
+<br>
 ASTConsumer *MatchFinder::newASTConsumer() {<br>
   return new internal::MatchASTConsumer(&MatcherCallbackPairs, ParsingDone);<br>
 }<br>
<br>
Modified: cfe/trunk/lib/ASTMatchers/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/CMakeLists.txt?rev=181768&r1=181767&r2=181768&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/CMakeLists.txt?rev=181768&r1=181767&r2=181768&view=diff</a><br>



==============================================================================<br>
--- cfe/trunk/lib/ASTMatchers/CMakeLists.txt (original)<br>
+++ cfe/trunk/lib/ASTMatchers/CMakeLists.txt Tue May 14 04:13:00 2013<br>
@@ -1,3 +1,5 @@<br>
+add_subdirectory(Dynamic)<br>
+<br>
 set(LLVM_LINK_COMPONENTS support)<br>
<br>
 add_clang_library(clangASTMatchers<br>
<br>
Added: cfe/trunk/lib/ASTMatchers/Dynamic/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/CMakeLists.txt?rev=181768&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/CMakeLists.txt?rev=181768&view=auto</a><br>



==============================================================================<br>
--- cfe/trunk/lib/ASTMatchers/Dynamic/CMakeLists.txt (added)<br>
+++ cfe/trunk/lib/ASTMatchers/Dynamic/CMakeLists.txt Tue May 14 04:13:00 2013<br>
@@ -0,0 +1,12 @@<br>
+set(LLVM_LINK_COMPONENTS support)<br>
+<br>
+add_clang_library(clangDynamicASTMatchers<br>
+  Diagnostics.cpp<br>
+  VariantValue.cpp<br>
+  Parser.cpp<br>
+  Registry.cpp<br>
+  )<br>
+<br>
+add_dependencies(clangDynamicASTMatchers<br>
+  clangASTMatchers<br>
+  )<br>
<br>
Added: cfe/trunk/lib/ASTMatchers/Dynamic/Diagnostics.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Diagnostics.cpp?rev=181768&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Diagnostics.cpp?rev=181768&view=auto</a><br>



==============================================================================<br>
--- cfe/trunk/lib/ASTMatchers/Dynamic/Diagnostics.cpp (added)<br>
+++ cfe/trunk/lib/ASTMatchers/Dynamic/Diagnostics.cpp Tue May 14 04:13:00 2013<br>
@@ -0,0 +1,113 @@<br>
+//===--- Diagnostics.cpp - Helper class for error diagnostics -----*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "clang/ASTMatchers/Dynamic/Diagnostics.h"<br>
+<br>
+namespace clang {<br>
+namespace ast_matchers {<br>
+namespace dynamic {<br>
+<br>
+Diagnostics::ArgStream &<br>
+Diagnostics::ArgStream::operator<<(const Twine &Arg) {<br>
+  Out->push_back(Arg.str());<br>
+  return *this;<br>
+}<br>
+<br>
+Diagnostics::ArgStream Diagnostics::pushErrorFrame(const SourceRange &Range,<br>
+                                                   ErrorType Error) {<br>
+  Frames.insert(Frames.begin(), ErrorFrame());<br>
+  ErrorFrame &Last = Frames.front();<br>
+  Last.Range = Range;<br>
+  Last.Type = Error;<br>
+  ArgStream Out = { &Last.Args };<br>
+  return Out;<br>
+}<br>
+<br>
+StringRef ErrorTypeToString(Diagnostics::ErrorType Type) {<br>
+  switch (Type) {<br>
+  case Diagnostics::ET_RegistryNotFound:<br>
+    return "Matcher not found: $0";<br>
+  case Diagnostics::ET_RegistryWrongArgCount:<br>
+    return "Incorrect argument count. (Expected = $0) != (Actual = $1)";<br>
+  case Diagnostics::ET_RegistryWrongArgType:<br>
+    return "Incorrect type on function $0 for arg $1.";<br>
+<br>
+  case Diagnostics::ET_ParserStringError:<br>
+    return "Error parsing string token: <$0>";<br>
+  case Diagnostics::ET_ParserMatcherArgFailure:<br>
+    return "Error parsing argument $0 for matcher $1.";<br>
+  case Diagnostics::ET_ParserMatcherFailure:<br>
+    return "Error building matcher $0.";<br>
+  case Diagnostics::ET_ParserNoOpenParen:<br>
+    return "Error parsing matcher. Found token <$0> while looking for '('.";<br>
+  case Diagnostics::ET_ParserNoCloseParen:<br>
+    return "Error parsing matcher. Found end-of-code while looking for ')'.";<br>
+  case Diagnostics::ET_ParserNoComma:<br>
+    return "Error parsing matcher. Found token <$0> while looking for ','.";<br>
+  case Diagnostics::ET_ParserNoCode:<br>
+    return "End of code found while looking for token.";<br>
+  case Diagnostics::ET_ParserNotAMatcher:<br>
+    return "Input value is not a matcher expression.";<br>
+  case Diagnostics::ET_ParserInvalidToken:<br>
+    return "Invalid token <$0> found when looking for a value.";<br>
+<br>
+  case Diagnostics::ET_None:<br>
+    return "<N/A>";<br>
+  }<br>
+  llvm_unreachable("Unknown ErrorType value.");<br>
+}<br>
+<br>
+std::string FormatErrorString(StringRef FormatString,<br>
+                              ArrayRef<std::string> Args) {<br>
+  std::string Out;<br>
+  while (!FormatString.empty()) {<br>
+    std::pair<StringRef, StringRef> Pieces = FormatString.split("$");<br>
+    Out += Pieces.first.str();<br>
+    if (Pieces.second.empty()) break;<br>
+<br>
+    const char Next = Pieces.second.front();<br>
+    FormatString = Pieces.second.drop_front();<br>
+    if (Next >= '0' && Next <= '9') {<br>
+      const unsigned Index = Next - '0';<br>
+      if (Index < Args.size()) {<br>
+        Out += Args[Index];<br>
+      } else {<br>
+        Out += "<Argument_Not_Provided>";<br>
+      }<br>
+    }<br>
+  }<br>
+  return Out;<br>
+}<br>
+<br>
+std::string Diagnostics::ErrorFrame::ToString() const {<br>
+  StringRef FormatString = ErrorTypeToString(Type);<br>
+  std::string ErrorOut = FormatErrorString(FormatString, Args);<br>
+  if (Range.Start.Line > 0 && Range.Start.Column > 0)<br>
+    return (Twine(Range.Start.Line) + ":" + Twine(Range.Start.Column) + ": " +<br>
+            ErrorOut).str();<br>
+  return ErrorOut;<br>
+}<br>
+<br>
+std::string Diagnostics::ToString() const {<br>
+  if (Frames.empty()) return "";<br>
+  return Frames[Frames.size() - 1].ToString();<br>
+}<br>
+<br>
+std::string Diagnostics::ToStringFull() const {<br>
+  std::string Result;<br>
+  for (size_t i = 0, end = Frames.size(); i != end; ++i) {<br>
+    if (i > 0) Result += "\n";<br>
+    Result += Frames[i].ToString();<br>
+  }<br>
+  return Result;<br>
+}<br>
+<br>
+}  // namespace dynamic<br>
+}  // namespace ast_matchers<br>
+}  // namespace clang<br>
<br>
Copied: cfe/trunk/lib/ASTMatchers/Dynamic/Makefile (from r181767, cfe/trunk/lib/ASTMatchers/Makefile)<br>
URL: <a href="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" target="_blank">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</a><br>



==============================================================================<br>
--- cfe/trunk/lib/ASTMatchers/Makefile (original)<br>
+++ cfe/trunk/lib/ASTMatchers/Dynamic/Makefile Tue May 14 04:13:00 2013<br>
@@ -1,4 +1,4 @@<br>
-##===- clang/lib/ASTMatchers/Makefile ----------------------*- Makefile -*-===##<br>
+##===- clang/lib/ASTMatchers/Dynamic/Makefile --------------*- Makefile -*-===##<br>
 #<br>
 #                     The LLVM Compiler Infrastructure<br>
 #<br>
@@ -7,7 +7,7 @@<br>
 #<br>
 ##===----------------------------------------------------------------------===##<br>
<br>
-CLANG_LEVEL := ../..<br>
-LIBRARYNAME := clangASTMatchers<br>
+CLANG_LEVEL := ../../..<br>
+LIBRARYNAME := clangDynamicASTMatchers<br>
<br>
 include $(CLANG_LEVEL)/Makefile<br>
<br>
Added: cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h?rev=181768&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h?rev=181768&view=auto</a><br>



==============================================================================<br>
--- cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h (added)<br>
+++ cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h Tue May 14 04:13:00 2013<br>
@@ -0,0 +1,223 @@<br>
+//===--- Marshallers.h - Generic matcher function marshallers -*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+///<br>
+/// \file<br>
+/// \brief Functions templates and classes to wrap matcher construct functions.<br>
+///<br>
+/// A collection of template function and classes that provide a generic<br>
+/// marshalling layer on top of matcher construct functions.<br>
+/// These are used by the registry to export all marshaller constructors with<br>
+/// the same generic interface.<br>
+///<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H<br>
+#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H<br>
+<br>
+#include <list><br>
+#include <string><br>
+#include <vector><br>
+<br>
+#include "clang/ASTMatchers/ASTMatchers.h"<br>
+#include "clang/ASTMatchers/Dynamic/Diagnostics.h"<br>
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"<br>
+#include "clang/Basic/LLVM.h"<br>
+#include "llvm/Support/type_traits.h"<br>
+<br>
+namespace clang {<br>
+namespace ast_matchers {<br>
+namespace dynamic {<br>
+<br>
+namespace internal {<br>
+<br>
+/// \brief Helper template class to just from argument type to the right is/get<br>
+///   functions in VariantValue.<br>
+/// Used to verify and extract the matcher arguments below.<br>
+template <class T> struct ArgTypeTraits;<br>
+template <class T> struct ArgTypeTraits<const T &> : public ArgTypeTraits<T> {<br>
+};<br>
+<br>
+template <> struct ArgTypeTraits<std::string> {<br>
+  static bool is(const VariantValue &Value) { return Value.isString(); }<br>
+  static const std::string &get(const VariantValue &Value) {<br>
+    return Value.getString();<br>
+  }<br>
+};<br>
+<br>
+template <class T> struct ArgTypeTraits<ast_matchers::internal::Matcher<T> > {<br>
+  static bool is(const VariantValue &Value) { return Value.isMatcher(); }<br>
+  static ast_matchers::internal::Matcher<T> get(const VariantValue &Value) {<br>
+    return Value.getTypedMatcher<T>();<br>
+  }<br>
+<br>
+};<br>
+<br>
+/// \brief Generic MatcherCreate interface.<br>
+///<br>
+/// Provides a \c run() method that constructs the matcher from the provided<br>
+/// arguments.<br>
+class MatcherCreateCallback {<br>
+public:<br>
+  virtual ~MatcherCreateCallback() {}<br>
+  virtual DynTypedMatcher *run(const SourceRange &NameRange,<br>
+                               ArrayRef<ParserValue> Args,<br>
+                               Diagnostics *Error) const = 0;<br>
+};<br>
+<br>
+/// \brief Simple callback implementation. Marshaller and function are provided.<br>
+///<br>
+/// \param Marshaller Function to unpack the arguments and call \c Func<br>
+/// \param Func Matcher construct function. This is the function that<br>
+///   compile-time matcher expressions would use to create the matcher.<br>
+template <typename MarshallerType, typename FuncType><br>
+class FixedArgCountMatcherCreateCallback : public MatcherCreateCallback {<br>
+public:<br>
+  FixedArgCountMatcherCreateCallback(MarshallerType Marshaller, FuncType Func,<br>
+                                     StringRef MatcherName)<br>
+      : Marshaller(Marshaller), Func(Func), MatcherName(MatcherName.str()) {}<br>
+<br>
+  DynTypedMatcher *run(const SourceRange &NameRange,<br>
+                       ArrayRef<ParserValue> Args, Diagnostics *Error) const {<br>
+    return Marshaller(Func, MatcherName, NameRange, Args, Error);<br>
+  }<br>
+<br>
+private:<br>
+  const MarshallerType Marshaller;<br>
+  const FuncType Func;<br>
+  const std::string MatcherName;<br>
+};<br>
+<br>
+/// \brief Helper function to do template argument deduction.<br>
+template <typename MarshallerType, typename FuncType><br>
+MatcherCreateCallback *<br>
+createMarshallerCallback(MarshallerType Marshaller, FuncType Func,<br>
+                         StringRef MatcherName) {<br>
+  return new FixedArgCountMatcherCreateCallback<MarshallerType, FuncType>(<br>
+      Marshaller, Func, MatcherName);<br>
+}<br>
+<br>
+/// \brief Helper macros to check the arguments on all marshaller functions.<br>
+#define CHECK_ARG_COUNT(count)                                                 \<br>
+  if (Args.size() != count) {                                                  \<br>
+    Error->pushErrorFrame(NameRange, Error->ET_RegistryWrongArgCount)          \<br>
+        << count << Args.size();                                               \<br>
+    return NULL;                                                               \<br>
+  }<br>
+<br>
+#define CHECK_ARG_TYPE(index, type)                                            \<br>
+  if (!ArgTypeTraits<type>::is(Args[index].Value)) {                           \<br>
+    Error->pushErrorFrame(Args[index].Range, Error->ET_RegistryWrongArgType)   \<br>
+        << MatcherName << (index + 1);                                         \<br>
+    return NULL;                                                               \<br>
+  }<br>
+<br>
+/// \brief Metafunction to normalize argument types.<br>
+///<br>
+/// We need to remove the const& out of the function parameters to be able to<br>
+/// find values on VariantValue.<br>
+template <typename T><br>
+struct remove_const_ref :<br>
+    public llvm::remove_const<typename llvm::remove_reference<T>::type> {<br>
+};<br>
+<br>
+/// \brief 0-arg marshaller function.<br>
+template <typename ReturnType><br>
+DynTypedMatcher *matcherMarshall0(ReturnType (*Func)(), StringRef MatcherName,<br>
+                                  const SourceRange &NameRange,<br>
+                                  ArrayRef<ParserValue> Args,<br>
+                                  Diagnostics *Error) {<br>
+  CHECK_ARG_COUNT(0);<br>
+  return Func().clone();<br>
+}<br>
+<br>
+/// \brief 1-arg marshaller function.<br>
+template <typename ReturnType, typename InArgType1><br>
+DynTypedMatcher *matcherMarshall1(ReturnType (*Func)(InArgType1),<br>
+                                  StringRef MatcherName,<br>
+                                  const SourceRange &NameRange,<br>
+                                  ArrayRef<ParserValue> Args,<br>
+                                  Diagnostics *Error) {<br>
+  typedef typename remove_const_ref<InArgType1>::type ArgType1;<br>
+  CHECK_ARG_COUNT(1);<br>
+  CHECK_ARG_TYPE(0, ArgType1);<br>
+  return Func(ArgTypeTraits<ArgType1>::get(Args[0].Value)).clone();<br>
+}<br>
+<br>
+/// \brief Variadic marshaller function.<br>
+template <typename BaseType, typename DerivedType><br>
+class VariadicMatcherCreateCallback : public MatcherCreateCallback {<br>
+public:<br>
+  explicit VariadicMatcherCreateCallback(StringRef MatcherName)<br>
+      : MatcherName(MatcherName.str()) {}<br>
+<br>
+  typedef ast_matchers::internal::Matcher<DerivedType> DerivedMatcherType;<br>
+<br>
+  DynTypedMatcher *run(const SourceRange &NameRange, ArrayRef<ParserValue> Args,<br>
+                       Diagnostics *Error) const {<br>
+    std::list<DerivedMatcherType> References;<br>
+    std::vector<const DerivedMatcherType *> InnerArgs(Args.size());<br>
+    for (size_t i = 0, e = Args.size(); i != e; ++i) {<br>
+      CHECK_ARG_TYPE(i, DerivedMatcherType);<br>
+      References.push_back(<br>
+          ArgTypeTraits<DerivedMatcherType>::get(Args[i].Value));<br>
+      InnerArgs[i] = &References.back();<br>
+    }<br>
+    return ast_matchers::internal::makeDynCastAllOfComposite<BaseType>(<br>
+        ArrayRef<const DerivedMatcherType *>(InnerArgs)).clone();<br>
+  }<br>
+<br>
+private:<br>
+  const std::string MatcherName;<br>
+};<br>
+<br>
+#undef CHECK_ARG_COUNT<br>
+#undef CHECK_ARG_TYPE<br>
+<br>
+/// Helper functions to select the appropriate marshaller functions.<br>
+/// They detects the number of arguments, arguments types and return type.<br>
+<br>
+/// \brief 0-arg overload<br>
+template <typename ReturnType><br>
+MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(),<br>
+                                               StringRef MatcherName) {<br>
+  return createMarshallerCallback(matcherMarshall0<ReturnType>, Func,<br>
+                                  MatcherName);<br>
+}<br>
+<br>
+/// \brief 1-arg overload<br>
+template <typename ReturnType, typename ArgType1><br>
+MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1),<br>
+                                               StringRef MatcherName) {<br>
+  return createMarshallerCallback(matcherMarshall1<ReturnType, ArgType1>, Func,<br>
+                                  MatcherName);<br>
+}<br>
+<br>
+/// \brief Variadic overload.<br>
+template <typename MatcherType><br>
+MatcherCreateCallback *makeMatcherAutoMarshall(<br>
+    ast_matchers::internal::VariadicAllOfMatcher<MatcherType> Func,<br>
+    StringRef MatcherName) {<br>
+  return new VariadicMatcherCreateCallback<MatcherType, MatcherType>(<br>
+      MatcherName);<br>
+}<br>
+<br>
+template <typename BaseType, typename MatcherType><br>
+MatcherCreateCallback *<br>
+makeMatcherAutoMarshall(ast_matchers::internal::VariadicDynCastAllOfMatcher<<br>
+                            BaseType, MatcherType> Func,<br>
+                        StringRef MatcherName) {<br>
+  return new VariadicMatcherCreateCallback<BaseType, MatcherType>(MatcherName);<br>
+}<br>
+<br>
+}  // namespace internal<br>
+}  // namespace dynamic<br>
+}  // namespace ast_matchers<br>
+}  // namespace clang<br>
+<br>
+#endif  // LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H<br>
<br>
Added: cfe/trunk/lib/ASTMatchers/Dynamic/Parser.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Parser.cpp?rev=181768&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Parser.cpp?rev=181768&view=auto</a><br>



==============================================================================<br>
--- cfe/trunk/lib/ASTMatchers/Dynamic/Parser.cpp (added)<br>
+++ cfe/trunk/lib/ASTMatchers/Dynamic/Parser.cpp Tue May 14 04:13:00 2013<br>
@@ -0,0 +1,332 @@<br>
+//===--- Parser.cpp - Matcher expression parser -----*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+///<br>
+/// \file<br>
+/// \brief Recursive parser implementation for the matcher expression grammar.<br>
+///<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include <string><br>
+#include <vector><br>
+<br>
+#include "clang/ASTMatchers/Dynamic/Parser.h"<br>
+#include "clang/ASTMatchers/Dynamic/Registry.h"<br>
+#include "clang/Basic/CharInfo.h"<br>
+#include "llvm/ADT/Twine.h"<br>
+<br>
+namespace clang {<br>
+namespace ast_matchers {<br>
+namespace dynamic {<br>
+<br>
+/// \brief Simple structure to hold information for one token from the parser.<br>
+struct Parser::TokenInfo {<br>
+  /// \brief Different possible tokens.<br>
+  enum TokenKind {<br>
+    TK_Eof = 0,<br>
+    TK_OpenParen = 1,<br>
+    TK_CloseParen = 2,<br>
+    TK_Comma = 3,<br>
+    TK_Literal = 4,<br>
+    TK_Ident = 5,<br>
+    TK_InvalidChar = 6,<br>
+    TK_Error = 7<br>
+  };<br>
+<br>
+  TokenInfo() : Text(), Kind(TK_Eof), Range(), Value() {}<br>
+<br>
+  StringRef Text;<br>
+  TokenKind Kind;<br>
+  SourceRange Range;<br>
+  VariantValue Value;<br>
+};<br>
+<br>
+/// \brief Simple tokenizer for the parser.<br>
+class Parser::CodeTokenizer {<br>
+public:<br>
+  explicit CodeTokenizer(StringRef MatcherCode, Diagnostics *Error)<br>
+      : Code(MatcherCode), StartOfLine(MatcherCode), Line(1), Error(Error) {<br>
+    NextToken = getNextToken();<br>
+  }<br>
+<br>
+  /// \brief Returns but doesn't consume the next token.<br>
+  const TokenInfo &peekNextToken() const { return NextToken; }<br>
+<br>
+  /// \brief Consumes and returns the next token.<br>
+  TokenInfo consumeNextToken() {<br>
+    TokenInfo ThisToken = NextToken;<br>
+    NextToken = getNextToken();<br>
+    return ThisToken;<br>
+  }<br>
+<br>
+  TokenInfo::TokenKind nextTokenKind() const { return NextToken.Kind; }<br>
+<br>
+private:<br>
+  TokenInfo getNextToken() {<br>
+    consumeWhitespace();<br>
+    TokenInfo Result;<br>
+    Result.Range.Start = currentLocation();<br>
+<br>
+    if (Code.empty()) {<br>
+      Result.Kind = TokenInfo::TK_Eof;<br>
+      Result.Text = "";<br>
+      return Result;<br>
+    }<br>
+<br>
+    switch (Code[0]) {<br>
+    case ',':<br>
+      Result.Kind = TokenInfo::TK_Comma;<br>
+      Result.Text = Code.substr(0, 1);<br>
+      Code = Code.drop_front();<br>
+      break;<br>
+    case '(':<br>
+      Result.Kind = TokenInfo::TK_OpenParen;<br>
+      Result.Text = Code.substr(0, 1);<br>
+      Code = Code.drop_front();<br>
+      break;<br>
+    case ')':<br>
+      Result.Kind = TokenInfo::TK_CloseParen;<br>
+      Result.Text = Code.substr(0, 1);<br>
+      Code = Code.drop_front();<br>
+      break;<br>
+<br>
+    case '"':<br>
+    case '\'':<br>
+      // Parse a string literal.<br>
+      consumeStringLiteral(&Result);<br>
+      break;<br>
+<br>
+    default:<br>
+      if (isAlphanumeric(Code[0])) {<br>
+        // Parse an identifier<br>
+        size_t TokenLength = 1;<br>
+        while (TokenLength < Code.size() && isAlphanumeric(Code[TokenLength]))<br>
+          ++TokenLength;<br>
+        Result.Kind = TokenInfo::TK_Ident;<br>
+        Result.Text = Code.substr(0, TokenLength);<br>
+        Code = Code.drop_front(TokenLength);<br>
+      } else {<br>
+        Result.Kind = TokenInfo::TK_InvalidChar;<br>
+        Result.Text = Code.substr(0, 1);<br>
+        Code = Code.drop_front(1);<br>
+      }<br>
+      break;<br>
+    }<br>
+<br>
+    Result.Range.End = currentLocation();<br>
+    return Result;<br>
+  }<br>
+<br>
+  /// \brief Consume a string literal.<br>
+  ///<br>
+  /// \c Code must be positioned at the start of the literal (the opening<br>
+  /// quote). Consumed until it finds the same closing quote character.<br>
+  void consumeStringLiteral(TokenInfo *Result) {<br>
+    bool InEscape = false;<br>
+    const char Marker = Code[0];<br>
+    for (size_t Length = 1, Size = Code.size(); Length != Size; ++Length) {<br>
+      if (InEscape) {<br>
+        InEscape = false;<br>
+        continue;<br>
+      }<br>
+      if (Code[Length] == '\\') {<br>
+        InEscape = true;<br>
+        continue;<br>
+      }<br>
+      if (Code[Length] == Marker) {<br>
+        Result->Kind = TokenInfo::TK_Literal;<br>
+        Result->Text = Code.substr(0, Length + 1);<br>
+        Result->Value = Code.substr(1, Length - 1).str();<br>
+        Code = Code.drop_front(Length + 1);<br>
+        return;<br>
+      }<br>
+    }<br>
+<br>
+    StringRef ErrorText = Code;<br>
+    Code = Code.drop_front(Code.size());<br>
+    SourceRange Range;<br>
+    Range.Start = Result->Range.Start;<br>
+    Range.End = currentLocation();<br>
+    Error->pushErrorFrame(Range, Error->ET_ParserStringError)<br>
+        << ErrorText;<br>
+    Result->Kind = TokenInfo::TK_Error;<br>
+  }<br>
+<br>
+  /// \brief Consume all leading whitespace from \c Code.<br>
+  void consumeWhitespace() {<br>
+    while (!Code.empty() && isWhitespace(Code[0])) {<br>
+      if (Code[0] == '\n') {<br>
+        ++Line;<br>
+        StartOfLine = Code.drop_front();<br>
+      }<br>
+      Code = Code.drop_front();<br>
+    }<br>
+  }<br>
+<br>
+  SourceLocation currentLocation() {<br>
+    SourceLocation Location;<br>
+    Location.Line = Line;<br>
+    Location.Column = Code.data() - StartOfLine.data() + 1;<br>
+    return Location;<br>
+  }<br>
+<br>
+  StringRef Code;<br>
+  StringRef StartOfLine;<br>
+  unsigned Line;<br>
+  Diagnostics *Error;<br>
+  TokenInfo NextToken;<br>
+};<br>
+<br>
+Parser::Sema::~Sema() {}<br>
+<br>
+/// \brief Parse and validate a matcher expression.<br>
+/// \return \c true on success, in which case \c Value has the matcher parsed.<br>
+///   If the input is malformed, or some argument has an error, it<br>
+///   returns \c false.<br>
+bool Parser::parseMatcherExpressionImpl(VariantValue *Value) {<br>
+  const TokenInfo NameToken = Tokenizer->consumeNextToken();<br>
+  assert(NameToken.Kind == TokenInfo::TK_Ident);<br>
+  const TokenInfo OpenToken = Tokenizer->consumeNextToken();<br>
+  if (OpenToken.Kind != TokenInfo::TK_OpenParen) {<br>
+    Error->pushErrorFrame(OpenToken.Range, Error->ET_ParserNoOpenParen)<br>
+        << OpenToken.Text;<br>
+    return false;<br>
+  }<br>
+<br>
+  std::vector<ParserValue> Args;<br>
+  TokenInfo EndToken;<br>
+  while (Tokenizer->nextTokenKind() != TokenInfo::TK_Eof) {<br>
+    if (Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen) {<br>
+      // End of args.<br>
+      EndToken = Tokenizer->consumeNextToken();<br>
+      break;<br>
+    }<br>
+    if (Args.size() > 0) {<br>
+      // We must find a , token to continue.<br>
+      const TokenInfo CommaToken = Tokenizer->consumeNextToken();<br>
+      if (CommaToken.Kind != TokenInfo::TK_Comma) {<br>
+        Error->pushErrorFrame(CommaToken.Range, Error->ET_ParserNoComma)<br>
+            << CommaToken.Text;<br>
+        return false;<br>
+      }<br>
+    }<br>
+<br>
+    ParserValue ArgValue;<br>
+    ArgValue.Text = Tokenizer->peekNextToken().Text;<br>
+    ArgValue.Range = Tokenizer->peekNextToken().Range;<br>
+    if (!parseExpressionImpl(&ArgValue.Value)) {<br>
+      Error->pushErrorFrame(NameToken.Range,<br>
+                            Error->ET_ParserMatcherArgFailure)<br>
+          << (Args.size() + 1) << NameToken.Text;<br>
+      return false;<br>
+    }<br>
+<br>
+    Args.push_back(ArgValue);<br>
+  }<br>
+<br>
+  if (EndToken.Kind == TokenInfo::TK_Eof) {<br>
+    Error->pushErrorFrame(OpenToken.Range, Error->ET_ParserNoCloseParen);<br>
+    return false;<br>
+  }<br>
+<br>
+  // Merge the start and end infos.<br>
+  SourceRange MatcherRange = NameToken.Range;<br>
+  MatcherRange.End = EndToken.Range.End;<br>
+  DynTypedMatcher *Result =<br>
+      S->actOnMatcherExpression(NameToken.Text, MatcherRange, Args, Error);<br>
+  if (Result == NULL) {<br>
+    Error->pushErrorFrame(NameToken.Range, Error->ET_ParserMatcherFailure)<br>
+        << NameToken.Text;<br>
+    return false;<br>
+  }<br>
+<br>
+  Value->takeMatcher(Result);<br>
+  return true;<br>
+}<br>
+<br>
+/// \brief Parse an <Expresssion><br>
+bool Parser::parseExpressionImpl(VariantValue *Value) {<br>
+  switch (Tokenizer->nextTokenKind()) {<br>
+  case TokenInfo::TK_Literal:<br>
+    *Value = Tokenizer->consumeNextToken().Value;<br>
+    return true;<br>
+<br>
+  case TokenInfo::TK_Ident:<br>
+    return parseMatcherExpressionImpl(Value);<br>
+<br>
+  case TokenInfo::TK_Eof:<br>
+    Error->pushErrorFrame(Tokenizer->consumeNextToken().Range,<br>
+                          Error->ET_ParserNoCode);<br>
+    return false;<br>
+<br>
+  case TokenInfo::TK_Error:<br>
+    // This error was already reported by the tokenizer.<br>
+    return false;<br>
+<br>
+  case TokenInfo::TK_OpenParen:<br>
+  case TokenInfo::TK_CloseParen:<br>
+  case TokenInfo::TK_Comma:<br>
+  case TokenInfo::TK_InvalidChar:<br>
+    const TokenInfo Token = Tokenizer->consumeNextToken();<br>
+    Error->pushErrorFrame(Token.Range, Error->ET_ParserInvalidToken)<br>
+        << Token.Text;<br>
+    return false;<br>
+  }<br>
+<br>
+  llvm_unreachable("Unknown token kind.");<br>
+}<br>
+<br>
+Parser::Parser(CodeTokenizer *Tokenizer, Sema *S,<br>
+               Diagnostics *Error)<br>
+    : Tokenizer(Tokenizer), S(S), Error(Error) {}<br>
+<br>
+class RegistrySema : public Parser::Sema {<br>
+public:<br>
+  virtual ~RegistrySema() {}<br>
+  DynTypedMatcher *actOnMatcherExpression(StringRef MatcherName,<br>
+                                          const SourceRange &NameRange,<br>
+                                          ArrayRef<ParserValue> Args,<br>
+                                          Diagnostics *Error) {<br>
+    return Registry::constructMatcher(MatcherName, NameRange, Args, Error);<br>
+  }<br>
+};<br>
+<br>
+bool Parser::parseExpression(StringRef Code, VariantValue *Value,<br>
+                             Diagnostics *Error) {<br>
+  RegistrySema S;<br>
+  return parseExpression(Code, &S, Value, Error);<br>
+}<br>
+<br>
+bool Parser::parseExpression(StringRef Code, Sema *S,<br>
+                             VariantValue *Value, Diagnostics *Error) {<br>
+  CodeTokenizer Tokenizer(Code, Error);<br>
+  return Parser(&Tokenizer, S, Error).parseExpressionImpl(Value);<br>
+}<br>
+<br>
+DynTypedMatcher *Parser::parseMatcherExpression(StringRef Code,<br>
+                                                Diagnostics *Error) {<br>
+  RegistrySema S;<br>
+  return parseMatcherExpression(Code, &S, Error);<br>
+}<br>
+<br>
+DynTypedMatcher *Parser::parseMatcherExpression(StringRef Code,<br>
+                                                Parser::Sema *S,<br>
+                                                Diagnostics *Error) {<br>
+  VariantValue Value;<br>
+  if (!parseExpression(Code, S, &Value, Error))<br>
+    return NULL;<br>
+  if (!Value.isMatcher()) {<br>
+    Error->pushErrorFrame(SourceRange(), Error->ET_ParserNotAMatcher);<br>
+    return NULL;<br>
+  }<br>
+  return Value.getMatcher().clone();<br>
+}<br>
+<br>
+}  // namespace dynamic<br>
+}  // namespace ast_matchers<br>
+}  // namespace clang<br>
<br>
Added: cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp?rev=181768&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp?rev=181768&view=auto</a><br>



==============================================================================<br>
--- cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp (added)<br>
+++ cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp Tue May 14 04:13:00 2013<br>
@@ -0,0 +1,153 @@<br>
+//===--- Registry.cpp - Matcher registry ------------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+///<br>
+/// \file<br>
+/// \brief Registry map populated at static initialization time.<br>
+///<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "clang/ASTMatchers/Dynamic/Registry.h"<br>
+<br>
+#include <utility><br>
+<br>
+#include "Marshallers.h"<br>
+#include "clang/ASTMatchers/ASTMatchers.h"<br>
+#include "llvm/ADT/StringMap.h"<br>
+#include "llvm/ADT/StringRef.h"<br>
+#include "llvm/Support/ManagedStatic.h"<br>
+<br>
+namespace clang {<br>
+namespace ast_matchers {<br>
+namespace dynamic {<br>
+namespace {<br>
+<br>
+using internal::MatcherCreateCallback;<br>
+<br>
+typedef llvm::StringMap<const MatcherCreateCallback *> ConstructorMap;<br>
+class RegistryMaps {<br>
+public:<br>
+  RegistryMaps();<br>
+  ~RegistryMaps();<br>
+<br>
+  const ConstructorMap &constructors() const { return Constructors; }<br>
+<br>
+private:<br>
+  void registerMatcher(StringRef MatcherName, MatcherCreateCallback *Callback);<br>
+  ConstructorMap Constructors;<br>
+};<br>
+<br>
+void RegistryMaps::registerMatcher(StringRef MatcherName,<br>
+                                   MatcherCreateCallback *Callback) {<br>
+  Constructors[MatcherName] = Callback;<br>
+}<br>
+<br>
+#define REGISTER_MATCHER(name)                                                 \<br>
+  registerMatcher(#name, internal::makeMatcherAutoMarshall(                    \<br>
+                             ::clang::ast_matchers::name, #name));<br>
+<br>
+/// \brief Generate a registry map with all the known matchers.<br>
+RegistryMaps::RegistryMaps() {<br>
+  // TODO: This list is not complete. It only has non-overloaded matchers,<br>
+  // which are the simplest to add to the system. Overloaded matchers require<br>
+  // more supporting code that was omitted from the first revision for<br>
+  // simplicitly of code review.<br>
+<br>
+  REGISTER_MATCHER(binaryOperator);<br>
+  REGISTER_MATCHER(bindTemporaryExpr);<br>
+  REGISTER_MATCHER(boolLiteral);<br>
+  REGISTER_MATCHER(callExpr);<br>
+  REGISTER_MATCHER(characterLiteral);<br>
+  REGISTER_MATCHER(compoundStmt);<br>
+  REGISTER_MATCHER(conditionalOperator);<br>
+  REGISTER_MATCHER(constCastExpr);<br>
+  REGISTER_MATCHER(constructExpr);<br>
+  REGISTER_MATCHER(constructorDecl);<br>
+  REGISTER_MATCHER(declRefExpr);<br>
+  REGISTER_MATCHER(declStmt);<br>
+  REGISTER_MATCHER(defaultArgExpr);<br>
+  REGISTER_MATCHER(doStmt);<br>
+  REGISTER_MATCHER(dynamicCastExpr);<br>
+  REGISTER_MATCHER(explicitCastExpr);<br>
+  REGISTER_MATCHER(expr);<br>
+  REGISTER_MATCHER(fieldDecl);<br>
+  REGISTER_MATCHER(forStmt);<br>
+  REGISTER_MATCHER(functionDecl);<br>
+  REGISTER_MATCHER(hasAnyParameter);<br>
+  REGISTER_MATCHER(hasAnySubstatement);<br>
+  REGISTER_MATCHER(hasConditionVariableStatement);<br>
+  REGISTER_MATCHER(hasDestinationType);<br>
+  REGISTER_MATCHER(hasEitherOperand);<br>
+  REGISTER_MATCHER(hasFalseExpression);<br>
+  REGISTER_MATCHER(hasImplicitDestinationType);<br>
+  REGISTER_MATCHER(hasInitializer);<br>
+  REGISTER_MATCHER(hasLHS);<br>
+  REGISTER_MATCHER(hasName);<br>
+  REGISTER_MATCHER(hasObjectExpression);<br>
+  REGISTER_MATCHER(hasRHS);<br>
+  REGISTER_MATCHER(hasSourceExpression);<br>
+  REGISTER_MATCHER(hasTrueExpression);<br>
+  REGISTER_MATCHER(hasUnaryOperand);<br>
+  REGISTER_MATCHER(ifStmt);<br>
+  REGISTER_MATCHER(implicitCastExpr);<br>
+  REGISTER_MATCHER(integerLiteral);<br>
+  REGISTER_MATCHER(isArrow);<br>
+  REGISTER_MATCHER(isConstQualified);<br>
+  REGISTER_MATCHER(isImplicit);<br>
+  REGISTER_MATCHER(member);<br>
+  REGISTER_MATCHER(memberExpr);<br>
+  REGISTER_MATCHER(methodDecl);<br>
+  REGISTER_MATCHER(namedDecl);<br>
+  REGISTER_MATCHER(newExpr);<br>
+  REGISTER_MATCHER(ofClass);<br>
+  REGISTER_MATCHER(on);<br>
+  REGISTER_MATCHER(onImplicitObjectArgument);<br>
+  REGISTER_MATCHER(operatorCallExpr);<br>
+  REGISTER_MATCHER(recordDecl);<br>
+  REGISTER_MATCHER(reinterpretCastExpr);<br>
+  REGISTER_MATCHER(staticCastExpr);<br>
+  REGISTER_MATCHER(stmt);<br>
+  REGISTER_MATCHER(stringLiteral);<br>
+  REGISTER_MATCHER(switchCase);<br>
+  REGISTER_MATCHER(to);<br>
+  REGISTER_MATCHER(unaryOperator);<br>
+  REGISTER_MATCHER(varDecl);<br>
+  REGISTER_MATCHER(whileStmt);<br>
+}<br>
+<br>
+RegistryMaps::~RegistryMaps() {<br>
+  for (ConstructorMap::iterator it = Constructors.begin(),<br>
+                                end = Constructors.end();<br>
+       it != end; ++it) {<br>
+    delete it->second;<br>
+  }<br>
+}<br>
+<br>
+static llvm::ManagedStatic<RegistryMaps> RegistryData;<br>
+<br>
+} // anonymous namespace<br>
+<br>
+// static<br>
+DynTypedMatcher *Registry::constructMatcher(StringRef MatcherName,<br>
+                                            const SourceRange &NameRange,<br>
+                                            ArrayRef<ParserValue> Args,<br>
+                                            Diagnostics *Error) {<br>
+  ConstructorMap::const_iterator it =<br>
+      RegistryData->constructors().find(MatcherName);<br>
+  if (it == RegistryData->constructors().end()) {<br>
+    Error->pushErrorFrame(NameRange, Error->ET_RegistryNotFound)<br>
+        << MatcherName;<br>
+    return NULL;<br>
+  }<br>
+<br>
+  return it->second->run(NameRange, Args, Error);<br>
+}<br>
+<br>
+}  // namespace dynamic<br>
+}  // namespace ast_matchers<br>
+}  // namespace clang<br>
<br>
Added: cfe/trunk/lib/ASTMatchers/Dynamic/VariantValue.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/VariantValue.cpp?rev=181768&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/VariantValue.cpp?rev=181768&view=auto</a><br>



==============================================================================<br>
--- cfe/trunk/lib/ASTMatchers/Dynamic/VariantValue.cpp (added)<br>
+++ cfe/trunk/lib/ASTMatchers/Dynamic/VariantValue.cpp Tue May 14 04:13:00 2013<br>
@@ -0,0 +1,105 @@<br>
+//===--- VariantValue.cpp - Polymorphic value type -*- C++ -*-===/<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+///<br>
+/// \file<br>
+/// \brief Polymorphic value type.<br>
+///<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"<br>
+<br>
+namespace clang {<br>
+namespace ast_matchers {<br>
+namespace dynamic {<br>
+<br>
+VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {<br>
+  *this = Other;<br>
+}<br>
+<br>
+VariantValue::VariantValue(const DynTypedMatcher &Matcher) : Type(VT_Nothing) {<br>
+  setMatcher(Matcher);<br>
+}<br>
+<br>
+VariantValue::VariantValue(const std::string &String) : Type(VT_Nothing) {<br>
+  setString(String);<br>
+}<br>
+<br>
+VariantValue::~VariantValue() { reset(); }<br>
+<br>
+VariantValue &VariantValue::operator=(const VariantValue &Other) {<br>
+  if (this == &Other) return *this;<br>
+  reset();<br>
+  switch (Other.Type) {<br>
+  case VT_String:<br>
+    setString(Other.getString());<br>
+    break;<br>
+  case VT_Matcher:<br>
+    setMatcher(Other.getMatcher());<br>
+    break;<br>
+  case VT_Nothing:<br>
+    Type = VT_Nothing;<br>
+    break;<br>
+  }<br>
+  return *this;<br>
+}<br>
+<br>
+void VariantValue::reset() {<br>
+  switch (Type) {<br>
+  case VT_String:<br>
+    delete Value.String;<br>
+    break;<br>
+  case VT_Matcher:<br>
+    delete Value.Matcher;<br>
+    break;<br>
+  // Cases that do nothing.<br>
+  case VT_Nothing:<br>
+    break;<br>
+  }<br>
+  Type = VT_Nothing;<br>
+}<br>
+<br>
+bool VariantValue::isString() const {<br>
+  return Type == VT_String;<br>
+}<br>
+<br>
+const std::string &VariantValue::getString() const {<br>
+  assert(isString());<br>
+  return *Value.String;<br>
+}<br>
+<br>
+void VariantValue::setString(const std::string &NewValue) {<br>
+  reset();<br>
+  Type = VT_String;<br>
+  Value.String = new std::string(NewValue);<br>
+}<br>
+<br>
+bool VariantValue::isMatcher() const {<br>
+  return Type == VT_Matcher;<br>
+}<br>
+<br>
+const DynTypedMatcher &VariantValue::getMatcher() const {<br>
+  assert(isMatcher());<br>
+  return *Value.Matcher;<br>
+}<br>
+<br>
+void VariantValue::setMatcher(const DynTypedMatcher &NewValue) {<br>
+  reset();<br>
+  Type = VT_Matcher;<br>
+  Value.Matcher = NewValue.clone();<br>
+}<br>
+<br>
+void VariantValue::takeMatcher(DynTypedMatcher *NewValue) {<br>
+  reset();<br>
+  Type = VT_Matcher;<br>
+  Value.Matcher = NewValue;<br>
+}<br>
+<br>
+} // end namespace dynamic<br>
+} // end namespace ast_matchers<br>
+} // end namespace clang<br>
<br>
Modified: cfe/trunk/lib/ASTMatchers/Makefile<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Makefile?rev=181768&r1=181767&r2=181768&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Makefile?rev=181768&r1=181767&r2=181768&view=diff</a><br>



==============================================================================<br>
--- cfe/trunk/lib/ASTMatchers/Makefile (original)<br>
+++ cfe/trunk/lib/ASTMatchers/Makefile Tue May 14 04:13:00 2013<br>
@@ -10,4 +10,6 @@<br>
 CLANG_LEVEL := ../..<br>
 LIBRARYNAME := clangASTMatchers<br>
<br>
+PARALLEL_DIRS = Dynamic<br>
+<br>
 include $(CLANG_LEVEL)/Makefile<br>
<br>
Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.h?rev=181768&r1=181767&r2=181768&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.h?rev=181768&r1=181767&r2=181768&view=diff</a><br>



==============================================================================<br>
--- cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.h (original)<br>
+++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.h Tue May 14 04:13:00 2013<br>
@@ -84,6 +84,41 @@ testing::AssertionResult notMatches(cons<br>
   return matchesConditionally(Code, AMatcher, false, "-std=c++11");<br>
 }<br>
<br>
+inline testing::AssertionResult<br>
+matchesConditionallyDynamic(const std::string &Code,<br>
+                            const internal::DynTypedMatcher &AMatcher,<br>
+                            bool ExpectMatch, llvm::StringRef CompileArg) {<br>
+  bool Found = false;<br>
+  MatchFinder Finder;<br>
+  Finder.addDynamicMatcher(AMatcher, new VerifyMatch(0, &Found));<br>
+  OwningPtr<FrontendActionFactory> Factory(newFrontendActionFactory(&Finder));<br>
+  // Some tests use typeof, which is a gnu extension.<br>
+  std::vector<std::string> Args(1, CompileArg);<br>
+  if (!runToolOnCodeWithArgs(Factory->create(), Code, Args)) {<br>
+    return testing::AssertionFailure() << "Parsing error in \"" << Code << "\"";<br>
+  }<br>
+  if (!Found && ExpectMatch) {<br>
+    return testing::AssertionFailure()<br>
+      << "Could not find match in \"" << Code << "\"";<br>
+  } else if (Found && !ExpectMatch) {<br>
+    return testing::AssertionFailure()<br>
+      << "Found unexpected match in \"" << Code << "\"";<br>
+  }<br>
+  return testing::AssertionSuccess();<br>
+}<br>
+<br>
+inline testing::AssertionResult<br>
+matchesDynamic(const std::string &Code,<br>
+               const internal::DynTypedMatcher &AMatcher) {<br>
+  return matchesConditionallyDynamic(Code, AMatcher, true, "-std=c++11");<br>
+}<br>
+<br>
+inline testing::AssertionResult<br>
+notMatchesDynamic(const std::string &Code,<br>
+                  const internal::DynTypedMatcher &AMatcher) {<br>
+  return matchesConditionallyDynamic(Code, AMatcher, false, "-std=c++11");<br>
+}<br>
+<br>
 template <typename T><br>
 testing::AssertionResult<br>
 matchAndVerifyResultConditionally(const std::string &Code, const T &AMatcher,<br>
<br>
Modified: cfe/trunk/unittests/ASTMatchers/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/CMakeLists.txt?rev=181768&r1=181767&r2=181768&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/CMakeLists.txt?rev=181768&r1=181767&r2=181768&view=diff</a><br>



==============================================================================<br>
--- cfe/trunk/unittests/ASTMatchers/CMakeLists.txt (original)<br>
+++ cfe/trunk/unittests/ASTMatchers/CMakeLists.txt Tue May 14 04:13:00 2013<br>
@@ -11,3 +11,5 @@ add_clang_unittest(ASTMatchersTests<br>
<br>
 target_link_libraries(ASTMatchersTests<br>
   gtest gtest_main clangASTMatchers clangTooling)<br>
+<br>
+add_subdirectory(Dynamic)<br>
<br>
Added: cfe/trunk/unittests/ASTMatchers/Dynamic/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/CMakeLists.txt?rev=181768&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/CMakeLists.txt?rev=181768&view=auto</a><br>



==============================================================================<br>
--- cfe/trunk/unittests/ASTMatchers/Dynamic/CMakeLists.txt (added)<br>
+++ cfe/trunk/unittests/ASTMatchers/Dynamic/CMakeLists.txt Tue May 14 04:13:00 2013<br>
@@ -0,0 +1,7 @@<br>
+add_clang_unittest(DynamicASTMatchersTests<br>
+  VariantValueTest.cpp<br>
+  ParserTest.cpp<br>
+  RegistryTest.cpp)<br>
+<br>
+target_link_libraries(DynamicASTMatchersTests<br>
+  gtest gtest_main clangASTMatchers clangDynamicASTMatchers clangTooling)<br>
<br>
Added: cfe/trunk/unittests/ASTMatchers/Dynamic/Makefile<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/Makefile?rev=181768&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/Makefile?rev=181768&view=auto</a><br>



==============================================================================<br>
--- cfe/trunk/unittests/ASTMatchers/Dynamic/Makefile (added)<br>
+++ cfe/trunk/unittests/ASTMatchers/Dynamic/Makefile Tue May 14 04:13:00 2013<br>
@@ -0,0 +1,18 @@<br>
+##===- unittests/ASTMatchers/Dynamic/Makefile --------------*- Makefile -*-===##<br>
+#<br>
+#                     The LLVM Compiler Infrastructure<br>
+#<br>
+# This file is distributed under the University of Illinois Open Source<br>
+# License. See LICENSE.TXT for details.<br>
+#<br>
+##===----------------------------------------------------------------------===##<br>
+<br>
+CLANG_LEVEL = ../../..<br>
+TESTNAME = DynamicASTMatchers<br>
+LINK_COMPONENTS := support mc<br>
+USEDLIBS = clangEdit.a clangTooling.a clangFrontend.a clangSerialization.a clangDriver.a \<br>
+           clangRewrite.a clangParse.a clangSema.a clangAnalysis.a \<br>
+           clangAST.a clangASTMatchers.a clangLex.a clangBasic.a \<br>
+           clangDynamicASTMatchers.a<br>
+<br>
+include $(CLANG_LEVEL)/unittests/Makefile<br>
<br>
Added: cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp?rev=181768&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp?rev=181768&view=auto</a><br>



==============================================================================<br>
--- cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp (added)<br>
+++ cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp Tue May 14 04:13:00 2013<br>
@@ -0,0 +1,194 @@<br>
+//===- unittest/ASTMatchers/Dynamic/ParserTest.cpp - Parser unit tests -===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===-------------------------------------------------------------------===//<br>
+<br>
+#include <string><br>
+#include <vector><br>
+<br>
+#include "../ASTMatchersTest.h"<br>
+#include "clang/ASTMatchers/Dynamic/Parser.h"<br>
+#include "clang/ASTMatchers/Dynamic/Registry.h"<br>
+#include "gtest/gtest.h"<br>
+#include "llvm/ADT/StringMap.h"<br>
+<br>
+namespace clang {<br>
+namespace ast_matchers {<br>
+namespace dynamic {<br>
+namespace {<br>
+<br>
+class DummyDynTypedMatcher : public DynTypedMatcher {<br>
+public:<br>
+  DummyDynTypedMatcher(uint64_t ID) : ID(ID) {}<br>
+<br>
+  typedef ast_matchers::internal::ASTMatchFinder ASTMatchFinder;<br>
+  typedef ast_matchers::internal::BoundNodesTreeBuilder BoundNodesTreeBuilder;<br>
+  virtual bool matches(const ast_type_traits::DynTypedNode DynNode,<br>
+                       ASTMatchFinder *Finder,<br>
+                       BoundNodesTreeBuilder *Builder) const {<br>
+    return false;<br>
+  }<br>
+<br>
+  /// \brief Makes a copy of this matcher object.<br>
+  virtual DynTypedMatcher *clone() const {<br>
+    return new DummyDynTypedMatcher(ID);<br>
+  }<br>
+<br>
+  /// \brief Returns a unique ID for the matcher.<br>
+  virtual uint64_t getID() const { return ID; }<br>
+<br>
+private:<br>
+  uint64_t ID;<br>
+};<br>
+<br>
+class MockSema : public Parser::Sema {<br>
+public:<br>
+  virtual ~MockSema() {}<br>
+<br>
+  uint64_t expectMatcher(StringRef MatcherName) {<br>
+    uint64_t ID = ExpectedMatchers.size() + 1;<br>
+    ExpectedMatchers[MatcherName] = ID;<br>
+    return ID;<br>
+  }<br>
+<br>
+  void parse(StringRef Code) {<br>
+    Diagnostics Error;<br>
+    VariantValue Value;<br>
+    Parser::parseExpression(Code, this, &Value, &Error);<br>
+    Values.push_back(Value);<br>
+    Errors.push_back(Error.ToStringFull());<br>
+  }<br>
+<br>
+  DynTypedMatcher *actOnMatcherExpression(StringRef MatcherName,<br>
+                                          const SourceRange &NameRange,<br>
+                                          ArrayRef<ParserValue> Args,<br>
+                                          Diagnostics *Error) {<br>
+    MatcherInfo ToStore = { MatcherName, NameRange, Args };<br>
+    Matchers.push_back(ToStore);<br>
+    return new DummyDynTypedMatcher(ExpectedMatchers[MatcherName]);<br>
+  }<br>
+<br>
+  struct MatcherInfo {<br>
+    StringRef MatcherName;<br>
+    SourceRange NameRange;<br>
+    std::vector<ParserValue> Args;<br>
+  };<br>
+<br>
+  std::vector<std::string> Errors;<br>
+  std::vector<VariantValue> Values;<br>
+  std::vector<MatcherInfo> Matchers;<br>
+  llvm::StringMap<uint64_t> ExpectedMatchers;<br>
+};<br>
+<br>
+TEST(ParserTest, ParseString) {<br>
+  MockSema Sema;<br>
+  Sema.parse("\"Foo\"");<br>
+  Sema.parse("\"\"");<br>
+  Sema.parse("\"Baz");<br>
+  EXPECT_EQ(3ULL, Sema.Values.size());<br>
+  EXPECT_EQ("Foo", Sema.Values[0].getString());<br>
+  EXPECT_EQ("", Sema.Values[1].getString());<br>
+  EXPECT_EQ("1:1: Error parsing string token: <\"Baz>", Sema.Errors[2]);<br>
+}<br>
+<br>
+bool matchesRange(const SourceRange &Range, unsigned StartLine,<br>
+                  unsigned EndLine, unsigned StartColumn, unsigned EndColumn) {<br>
+  EXPECT_EQ(StartLine, Range.Start.Line);<br>
+  EXPECT_EQ(EndLine, Range.End.Line);<br>
+  EXPECT_EQ(StartColumn, Range.Start.Column);<br>
+  EXPECT_EQ(EndColumn, Range.End.Column);<br>
+  return Range.Start.Line == StartLine && Range.End.Line == EndLine &&<br>
+         Range.Start.Column == StartColumn && Range.End.Column == EndColumn;<br>
+}<br>
+<br>
+TEST(ParserTest, ParseMatcher) {<br>
+  MockSema Sema;<br>
+  const uint64_t ExpectedFoo = Sema.expectMatcher("Foo");<br>
+  const uint64_t ExpectedBar = Sema.expectMatcher("Bar");<br>
+  const uint64_t ExpectedBaz = Sema.expectMatcher("Baz");<br>
+  Sema.parse(" Foo ( Bar (), Baz( \n \"B A,Z\") )  ");<br>
+  for (size_t i = 0, e = Sema.Errors.size(); i != e; ++i) {<br>
+    EXPECT_EQ("", Sema.Errors[i]);<br>
+  }<br>
+<br>
+  EXPECT_EQ(1ULL, Sema.Values.size());<br>
+  EXPECT_EQ(ExpectedFoo, Sema.Values[0].getMatcher().getID());<br>
+<br>
+  EXPECT_EQ(3ULL, Sema.Matchers.size());<br>
+  const MockSema::MatcherInfo Bar = Sema.Matchers[0];<br>
+  EXPECT_EQ("Bar", Bar.MatcherName);<br>
+  EXPECT_TRUE(matchesRange(Bar.NameRange, 1, 1, 8, 14));<br>
+  EXPECT_EQ(0ULL, Bar.Args.size());<br>
+<br>
+  const MockSema::MatcherInfo Baz = Sema.Matchers[1];<br>
+  EXPECT_EQ("Baz", Baz.MatcherName);<br>
+  EXPECT_TRUE(matchesRange(Baz.NameRange, 1, 2, 16, 10));<br>
+  EXPECT_EQ(1ULL, Baz.Args.size());<br>
+  EXPECT_EQ("B A,Z", Baz.Args[0].Value.getString());<br>
+<br>
+  const MockSema::MatcherInfo Foo = Sema.Matchers[2];<br>
+  EXPECT_EQ("Foo", Foo.MatcherName);<br>
+  EXPECT_TRUE(matchesRange(Foo.NameRange, 1, 2, 2, 12));<br>
+  EXPECT_EQ(2ULL, Foo.Args.size());<br>
+  EXPECT_EQ(ExpectedBar, Foo.Args[0].Value.getMatcher().getID());<br>
+  EXPECT_EQ(ExpectedBaz, Foo.Args[1].Value.getMatcher().getID());<br>
+}<br>
+<br>
+using ast_matchers::internal::Matcher;<br>
+<br>
+TEST(ParserTest, FullParserTest) {<br>
+  OwningPtr<DynTypedMatcher> Matcher(Parser::parseMatcherExpression(<br>
+      "hasInitializer(binaryOperator(hasLHS(integerLiteral())))", NULL));<br>
+  EXPECT_TRUE(matchesDynamic("int x = 1 + false;", *Matcher));<br>
+  EXPECT_FALSE(matchesDynamic("int x = true + 1;", *Matcher));<br>
+<br>
+  Diagnostics Error;<br>
+  EXPECT_TRUE(Parser::parseMatcherExpression(<br>
+      "hasInitializer(\n    binaryOperator(hasLHS(\"A\")))", &Error) == NULL);<br>
+  EXPECT_EQ("1:1: Error parsing argument 1 for matcher hasInitializer.\n"<br>
+            "2:5: Error parsing argument 1 for matcher binaryOperator.\n"<br>
+            "2:20: Error building matcher hasLHS.\n"<br>
+            "2:27: Incorrect type on function hasLHS for arg 1.",<br>
+            Error.ToStringFull());<br>
+}<br>
+<br>
+std::string ParseWithError(StringRef Code) {<br>
+  Diagnostics Error;<br>
+  VariantValue Value;<br>
+  Parser::parseExpression(Code, &Value, &Error);<br>
+  return Error.ToStringFull();<br>
+}<br>
+<br>
+std::string ParseMatcherWithError(StringRef Code) {<br>
+  Diagnostics Error;<br>
+  Parser::parseMatcherExpression(Code, &Error);<br>
+  return Error.ToStringFull();<br>
+}<br>
+<br>
+TEST(ParserTest, Errors) {<br>
+  EXPECT_EQ(<br>
+      "1:5: Error parsing matcher. Found token <123> while looking for '('.",<br>
+      ParseWithError("Foo 123"));<br>
+  EXPECT_EQ(<br>
+      "1:9: Error parsing matcher. Found token <123> while looking for ','.",<br>
+      ParseWithError("Foo(\"A\" 123)"));<br>
+  EXPECT_EQ(<br>
+      "1:4: Error parsing matcher. Found end-of-code while looking for ')'.",<br>
+      ParseWithError("Foo("));<br>
+  EXPECT_EQ("1:1: End of code found while looking for token.",<br>
+            ParseWithError(""));<br>
+  EXPECT_EQ("Input value is not a matcher expression.",<br>
+            ParseMatcherWithError("\"A\""));<br>
+  EXPECT_EQ("1:1: Error parsing argument 1 for matcher Foo.\n"<br>
+            "1:5: Invalid token <(> found when looking for a value.",<br>
+            ParseWithError("Foo(("));<br>
+}<br>
+<br>
+}  // end anonymous namespace<br>
+}  // end namespace dynamic<br>
+}  // end namespace ast_matchers<br>
+}  // end namespace clang<br>
<br>
Added: cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp?rev=181768&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp?rev=181768&view=auto</a><br>



==============================================================================<br>
--- cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp (added)<br>
+++ cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp Tue May 14 04:13:00 2013<br>
@@ -0,0 +1,112 @@<br>
+//===- unittest/ASTMatchers/Dynamic/RegistryTest.cpp - Registry unit tests -===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===-----------------------------------------------------------------------===//<br>
+<br>
+#include <vector><br>
+<br>
+#include "../ASTMatchersTest.h"<br>
+#include "clang/ASTMatchers/Dynamic/Registry.h"<br>
+#include "gtest/gtest.h"<br>
+<br>
+namespace clang {<br>
+namespace ast_matchers {<br>
+namespace dynamic {<br>
+namespace {<br>
+<br>
+using ast_matchers::internal::Matcher;<br>
+<br>
+DynTypedMatcher *constructMatcher(StringRef MatcherName, Diagnostics *Error) {<br>
+  const std::vector<ParserValue> Args;<br>
+  return Registry::constructMatcher(MatcherName, SourceRange(), Args, Error);<br>
+}<br>
+<br>
+DynTypedMatcher *constructMatcher(StringRef MatcherName,<br>
+                                  const VariantValue &Arg1,<br>
+                                  Diagnostics *Error) {<br>
+  std::vector<ParserValue> Args(1);<br>
+  Args[0].Value = Arg1;<br>
+  return Registry::constructMatcher(MatcherName, SourceRange(), Args, Error);<br>
+}<br>
+<br>
+DynTypedMatcher *constructMatcher(StringRef MatcherName,<br>
+                                  const VariantValue &Arg1,<br>
+                                  const VariantValue &Arg2,<br>
+                                  Diagnostics *Error) {<br>
+  std::vector<ParserValue> Args(2);<br>
+  Args[0].Value = Arg1;<br>
+  Args[1].Value = Arg2;<br>
+  return Registry::constructMatcher(MatcherName, SourceRange(), Args, Error);<br>
+}<br>
+<br>
+TEST(RegistryTest, CanConstructNoArgs) {<br>
+  OwningPtr<DynTypedMatcher> IsArrowValue(constructMatcher("isArrow", NULL));<br>
+  OwningPtr<DynTypedMatcher> BoolValue(constructMatcher("boolLiteral", NULL));<br>
+<br>
+  const std::string ClassSnippet = "struct Foo { int x; };\n"<br>
+                                   "Foo *foo = new Foo;\n"<br>
+                                   "int i = foo->x;\n";<br>
+  const std::string BoolSnippet = "bool Foo = true;\n";<br>
+<br>
+  EXPECT_TRUE(matchesDynamic(ClassSnippet, *IsArrowValue));<br>
+  EXPECT_TRUE(matchesDynamic(BoolSnippet, *BoolValue));<br>
+  EXPECT_FALSE(matchesDynamic(ClassSnippet, *BoolValue));<br>
+  EXPECT_FALSE(matchesDynamic(BoolSnippet, *IsArrowValue));<br>
+}<br>
+<br>
+TEST(RegistryTest, ConstructWithSimpleArgs) {<br>
+  OwningPtr<DynTypedMatcher> Value(<br>
+      constructMatcher("hasName", std::string("X"), NULL));<br>
+  EXPECT_TRUE(matchesDynamic("class X {};", *Value));<br>
+  EXPECT_FALSE(matchesDynamic("int x;", *Value));<br>
+}<br>
+<br>
+TEST(RegistryTest, ConstructWithMatcherArgs) {<br>
+  OwningPtr<DynTypedMatcher> HasInitializerSimple(<br>
+      constructMatcher("hasInitializer", stmt(), NULL));<br>
+  OwningPtr<DynTypedMatcher> HasInitializerComplex(<br>
+      constructMatcher("hasInitializer", callExpr(), NULL));<br>
+<br>
+  std::string code = "int i;";<br>
+  EXPECT_FALSE(matchesDynamic(code, *HasInitializerSimple));<br>
+  EXPECT_FALSE(matchesDynamic(code, *HasInitializerComplex));<br>
+<br>
+  code = "int i = 1;";<br>
+  EXPECT_TRUE(matchesDynamic(code, *HasInitializerSimple));<br>
+  EXPECT_FALSE(matchesDynamic(code, *HasInitializerComplex));<br>
+<br>
+  code = "int y(); int i = y();";<br>
+  EXPECT_TRUE(matchesDynamic(code, *HasInitializerSimple));<br>
+  EXPECT_TRUE(matchesDynamic(code, *HasInitializerComplex));<br>
+}<br>
+<br>
+TEST(RegistryTest, Errors) {<br>
+  // Incorrect argument count.<br>
+  OwningPtr<Diagnostics> Error(new Diagnostics());<br>
+  EXPECT_TRUE(NULL == constructMatcher("hasInitializer", Error.get()));<br>
+  EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)",<br>
+            Error->ToString());<br>
+  Error.reset(new Diagnostics());<br>
+  EXPECT_TRUE(NULL == constructMatcher("isArrow", std::string(), Error.get()));<br>
+  EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)",<br>
+            Error->ToString());<br>
+<br>
+  // Bad argument type<br>
+  Error.reset(new Diagnostics());<br>
+  EXPECT_TRUE(NULL == constructMatcher("ofClass", std::string(), Error.get()));<br>
+  EXPECT_EQ("Incorrect type on function ofClass for arg 1.", Error->ToString());<br>
+  Error.reset(new Diagnostics());<br>
+  EXPECT_TRUE(NULL == constructMatcher("recordDecl", recordDecl(),<br>
+                                       ::std::string(), Error.get()));<br>
+  EXPECT_EQ("Incorrect type on function recordDecl for arg 2.",<br>
+            Error->ToString());<br>
+}<br>
+<br>
+} // end anonymous namespace<br>
+} // end namespace dynamic<br>
+} // end namespace ast_matchers<br>
+} // end namespace clang<br>
<br>
Added: cfe/trunk/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp?rev=181768&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp?rev=181768&view=auto</a><br>



==============================================================================<br>
--- cfe/trunk/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp (added)<br>
+++ cfe/trunk/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp Tue May 14 04:13:00 2013<br>
@@ -0,0 +1,97 @@<br>
+//===- unittest/ASTMatchers/Dynamic/VariantValueTest.cpp - VariantValue unit tests -===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===-----------------------------------------------------------------------------===//<br>
+<br>
+#include "../ASTMatchersTest.h"<br>
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"<br>
+#include "gtest/gtest.h"<br>
+<br>
+namespace clang {<br>
+namespace ast_matchers {<br>
+namespace dynamic {<br>
+namespace {<br>
+<br>
+using ast_matchers::internal::DynTypedMatcher;<br>
+using ast_matchers::internal::Matcher;<br>
+<br>
+TEST(VariantValueTest, String) {<br>
+  const ::std::string kString = "string";<br>
+  VariantValue Value = kString;<br>
+<br>
+  EXPECT_TRUE(Value.isString());<br>
+  EXPECT_EQ(kString, Value.getString());<br>
+<br>
+  EXPECT_FALSE(Value.isMatcher());<br>
+  EXPECT_FALSE(Value.isTypedMatcher<clang::Decl>());<br>
+  EXPECT_FALSE(Value.isTypedMatcher<clang::UnaryOperator>());<br>
+}<br>
+<br>
+TEST(VariantValueTest, DynTypedMatcher) {<br>
+  VariantValue Value = stmt();<br>
+<br>
+  EXPECT_FALSE(Value.isString());<br>
+<br>
+  EXPECT_TRUE(Value.isMatcher());<br>
+  EXPECT_TRUE(Value.isTypedMatcher<clang::Decl>());<br>
+  EXPECT_TRUE(Value.isTypedMatcher<clang::UnaryOperator>());<br>
+<br>
+  // Conversion to any type of matcher works.<br>
+  // If they are not compatible it would just return a matcher that matches<br>
+  // nothing. We test this below.<br>
+  Value = recordDecl();<br>
+  EXPECT_TRUE(Value.isMatcher());<br>
+  EXPECT_TRUE(Value.isTypedMatcher<clang::Decl>());<br>
+  EXPECT_TRUE(Value.isTypedMatcher<clang::UnaryOperator>());<br>
+<br>
+  Value = unaryOperator();<br>
+  EXPECT_TRUE(Value.isMatcher());<br>
+  EXPECT_TRUE(Value.isTypedMatcher<clang::Decl>());<br>
+  EXPECT_TRUE(Value.isTypedMatcher<clang::Stmt>());<br>
+  EXPECT_TRUE(Value.isTypedMatcher<clang::UnaryOperator>());<br>
+}<br>
+<br>
+TEST(VariantValueTest, Assignment) {<br>
+  VariantValue Value = std::string("A");<br>
+  EXPECT_TRUE(Value.isString());<br>
+  EXPECT_EQ("A", Value.getString());<br>
+  EXPECT_FALSE(Value.isMatcher());<br>
+<br>
+  Value = recordDecl();<br>
+  EXPECT_FALSE(Value.isString());<br>
+  EXPECT_TRUE(Value.isMatcher());<br>
+  EXPECT_TRUE(Value.isTypedMatcher<clang::Decl>());<br>
+  EXPECT_TRUE(Value.isTypedMatcher<clang::UnaryOperator>());<br>
+<br>
+  Value = VariantValue();<br>
+  EXPECT_FALSE(Value.isString());<br>
+  EXPECT_FALSE(Value.isMatcher());<br>
+}<br>
+<br>
+TEST(GeneicValueTest, Matcher) {<br>
+  EXPECT_TRUE(matchesDynamic(<br>
+      "class X {};", VariantValue(recordDecl(hasName("X"))).getMatcher()));<br>
+  EXPECT_TRUE(matchesDynamic(<br>
+      "int x;", VariantValue(varDecl()).getTypedMatcher<clang::Decl>()));<br>
+  EXPECT_TRUE(matchesDynamic("int foo() { return 1 + 1; }",<br>
+                             VariantValue(functionDecl()).getMatcher()));<br>
+  // Going through the wrong Matcher<T> will fail to match, even if the<br>
+  // underlying matcher is correct.<br>
+  EXPECT_FALSE(matchesDynamic(<br>
+      "int x;", VariantValue(varDecl()).getTypedMatcher<clang::Stmt>()));<br>
+<br>
+  EXPECT_FALSE(<br>
+      matchesDynamic("int x;", VariantValue(functionDecl()).getMatcher()));<br>
+  EXPECT_FALSE(matchesDynamic(<br>
+      "int foo() { return 1 + 1; }",<br>
+      VariantValue(declRefExpr()).getTypedMatcher<clang::DeclRefExpr>()));<br>
+}<br>
+<br>
+} // end anonymous namespace<br>
+} // end namespace dynamic<br>
+} // end namespace ast_matchers<br>
+} // end namespace clang<br>
<br>
Modified: cfe/trunk/unittests/ASTMatchers/Makefile<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Makefile?rev=181768&r1=181767&r2=181768&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Makefile?rev=181768&r1=181767&r2=181768&view=diff</a><br>



==============================================================================<br>
--- cfe/trunk/unittests/ASTMatchers/Makefile (original)<br>
+++ cfe/trunk/unittests/ASTMatchers/Makefile Tue May 14 04:13:00 2013<br>
@@ -9,6 +9,8 @@<br>
<br>
 CLANG_LEVEL = ../..<br>
<br>
+PARALLEL_DIRS = Dynamic<br>
+<br>
 TESTNAME = ASTMatchers<br>
 include $(CLANG_LEVEL)/../../Makefile.config<br>
 LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu" target="_blank">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>
</blockquote></div>
</div></div></blockquote></div><br></div>