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

This adds a 'refersToPack' AST matcher, which can be used to match against 
template arguments that are inside parameter packs. The inner matcher is 
evaluated against each argument in the parameter pack, such that given:

```cpp
template<typename T, typename... Params> class A {};
A<int, double> a;
A<double, int> b;
A<double, int, long> c;
```

The matcher 
`classTemplateSpecializationDecl(hasAnyTemplateArgument(refersToPack(refersToType(...))))`
 would evaluate the `refersToType` against:

- For `a`, the `double` template argument. 
- For `b`, the `int` template argument.
- For `c`, the `int` template argument, then the `long` template argument.

If the inner matcher matches against any argument of the parameter pack, then 
`refersToPack` matches.

>From e298ea2437dfdd3d44e7d53ef2a5e41bf17bd329 Mon Sep 17 00:00:00 2001
From: June Rhodes <jrhodes@redpoint.games>
Date: Fri, 22 Mar 2024 12:51:40 +1100
Subject: [PATCH] Add 'refersToPack' AST matcher

---
 clang/include/clang/ASTMatchers/ASTMatchers.h | 29 +++++++++++++++++++
 clang/lib/ASTMatchers/Dynamic/Registry.cpp    |  1 +
 2 files changed, 30 insertions(+)

diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h 
b/clang/include/clang/ASTMatchers/ASTMatchers.h
index 2f71053d030f68..df30d4c85c22c6 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -1151,6 +1151,35 @@ AST_MATCHER_P(TemplateArgument, refersToDeclaration,
   return false;
 }
 
+/// Matches template arguments within a pack template argument; the inner
+/// matcher is compared against each argument of the parameter pack.
+///
+/// Given
+/// \code
+///   template<typename T, typename... Params> class A {};
+///   A<int, double> a;
+///   A<double, int> b;
+/// \endcode
+///
+/// \endcode
+/// classTemplateSpecializationDecl(hasAnyTemplateArgument(
+///     refersToPack(refersToType(asString("double")))))
+///   matches the specialization \c A<int, double>
+///   but does not match the specialization \c A<double, int>
+AST_MATCHER_P(TemplateArgument, refersToPack,
+              internal::Matcher<TemplateArgument>, InnerMatcher) {
+  if (Node.getKind() == TemplateArgument::Pack) {
+    for (const TemplateArgument &Arg : Node.pack_elements()) {
+      BoundNodesTreeBuilder Result(*Builder);
+      if (InnerMatcher.matches(Arg, Finder, &Result)) {
+        *Builder = std::move(Result);
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
 /// Matches a sugar TemplateArgument that refers to a certain expression.
 ///
 /// Given
diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp 
b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
index 2c75e6beb74301..732d49e850288a 100644
--- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -551,6 +551,7 @@ RegistryMaps::RegistryMaps() {
   REGISTER_MATCHER(referenceType);
   REGISTER_MATCHER(referenceTypeLoc);
   REGISTER_MATCHER(refersToDeclaration);
+  REGISTER_MATCHER(refersToPack);
   REGISTER_MATCHER(refersToIntegralType);
   REGISTER_MATCHER(refersToTemplate);
   REGISTER_MATCHER(refersToType);

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to