Support in hasDeclaration for types with getDecl()

Re-introducing r175532. The has_getDecl metafunction didn't compile with
Visual Studio. This revision uses approaches has_getDecl from a
different angle that isn't a problem for Visual Studio.

Added dedicated tests for the metafunction.

Reviewers: klimek
llvm-svn: 176024
This commit is contained in:
Edwin Vane 2013-02-25 14:32:42 +00:00
parent 121dbf8846
commit ed93645739
2 changed files with 26 additions and 2 deletions

View File

@ -353,6 +353,23 @@ inline Matcher<T> makeMatcher(MatcherInterface<T> *Implementation) {
return Matcher<T>(Implementation);
}
/// \brief Metafunction to determine if type T has a member called getDecl.
template <typename T> struct has_getDecl {
struct Default { int getDecl; };
struct Derived : T, Default { };
template<typename C, C> struct CheckT;
// If T::getDecl exists, an ambiguity arises and CheckT will
// not be instantiable. This makes f(...) the only available
// overload.
template<typename C>
static char (&f(CheckT<int Default::*, &C::getDecl>*))[1];
template<typename C> static char (&f(...))[2];
static bool const value = sizeof(f<Derived>(0)) == 2;
};
/// \brief Matches declarations for QualType and CallExpr.
///
/// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but
@ -376,8 +393,9 @@ private:
/// \brief If getDecl exists as a member of U, returns whether the inner
/// matcher matches Node.getDecl().
template <typename U>
bool matchesSpecialized(const U &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const {
bool matchesSpecialized(
const U &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
typename llvm::enable_if<has_getDecl<U>, int>::type = 0) const {
return matchesDecl(Node.getDecl(), Finder, Builder);
}

View File

@ -818,6 +818,12 @@ TEST(HasDeclaration, HasDeclarationOfEnumType) {
qualType(hasDeclaration(enumDecl(hasName("X")))))))));
}
TEST(HasDeclaration, HasGetDeclTraitTest) {
EXPECT_TRUE(internal::has_getDecl<TypedefType>::value);
EXPECT_TRUE(internal::has_getDecl<RecordType>::value);
EXPECT_FALSE(internal::has_getDecl<TemplateSpecializationType>::value);
}
TEST(HasDeclaration, HasDeclarationOfTypeWithDecl) {
EXPECT_TRUE(matches("typedef int X; X a;",
varDecl(hasName("a"),