Provide better error messages for incorrect matchers.

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
This commit is contained in:
Daniel Jasper 2012-09-20 09:24:58 +00:00
Родитель 2d9cc1367a
Коммит b3278162bd
1 изменённых файлов: 17 добавлений и 15 удалений

Просмотреть файл

@ -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;