[clang] Add 'forNone' AST matcher (PR #86230)

2024-03-21 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: June Rhodes (hach-que)


Changes

This adds a `forNone` AST matcher, which matches only if there are no immediate 
children of the current node that match the inner matcher. For example, given:

```cpp
class F
{
public:
  int A;

  F() {};
};
```

the matcher:

```
cxxConstructorDecl(
unless(isImplicit()),
unless(isDelegatingConstructor()),
unless(isDeleted()),
unless(isDefaulted()),
hasBody(stmt()),
ofClass(cxxRecordDecl(forEach(fieldDecl().bind("declared_field",

forNone(cxxCtorInitializer(forField(fieldDecl(equalsBoundNode("declared_field")).bind("referenced_field"
).bind("bad_constructor")
```

would match `F()`, because it does not have an initializer for `A`. We use this 
in our modified version of Clang to detect constructors that do not fully 
initialize all fields.


---
Full diff: https://github.com/llvm/llvm-project/pull/86230.diff


4 Files Affected:

- (modified) clang/include/clang/ASTMatchers/ASTMatchers.h (+7) 
- (modified) clang/include/clang/ASTMatchers/ASTMatchersInternal.h (+36) 
- (modified) clang/lib/ASTMatchers/ASTMatchersInternal.cpp (+2) 
- (modified) clang/lib/ASTMatchers/Dynamic/Registry.cpp (+1) 


``diff
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h 
b/clang/include/clang/ASTMatchers/ASTMatchers.h
index 2f71053d030f68..8cc7a0e92acbdd 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -3547,6 +3547,13 @@ extern const internal::ArgumentAdaptingMatcherFunc<
 internal::ForEachDescendantMatcher>
 forEachDescendant;
 
+/// Matches AST nodes that have no child AST nodes that match the
+/// provided matcher.
+///
+/// Usable as: Any Matcher
+extern const internal::ArgumentAdaptingMatcherFunc
+forNone;
+
 /// Matches if the node or any descendant matches.
 ///
 /// Generates results for each match.
diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h 
b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
index 47d912c73dd7eb..bf5aaf74c0ef9a 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -1626,6 +1626,42 @@ class ForEachMatcher : public MatcherInterface {
   }
 };
 
+/// Matches nodes of type T that have no child nodes of type ChildT for
+/// which a specified child matcher matches. ChildT must be an AST base
+/// type.
+/// ForNoneMatcher will only match if none of the child nodes match
+/// the inner matcher.
+template 
+class ForNoneMatcher : public MatcherInterface {
+  static_assert(IsBaseType::value,
+"for none only accepts base type matcher");
+
+  DynTypedMatcher InnerMatcher;
+
+public:
+  explicit ForNoneMatcher(const Matcher )
+  : InnerMatcher(InnerMatcher) {}
+
+  bool matches(const T , ASTMatchFinder *Finder,
+   BoundNodesTreeBuilder *Builder) const override {
+BoundNodesTreeBuilder MatchingBuilder(*Builder);
+bool AnyMatched = Finder->matchesChildOf(Node, this->InnerMatcher, 
,
+ASTMatchFinder::BK_All);
+if (!AnyMatched) {
+  // We didn't iterate over any nodes that matched, so
+  // Builder would be empty. This is a success case.
+  return true;
+}
+// Otherwise remove from Builder any entries that we
+// also have in MatchingBuilder because we want to leave
+// only the remaining entries.
+return Builder->removeBindings(
+[](const internal::BoundNodesMap ) {
+  return MatchingBuilder.contains(Nodes);
+});
+  }
+};
+
 /// @}
 
 template 
diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp 
b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
index bf87b1aa0992a5..4a8f383011b336 100644
--- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -1022,6 +1022,8 @@ const 
internal::ArgumentAdaptingMatcherFunc
 hasDescendant = {};
 const internal::ArgumentAdaptingMatcherFunc forEach =
 {};
+const internal::ArgumentAdaptingMatcherFunc forNone =
+{};
 const internal::ArgumentAdaptingMatcherFunc
 forEachDescendant = {};
 const internal::ArgumentAdaptingMatcherFunc<
diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp 
b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
index 2c75e6beb74301..f6b866e6a0bcbf 100644
--- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -259,6 +259,7 @@ RegistryMaps::RegistryMaps() {
   REGISTER_MATCHER(forEachOverridden);
   REGISTER_MATCHER(forEachSwitchCase);
   REGISTER_MATCHER(forEachTemplateArgument);
+  REGISTER_MATCHER(forNone);
   REGISTER_MATCHER(forField);
   REGISTER_MATCHER(forFunction);
   REGISTER_MATCHER(forStmt);

``




https://github.com/llvm/llvm-project/pull/86230
___
cfe-commits mailing list
cfe-commits@lists.llvm.org

[clang] Add 'forNone' AST matcher (PR #86230)

2024-03-21 Thread June Rhodes via cfe-commits

https://github.com/hach-que updated 
https://github.com/llvm/llvm-project/pull/86230

>From 9b04a03646992a3366022dd7022858c98f7560e7 Mon Sep 17 00:00:00 2001
From: June Rhodes 
Date: Fri, 22 Mar 2024 13:07:57 +1100
Subject: [PATCH] Add 'forNone' and 'forNoDescendant' AST matchers

---
 clang/include/clang/ASTMatchers/ASTMatchers.h | 15 +++
 .../clang/ASTMatchers/ASTMatchersInternal.h   | 97 +++
 clang/lib/ASTMatchers/ASTMatchersInternal.cpp | 13 +++
 clang/lib/ASTMatchers/Dynamic/Registry.cpp|  2 +
 4 files changed, 127 insertions(+)

diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h 
b/clang/include/clang/ASTMatchers/ASTMatchers.h
index 2f71053d030f68..fa6afe2f02f6b0 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -3547,6 +3547,21 @@ extern const internal::ArgumentAdaptingMatcherFunc<
 internal::ForEachDescendantMatcher>
 forEachDescendant;
 
+/// Matches AST nodes that have no child AST nodes that match the
+/// provided matcher.
+///
+/// Usable as: Any Matcher
+extern const internal::ArgumentAdaptingMatcherFunc
+forNone;
+
+/// Matches AST nodes that have no descendant AST nodes that match the
+/// provided matcher.
+///
+/// Usable as: Any Matcher
+extern const internal::ArgumentAdaptingMatcherFunc<
+internal::ForNoDescendantMatcher>
+forNoDescendant;
+
 /// Matches if the node or any descendant matches.
 ///
 /// Generates results for each match.
diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h 
b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
index 47d912c73dd7eb..5612730462465a 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -268,6 +268,26 @@ class BoundNodesMap {
 return true;
   }
 
+  /// Returns \c true if the \c BoundNodesMap entirely contains the values
+  /// in \c Subset.
+  bool contains(const BoundNodesMap& Subset) {
+const auto  = this->NodeMap.end();
+if (Subset.NodeMap.size() == 1) {
+  // Avoid iteration if the subset only has a single value.
+  const auto  = Subset.NodeMap.begin();
+  const auto  = this->NodeMap.find(F->first);
+  return T != N && T->second == F->second;
+} else {
+  for (const auto  : Subset.NodeMap) {
+const auto  = this->NodeMap.find(F.first);
+if (T == N || T->second != F.second) {
+  return false;
+}
+  }
+}
+return true;
+  }
+
 private:
   IDToNodeMap NodeMap;
 };
@@ -306,6 +326,10 @@ class BoundNodesTreeBuilder {
   /// The ownership of 'ResultVisitor' remains at the caller.
   void visitMatches(Visitor* ResultVisitor);
 
+  /// Returns true if any of the entries in this tree contain the
+  /// other bound nodes map.
+  bool contains(const internal::BoundNodesMap );
+
   template 
   bool removeBindings(const ExcludePredicate ) {
 llvm::erase_if(Bindings, Predicate);
@@ -1626,6 +1650,42 @@ class ForEachMatcher : public MatcherInterface {
   }
 };
 
+/// Matches nodes of type T that have no child nodes of type ChildT for
+/// which a specified child matcher matches. ChildT must be an AST base
+/// type.
+/// ForNoneMatcher will only match if none of the child nodes match
+/// the inner matcher.
+template 
+class ForNoneMatcher : public MatcherInterface {
+  static_assert(IsBaseType::value,
+"for none only accepts base type matcher");
+
+  DynTypedMatcher InnerMatcher;
+
+public:
+  explicit ForNoneMatcher(const Matcher )
+  : InnerMatcher(InnerMatcher) {}
+
+  bool matches(const T , ASTMatchFinder *Finder,
+   BoundNodesTreeBuilder *Builder) const override {
+BoundNodesTreeBuilder MatchingBuilder(*Builder);
+bool AnyMatched = Finder->matchesChildOf(Node, this->InnerMatcher, 
,
+ASTMatchFinder::BK_All);
+if (!AnyMatched) {
+  // We didn't iterate over any nodes that matched, so
+  // Builder would be empty. This is a success case.
+  return true;
+}
+// Otherwise remove from Builder any entries that we
+// also have in MatchingBuilder because we want to leave
+// only the remaining entries.
+return Builder->removeBindings(
+[](const internal::BoundNodesMap ) {
+  return MatchingBuilder.contains(Nodes);
+});
+  }
+};
+
 /// @}
 
 template 
@@ -1724,6 +1784,43 @@ class ForEachDescendantMatcher : public 
MatcherInterface {
   }
 };
 
+/// Matches nodes of type T that have no descendant node of
+/// type DescendantT for which the given inner matcher matches.
+///
+/// DescendantT must be an AST base type.
+/// ForNoDescendantMatcher only matches if none of the descendant nodes
+/// match.
+template 
+class ForNoDescendantMatcher : public MatcherInterface {
+  static_assert(IsBaseType::value,
+"for no descendant only accepts base type matcher");
+
+  DynTypedMatcher DescendantMatcher;
+
+public:
+  explicit 

[clang] Add 'forNone' AST matcher (PR #86230)

2024-03-21 Thread June Rhodes via cfe-commits

https://github.com/hach-que updated 
https://github.com/llvm/llvm-project/pull/86230

>From bf78fb2172048c703824698b839e20ad1b8bf0b2 Mon Sep 17 00:00:00 2001
From: June Rhodes 
Date: Fri, 22 Mar 2024 13:07:57 +1100
Subject: [PATCH] Add 'forNone' AST matcher

---
 clang/include/clang/ASTMatchers/ASTMatchers.h |  7 +++
 .../clang/ASTMatchers/ASTMatchersInternal.h   | 60 +++
 clang/lib/ASTMatchers/ASTMatchersInternal.cpp | 11 
 clang/lib/ASTMatchers/Dynamic/Registry.cpp|  1 +
 4 files changed, 79 insertions(+)

diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h 
b/clang/include/clang/ASTMatchers/ASTMatchers.h
index 2f71053d030f68..8cc7a0e92acbdd 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -3547,6 +3547,13 @@ extern const internal::ArgumentAdaptingMatcherFunc<
 internal::ForEachDescendantMatcher>
 forEachDescendant;
 
+/// Matches AST nodes that have no child AST nodes that match the
+/// provided matcher.
+///
+/// Usable as: Any Matcher
+extern const internal::ArgumentAdaptingMatcherFunc
+forNone;
+
 /// Matches if the node or any descendant matches.
 ///
 /// Generates results for each match.
diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h 
b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
index 47d912c73dd7eb..fc6d44c3b8b933 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -268,6 +268,26 @@ class BoundNodesMap {
 return true;
   }
 
+  /// Returns \c true if the \c BoundNodesMap entirely contains the values
+  /// in \c Subset.
+  bool contains(const BoundNodesMap& Subset) {
+const auto  = this->NodeMap.end();
+if (Subset.NodeMap.size() == 1) {
+  // Avoid iteration if the subset only has a single value.
+  const auto  = Subset.NodeMap.begin();
+  const auto  = this->NodeMap.find(F->first);
+  return T != N && T->second == F->second;
+} else {
+  for (const auto  : Subset.NodeMap) {
+const auto  = this->NodeMap.find(F.first);
+if (T == N || T->second != F.second) {
+  return false;
+}
+  }
+}
+return true;
+  }
+
 private:
   IDToNodeMap NodeMap;
 };
@@ -306,6 +326,10 @@ class BoundNodesTreeBuilder {
   /// The ownership of 'ResultVisitor' remains at the caller.
   void visitMatches(Visitor* ResultVisitor);
 
+  /// Returns true if any of the entries in this tree contain the
+  /// other bound nodes map.
+  bool contains(const internal::BoundNodesMap );
+
   template 
   bool removeBindings(const ExcludePredicate ) {
 llvm::erase_if(Bindings, Predicate);
@@ -1626,6 +1650,42 @@ class ForEachMatcher : public MatcherInterface {
   }
 };
 
+/// Matches nodes of type T that have no child nodes of type ChildT for
+/// which a specified child matcher matches. ChildT must be an AST base
+/// type.
+/// ForNoneMatcher will only match if none of the child nodes match
+/// the inner matcher.
+template 
+class ForNoneMatcher : public MatcherInterface {
+  static_assert(IsBaseType::value,
+"for none only accepts base type matcher");
+
+  DynTypedMatcher InnerMatcher;
+
+public:
+  explicit ForNoneMatcher(const Matcher )
+  : InnerMatcher(InnerMatcher) {}
+
+  bool matches(const T , ASTMatchFinder *Finder,
+   BoundNodesTreeBuilder *Builder) const override {
+BoundNodesTreeBuilder MatchingBuilder(*Builder);
+bool AnyMatched = Finder->matchesChildOf(Node, this->InnerMatcher, 
,
+ASTMatchFinder::BK_All);
+if (!AnyMatched) {
+  // We didn't iterate over any nodes that matched, so
+  // Builder would be empty. This is a success case.
+  return true;
+}
+// Otherwise remove from Builder any entries that we
+// also have in MatchingBuilder because we want to leave
+// only the remaining entries.
+return Builder->removeBindings(
+[](const internal::BoundNodesMap ) {
+  return MatchingBuilder.contains(Nodes);
+});
+  }
+};
+
 /// @}
 
 template 
diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp 
b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
index bf87b1aa0992a5..f36a8c3ae834c3 100644
--- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -106,6 +106,15 @@ void BoundNodesTreeBuilder::visitMatches(Visitor 
*ResultVisitor) {
   }
 }
 
+bool BoundNodesTreeBuilder::contains(const internal::BoundNodesMap ) {
+  for (BoundNodesMap  : Bindings) {
+if (Binding.contains(Subset)) {
+  return true;
+}
+  }
+  return false;
+}
+
 namespace {
 
 using VariadicOperatorFunction = bool (*)(
@@ -1022,6 +1031,8 @@ const 
internal::ArgumentAdaptingMatcherFunc
 hasDescendant = {};
 const internal::ArgumentAdaptingMatcherFunc forEach =
 {};
+const internal::ArgumentAdaptingMatcherFunc forNone =
+{};
 const 

[clang] Add 'forNone' AST matcher (PR #86230)

2024-03-21 Thread via cfe-commits

github-actions[bot] wrote:



Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be
notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this 
page.

If this is not working for you, it is probably because you do not have write
permissions for the repository. In which case you can instead tag reviewers by
name in a comment by using `@` followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review
by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate
is once a week. Please remember that you are asking for valuable time from 
other developers.

If you have further questions, they may be answered by the [LLVM GitHub User 
Guide](https://llvm.org/docs/GitHub.html).

You can also ask questions in a comment on this PR, on the [LLVM 
Discord](https://discord.com/invite/xS7Z362) or on the 
[forums](https://discourse.llvm.org/).

https://github.com/llvm/llvm-project/pull/86230
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Add 'forNone' AST matcher (PR #86230)

2024-03-21 Thread via cfe-commits

github-actions[bot] wrote:




:warning: C/C++ code formatter, clang-format found issues in your code. 
:warning:



You can test this locally with the following command:


``bash
git-clang-format --diff 718fbbef5f18a2b7e7fc4f842b1452ae9bee581a 
b0ef223dfab9c8ebc67601ccfbbe0ce3abe15f12 -- 
clang/include/clang/ASTMatchers/ASTMatchers.h 
clang/include/clang/ASTMatchers/ASTMatchersInternal.h 
clang/lib/ASTMatchers/ASTMatchersInternal.cpp 
clang/lib/ASTMatchers/Dynamic/Registry.cpp
``





View the diff from clang-format here.


``diff
diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h 
b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
index bf5aaf74c0..31c0ec2c29 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -1645,8 +1645,8 @@ public:
   bool matches(const T , ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
 BoundNodesTreeBuilder MatchingBuilder(*Builder);
-bool AnyMatched = Finder->matchesChildOf(Node, this->InnerMatcher, 
,
-ASTMatchFinder::BK_All);
+bool AnyMatched = Finder->matchesChildOf(
+Node, this->InnerMatcher, , ASTMatchFinder::BK_All);
 if (!AnyMatched) {
   // We didn't iterate over any nodes that matched, so
   // Builder would be empty. This is a success case.

``




https://github.com/llvm/llvm-project/pull/86230
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Add 'forNone' AST matcher (PR #86230)

2024-03-21 Thread June Rhodes via cfe-commits

https://github.com/hach-que edited 
https://github.com/llvm/llvm-project/pull/86230
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Add 'forNone' AST matcher (PR #86230)

2024-03-21 Thread June Rhodes via cfe-commits

https://github.com/hach-que created 
https://github.com/llvm/llvm-project/pull/86230

This adds a `forNone` AST matcher, which matches only if there are no immediate 
children of the current node that match the inner matcher. For example, given:

```cpp
class F
{
public:
  int A;

  F() {};
};
```

the matcher:

```
cxxConstructorDecl(
unless(isImplicit()),
unless(isDelegatingConstructor()),
unless(isDeleted()),
unless(isDefaulted()),
hasBody(stmt()),
unless(ofClass(cxxRecordDecl(isUClass(,
unless(ofClass(cxxRecordDecl(isUInterface(,
ofClass(cxxRecordDecl(forEach(fieldDecl().bind("declared_field",

forNone(cxxCtorInitializer(forField(fieldDecl(equalsBoundNode("declared_field")).bind("referenced_field"
).bind("bad_constructor")
```

would match `F()`, because it does not have an initializer for `A`. We use this 
in our modified version of Clang to detect constructors that do not fully 
initialize all fields.


>From b0ef223dfab9c8ebc67601ccfbbe0ce3abe15f12 Mon Sep 17 00:00:00 2001
From: June Rhodes 
Date: Fri, 22 Mar 2024 13:07:57 +1100
Subject: [PATCH] Add 'forNone' AST matcher

---
 clang/include/clang/ASTMatchers/ASTMatchers.h |  7 
 .../clang/ASTMatchers/ASTMatchersInternal.h   | 36 +++
 clang/lib/ASTMatchers/ASTMatchersInternal.cpp |  2 ++
 clang/lib/ASTMatchers/Dynamic/Registry.cpp|  1 +
 4 files changed, 46 insertions(+)

diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h 
b/clang/include/clang/ASTMatchers/ASTMatchers.h
index 2f71053d030f68..8cc7a0e92acbdd 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -3547,6 +3547,13 @@ extern const internal::ArgumentAdaptingMatcherFunc<
 internal::ForEachDescendantMatcher>
 forEachDescendant;
 
+/// Matches AST nodes that have no child AST nodes that match the
+/// provided matcher.
+///
+/// Usable as: Any Matcher
+extern const internal::ArgumentAdaptingMatcherFunc
+forNone;
+
 /// Matches if the node or any descendant matches.
 ///
 /// Generates results for each match.
diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h 
b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
index 47d912c73dd7eb..bf5aaf74c0ef9a 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -1626,6 +1626,42 @@ class ForEachMatcher : public MatcherInterface {
   }
 };
 
+/// Matches nodes of type T that have no child nodes of type ChildT for
+/// which a specified child matcher matches. ChildT must be an AST base
+/// type.
+/// ForNoneMatcher will only match if none of the child nodes match
+/// the inner matcher.
+template 
+class ForNoneMatcher : public MatcherInterface {
+  static_assert(IsBaseType::value,
+"for none only accepts base type matcher");
+
+  DynTypedMatcher InnerMatcher;
+
+public:
+  explicit ForNoneMatcher(const Matcher )
+  : InnerMatcher(InnerMatcher) {}
+
+  bool matches(const T , ASTMatchFinder *Finder,
+   BoundNodesTreeBuilder *Builder) const override {
+BoundNodesTreeBuilder MatchingBuilder(*Builder);
+bool AnyMatched = Finder->matchesChildOf(Node, this->InnerMatcher, 
,
+ASTMatchFinder::BK_All);
+if (!AnyMatched) {
+  // We didn't iterate over any nodes that matched, so
+  // Builder would be empty. This is a success case.
+  return true;
+}
+// Otherwise remove from Builder any entries that we
+// also have in MatchingBuilder because we want to leave
+// only the remaining entries.
+return Builder->removeBindings(
+[](const internal::BoundNodesMap ) {
+  return MatchingBuilder.contains(Nodes);
+});
+  }
+};
+
 /// @}
 
 template 
diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp 
b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
index bf87b1aa0992a5..4a8f383011b336 100644
--- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -1022,6 +1022,8 @@ const 
internal::ArgumentAdaptingMatcherFunc
 hasDescendant = {};
 const internal::ArgumentAdaptingMatcherFunc forEach =
 {};
+const internal::ArgumentAdaptingMatcherFunc forNone =
+{};
 const internal::ArgumentAdaptingMatcherFunc
 forEachDescendant = {};
 const internal::ArgumentAdaptingMatcherFunc<
diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp 
b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
index 2c75e6beb74301..f6b866e6a0bcbf 100644
--- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -259,6 +259,7 @@ RegistryMaps::RegistryMaps() {
   REGISTER_MATCHER(forEachOverridden);
   REGISTER_MATCHER(forEachSwitchCase);
   REGISTER_MATCHER(forEachTemplateArgument);
+  REGISTER_MATCHER(forNone);
   REGISTER_MATCHER(forField);
   REGISTER_MATCHER(forFunction);
   REGISTER_MATCHER(forStmt);