diff options
author | Edwin Vane <edwin.vane@intel.com> | 2013-02-25 13:59:06 +0000 |
---|---|---|
committer | Edwin Vane <edwin.vane@intel.com> | 2013-02-25 13:59:06 +0000 |
commit | 0b6f23a23c55b7024e7a0edca1fecf9bd4c380a1 (patch) | |
tree | 7e8f866688772164283d3960c1746856d1f8cb7a | |
parent | c7093d96d1fac7f34acd2b63bca4ea39acb5cad5 (diff) |
Support in hasDeclaration for types with getDecl()
Re-introducing r175532. The has_getDecl metafunction didn't compile with Visual
Studio. This revision 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@176019 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/ASTMatchers/ASTMatchersInternal.h | 32 | ||||
-rw-r--r-- | unittests/ASTMatchers/ASTMatchersTest.cpp | 6 |
2 files changed, 36 insertions, 2 deletions
diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h index e18e325942..cdbde76247 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,11 +393,13 @@ 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); } + /// \brief Extracts the CXXRecordDecl or EnumDecl of a QualType and returns /// whether the inner matcher matches on it. bool matchesSpecialized(const QualType &Node, ASTMatchFinder *Finder, @@ -393,6 +412,15 @@ private: return matchesDecl(Node->getAsCXXRecordDecl(), Finder, Builder); } + /// \brief Gets the TemplateDecl from a TemplateSpecializationType + /// and returns whether the inner matches on it. + bool matchesSpecialized(const TemplateSpecializationType &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return matchesDecl(Node.getTemplateName().getAsTemplateDecl(), + Finder, Buidler); + } + /// \brief Extracts the Decl of the callee of a CallExpr and returns whether /// the inner matcher matches on it. bool matchesSpecialized(const CallExpr &Node, ASTMatchFinder *Finder, 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"), |