]> granicus.if.org Git - clang/commitdiff
Provide better error messages for incorrect matchers.
authorDaniel Jasper <djasper@google.com>
Thu, 20 Sep 2012 09:24:58 +0000 (09:24 +0000)
committerDaniel Jasper <djasper@google.com>
Thu, 20 Sep 2012 09:24:58 +0000 (09:24 +0000)
By changing the conversion operator into a conversion constructor, we
can enabled based on the template parameters leading to better error
messages. E.g.: stmt(decl()) will now create an error message including:

  note: candidate function not viable: no known conversion from
  'clang::ast_matchers::internal::BindableMatcher<clang::Decl>' to 'const
  clang::ast_matchers::internal::Matcher<clang::Stmt>' for 1st argument

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@164298 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/ASTMatchers/ASTMatchersInternal.h

index 38ffb2de75731c836bd750ebb5660b86d1d8d09e..41b56418dece147ba16bd1f0537f5d1636dc3a57 100644 (file)
@@ -257,6 +257,16 @@ public:
   explicit Matcher(MatcherInterface<T> *Implementation)
       : Implementation(Implementation) {}
 
+  /// \brief Implicitly converts \c Other to a Matcher<T>.
+  ///
+  /// Requires \c T to be derived from \c From.
+  template <typename From>
+  Matcher(const Matcher<From> &Other,
+          typename llvm::enable_if_c<
+            llvm::is_base_of<From, T>::value &&
+            !llvm::is_same<From, T>::value >::type* = 0)
+      : Implementation(new ImplicitCastMatcher<From>(Other)) {}
+
   /// \brief Forwards the call to the underlying MatcherInterface<T> pointer.
   bool matches(const T &Node,
                ASTMatchFinder *Finder,
@@ -264,14 +274,6 @@ public:
     return Implementation->matches(Node, Finder, Builder);
   }
 
-  /// \brief Implicitly converts this object to a Matcher<Derived>.
-  ///
-  /// Requires Derived to be derived from T.
-  template <typename Derived>
-  operator Matcher<Derived>() const {
-    return Matcher<Derived>(new ImplicitCastMatcher<Derived>(*this));
-  }
-
   /// \brief Returns an ID that uniquely identifies the matcher.
   uint64_t getID() const {
     /// FIXME: Document the requirements this imposes on matcher
@@ -289,22 +291,22 @@ public:
   }
 
 private:
-  /// \brief Allows conversion from Matcher<T> to Matcher<Derived> if Derived
-  /// is derived from T.
-  template <typename Derived>
-  class ImplicitCastMatcher : public MatcherInterface<Derived> {
+  /// \brief Allows conversion from Matcher<Base> to Matcher<T> if T
+  /// is derived from Base.
+  template <typename Base>
+  class ImplicitCastMatcher : public MatcherInterface<T> {
   public:
-    explicit ImplicitCastMatcher(const Matcher<T> &From)
+    explicit ImplicitCastMatcher(const Matcher<Base> &From)
         : From(From) {}
 
-    virtual bool matches(const Derived &Node,
+    virtual bool matches(const T &Node,
                          ASTMatchFinder *Finder,
                          BoundNodesTreeBuilder *Builder) const {
       return From.matches(Node, Finder, Builder);
     }
 
   private:
-    const Matcher<T> From;
+    const Matcher<Base> From;
   };
 
   llvm::IntrusiveRefCntPtr< MatcherInterface<T> > Implementation;