aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdwin Vane <edwin.vane@intel.com>2013-02-25 14:32:42 +0000
committerEdwin Vane <edwin.vane@intel.com>2013-02-25 14:32:42 +0000
commitb45083d08377a8b9528401fdafd7210e78895dbe (patch)
tree676d53c5fb9180d0d480c839175f46458bc3c40b
parent1b354b868c1aa227619d81e299fe6e384e1999b7 (diff)
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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@176024 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/ASTMatchers/ASTMatchersInternal.h22
-rw-r--r--unittests/ASTMatchers/ASTMatchersTest.cpp6
2 files changed, 26 insertions, 2 deletions
diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h
index e18e325942..ac85f50107 100644
--- a/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -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);
}
diff --git a/unittests/ASTMatchers/ASTMatchersTest.cpp b/unittests/ASTMatchers/ASTMatchersTest.cpp
index 63017473f4..a759df9070 100644
--- a/unittests/ASTMatchers/ASTMatchersTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersTest.cpp
@@ -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"),