forked from OSchip/llvm-project
[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 llvm-svn: 278123
This commit is contained in:
parent
c710a461b5
commit
8cef2c2f2d
|
@ -4970,6 +4970,19 @@ Usable as: Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Block
|
|||
</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 invocation.
|
|||
<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.
|
||||
|
||||
|
|
|
@ -2468,6 +2468,25 @@ hasDeclaration(const internal::Matcher<Decl> &InnerMatcher) {
|
|||
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, throughUsingDecl,
|
|||
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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -241,6 +241,21 @@ TEST(HasDeclaration, HasDeclarationOfTemplateSpecializationType) {
|
|||
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
|
||||
|
|
Loading…
Reference in New Issue