Refactor "MatcherList" into "VariantMatcher" and abstract the notion of a list of...
authorSamuel Benzaquen <sbenza@google.com>
Tue, 13 Aug 2013 14:54:51 +0000 (14:54 +0000)
committerSamuel Benzaquen <sbenza@google.com>
Tue, 13 Aug 2013 14:54:51 +0000 (14:54 +0000)
Summary:
Refactor "MatcherList" into "VariantMatcher" and abstract the notion of a list of matchers for the polymorphic case.
This work is to support future changes needed for eachOf/allOf/anyOf matchers. We will add a new type on VariantMatcher.

Reviewers: klimek

CC: cfe-commits, revane
Differential Revision: http://llvm-reviews.chandlerc.com/D1365

llvm-svn: 188272

clang/include/clang/ASTMatchers/Dynamic/Parser.h
clang/include/clang/ASTMatchers/Dynamic/Registry.h
clang/include/clang/ASTMatchers/Dynamic/VariantValue.h
clang/lib/ASTMatchers/Dynamic/Marshallers.h
clang/lib/ASTMatchers/Dynamic/Parser.cpp
clang/lib/ASTMatchers/Dynamic/Registry.cpp
clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
clang/unittests/ASTMatchers/Dynamic/ParserTest.cpp
clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
clang/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp

index b3fd7d607fb87df77a2a31cc1f15d9ac286d6aff..3759f631b36c3674774b067f0defa40351bae9bf 100644 (file)
@@ -74,14 +74,14 @@ public:
     ///
     /// \param Args The argument list for the matcher.
     ///
-    /// \return The matcher objects constructed by the processor, or an empty
-    ///   list if an error occurred. In that case, \c Error will contain a
+    /// \return The matcher objects constructed by the processor, or a null
+    ///   matcher if an error occurred. In that case, \c Error will contain a
     ///   description of the error.
-    virtual MatcherList actOnMatcherExpression(StringRef MatcherName,
-                                               const SourceRange &NameRange,
-                                               StringRef BindID,
-                                               ArrayRef<ParserValue> Args,
-                                               Diagnostics *Error) = 0;
+    virtual VariantMatcher actOnMatcherExpression(StringRef MatcherName,
+                                                  const SourceRange &NameRange,
+                                                  StringRef BindID,
+                                                  ArrayRef<ParserValue> Args,
+                                                  Diagnostics *Error) = 0;
   };
 
   /// \brief Parse a matcher expression, creating matchers from the registry.
index a75f29641ab08ace3af987dccd82ca02f8d73813..c113c1404ef0d7222dafc335172ce96c294732fc 100644 (file)
@@ -43,26 +43,26 @@ public:
   ///   values must be valid for the matcher requested. Otherwise, the function
   ///   will return an error.
   ///
-  /// \return The matcher objects constructed if no error was found.
-  ///   An empty list if the matcher is not found, or if the number of
+  /// \return The matcher object constructed if no error was found.
+  ///   A null matcher if the matcher is not found, or if the number of
   ///   arguments or argument types do not match the signature.
   ///   In that case \c Error will contain the description of the error.
-  static MatcherList constructMatcher(StringRef MatcherName,
-                                      const SourceRange &NameRange,
-                                      ArrayRef<ParserValue> Args,
-                                      Diagnostics *Error);
+  static VariantMatcher constructMatcher(StringRef MatcherName,
+                                         const SourceRange &NameRange,
+                                         ArrayRef<ParserValue> Args,
+                                         Diagnostics *Error);
 
   /// \brief Construct a matcher from the registry and bind it.
   ///
   /// Similar the \c constructMatcher() above, but it then tries to bind the
   /// matcher to the specified \c BindID.
   /// If the matcher is not bindable, it sets an error in \c Error and returns
-  /// an empty list.
-  static MatcherList constructBoundMatcher(StringRef MatcherName,
-                                           const SourceRange &NameRange,
-                                           StringRef BindID,
-                                           ArrayRef<ParserValue> Args,
-                                           Diagnostics *Error);
+  /// a null matcher.
+  static VariantMatcher constructBoundMatcher(StringRef MatcherName,
+                                              const SourceRange &NameRange,
+                                              StringRef BindID,
+                                              ArrayRef<ParserValue> Args,
+                                              Diagnostics *Error);
 
 private:
   Registry() LLVM_DELETED_FUNCTION;
index 44f497248ae2bbc6fdf9ba0bcec5a52f9029afc1..abfce078b3cbfad99f8476d65222cdd87a6baba6 100644 (file)
@@ -30,32 +30,53 @@ namespace dynamic {
 
 using ast_matchers::internal::DynTypedMatcher;
 
-/// \brief A list of \c DynTypedMatcher objects.
+/// \brief A variant matcher object.
 ///
-/// The purpose of this list is to wrap multiple different matchers and
-/// provide the right one when calling \c hasTypedMatcher/getTypedMatcher.
-class MatcherList {
+/// The purpose of this object is to abstract simple and polymorphic matchers
+/// into a single object type.
+/// Polymorphic matchers might be implemented as a list of all the possible
+/// overloads of the matcher. \c VariantMatcher knows how to select the
+/// appropriate overload when needed.
+/// To get a real matcher object out of a \c VariantMatcher you can do:
+///  - getSingleMatcher() which returns a matcher, only if it is not ambiguous
+///    to decide which matcher to return. Eg. it contains only a single
+///    matcher, or a polymorphic one with only one overload.
+///  - hasTypedMatcher<T>()/getTypedMatcher<T>(): These calls will determine if
+///    the underlying matcher(s) can unambiguously return a Matcher<T>.
+class VariantMatcher {
 public:
-  /// \brief An empty list.
-  MatcherList();
+  /// \brief A null matcher.
+  VariantMatcher();
+
   /// \brief Clones the matcher objects.
-  MatcherList(const MatcherList &Other);
+  VariantMatcher(const VariantMatcher &Other);
+
   /// \brief Clones the provided matcher.
-  MatcherList(const DynTypedMatcher &Matcher);
-  ~MatcherList();
+  static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher);
+
+  /// \brief Clones the provided matchers.
+  ///
+  /// They should be the result of a polymorphic matcher.
+  static VariantMatcher
+  PolymorphicMatcher(ArrayRef<const DynTypedMatcher *> Matchers);
 
-  MatcherList &operator=(const MatcherList &Other);
+  ~VariantMatcher();
 
-  /// \brief Add a matcher to this list. The matcher is cloned.
-  void add(const DynTypedMatcher &Matcher);
+  /// \brief Copy the \c VariantMatcher, by making a copy of its representation.
+  VariantMatcher &operator=(const VariantMatcher &Other);
 
-  /// \brief Empties the list.
+  /// \brief Makes the matcher the "null" matcher.
   void reset();
 
-  /// \brief Whether the list is empty.
-  bool empty() const { return List.empty(); }
+  /// \brief Whether the matcher is null.
+  bool isNull() const { return List.empty(); }
 
-  ArrayRef<const DynTypedMatcher *> matchers() const { return List; }
+  /// \brief Return a single matcher, if there is no ambiguity.
+  ///
+  /// \returns True, and set Out to the matcher, if there is only one matcher.
+  /// False, if the underlying matcher is a polymorphic matcher with
+  /// more than one representation.
+  bool getSingleMatcher(const DynTypedMatcher *&Out) const;
 
   /// \brief Determines if any of the contained matchers can be converted
   ///   to \c Matcher<T>.
@@ -65,35 +86,35 @@ public:
   /// result would be ambigous and false is returned.
   template <class T>
   bool hasTypedMatcher() const {
-    size_t Matches = 0;
-    for (size_t I = 0, E = List.size(); I != E; ++I) {
-      Matches += ast_matchers::internal::Matcher<T>::canConstructFrom(*List[I]);
-    }
-    return Matches == 1;
+    return getTypedMatcher(
+        &ast_matchers::internal::Matcher<T>::canConstructFrom) != NULL;
   }
 
   /// \brief Wrap the correct matcher as a \c Matcher<T>.
   ///
-  /// Selects the appropriate matcher from the list and returns it as a
-  /// \c Matcher<T>.
+  /// Selects the appropriate matcher from the wrapped matchers and returns it
+  /// as a \c Matcher<T>.
   /// Asserts that \c hasTypedMatcher<T>() is true.
   template <class T>
   ast_matchers::internal::Matcher<T> getTypedMatcher() const {
     assert(hasTypedMatcher<T>());
-    for (size_t I = 0, E = List.size(); I != E; ++I) {
-      if (ast_matchers::internal::Matcher<T>::canConstructFrom(*List[I]))
-        return ast_matchers::internal::Matcher<T>::constructFrom(*List[I]);
-    }
-    llvm_unreachable("!hasTypedMatcher<T>()");
+    return ast_matchers::internal::Matcher<T>::constructFrom(*getTypedMatcher(
+        &ast_matchers::internal::Matcher<T>::canConstructFrom));
   }
 
   /// \brief String representation of the type of the value.
   ///
-  /// If there are more than one matcher on the list, the string will show all
+  /// If the underlying matcher is a polymorphic one, the string will show all
   /// the types.
   std::string getTypeAsString() const;
 
 private:
+  /// \brief Returns the matcher that passes the callback.
+  ///
+  /// Returns NULL if no matcher passes the test, or if more than one do.
+  const DynTypedMatcher *
+  getTypedMatcher(bool (*CanConstructCallback)(const DynTypedMatcher &)) const;
+
   std::vector<const DynTypedMatcher *> List;
 };
 
@@ -108,7 +129,7 @@ private:
 /// Supported types:
 ///  - \c unsigned
 ///  - \c std::string
-///  - \c MatcherList (\c DynTypedMatcher / \c Matcher<T>)
+///  - \c VariantMatcher (\c DynTypedMatcher / \c Matcher<T>)
 class VariantValue {
 public:
   VariantValue() : Type(VT_Nothing) {}
@@ -120,8 +141,7 @@ public:
   /// \brief Specific constructors for each supported type.
   VariantValue(unsigned Unsigned);
   VariantValue(const std::string &String);
-  VariantValue(const DynTypedMatcher &Matcher);
-  VariantValue(const MatcherList &Matchers);
+  VariantValue(const VariantMatcher &Matchers);
 
   /// \brief Unsigned value functions.
   bool isUnsigned() const;
@@ -134,19 +154,19 @@ public:
   void setString(const std::string &String);
 
   /// \brief Matcher value functions.
-  bool isMatchers() const;
-  const MatcherList &getMatchers() const;
-  void setMatchers(const MatcherList &Matchers);
+  bool isMatcher() const;
+  const VariantMatcher &getMatcher() const;
+  void setMatcher(const VariantMatcher &Matcher);
 
   /// \brief Shortcut functions.
   template <class T>
   bool hasTypedMatcher() const {
-    return isMatchers() && getMatchers().hasTypedMatcher<T>();
+    return isMatcher() && getMatcher().hasTypedMatcher<T>();
   }
 
   template <class T>
   ast_matchers::internal::Matcher<T> getTypedMatcher() const {
-    return getMatchers().getTypedMatcher<T>();
+    return getMatcher().getTypedMatcher<T>();
   }
 
   /// \brief String representation of the type of the value.
@@ -160,14 +180,14 @@ private:
     VT_Nothing,
     VT_Unsigned,
     VT_String,
-    VT_Matchers
+    VT_Matcher
   };
 
   /// \brief All supported value types.
   union AllValues {
     unsigned Unsigned;
     std::string *String;
-    MatcherList *Matchers;
+    VariantMatcher *Matcher;
   };
 
   ValueType Type;
index 9f1cfe3443fee5f8acf162169703984546d8071e..abd5d402f1590db9263f4b4e3c187170a95a9c83 100644 (file)
@@ -26,6 +26,7 @@
 #include "clang/ASTMatchers/Dynamic/Diagnostics.h"
 #include "clang/ASTMatchers/Dynamic/VariantValue.h"
 #include "clang/Basic/LLVM.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/type_traits.h"
 
 namespace clang {
@@ -82,9 +83,9 @@ template <> struct ArgTypeTraits<unsigned> {
 class MatcherCreateCallback {
 public:
   virtual ~MatcherCreateCallback() {}
-  virtual MatcherList run(const SourceRange &NameRange,
-                          ArrayRef<ParserValue> Args,
-                          Diagnostics *Error) const = 0;
+  virtual VariantMatcher run(const SourceRange &NameRange,
+                             ArrayRef<ParserValue> Args,
+                             Diagnostics *Error) const = 0;
 };
 
 /// \brief Simple callback implementation. Marshaller and function are provided.
@@ -99,10 +100,10 @@ public:
   /// FIXME: Use void(*)() as FuncType on this interface to remove the template
   /// argument of this class. The marshaller can cast the function pointer back
   /// to the original type.
-  typedef MatcherList (*MarshallerType)(FuncType, StringRef,
-                                        const SourceRange &,
-                                        ArrayRef<ParserValue>,
-                                        Diagnostics *);
+  typedef VariantMatcher (*MarshallerType)(FuncType, StringRef,
+                                           const SourceRange &,
+                                           ArrayRef<ParserValue>,
+                                           Diagnostics *);
 
   /// \param Marshaller Function to unpack the arguments and call \c Func
   /// \param Func Matcher construct function. This is the function that
@@ -111,8 +112,8 @@ public:
                                      StringRef MatcherName)
       : Marshaller(Marshaller), Func(Func), MatcherName(MatcherName.str()) {}
 
-  MatcherList run(const SourceRange &NameRange, ArrayRef<ParserValue> Args,
-                  Diagnostics *Error) const {
+  VariantMatcher run(const SourceRange &NameRange, ArrayRef<ParserValue> Args,
+                     Diagnostics *Error) const {
     return Marshaller(Func, MatcherName, NameRange, Args, Error);
   }
 
@@ -131,16 +132,16 @@ private:
 /// object file.
 class FreeFuncMatcherCreateCallback : public MatcherCreateCallback {
 public:
-  typedef MatcherList (*RunFunc)(StringRef MatcherName,
-                                 const SourceRange &NameRange,
-                                 ArrayRef<ParserValue> Args,
-                                 Diagnostics *Error);
+  typedef VariantMatcher (*RunFunc)(StringRef MatcherName,
+                                    const SourceRange &NameRange,
+                                    ArrayRef<ParserValue> Args,
+                                    Diagnostics *Error);
 
   FreeFuncMatcherCreateCallback(RunFunc Func, StringRef MatcherName)
       : Func(Func), MatcherName(MatcherName.str()) {}
 
-  MatcherList run(const SourceRange &NameRange, ArrayRef<ParserValue> Args,
-                  Diagnostics *Error) const {
+  VariantMatcher run(const SourceRange &NameRange, ArrayRef<ParserValue> Args,
+                     Diagnostics *Error) const {
     return Func(MatcherName, NameRange, Args, Error);
   }
 
@@ -154,7 +155,7 @@ private:
   if (Args.size() != count) {                                                  \
     Error->addError(NameRange, Error->ET_RegistryWrongArgCount)                \
         << count << Args.size();                                               \
-    return MatcherList();                                                      \
+    return VariantMatcher();                                                   \
   }
 
 #define CHECK_ARG_TYPE(index, type)                                            \
@@ -162,76 +163,80 @@ private:
     Error->addError(Args[index].Range, Error->ET_RegistryWrongArgType)         \
         << (index + 1) << ArgTypeTraits<type>::asString()                      \
         << Args[index].Value.getTypeAsString();                                \
-    return MatcherList();                                                      \
+    return VariantMatcher();                                                   \
   }
 
 /// \brief Helper methods to extract and merge all possible typed matchers
 /// out of the polymorphic object.
 template <class PolyMatcher>
-static void mergePolyMatchers(const PolyMatcher &Poly, MatcherList *Out,
+static void mergePolyMatchers(const PolyMatcher &Poly,
+                              std::vector<const DynTypedMatcher *> &Out,
                               ast_matchers::internal::EmptyTypeList) {}
 
 template <class PolyMatcher, class TypeList>
-static void mergePolyMatchers(const PolyMatcher &Poly, MatcherList *Out,
+static void mergePolyMatchers(const PolyMatcher &Poly,
+                              std::vector<const DynTypedMatcher *> &Out,
                               TypeList) {
-  Out->add(ast_matchers::internal::Matcher<typename TypeList::head>(Poly));
+  Out.push_back(ast_matchers::internal::Matcher<typename TypeList::head>(Poly)
+                    .clone());
   mergePolyMatchers(Poly, Out, typename TypeList::tail());
 }
 
-/// \brief Convert the return values of the functions into a MatcherList.
+/// \brief Convert the return values of the functions into a VariantMatcher.
 ///
 /// There are 2 cases right now: The return value is a Matcher<T> or is a
-/// polymorphic matcher. For the former, we just construct the MatcherList. For
-/// the latter, we instantiate all the possible Matcher<T> of the poly matcher.
+/// polymorphic matcher. For the former, we just construct the VariantMatcher.
+/// For the latter, we instantiate all the possible Matcher<T> of the poly
+/// matcher.
 template <typename T>
-static MatcherList
-outvalueToMatcherList(const ast_matchers::internal::Matcher<T> &Matcher) {
-  return MatcherList(Matcher);
+static VariantMatcher
+outvalueToVariantMatcher(const ast_matchers::internal::Matcher<T> &Matcher) {
+  return VariantMatcher::SingleMatcher(Matcher);
 }
 
 template <typename T>
-static MatcherList
-outvalueToMatcherList(const T& PolyMatcher, typename T::ReturnTypes* = NULL) {
-  MatcherList Matchers;
-  mergePolyMatchers(PolyMatcher, &Matchers, typename T::ReturnTypes());
-  return Matchers;
+static VariantMatcher outvalueToVariantMatcher(const T &PolyMatcher,
+                                               typename T::ReturnTypes * =
+                                                   NULL) {
+  std::vector<const DynTypedMatcher *> Matchers;
+  mergePolyMatchers(PolyMatcher, Matchers, typename T::ReturnTypes());
+  VariantMatcher Out = VariantMatcher::PolymorphicMatcher(Matchers);
+  llvm::DeleteContainerPointers(Matchers);
+  return Out;
 }
 
 /// \brief 0-arg marshaller function.
 template <typename ReturnType>
-static MatcherList matcherMarshall0(ReturnType (*Func)(),
-                                    StringRef MatcherName,
-                                    const SourceRange &NameRange,
-                                    ArrayRef<ParserValue> Args,
-                                    Diagnostics *Error) {
+static VariantMatcher
+matcherMarshall0(ReturnType (*Func)(), StringRef MatcherName,
+                 const SourceRange &NameRange, ArrayRef<ParserValue> Args,
+                 Diagnostics *Error) {
   CHECK_ARG_COUNT(0);
-  return outvalueToMatcherList(Func());
+  return outvalueToVariantMatcher(Func());
 }
 
 /// \brief 1-arg marshaller function.
 template <typename ReturnType, typename ArgType1>
-static MatcherList matcherMarshall1(ReturnType (*Func)(ArgType1),
-                                    StringRef MatcherName,
-                                    const SourceRange &NameRange,
-                                    ArrayRef<ParserValue> Args,
-                                    Diagnostics *Error) {
+static VariantMatcher
+matcherMarshall1(ReturnType (*Func)(ArgType1), StringRef MatcherName,
+                 const SourceRange &NameRange, ArrayRef<ParserValue> Args,
+                 Diagnostics *Error) {
   CHECK_ARG_COUNT(1);
   CHECK_ARG_TYPE(0, ArgType1);
-  return outvalueToMatcherList(
+  return outvalueToVariantMatcher(
       Func(ArgTypeTraits<ArgType1>::get(Args[0].Value)));
 }
 
 /// \brief 2-arg marshaller function.
 template <typename ReturnType, typename ArgType1, typename ArgType2>
-static MatcherList matcherMarshall2(ReturnType (*Func)(ArgType1, ArgType2),
-                                    StringRef MatcherName,
-                                    const SourceRange &NameRange,
-                                    ArrayRef<ParserValue> Args,
-                                    Diagnostics *Error) {
+static VariantMatcher
+matcherMarshall2(ReturnType (*Func)(ArgType1, ArgType2), StringRef MatcherName,
+                 const SourceRange &NameRange, ArrayRef<ParserValue> Args,
+                 Diagnostics *Error) {
   CHECK_ARG_COUNT(2);
   CHECK_ARG_TYPE(0, ArgType1);
   CHECK_ARG_TYPE(1, ArgType2);
-  return outvalueToMatcherList(
+  return outvalueToVariantMatcher(
       Func(ArgTypeTraits<ArgType1>::get(Args[0].Value),
            ArgTypeTraits<ArgType2>::get(Args[1].Value)));
 }
@@ -242,10 +247,10 @@ static MatcherList matcherMarshall2(ReturnType (*Func)(ArgType1, ArgType2),
 /// \brief Variadic marshaller function.
 template <typename ResultT, typename ArgT,
           ResultT (*Func)(ArrayRef<const ArgT *>)>
-MatcherList variadicMatcherCreateCallback(StringRef MatcherName,
-                                          const SourceRange &NameRange,
-                                          ArrayRef<ParserValue> Args,
-                                          Diagnostics *Error) {
+VariantMatcher
+variadicMatcherCreateCallback(StringRef MatcherName,
+                              const SourceRange &NameRange,
+                              ArrayRef<ParserValue> Args, Diagnostics *Error) {
   ArgT **InnerArgs = new ArgT *[Args.size()]();
 
   bool HasError = false;
@@ -262,9 +267,9 @@ MatcherList variadicMatcherCreateCallback(StringRef MatcherName,
     InnerArgs[i] = new ArgT(ArgTraits::get(Value));
   }
 
-  MatcherList Out;
+  VariantMatcher Out;
   if (!HasError) {
-    Out = outvalueToMatcherList(
+    Out = outvalueToVariantMatcher(
         Func(ArrayRef<const ArgT *>(InnerArgs, Args.size())));
   }
 
index 54424cea7e21a9e5bfa815399916b46cb5ffe5d7..37e6c10478cc7879e686ab7b4f0e5bf75c8c995a 100644 (file)
@@ -311,9 +311,9 @@ bool Parser::parseMatcherExpressionImpl(VariantValue *Value) {
                            NameToken.Text, NameToken.Range);
   SourceRange MatcherRange = NameToken.Range;
   MatcherRange.End = EndToken.Range.End;
-  MatcherList Result = S->actOnMatcherExpression(
+  VariantMatcher Result = S->actOnMatcherExpression(
       NameToken.Text, MatcherRange, BindID, Args, Error);
-  if (Result.empty()) return false;
+  if (Result.isNull()) return false;
 
   *Value = Result;
   return true;
@@ -358,11 +358,11 @@ Parser::Parser(CodeTokenizer *Tokenizer, Sema *S,
 class RegistrySema : public Parser::Sema {
 public:
   virtual ~RegistrySema() {}
-  MatcherList actOnMatcherExpression(StringRef MatcherName,
-                                     const SourceRange &NameRange,
-                                     StringRef BindID,
-                                     ArrayRef<ParserValue> Args,
-                                     Diagnostics *Error) {
+  VariantMatcher actOnMatcherExpression(StringRef MatcherName,
+                                        const SourceRange &NameRange,
+                                        StringRef BindID,
+                                        ArrayRef<ParserValue> Args,
+                                        Diagnostics *Error) {
     if (BindID.empty()) {
       return Registry::constructMatcher(MatcherName, NameRange, Args, Error);
     } else {
@@ -402,16 +402,17 @@ DynTypedMatcher *Parser::parseMatcherExpression(StringRef Code,
   VariantValue Value;
   if (!parseExpression(Code, S, &Value, Error))
     return NULL;
-  if (!Value.isMatchers()) {
+  if (!Value.isMatcher()) {
     Error->addError(SourceRange(), Error->ET_ParserNotAMatcher);
     return NULL;
   }
-  if (Value.getMatchers().matchers().size() != 1) {
+  const DynTypedMatcher *Result;
+  if (!Value.getMatcher().getSingleMatcher(Result)) {
     Error->addError(SourceRange(), Error->ET_ParserOverloadedType)
         << Value.getTypeAsString();
     return NULL;
   }
-  return Value.getMatchers().matchers()[0]->clone();
+  return Result->clone();
 }
 
 }  // namespace dynamic
index e0c72806d9b2b1820eebe5bab33c3d0f80a527d1..47957c760b1abd627a6e6e0709526df93e013270 100644 (file)
@@ -63,25 +63,25 @@ class OverloadedMatcherCreateCallback : public MatcherCreateCallback {
       delete Overloads[i];
   }
 
-  virtual MatcherList run(const SourceRange &NameRange,
-                          ArrayRef<ParserValue> Args,
-                          Diagnostics *Error) const {
-    std::vector<MatcherList> Constructed;
+  virtual VariantMatcher run(const SourceRange &NameRange,
+                             ArrayRef<ParserValue> Args,
+                             Diagnostics *Error) const {
+    std::vector<VariantMatcher> Constructed;
     Diagnostics::OverloadContext Ctx(Error);
     for (size_t i = 0, e = Overloads.size(); i != e; ++i) {
-      MatcherList SubMatcher = Overloads[i]->run(NameRange, Args, Error);
-      if (!SubMatcher.empty()) {
+      VariantMatcher SubMatcher = Overloads[i]->run(NameRange, Args, Error);
+      if (!SubMatcher.isNull()) {
         Constructed.push_back(SubMatcher);
       }
     }
 
-    if (Constructed.empty()) return MatcherList();  // No overload matched.
+    if (Constructed.empty()) return VariantMatcher();  // No overload matched.
     // We ignore the errors if any matcher succeeded.
     Ctx.revertErrors();
     if (Constructed.size() > 1) {
       // More than one constructed. It is ambiguous.
       Error->addError(NameRange, Error->ET_RegistryAmbiguousOverload);
-      return MatcherList();
+      return VariantMatcher();
     }
     return Constructed[0];
   }
@@ -405,38 +405,38 @@ static llvm::ManagedStatic<RegistryMaps> RegistryData;
 } // anonymous namespace
 
 // static
-MatcherList Registry::constructMatcher(StringRef MatcherName,
-                                       const SourceRange &NameRange,
-                                       ArrayRef<ParserValue> Args,
-                                       Diagnostics *Error) {
+VariantMatcher Registry::constructMatcher(StringRef MatcherName,
+                                          const SourceRange &NameRange,
+                                          ArrayRef<ParserValue> Args,
+                                          Diagnostics *Error) {
   ConstructorMap::const_iterator it =
       RegistryData->constructors().find(MatcherName);
   if (it == RegistryData->constructors().end()) {
     Error->addError(NameRange, Error->ET_RegistryNotFound) << MatcherName;
-    return MatcherList();
+    return VariantMatcher();
   }
 
   return it->second->run(NameRange, Args, Error);
 }
 
 // static
-MatcherList Registry::constructBoundMatcher(StringRef MatcherName,
-                                            const SourceRange &NameRange,
-                                            StringRef BindID,
-                                            ArrayRef<ParserValue> Args,
-                                            Diagnostics *Error) {
-  MatcherList Out = constructMatcher(MatcherName, NameRange, Args, Error);
-  if (Out.empty()) return Out;
-
-  ArrayRef<const DynTypedMatcher*> Matchers = Out.matchers();
-  if (Matchers.size() == 1) {
-    OwningPtr<DynTypedMatcher> Bound(Matchers[0]->tryBind(BindID));
+VariantMatcher Registry::constructBoundMatcher(StringRef MatcherName,
+                                               const SourceRange &NameRange,
+                                               StringRef BindID,
+                                               ArrayRef<ParserValue> Args,
+                                               Diagnostics *Error) {
+  VariantMatcher Out = constructMatcher(MatcherName, NameRange, Args, Error);
+  if (Out.isNull()) return Out;
+
+  const DynTypedMatcher *Result;
+  if (Out.getSingleMatcher(Result)) {
+    OwningPtr<DynTypedMatcher> Bound(Result->tryBind(BindID));
     if (Bound) {
-      return *Bound;
+      return VariantMatcher::SingleMatcher(*Bound);
     }
   }
   Error->addError(NameRange, Error->ET_RegistryNotBindable);
-  return MatcherList();
+  return VariantMatcher();
 }
 
 }  // namespace dynamic
index 79c5c8e23a65dff1d8ab2a3a31b08aa0215ec9c2..a8fd7c6bbb9c6d2add5d68357381083d22467c95 100644 (file)
 #include "clang/ASTMatchers/Dynamic/VariantValue.h"
 
 #include "clang/Basic/LLVM.h"
+#include "llvm/ADT/STLExtras.h"
 
 namespace clang {
 namespace ast_matchers {
 namespace dynamic {
 
-MatcherList::MatcherList() : List() {}
+VariantMatcher::VariantMatcher() : List() {}
 
-MatcherList::MatcherList(const DynTypedMatcher &Matcher)
-    : List(1, Matcher.clone()) {}
-
-MatcherList::MatcherList(const MatcherList& Other) {
+VariantMatcher::VariantMatcher(const VariantMatcher& Other) {
   *this = Other;
 }
 
-MatcherList::~MatcherList() {
+VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
+  VariantMatcher Out;
+  Out.List.push_back(Matcher.clone());
+  return Out;
+}
+
+VariantMatcher
+VariantMatcher::PolymorphicMatcher(ArrayRef<const DynTypedMatcher *> Matchers) {
+  VariantMatcher Out;
+  for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
+    Out.List.push_back(Matchers[i]->clone());
+  }
+  return Out;
+}
+
+VariantMatcher::~VariantMatcher() {
   reset();
 }
 
-MatcherList &MatcherList::operator=(const MatcherList &Other) {
+VariantMatcher &VariantMatcher::operator=(const VariantMatcher &Other) {
   if (this == &Other) return *this;
   reset();
   for (size_t i = 0, e = Other.List.size(); i != e; ++i) {
@@ -42,18 +55,17 @@ MatcherList &MatcherList::operator=(const MatcherList &Other) {
   return *this;
 }
 
-void MatcherList::add(const DynTypedMatcher &Matcher) {
-  List.push_back(Matcher.clone());
+bool VariantMatcher::getSingleMatcher(const DynTypedMatcher *&Out) const {
+  if (List.size() != 1) return false;
+  Out = List[0];
+  return true;
 }
 
-void MatcherList::reset() {
-  for (size_t i = 0, e = List.size(); i != e; ++i) {
-    delete List[i];
-  }
-  List.resize(0);
+void VariantMatcher::reset() {
+  llvm::DeleteContainerPointers(List);
 }
 
-std::string MatcherList::getTypeAsString() const {
+std::string VariantMatcher::getTypeAsString() const {
   std::string Inner;
   for (size_t I = 0, E = List.size(); I != E; ++I) {
     if (I != 0) Inner += "|";
@@ -62,6 +74,18 @@ std::string MatcherList::getTypeAsString() const {
   return (Twine("Matcher<") + Inner + ">").str();
 }
 
+const DynTypedMatcher *VariantMatcher::getTypedMatcher(
+    bool (*CanConstructCallback)(const DynTypedMatcher &)) const {
+  const DynTypedMatcher *Out = NULL;
+  for (size_t i = 0, e = List.size(); i != e; ++i) {
+    if (CanConstructCallback(*List[i])) {
+      if (Out) return NULL;
+      Out = List[i];
+    }
+  }
+  return Out;
+}
+
 VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
   *this = Other;
 }
@@ -74,12 +98,8 @@ VariantValue::VariantValue(const std::string &String) : Type(VT_Nothing) {
   setString(String);
 }
 
-VariantValue::VariantValue(const DynTypedMatcher &Matcher) : Type(VT_Nothing) {
-  setMatchers(MatcherList(Matcher));
-}
-
-VariantValue::VariantValue(const MatcherList &Matchers) : Type(VT_Nothing) {
-  setMatchers(Matchers);
+VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
+  setMatcher(Matcher);
 }
 
 VariantValue::~VariantValue() { reset(); }
@@ -94,8 +114,8 @@ VariantValue &VariantValue::operator=(const VariantValue &Other) {
   case VT_String:
     setString(Other.getString());
     break;
-  case VT_Matchers:
-    setMatchers(Other.getMatchers());
+  case VT_Matcher:
+    setMatcher(Other.getMatcher());
     break;
   case VT_Nothing:
     Type = VT_Nothing;
@@ -109,8 +129,8 @@ void VariantValue::reset() {
   case VT_String:
     delete Value.String;
     break;
-  case VT_Matchers:
-    delete Value.Matchers;
+  case VT_Matcher:
+    delete Value.Matcher;
     break;
   // Cases that do nothing.
   case VT_Unsigned:
@@ -150,25 +170,25 @@ void VariantValue::setString(const std::string &NewValue) {
   Value.String = new std::string(NewValue);
 }
 
-bool VariantValue::isMatchers() const {
-  return Type == VT_Matchers;
+bool VariantValue::isMatcher() const {
+  return Type == VT_Matcher;
 }
 
-const MatcherList &VariantValue::getMatchers() const {
-  assert(isMatchers());
-  return *Value.Matchers;
+const VariantMatcher &VariantValue::getMatcher() const {
+  assert(isMatcher());
+  return *Value.Matcher;
 }
 
-void VariantValue::setMatchers(const MatcherList &NewValue) {
+void VariantValue::setMatcher(const VariantMatcher &NewValue) {
   reset();
-  Type = VT_Matchers;
-  Value.Matchers = new MatcherList(NewValue);
+  Type = VT_Matcher;
+  Value.Matcher = new VariantMatcher(NewValue);
 }
 
 std::string VariantValue::getTypeAsString() const {
   switch (Type) {
   case VT_String: return "String";
-  case VT_Matchers: return getMatchers().getTypeAsString();
+  case VT_Matcher: return getMatcher().getTypeAsString();
   case VT_Unsigned: return "Unsigned";
   case VT_Nothing: return "Nothing";
   }
index d9b2d3c87f49685bd1bee249e505598360953f11..71b0f87e027698fce7768e09fe2c99f0a9022abf 100644 (file)
@@ -76,16 +76,16 @@ public:
     Errors.push_back(Error.toStringFull());
   }
 
-  MatcherList actOnMatcherExpression(StringRef MatcherName,
-                                     const SourceRange &NameRange,
-                                     StringRef BindID,
-                                     ArrayRef<ParserValue> Args,
-                                     Diagnostics *Error) {
+  VariantMatcher actOnMatcherExpression(StringRef MatcherName,
+                                        const SourceRange &NameRange,
+                                        StringRef BindID,
+                                        ArrayRef<ParserValue> Args,
+                                        Diagnostics *Error) {
     MatcherInfo ToStore = { MatcherName, NameRange, Args, BindID };
     Matchers.push_back(ToStore);
     DummyDynTypedMatcher Matcher(ExpectedMatchers[MatcherName]);
     OwningPtr<DynTypedMatcher> Out(Matcher.tryBind(BindID));
-    return *Out;
+    return VariantMatcher::SingleMatcher(*Out);
   }
 
   struct MatcherInfo {
@@ -137,6 +137,12 @@ bool matchesRange(const SourceRange &Range, unsigned StartLine,
          Range.Start.Column == StartColumn && Range.End.Column == EndColumn;
 }
 
+const DynTypedMatcher *getSingleMatcher(const VariantValue &value) {
+  const DynTypedMatcher *Out;
+  EXPECT_TRUE(value.getMatcher().getSingleMatcher(Out));
+  return Out;
+}
+
 TEST(ParserTest, ParseMatcher) {
   MockSema Sema;
   const uint64_t ExpectedFoo = Sema.expectMatcher("Foo");
@@ -148,9 +154,9 @@ TEST(ParserTest, ParseMatcher) {
   }
 
   EXPECT_EQ(1ULL, Sema.Values.size());
-  EXPECT_EQ(ExpectedFoo, Sema.Values[0].getMatchers().matchers()[0]->getID());
+  EXPECT_EQ(ExpectedFoo, getSingleMatcher(Sema.Values[0])->getID());
   EXPECT_EQ("Yo!", static_cast<const DummyDynTypedMatcher *>(
-                       Sema.Values[0].getMatchers().matchers()[0])->boundID());
+                       getSingleMatcher(Sema.Values[0]))->boundID());
 
   EXPECT_EQ(3ULL, Sema.Matchers.size());
   const MockSema::MatcherInfo Bar = Sema.Matchers[0];
@@ -169,10 +175,8 @@ TEST(ParserTest, ParseMatcher) {
   EXPECT_EQ("Foo", Foo.MatcherName);
   EXPECT_TRUE(matchesRange(Foo.NameRange, 1, 2, 2, 12));
   EXPECT_EQ(2ULL, Foo.Args.size());
-  EXPECT_EQ(ExpectedBar,
-            Foo.Args[0].Value.getMatchers().matchers()[0]->getID());
-  EXPECT_EQ(ExpectedBaz,
-            Foo.Args[1].Value.getMatchers().matchers()[0]->getID());
+  EXPECT_EQ(ExpectedBar, getSingleMatcher(Foo.Args[0].Value)->getID());
+  EXPECT_EQ(ExpectedBaz, getSingleMatcher(Foo.Args[1].Value)->getID());
   EXPECT_EQ("Yo!", Foo.BoundID);
 }
 
index 7f49b6a4ac7b8fd73af7f7a83fb396c41ec99b0c..55490a5bab9eaae94f1aeb1d49e7f4a48af7b222 100644 (file)
@@ -36,32 +36,34 @@ public:
     return Out;
   }
 
-  MatcherList constructMatcher(StringRef MatcherName,
-                               Diagnostics *Error = NULL) {
+  VariantMatcher constructMatcher(StringRef MatcherName,
+                                  Diagnostics *Error = NULL) {
     Diagnostics DummyError;
     if (!Error) Error = &DummyError;
-    const MatcherList Out =
+    const VariantMatcher Out =
         Registry::constructMatcher(MatcherName, SourceRange(), Args(), Error);
     EXPECT_EQ("", DummyError.toStringFull());
     return Out;
   }
 
-  MatcherList constructMatcher(StringRef MatcherName, const VariantValue &Arg1,
-                               Diagnostics *Error = NULL) {
+  VariantMatcher constructMatcher(StringRef MatcherName,
+                                  const VariantValue &Arg1,
+                                  Diagnostics *Error = NULL) {
     Diagnostics DummyError;
     if (!Error) Error = &DummyError;
-    const MatcherList Out = Registry::constructMatcher(
+    const VariantMatcher Out = Registry::constructMatcher(
         MatcherName, SourceRange(), Args(Arg1), Error);
     EXPECT_EQ("", DummyError.toStringFull());
     return Out;
   }
 
-  MatcherList constructMatcher(StringRef MatcherName, const VariantValue &Arg1,
-                               const VariantValue &Arg2,
-                               Diagnostics *Error = NULL) {
+  VariantMatcher constructMatcher(StringRef MatcherName,
+                                  const VariantValue &Arg1,
+                                  const VariantValue &Arg2,
+                                  Diagnostics *Error = NULL) {
     Diagnostics DummyError;
     if (!Error) Error = &DummyError;
-    const MatcherList Out = Registry::constructMatcher(
+    const VariantMatcher Out = Registry::constructMatcher(
         MatcherName, SourceRange(), Args(Arg1, Arg2), Error);
     EXPECT_EQ("", DummyError.toStringFull());
     return Out;
@@ -99,11 +101,12 @@ TEST_F(RegistryTest, ConstructWithSimpleArgs) {
 }
 
 TEST_F(RegistryTest, ConstructWithMatcherArgs) {
-  Matcher<Decl> HasInitializerSimple =
-      constructMatcher("varDecl", constructMatcher("hasInitializer", stmt()))
-          .getTypedMatcher<Decl>();
+  Matcher<Decl> HasInitializerSimple = constructMatcher(
+      "varDecl", constructMatcher("hasInitializer", constructMatcher("stmt")))
+      .getTypedMatcher<Decl>();
   Matcher<Decl> HasInitializerComplex = constructMatcher(
-      "varDecl", constructMatcher("hasInitializer", callExpr()))
+      "varDecl",
+      constructMatcher("hasInitializer", constructMatcher("callExpr")))
       .getTypedMatcher<Decl>();
 
   std::string code = "int i;";
@@ -118,8 +121,10 @@ TEST_F(RegistryTest, ConstructWithMatcherArgs) {
   EXPECT_TRUE(matches(code, HasInitializerSimple));
   EXPECT_TRUE(matches(code, HasInitializerComplex));
 
-  Matcher<Decl> HasParameter = functionDecl(constructMatcher(
-      "hasParameter", 1, hasName("x")).getTypedMatcher<FunctionDecl>());
+  Matcher<Decl> HasParameter =
+      functionDecl(constructMatcher(
+          "hasParameter", 1, constructMatcher("hasName", std::string("x")))
+                       .getTypedMatcher<FunctionDecl>());
   EXPECT_TRUE(matches("void f(int a, int x);", HasParameter));
   EXPECT_FALSE(matches("void f(int x, int a);", HasParameter));
 }
@@ -149,7 +154,7 @@ TEST_F(RegistryTest, OverloadedMatchers) {
 }
 
 TEST_F(RegistryTest, PolymorphicMatchers) {
-  const MatcherList IsDefinition = constructMatcher("isDefinition");
+  const VariantMatcher IsDefinition = constructMatcher("isDefinition");
   Matcher<Decl> Var =
       constructMatcher("varDecl", IsDefinition).getTypedMatcher<Decl>();
   Matcher<Decl> Class =
@@ -165,7 +170,8 @@ TEST_F(RegistryTest, PolymorphicMatchers) {
 
   Matcher<Decl> Anything = constructMatcher("anything").getTypedMatcher<Decl>();
   Matcher<Decl> RecordDecl =
-      constructMatcher("recordDecl", Anything).getTypedMatcher<Decl>();
+      constructMatcher("recordDecl", VariantMatcher::SingleMatcher(Anything))
+          .getTypedMatcher<Decl>();
 
   EXPECT_TRUE(matches("int a;", Anything));
   EXPECT_TRUE(matches("class A {};", Anything));
@@ -214,8 +220,10 @@ TEST_F(RegistryTest, TypeTraversal) {
 TEST_F(RegistryTest, CXXCtorInitializer) {
   Matcher<Decl> CtorDecl = constructMatcher(
       "constructorDecl",
-      constructMatcher("hasAnyConstructorInitializer",
-                       constructMatcher("forField", hasName("foo"))))
+      constructMatcher(
+          "hasAnyConstructorInitializer",
+          constructMatcher("forField",
+                           constructMatcher("hasName", std::string("foo")))))
       .getTypedMatcher<Decl>();
   EXPECT_TRUE(matches("struct Foo { Foo() : foo(1) {} int foo; };", CtorDecl));
   EXPECT_FALSE(matches("struct Foo { Foo() {} int foo; };", CtorDecl));
@@ -256,23 +264,24 @@ TEST_F(RegistryTest, Adaptative) {
 TEST_F(RegistryTest, Errors) {
   // Incorrect argument count.
   OwningPtr<Diagnostics> Error(new Diagnostics());
-  EXPECT_TRUE(constructMatcher("hasInitializer", Error.get()).empty());
+  EXPECT_TRUE(constructMatcher("hasInitializer", Error.get()).isNull());
   EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)",
             Error->toString());
   Error.reset(new Diagnostics());
-  EXPECT_TRUE(constructMatcher("isArrow", std::string(), Error.get()).empty());
+  EXPECT_TRUE(constructMatcher("isArrow", std::string(), Error.get()).isNull());
   EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)",
             Error->toString());
 
   // Bad argument type
   Error.reset(new Diagnostics());
-  EXPECT_TRUE(constructMatcher("ofClass", std::string(), Error.get()).empty());
+  EXPECT_TRUE(constructMatcher("ofClass", std::string(), Error.get()).isNull());
   EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != "
             "(Actual = String)",
             Error->toString());
   Error.reset(new Diagnostics());
-  EXPECT_TRUE(constructMatcher("recordDecl", recordDecl(), parameterCountIs(3),
-                               Error.get()).empty());
+  EXPECT_TRUE(constructMatcher("recordDecl", constructMatcher("recordDecl"),
+                               constructMatcher("parameterCountIs", 3),
+                               Error.get()).isNull());
   EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != "
             "(Actual = Matcher<FunctionDecl>)",
             Error->toString());
index 625f70bd4655ac8e15766c0de1b1d80aa3d53ef8..168741ca4d9d4f0f39ea030279fb9cbd72553447 100644 (file)
@@ -27,7 +27,7 @@ TEST(VariantValueTest, Unsigned) {
   EXPECT_EQ(kUnsigned, Value.getUnsigned());
 
   EXPECT_FALSE(Value.isString());
-  EXPECT_FALSE(Value.isMatchers());
+  EXPECT_FALSE(Value.isMatcher());
   EXPECT_FALSE(Value.hasTypedMatcher<Decl>());
   EXPECT_FALSE(Value.hasTypedMatcher<UnaryOperator>());
 }
@@ -41,29 +41,29 @@ TEST(VariantValueTest, String) {
   EXPECT_EQ("String", Value.getTypeAsString());
 
   EXPECT_FALSE(Value.isUnsigned());
-  EXPECT_FALSE(Value.isMatchers());
+  EXPECT_FALSE(Value.isMatcher());
 }
 
 TEST(VariantValueTest, DynTypedMatcher) {
-  VariantValue Value = stmt();
+  VariantValue Value = VariantMatcher::SingleMatcher(stmt());
 
   EXPECT_FALSE(Value.isUnsigned());
   EXPECT_FALSE(Value.isString());
 
-  EXPECT_TRUE(Value.isMatchers());
+  EXPECT_TRUE(Value.isMatcher());
   EXPECT_FALSE(Value.hasTypedMatcher<Decl>());
   EXPECT_TRUE(Value.hasTypedMatcher<UnaryOperator>());
   EXPECT_EQ("Matcher<Stmt>", Value.getTypeAsString());
 
   // Can only convert to compatible matchers.
-  Value = recordDecl();
-  EXPECT_TRUE(Value.isMatchers());
+  Value = VariantMatcher::SingleMatcher(recordDecl());
+  EXPECT_TRUE(Value.isMatcher());
   EXPECT_TRUE(Value.hasTypedMatcher<Decl>());
   EXPECT_FALSE(Value.hasTypedMatcher<UnaryOperator>());
   EXPECT_EQ("Matcher<Decl>", Value.getTypeAsString());
 
-  Value = ignoringImpCasts(expr());
-  EXPECT_TRUE(Value.isMatchers());
+  Value = VariantMatcher::SingleMatcher(ignoringImpCasts(expr()));
+  EXPECT_TRUE(Value.isMatcher());
   EXPECT_FALSE(Value.hasTypedMatcher<Decl>());
   EXPECT_FALSE(Value.hasTypedMatcher<Stmt>());
   EXPECT_TRUE(Value.hasTypedMatcher<Expr>());
@@ -77,13 +77,13 @@ TEST(VariantValueTest, Assignment) {
   EXPECT_TRUE(Value.isString());
   EXPECT_EQ("A", Value.getString());
   EXPECT_FALSE(Value.isUnsigned());
-  EXPECT_FALSE(Value.isMatchers());
+  EXPECT_FALSE(Value.isMatcher());
   EXPECT_EQ("String", Value.getTypeAsString());
 
-  Value = recordDecl();
+  Value = VariantMatcher::SingleMatcher(recordDecl());
   EXPECT_FALSE(Value.isUnsigned());
   EXPECT_FALSE(Value.isString());
-  EXPECT_TRUE(Value.isMatchers());
+  EXPECT_TRUE(Value.isMatcher());
   EXPECT_TRUE(Value.hasTypedMatcher<Decl>());
   EXPECT_FALSE(Value.hasTypedMatcher<UnaryOperator>());
   EXPECT_EQ("Matcher<Decl>", Value.getTypeAsString());
@@ -91,39 +91,46 @@ TEST(VariantValueTest, Assignment) {
   Value = 17;
   EXPECT_TRUE(Value.isUnsigned());
   EXPECT_EQ(17U, Value.getUnsigned());
-  EXPECT_FALSE(Value.isMatchers());
+  EXPECT_FALSE(Value.isMatcher());
   EXPECT_FALSE(Value.isString());
 
   Value = VariantValue();
   EXPECT_FALSE(Value.isUnsigned());
   EXPECT_FALSE(Value.isString());
-  EXPECT_FALSE(Value.isMatchers());
+  EXPECT_FALSE(Value.isMatcher());
   EXPECT_EQ("Nothing", Value.getTypeAsString());
 }
 
 TEST(VariantValueTest, Matcher) {
-  EXPECT_TRUE(matches("class X {};", VariantValue(recordDecl(hasName("X")))
+  EXPECT_TRUE(matches("class X {};", VariantValue(VariantMatcher::SingleMatcher(
+                                                      recordDecl(hasName("X"))))
                                          .getTypedMatcher<Decl>()));
+  EXPECT_TRUE(matches("int x;",
+                      VariantValue(VariantMatcher::SingleMatcher(varDecl()))
+                          .getTypedMatcher<Decl>()));
   EXPECT_TRUE(
-      matches("int x;", VariantValue(varDecl()).getTypedMatcher<Decl>()));
-  EXPECT_TRUE(matches("int foo() { return 1 + 1; }",
-                      VariantValue(functionDecl()).getTypedMatcher<Decl>()));
+      matches("int foo() { return 1 + 1; }",
+              VariantValue(VariantMatcher::SingleMatcher(functionDecl()))
+                  .getTypedMatcher<Decl>()));
   // Can't get the wrong matcher.
-  EXPECT_FALSE(VariantValue(varDecl()).hasTypedMatcher<Stmt>());
+  EXPECT_FALSE(VariantValue(VariantMatcher::SingleMatcher(varDecl()))
+                   .hasTypedMatcher<Stmt>());
 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST && !defined(_MSC_VER)
   // Trying to get the wrong matcher fails an assertion in Matcher<T>.  We don't
   // do this test when building with MSVC because its debug C runtime prints the
   // assertion failure message as a wide string, which gtest doesn't understand.
-  EXPECT_DEATH(VariantValue(varDecl()).getTypedMatcher<Stmt>(),
+  EXPECT_DEATH(VariantValue(VariantMatcher::SingleMatcher(varDecl()))
+                   .getTypedMatcher<Stmt>(),
                "hasTypedMatcher");
 #endif
 
-  EXPECT_FALSE(
-      matches("int x;", VariantValue(functionDecl()).getTypedMatcher<Decl>()));
+  EXPECT_FALSE(matches(
+      "int x;", VariantValue(VariantMatcher::SingleMatcher(functionDecl()))
+                    .getTypedMatcher<Decl>()));
   EXPECT_FALSE(
       matches("int foo() { return 1 + 1; }",
-
-              VariantValue(declRefExpr()).getTypedMatcher<Stmt>()));
+              VariantValue(VariantMatcher::SingleMatcher(declRefExpr()))
+                  .getTypedMatcher<Stmt>()));
 }
 
 } // end anonymous namespace