mboehme updated this revision to Diff 66808.
https://reviews.llvm.org/D23004
Files:
docs/LibASTMatchersReference.html
include/clang/ASTMatchers/ASTMatchers.h
lib/ASTMatchers/Dynamic/Registry.cpp
unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
Index: unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===================================================================
--- unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -241,6 +241,21 @@
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(canReferToDecl(
+ 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(canReferToDecl(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(canReferToDecl(namedDecl(hasName("::N::f"))))));
+}
+
TEST(HasType, TakesQualTypeMatcherAndMatchesExpr) {
TypeMatcher ClassX = hasDeclaration(recordDecl(hasName("X")));
EXPECT_TRUE(
@@ -2072,5 +2087,24 @@
EXPECT_TRUE(notMatches(Code2, ForEachOverriddenInClass("A1")));
}
+TEST(Matcher, CanReferToDecl) {
+ 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(canReferToDecl(functionDecl(
+ hasParameter(0, parmVarDecl(hasName("p1"))))))));
+ EXPECT_TRUE(
+ matches(Fragment, unresolvedLookupExpr(canReferToDecl(functionDecl(
+ hasParameter(0, parmVarDecl(hasName("p2"))))))));
+ EXPECT_TRUE(
+ notMatches(Fragment, unresolvedLookupExpr(canReferToDecl(functionDecl(
+ hasParameter(0, parmVarDecl(hasName("p3"))))))));
+ EXPECT_TRUE(notMatches(Fragment, unresolvedLookupExpr(canReferToDecl(
+ functionDecl(hasName("bar"))))));
+}
+
} // namespace ast_matchers
} // namespace clang
Index: lib/ASTMatchers/Dynamic/Registry.cpp
===================================================================
--- lib/ASTMatchers/Dynamic/Registry.cpp
+++ lib/ASTMatchers/Dynamic/Registry.cpp
@@ -115,6 +115,7 @@
REGISTER_MATCHER(breakStmt);
REGISTER_MATCHER(builtinType);
REGISTER_MATCHER(callExpr);
+ REGISTER_MATCHER(canReferToDecl);
REGISTER_MATCHER(caseStmt);
REGISTER_MATCHER(castExpr);
REGISTER_MATCHER(characterLiteral);
@@ -265,6 +266,7 @@
REGISTER_MATCHER(hasTypeLoc);
REGISTER_MATCHER(hasUnaryOperand);
REGISTER_MATCHER(hasUnarySelector);
+ REGISTER_MATCHER(hasUnderlyingDecl);
REGISTER_MATCHER(hasValueType);
REGISTER_MATCHER(ifStmt);
REGISTER_MATCHER(ignoringImplicit);
Index: include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchers.h
+++ include/clang/ASTMatchers/ASTMatchers.h
@@ -2468,6 +2468,25 @@
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(canReferToDecl(
+/// 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,26 @@
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(canReferToDecl(functionTemplateDecl(hasName("foo"))))
+/// matches \c foo in \c foo(t); but not \c bar in \c bar(t);
+AST_MATCHER_P(OverloadExpr, canReferToDecl, 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
Index: docs/LibASTMatchersReference.html
===================================================================
--- docs/LibASTMatchersReference.html
+++ docs/LibASTMatchersReference.html
@@ -4958,6 +4958,19 @@
</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(canReferToDecl(
+ 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.
@@ -5045,6 +5058,22 @@
<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('canReferToDecl0')"><a name="canReferToDecl0Anchor">canReferToDecl</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="canReferToDecl0"><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(canReferToDecl(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.
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits