ymandel updated this revision to Diff 294312.
ymandel added a comment.

update dynamic registry and the ast matcher doc.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D88275/new/

https://reviews.llvm.org/D88275

Files:
  clang/docs/LibASTMatchersReference.html
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/include/clang/ASTMatchers/ASTMatchersInternal.h
  clang/lib/ASTMatchers/ASTMatchFinder.cpp
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===================================================================
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -3190,6 +3190,26 @@
                compoundStmt(hasParent(recordDecl()))));
 }
 
+TEST(HasParentIgnoringImplicit, MatchesExplicitParents) {
+  std::string Input = R"cc(
+    float f() {
+        int x = 3;
+        int y = 3.0;
+        return y;
+    }
+  )cc";
+  EXPECT_TRUE(
+      matches(Input, declRefExpr(hasParentIgnoringImplicit(returnStmt()))));
+  EXPECT_TRUE(
+      matches(Input, floatLiteral(hasParentIgnoringImplicit(varDecl()))));
+  EXPECT_TRUE(
+      matches(Input, integerLiteral(hasParentIgnoringImplicit(varDecl()))));
+
+  // Make sure it only ignores implicit ancestors.
+  EXPECT_TRUE(
+      notMatches(Input, integerLiteral(hasParentIgnoringImplicit(declStmt()))));
+}
+
 TEST(HasParent, NoDuplicateParents) {
   class HasDuplicateParents : public BoundNodesCallback {
   public:
Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp
===================================================================
--- clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -311,6 +311,7 @@
   REGISTER_MATCHER(hasOverloadedOperatorName);
   REGISTER_MATCHER(hasParameter);
   REGISTER_MATCHER(hasParent);
+  REGISTER_MATCHER(hasParentIgnoringImplicit);
   REGISTER_MATCHER(hasQualifier);
   REGISTER_MATCHER(hasRHS);
   REGISTER_MATCHER(hasRangeInit);
Index: clang/lib/ASTMatchers/ASTMatchFinder.cpp
===================================================================
--- clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -544,9 +544,14 @@
     // don't invalidate any iterators.
     if (ResultCache.size() > MaxMemoizationEntries)
       ResultCache.clear();
-    if (MatchMode == AncestorMatchMode::AMM_ParentOnly)
+    switch (MatchMode) {
+    case AncestorMatchMode::AMM_ParentOnly:
       return matchesParentOf(Node, Matcher, Builder);
-    return matchesAnyAncestorOf(Node, Ctx, Matcher, Builder);
+    case AncestorMatchMode::AMM_FirstExplicitOnly:
+      return matchesFirstExplicitAncestorOf(Node, Matcher, Builder);
+    case AncestorMatchMode::AMM_All:
+      return matchesAnyAncestorOf(Node, Ctx, Matcher, Builder);
+    }
   }
 
   // Matches all registered matchers on the given node and calls the
@@ -714,6 +719,33 @@
     return false;
   }
 
+  // Returns whether the first explicit (`Expr`) ancestor of \p Node matches \p
+  // Matcher. That is, like matchesParentOf but skipping implicit parents.
+  // Unlike matchesAnyAncestorOf there's no memoization: it doesn't save much.
+  bool matchesFirstExplicitAncestorOf(const DynTypedNode &Node,
+                                      const DynTypedMatcher &Matcher,
+                                      BoundNodesTreeBuilder *Builder) {
+    for (const auto &Parent : ActiveASTContext->getParents(Node)) {
+      if (const auto *E = Parent.get<clang::Expr>())
+        // If the parent is an implicit node, match on *its* parents
+        // instead. Use DFS, since we expect that expressions are relatively
+        // shallow.
+        if (clang::isa<ImplicitCastExpr>(E) || clang::isa<FullExpr>(E) ||
+            clang::isa<MaterializeTemporaryExpr>(E) ||
+            clang::isa<CXXBindTemporaryExpr>(E)) {
+          if (matchesFirstExplicitAncestorOf(Parent, Matcher, Builder))
+            return true;
+          continue;
+        }
+      BoundNodesTreeBuilder BuilderCopy = *Builder;
+      if (Matcher.matches(Parent, this, &BuilderCopy)) {
+        *Builder = std::move(BuilderCopy);
+        return true;
+      }
+    }
+    return false;
+  }
+
   // Returns whether an ancestor of \p Node matches \p Matcher.
   //
   // The order of matching (which can lead to different nodes being bound in
Index: clang/include/clang/ASTMatchers/ASTMatchersInternal.h
===================================================================
--- clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -985,7 +985,11 @@
     AMM_All,
 
     /// Direct parent only.
-    AMM_ParentOnly
+    AMM_ParentOnly,
+
+    /// Considers the first non-implicit `Expr` ancestor. Intuitively, like
+    /// `ignoringImplicit` for matching parents.
+    AMM_FirstExplicitOnly
   };
 
   virtual ~ASTMatchFinder() = default;
@@ -1515,6 +1519,26 @@
   }
 };
 
+/// Matches nodes of type \c T that have a parent node for which the given inner
+/// matcher matches. If the parent is an implicit expression, considers the
+/// parent's parent (and so on) instead, until an explicit parent is found. That
+/// is, looks for an ancestor that is separated from `Node` only by implicit
+/// expression nodes and matches `ParentMatcher`.
+template <typename T, typename ArgT>
+class HasParentIgnoringImplicitMatcher : public MatcherInterface<T> {
+  const DynTypedMatcher ParentMatcher;
+
+public:
+  explicit HasParentIgnoringImplicitMatcher(const ArgT &ParentMatcher)
+      : ParentMatcher(ParentMatcher) {}
+
+  bool matches(const T &Node, ASTMatchFinder *Finder,
+               BoundNodesTreeBuilder *Builder) const override {
+    return Finder->matchesAncestorOf(Node, this->ParentMatcher, Builder,
+                                     ASTMatchFinder::AMM_FirstExplicitOnly);
+  }
+};
+
 /// Matches nodes of type \c T that have at least one ancestor node of
 /// type \c AncestorT for which the given inner matcher matches.
 ///
Index: clang/include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- clang/include/clang/ASTMatchers/ASTMatchers.h
+++ clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -3176,6 +3176,26 @@
     internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>>
     hasParent;
 
+/// Matches AST nodes that have an ancestor, reachable only through
+/// implicit-expression nodes, that matches the provided matcher.
+///
+/// Given
+/// \code
+/// float f() { return 3; }
+/// \endcode
+/// \c integerLiteral(hasParentIgnoringImplicit(returnStmt())) matches "3",
+/// while \c integerLiteral(hasParent(returnStmt())) does not.
+///
+/// Usable as: Any Matcher
+template <typename MatcherT>
+internal::PolymorphicMatcherWithParam1<
+    internal::HasParentIgnoringImplicitMatcher, MatcherT>
+hasParentIgnoringImplicit(MatcherT InnerMatcher) {
+  return internal::PolymorphicMatcherWithParam1<
+      internal::HasParentIgnoringImplicitMatcher, MatcherT>(
+      std::move(InnerMatcher));
+}
+
 /// Matches AST nodes that have an ancestor that matches the provided
 /// matcher.
 ///
Index: clang/docs/LibASTMatchersReference.html
===================================================================
--- clang/docs/LibASTMatchersReference.html
+++ clang/docs/LibASTMatchersReference.html
@@ -422,7 +422,7 @@
 </pre></td></tr>
 
 
-<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html";>Decl</a>&gt;</td><td class="name" onclick="toggle('objcIvarDecl0')"><a name="objcIvarDecl0Anchor">objcIvarDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCIvarDecl.html";>ObjCIvarDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html";>Decl</a>&gt;</td><td class="name" onclick="toggle('objcIvarDecl0')"><a name="objcIvarDecl0Anchor">objcIvarDecl</a></td><td>Matcher&lt;ObjCIvarDecl&gt;...</td></tr>
 <tr><td colspan="4" class="doc" id="objcIvarDecl0"><pre>Matches Objective-C instance variable declarations.
 
 Example matches _enabled
@@ -447,7 +447,7 @@
 </pre></td></tr>
 
 
-<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html";>Decl</a>&gt;</td><td class="name" onclick="toggle('objcPropertyDecl0')"><a name="objcPropertyDecl0Anchor">objcPropertyDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCPropertyDecl.html";>ObjCPropertyDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html";>Decl</a>&gt;</td><td class="name" onclick="toggle('objcPropertyDecl0')"><a name="objcPropertyDecl0Anchor">objcPropertyDecl</a></td><td>Matcher&lt;ObjCPropertyDecl&gt;...</td></tr>
 <tr><td colspan="4" class="doc" id="objcPropertyDecl0"><pre>Matches Objective-C property declarations.
 
 Example matches enabled
@@ -487,7 +487,7 @@
 </pre></td></tr>
 
 
-<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html";>Decl</a>&gt;</td><td class="name" onclick="toggle('staticAssertDecl0')"><a name="staticAssertDecl0Anchor">staticAssertDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1StaticAssertDecl.html";>StaticAssertDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html";>Decl</a>&gt;</td><td class="name" onclick="toggle('staticAssertDecl0')"><a name="staticAssertDecl0Anchor">staticAssertDecl</a></td><td>Matcher&lt;StaticAssertDecl&gt;...</td></tr>
 <tr><td colspan="4" class="doc" id="staticAssertDecl0"><pre>Matches a C++ static_assert declaration.
 
 Example:
@@ -762,7 +762,7 @@
 </pre></td></tr>
 
 
-<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html";>Stmt</a>&gt;</td><td class="name" onclick="toggle('binaryConditionalOperator0')"><a name="binaryConditionalOperator0Anchor">binaryConditionalOperator</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryConditionalOperator.html";>BinaryConditionalOperator</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html";>Stmt</a>&gt;</td><td class="name" onclick="toggle('binaryConditionalOperator0')"><a name="binaryConditionalOperator0Anchor">binaryConditionalOperator</a></td><td>Matcher&lt;BinaryConditionalOperator&gt;...</td></tr>
 <tr><td colspan="4" class="doc" id="binaryConditionalOperator0"><pre>Matches binary conditional operator expressions (GNU extension).
 
 Example matches a ?: b
@@ -935,7 +935,7 @@
 </pre></td></tr>
 
 
-<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html";>Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxConstCastExpr0')"><a name="cxxConstCastExpr0Anchor">cxxConstCastExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstCastExpr.html";>CXXConstCastExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html";>Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxConstCastExpr0')"><a name="cxxConstCastExpr0Anchor">cxxConstCastExpr</a></td><td>Matcher&lt;CXXConstCastExpr&gt;...</td></tr>
 <tr><td colspan="4" class="doc" id="cxxConstCastExpr0"><pre>Matches a const_cast expression.
 
 Example: Matches const_cast&lt;int*&gt;(&amp;r) in
@@ -989,7 +989,7 @@
 </pre></td></tr>
 
 
-<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html";>Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxDynamicCastExpr0')"><a name="cxxDynamicCastExpr0Anchor">cxxDynamicCastExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXDynamicCastExpr.html";>CXXDynamicCastExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html";>Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxDynamicCastExpr0')"><a name="cxxDynamicCastExpr0Anchor">cxxDynamicCastExpr</a></td><td>Matcher&lt;CXXDynamicCastExpr&gt;...</td></tr>
 <tr><td colspan="4" class="doc" id="cxxDynamicCastExpr0"><pre>Matches a dynamic_cast expression.
 
 Example:
@@ -1077,7 +1077,7 @@
 </pre></td></tr>
 
 
-<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html";>Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxReinterpretCastExpr0')"><a name="cxxReinterpretCastExpr0Anchor">cxxReinterpretCastExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXReinterpretCastExpr.html";>CXXReinterpretCastExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html";>Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxReinterpretCastExpr0')"><a name="cxxReinterpretCastExpr0Anchor">cxxReinterpretCastExpr</a></td><td>Matcher&lt;CXXReinterpretCastExpr&gt;...</td></tr>
 <tr><td colspan="4" class="doc" id="cxxReinterpretCastExpr0"><pre>Matches a reinterpret_cast expression.
 
 Either the source expression or the destination type can be matched
@@ -1089,7 +1089,7 @@
 </pre></td></tr>
 
 
-<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html";>Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxStaticCastExpr0')"><a name="cxxStaticCastExpr0Anchor">cxxStaticCastExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXStaticCastExpr.html";>CXXStaticCastExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html";>Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxStaticCastExpr0')"><a name="cxxStaticCastExpr0Anchor">cxxStaticCastExpr</a></td><td>Matcher&lt;CXXStaticCastExpr&gt;...</td></tr>
 <tr><td colspan="4" class="doc" id="cxxStaticCastExpr0"><pre>Matches a C++ static_cast expression.
 
 See also: hasDestinationType
@@ -1241,7 +1241,7 @@
 </pre></td></tr>
 
 
-<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html";>Stmt</a>&gt;</td><td class="name" onclick="toggle('exprWithCleanups0')"><a name="exprWithCleanups0Anchor">exprWithCleanups</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ExprWithCleanups.html";>ExprWithCleanups</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html";>Stmt</a>&gt;</td><td class="name" onclick="toggle('exprWithCleanups0')"><a name="exprWithCleanups0Anchor">exprWithCleanups</a></td><td>Matcher&lt;ExprWithCleanups&gt;...</td></tr>
 <tr><td colspan="4" class="doc" id="exprWithCleanups0"><pre>Matches expressions that introduce cleanups to be run at the end
 of the sub-expression's evaluation.
 
@@ -1398,7 +1398,7 @@
 </pre></td></tr>
 
 
-<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html";>Stmt</a>&gt;</td><td class="name" onclick="toggle('objcCatchStmt0')"><a name="objcCatchStmt0Anchor">objcCatchStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCAtCatchStmt.html";>ObjCAtCatchStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html";>Stmt</a>&gt;</td><td class="name" onclick="toggle('objcCatchStmt0')"><a name="objcCatchStmt0Anchor">objcCatchStmt</a></td><td>Matcher&lt;ObjCAtCatchStmt&gt;...</td></tr>
 <tr><td colspan="4" class="doc" id="objcCatchStmt0"><pre>Matches Objective-C @catch statements.
 
 Example matches @catch
@@ -1407,7 +1407,7 @@
 </pre></td></tr>
 
 
-<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html";>Stmt</a>&gt;</td><td class="name" onclick="toggle('objcFinallyStmt0')"><a name="objcFinallyStmt0Anchor">objcFinallyStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCAtFinallyStmt.html";>ObjCAtFinallyStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html";>Stmt</a>&gt;</td><td class="name" onclick="toggle('objcFinallyStmt0')"><a name="objcFinallyStmt0Anchor">objcFinallyStmt</a></td><td>Matcher&lt;ObjCAtFinallyStmt&gt;...</td></tr>
 <tr><td colspan="4" class="doc" id="objcFinallyStmt0"><pre>Matches Objective-C @finally statements.
 
 Example matches @finally
@@ -1440,14 +1440,14 @@
 </pre></td></tr>
 
 
-<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html";>Stmt</a>&gt;</td><td class="name" onclick="toggle('objcThrowStmt0')"><a name="objcThrowStmt0Anchor">objcThrowStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCAtThrowStmt.html";>ObjCAtThrowStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html";>Stmt</a>&gt;</td><td class="name" onclick="toggle('objcThrowStmt0')"><a name="objcThrowStmt0Anchor">objcThrowStmt</a></td><td>Matcher&lt;ObjCAtThrowStmt&gt;...</td></tr>
 <tr><td colspan="4" class="doc" id="objcThrowStmt0"><pre>Matches Objective-C statements.
 
 Example matches @throw obj;
 </pre></td></tr>
 
 
-<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html";>Stmt</a>&gt;</td><td class="name" onclick="toggle('objcTryStmt0')"><a name="objcTryStmt0Anchor">objcTryStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCAtTryStmt.html";>ObjCAtTryStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html";>Stmt</a>&gt;</td><td class="name" onclick="toggle('objcTryStmt0')"><a name="objcTryStmt0Anchor">objcTryStmt</a></td><td>Matcher&lt;ObjCAtTryStmt&gt;...</td></tr>
 <tr><td colspan="4" class="doc" id="objcTryStmt0"><pre>Matches Objective-C @try statements.
 
 Example matches @try
@@ -1470,7 +1470,7 @@
 </pre></td></tr>
 
 
-<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html";>Stmt</a>&gt;</td><td class="name" onclick="toggle('opaqueValueExpr0')"><a name="opaqueValueExpr0Anchor">opaqueValueExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1OpaqueValueExpr.html";>OpaqueValueExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html";>Stmt</a>&gt;</td><td class="name" onclick="toggle('opaqueValueExpr0')"><a name="opaqueValueExpr0Anchor">opaqueValueExpr</a></td><td>Matcher&lt;OpaqueValueExpr&gt;...</td></tr>
 <tr><td colspan="4" class="doc" id="opaqueValueExpr0"><pre>Matches opaque value expressions. They are used as helpers
 to reference another expressions and can be met
 in BinaryConditionalOperators, for example.
@@ -2157,6 +2157,19 @@
 </pre></td></tr>
 
 
+<tr><td>Matcher&lt;*&gt;</td><td class="name" onclick="toggle('hasParentIgnoringImplicit0')"><a name="hasParentIgnoringImplicit0Anchor">hasParentIgnoringImplicit</a></td><td>MatcherT InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasParentIgnoringImplicit0"><pre>Matches AST nodes that have an ancestor, reachable only through
+implicit-expression nodes, that matches the provided matcher.
+
+Given
+float f() { return 3; }
+integerLiteral(hasParentIgnoringImplicit(returnStmt())) matches "3",
+while integerLiteral(hasParent(returnStmt())) does not.
+
+Usable as: Any Matcher
+</pre></td></tr>
+
+
 <tr><td>Matcher&lt;*&gt;</td><td class="name" onclick="toggle('unless0')"><a name="unless0Anchor">unless</a></td><td>Matcher&lt;*&gt;</td></tr>
 <tr><td colspan="4" class="doc" id="unless0"><pre>Matches if the provided matcher does not match.
 
@@ -7239,7 +7252,7 @@
 </pre></td></tr>
 
 
-<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1OpaqueValueExpr.html";>OpaqueValueExpr</a>&gt;</td><td class="name" onclick="toggle('hasSourceExpression1')"><a name="hasSourceExpression1Anchor">hasSourceExpression</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html";>Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;OpaqueValueExpr&gt;</td><td class="name" onclick="toggle('hasSourceExpression1')"><a name="hasSourceExpression1Anchor">hasSourceExpression</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html";>Expr</a>&gt; InnerMatcher</td></tr>
 <tr><td colspan="4" class="doc" id="hasSourceExpression1"><pre>Matches if the cast's source expression
 or opaque value's source expression matches the given matcher.
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to