mboehme created this revision.
mboehme added reviewers: aaron.ballman, sbenza.
mboehme added a subscriber: cfe-commits.
Herald added a subscriber: klimek.

Required for D22220

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,17 @@
                         hasDeclaration(namedDecl(hasName("A"))))))));
 }
 
+TEST(HasUnderlyingDecl, Matches) {
+  EXPECT_TRUE(matches("class A{};"),
+              cxxRecordDecl(hasName("A"), hasUnderlyingDecl(hasName("A"))));
+  EXPECT_TRUE(matches("class A{}; typedef A B;"),
+              typedefDecl(hasName("B"), hasUnderlyingDecl(hasName("A"))));
+  EXPECT_TRUE(matches("class A{}; typedef A B; typedef B C;"),
+              typedefDecl(hasName("C"), hasUnderlyingDecl(hasName("A"))));
+  EXPECT_TRUE(notMatches("class A{}; class B{}; typedef B C;"),
+              typedefDecl(hasName("C"), hasUnderlyingDecl(hasName("A"))));
+}
+
 TEST(HasType, TakesQualTypeMatcherAndMatchesExpr) {
   TypeMatcher ClassX = hasDeclaration(recordDecl(hasName("X")));
   EXPECT_TRUE(
@@ -2051,5 +2062,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
@@ -2422,6 +2422,24 @@
       void(internal::HasDeclarationSupportedTypes)>(InnerMatcher);
 }
 
+/// \brief Matches a \c NamedDecl whose underlying declaration matches the given
+/// matcher.
+///
+/// Given
+/// \code
+///   class X {};
+///   typedef X Y;
+/// \endcode
+/// \c namedDecl(hasUnderlyingDecl(hasName("X")))
+///   matches both \c X and \c Y .
+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()
@@ -2777,6 +2795,22 @@
   return false;
 }
 
+/// \brief Matches any \c Decl of an \c OverloadExpr that matches the given
+/// matcher.
+///
+/// Given
+/// \code
+///   void foo(int);
+///   template <typename T> void bar(T t) { foo(t); }
+/// \endcode
+/// unresolvedLookupExpr(canReferToDecl(functionDecl()))
+///   matches \c foo in \c foo(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
@@ -4891,6 +4891,18 @@
 </pre></td></tr>
 
 
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html";>NamedDecl</a>&gt;</td><td class="name" onclick="toggle('hasUnderlyingDecl0')"><a name="hasUnderlyingDecl0Anchor">hasUnderlyingDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html";>NamedDecl</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasUnderlyingDecl0"><pre>Matches a NamedDecl whose underlying declaration matches the given
+matcher.
+
+Given
+  class X {};
+  typedef X Y;
+namedDecl(hasUnderlyingDecl(hasName("X")))
+  matches both X and Y .
+</pre></td></tr>
+
+
 <tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html";>NestedNameSpecifierLoc</a>&gt;</td><td class="name" onclick="toggle('hasPrefix1')"><a name="hasPrefix1Anchor">hasPrefix</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html";>NestedNameSpecifierLoc</a>&gt; InnerMatcher</td></tr>
 <tr><td colspan="4" class="doc" id="hasPrefix1"><pre>Matches on the prefix of a NestedNameSpecifierLoc.
 
@@ -4978,6 +4990,18 @@
 <tr><td colspan="4" class="doc" id="hasSourceExpression1"><pre></pre></td></tr>
 
 
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1OverloadExpr.html";>OverloadExpr</a>&gt;</td><td class="name" onclick="toggle('canReferToDecl0')"><a name="canReferToDecl0Anchor">canReferToDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html";>Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="canReferToDecl0"><pre>Matches any Decl of an OverloadExpr that matches the given
+matcher.
+
+Given
+  void foo(int);
+  template &lt;typename T&gt; void bar(T t) { foo(t); }
+unresolvedLookupExpr(canReferToDecl(functionDecl()))
+  matches foo in foo(t);
+</pre></td></tr>
+
+
 <tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParenType.html";>ParenType</a>&gt;</td><td class="name" onclick="toggle('innerType0')"><a name="innerType0Anchor">innerType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html";>Type</a>&gt;</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
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to