Author: mboehme Date: Tue Aug 9 10:07:52 2016 New Revision: 278123 URL: http://llvm.org/viewvc/llvm-project?rev=278123&view=rev Log: [ASTMatchers] Add matchers canReferToDecl() and hasUnderlyingDecl()
Summary: Required for D22220 Reviewers: sbenza, klimek, aaron.ballman, alexfh Subscribers: alexfh, klimek, cfe-commits Differential Revision: https://reviews.llvm.org/D23004 Modified: cfe/trunk/docs/LibASTMatchersReference.html cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp Modified: cfe/trunk/docs/LibASTMatchersReference.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LibASTMatchersReference.html?rev=278123&r1=278122&r2=278123&view=diff ============================================================================== --- cfe/trunk/docs/LibASTMatchersReference.html (original) +++ cfe/trunk/docs/LibASTMatchersReference.html Tue Aug 9 10:07:52 2016 @@ -4970,6 +4970,19 @@ Usable as: Matcher<<a href="http://cl </pre></td></tr> +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>></td><td class="name" onclick="toggle('hasUnderlyingDecl0')"><a name="hasUnderlyingDecl0Anchor">hasUnderlyingDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasUnderlyingDecl0"><pre>Matches a NamedDecl whose underlying declaration matches the given +matcher. + +Given + namespace N { template<class T> void f(T t); } + template <class T> void g() { using N::f; f(T()); } +unresolvedLookupExpr(hasAnyDeclaration( + namedDecl(hasUnderlyingDecl(hasName("::N::f"))))) + matches the use of f in g() . +</pre></td></tr> + + <tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html">NestedNameSpecifierLoc</a>></td><td class="name" onclick="toggle('hasPrefix1')"><a name="hasPrefix1Anchor">hasPrefix</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html">NestedNameSpecifierLoc</a>> InnerMatcher</td></tr> <tr><td colspan="4" class="doc" id="hasPrefix1"><pre>Matches on the prefix of a NestedNameSpecifierLoc. @@ -5057,6 +5070,23 @@ matches the [webView ...] message invoca <tr><td colspan="4" class="doc" id="hasSourceExpression1"><pre></pre></td></tr> +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1OverloadExpr.html">OverloadExpr</a>></td><td class="name" onclick="toggle('hasAnyDeclaration0')"><a name="hasAnyDeclaration0Anchor">hasAnyDeclaration</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="hasAnyDeclaration0"><pre>Matches an OverloadExpr if any of the declarations in the set of +overloads matches the given matcher. + +Given + template <typename T> void foo(T); + template <typename T> void bar(T); + template <typename T> void baz(T t) { + foo(t); + bar(t); + } +unresolvedLookupExpr(hasAnyDeclaration( + functionTemplateDecl(hasName("foo")))) + matches foo in foo(t); but not bar in bar(t); +</pre></td></tr> + + <tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ParenType.html">ParenType</a>></td><td class="name" onclick="toggle('innerType0')"><a name="innerType0Anchor">innerType</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td></tr> <tr><td colspan="4" class="doc" id="innerType0"><pre>Matches ParenType nodes where the inner type is a specific type. Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=278123&r1=278122&r2=278123&view=diff ============================================================================== --- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original) +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Tue Aug 9 10:07:52 2016 @@ -2468,6 +2468,25 @@ hasDeclaration(const internal::Matcher<D void(internal::HasDeclarationSupportedTypes)>(InnerMatcher); } +/// \brief Matches a \c NamedDecl whose underlying declaration matches the given +/// matcher. +/// +/// Given +/// \code +/// namespace N { template<class T> void f(T t); } +/// template <class T> void g() { using N::f; f(T()); } +/// \endcode +/// \c unresolvedLookupExpr(hasAnyDeclaration( +/// namedDecl(hasUnderlyingDecl(hasName("::N::f"))))) +/// matches the use of \c f in \c g() . +AST_MATCHER_P(NamedDecl, hasUnderlyingDecl, internal::Matcher<NamedDecl>, + InnerMatcher) { + const NamedDecl *UnderlyingDecl = Node.getUnderlyingDecl(); + + return UnderlyingDecl != nullptr && + InnerMatcher.matches(*UnderlyingDecl, Finder, Builder); +} + /// \brief Matches on the implicit object argument of a member call expression. /// /// Example matches y.x() @@ -2823,6 +2842,27 @@ AST_MATCHER_P(DeclRefExpr, throughUsingD return false; } +/// \brief Matches an \c OverloadExpr if any of the declarations in the set of +/// overloads matches the given matcher. +/// +/// Given +/// \code +/// template <typename T> void foo(T); +/// template <typename T> void bar(T); +/// template <typename T> void baz(T t) { +/// foo(t); +/// bar(t); +/// } +/// \endcode +/// unresolvedLookupExpr(hasAnyDeclaration( +/// functionTemplateDecl(hasName("foo")))) +/// matches \c foo in \c foo(t); but not \c bar in \c bar(t); +AST_MATCHER_P(OverloadExpr, hasAnyDeclaration, internal::Matcher<Decl>, + InnerMatcher) { + return matchesFirstInPointerRange(InnerMatcher, Node.decls_begin(), + Node.decls_end(), Finder, Builder); +} + /// \brief Matches the Decl of a DeclStmt which has a single declaration. /// /// Given Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp?rev=278123&r1=278122&r2=278123&view=diff ============================================================================== --- cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp (original) +++ cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp Tue Aug 9 10:07:52 2016 @@ -198,6 +198,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(hasAncestor); REGISTER_MATCHER(hasAnyArgument); REGISTER_MATCHER(hasAnyConstructorInitializer); + REGISTER_MATCHER(hasAnyDeclaration); REGISTER_MATCHER(hasAnyName); REGISTER_MATCHER(hasAnyParameter); REGISTER_MATCHER(hasAnySubstatement); @@ -265,6 +266,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(hasTypeLoc); REGISTER_MATCHER(hasUnaryOperand); REGISTER_MATCHER(hasUnarySelector); + REGISTER_MATCHER(hasUnderlyingDecl); REGISTER_MATCHER(hasValueType); REGISTER_MATCHER(ifStmt); REGISTER_MATCHER(ignoringImplicit); Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp?rev=278123&r1=278122&r2=278123&view=diff ============================================================================== --- cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp (original) +++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp Tue Aug 9 10:07:52 2016 @@ -241,6 +241,21 @@ TEST(HasDeclaration, HasDeclarationOfTem hasDeclaration(namedDecl(hasName("A")))))))); } +TEST(HasUnderlyingDecl, Matches) { + EXPECT_TRUE(matches("namespace N { template <class T> void f(T t); }" + "template <class T> void g() { using N::f; f(T()); }", + unresolvedLookupExpr(hasAnyDeclaration( + namedDecl(hasUnderlyingDecl(hasName("::N::f"))))))); + EXPECT_TRUE(matches( + "namespace N { template <class T> void f(T t); }" + "template <class T> void g() { N::f(T()); }", + unresolvedLookupExpr(hasAnyDeclaration(namedDecl(hasName("::N::f")))))); + EXPECT_TRUE(notMatches( + "namespace N { template <class T> void f(T t); }" + "template <class T> void g() { using N::f; f(T()); }", + unresolvedLookupExpr(hasAnyDeclaration(namedDecl(hasName("::N::f")))))); +} + TEST(HasType, TakesQualTypeMatcherAndMatchesExpr) { TypeMatcher ClassX = hasDeclaration(recordDecl(hasName("X"))); EXPECT_TRUE( @@ -2072,5 +2087,24 @@ TEST(Matcher, ForEachOverriden) { EXPECT_TRUE(notMatches(Code2, ForEachOverriddenInClass("A1"))); } +TEST(Matcher, HasAnyDeclaration) { + std::string Fragment = "void foo(int p1);" + "void foo(int *p2);" + "void bar(int p3);" + "template <typename T> void baz(T t) { foo(t); }"; + + EXPECT_TRUE( + matches(Fragment, unresolvedLookupExpr(hasAnyDeclaration(functionDecl( + hasParameter(0, parmVarDecl(hasName("p1")))))))); + EXPECT_TRUE( + matches(Fragment, unresolvedLookupExpr(hasAnyDeclaration(functionDecl( + hasParameter(0, parmVarDecl(hasName("p2")))))))); + EXPECT_TRUE( + notMatches(Fragment, unresolvedLookupExpr(hasAnyDeclaration(functionDecl( + hasParameter(0, parmVarDecl(hasName("p3")))))))); + EXPECT_TRUE(notMatches(Fragment, unresolvedLookupExpr(hasAnyDeclaration( + functionDecl(hasName("bar")))))); +} + } // namespace ast_matchers } // namespace clang _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits