diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html index 930b922cdd175a1998a0d083760b33f91eed604f..4f85395c0ac2808b39afeba62527c244d0cc499f 100644 --- a/docs/LibASTMatchersReference.html +++ b/docs/LibASTMatchersReference.html @@ -1979,12 +1979,16 @@ Usable as: Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockP </pre></td></tr> -<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>></td><td class="name" onclick="toggle('hasDeclaration1')"><a name="hasDeclaration1Anchor">hasDeclaration</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="hasDeclaration1"><pre>Matches a type if the declaration of the type matches the given +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>></td><td class="name" onclick="toggle('hasDeclaration2')"><a name="hasDeclaration2Anchor">hasDeclaration</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasDeclaration2"><pre>Matches a type if the declaration of the type matches the given matcher. +In addition to being usable as Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>>, also usable as +Matcher<T> for any T supporting the getDecl() member function. e.g. various +subtypes of clang::Type. + Usable as: Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>>, - Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>> + Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>> </pre></td></tr> @@ -2130,12 +2134,16 @@ Example matches y in x(y) </pre></td></tr> -<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>></td><td class="name" onclick="toggle('hasDeclaration2')"><a name="hasDeclaration2Anchor">hasDeclaration</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="hasDeclaration2"><pre>Matches a type if the declaration of the type matches the given +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>></td><td class="name" onclick="toggle('hasDeclaration3')"><a name="hasDeclaration3Anchor">hasDeclaration</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasDeclaration3"><pre>Matches a type if the declaration of the type matches the given matcher. +In addition to being usable as Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>>, also usable as +Matcher<T> for any T supporting the getDecl() member function. e.g. various +subtypes of clang::Type. + Usable as: Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>>, - Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>> + Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>> </pre></td></tr> @@ -2523,12 +2531,16 @@ FIXME: Unit test this matcher </pre></td></tr> -<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>></td><td class="name" onclick="toggle('hasDeclaration0')"><a name="hasDeclaration0Anchor">hasDeclaration</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="hasDeclaration0"><pre>Matches a type if the declaration of the type matches the given +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>></td><td class="name" onclick="toggle('hasDeclaration1')"><a name="hasDeclaration1Anchor">hasDeclaration</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasDeclaration1"><pre>Matches a type if the declaration of the type matches the given matcher. +In addition to being usable as Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>>, also usable as +Matcher<T> for any T supporting the getDecl() member function. e.g. various +subtypes of clang::Type. + Usable as: Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>>, - Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>> + Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>> </pre></td></tr> @@ -2689,12 +2701,16 @@ Usable as: Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockP </pre></td></tr> -<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>></td><td class="name" onclick="toggle('hasDeclaration3')"><a name="hasDeclaration3Anchor">hasDeclaration</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="hasDeclaration3"><pre>Matches a type if the declaration of the type matches the given +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>></td><td class="name" onclick="toggle('hasDeclaration4')"><a name="hasDeclaration4Anchor">hasDeclaration</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasDeclaration4"><pre>Matches a type if the declaration of the type matches the given matcher. +In addition to being usable as Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>>, also usable as +Matcher<T> for any T supporting the getDecl() member function. e.g. various +subtypes of clang::Type. + Usable as: Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>>, - Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>> + Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>> </pre></td></tr> @@ -2785,9 +2801,16 @@ QualType-matcher matches. </pre></td></tr> -<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>></td><td class="name" onclick="toggle('hasDecl0')"><a name="hasDecl0Anchor">hasDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefNameDecl.html">TypedefNameDecl</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="hasDecl0"><pre>Matches TypedefTypes referring to a specific -TypedefNameDecl. +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>></td><td class="name" onclick="toggle('hasDeclaration0')"><a name="hasDeclaration0Anchor">hasDeclaration</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasDeclaration0"><pre>Matches a type if the declaration of the type matches the given +matcher. + +In addition to being usable as Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>>, also usable as +Matcher<T> for any T supporting the getDecl() member function. e.g. various +subtypes of clang::Type. + +Usable as: Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>>, + Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>> </pre></td></tr> diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index fe2c14f58bf701db7c106da6587df6ffe673a741..de9919aaf0da2df994300d3198df75a50b9197d2 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -1561,8 +1561,12 @@ unless(const M &InnerMatcher) { /// \brief Matches a type if the declaration of the type matches the given /// matcher. /// +/// In addition to being usable as Matcher<TypedefType>, also usable as +/// Matcher<T> for any T supporting the getDecl() member function. e.g. various +/// subtypes of clang::Type. +/// /// Usable as: Matcher<QualType>, Matcher<CallExpr>, Matcher<CXXConstructExpr>, -/// Matcher<MemberExpr> +/// Matcher<MemberExpr>, Matcher<TypedefType> inline internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher, internal::Matcher<Decl> > hasDeclaration(const internal::Matcher<Decl> &InnerMatcher) { @@ -2846,13 +2850,6 @@ AST_TYPELOC_TRAVERSE_MATCHER(pointee, getPointee); /// matches "typedef int X" AST_TYPE_MATCHER(TypedefType, typedefType); -/// \brief Matches \c TypedefTypes referring to a specific -/// \c TypedefNameDecl. -AST_MATCHER_P(TypedefType, hasDecl, - internal::Matcher<TypedefNameDecl>, InnerMatcher) { - return InnerMatcher.matches(*Node.getDecl(), Finder, Builder); -} - /// \brief Matches nested name specifiers. /// /// Given diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h index b41a74ce8378150f27393f435bc7b84b55aa1784..cc4edacf42d8538e39b90ba74e5d4500d6c7a0fa 100644 --- a/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -353,6 +353,18 @@ 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 { + typedef char yes[1]; + typedef char no[2]; + + template <typename TestType> + static yes &test(char[sizeof(&TestType::getDecl)]); + template <typename> static no &test(...); + + static bool const value = sizeof(test<T>(0)) == sizeof(yes); +}; + /// \brief Matches declarations for QualType and CallExpr. /// /// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but @@ -373,6 +385,15 @@ public: } 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, + 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, diff --git a/unittests/ASTMatchers/ASTMatchersTest.cpp b/unittests/ASTMatchers/ASTMatchersTest.cpp index 608e7479a6b166e6b5f3a2d38807a347d7f92b2d..8e4f3e93274820d6c6c8c6382b01d79ded5e532d 100644 --- a/unittests/ASTMatchers/ASTMatchersTest.cpp +++ b/unittests/ASTMatchers/ASTMatchersTest.cpp @@ -818,6 +818,14 @@ TEST(HasDeclaration, HasDeclarationOfEnumType) { qualType(hasDeclaration(enumDecl(hasName("X"))))))))); } +TEST(HasDeclaration, HasDeclarationOfTypeWithDecl) { + EXPECT_TRUE(matches("typedef int X; X a;", + varDecl(hasName("a"), + hasType(typedefType(hasDeclaration(decl())))))); + + // FIXME: Add tests for other types with getDecl() (e.g. RecordType) +} + TEST(HasType, TakesQualTypeMatcherAndMatchesExpr) { TypeMatcher ClassX = hasDeclaration(recordDecl(hasName("X"))); EXPECT_TRUE( @@ -3350,10 +3358,6 @@ TEST(TypeMatching, MatchesPointersToConstTypes) { TEST(TypeMatching, MatchesTypedefTypes) { EXPECT_TRUE(matches("typedef int X; X a;", varDecl(hasName("a"), hasType(typedefType())))); - - EXPECT_TRUE(matches("typedef int X; X a;", - varDecl(hasName("a"), - hasType(typedefType(hasDecl(decl())))))); } TEST(NNS, MatchesNestedNameSpecifiers) {