[clang] Add 'refersToPack' AST matcher (PR #86228)

via cfe-commits cfe-commits at lists.llvm.org
Thu Mar 21 19:04:00 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: June Rhodes (hach-que)

<details>
<summary>Changes</summary>

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.

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


2 Files Affected:

- (modified) clang/include/clang/ASTMatchers/ASTMatchers.h (+29) 
- (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..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);

``````````

</details>


https://github.com/llvm/llvm-project/pull/86228


More information about the cfe-commits mailing list