[clang-tools-extra] [clang-tidy] do not diagnose array types within implicit instantiations of a template (PR #132924)

Julian Schmidt via cfe-commits cfe-commits at lists.llvm.org
Sun Aug 31 15:40:34 PDT 2025


================
@@ -39,6 +39,55 @@ AST_MATCHER(clang::ParmVarDecl, isArgvOfMain) {
   return FD ? FD->isMain() : false;
 }
 
+template <typename TargetType, typename NodeType>
+const TargetType *getAs(const NodeType *Node) {
+  if constexpr (std::is_same_v<NodeType, clang::DynTypedNode>)
+    return Node->template get<TargetType>();
+  else
+    return llvm::dyn_cast<TargetType>(Node);
+}
+
+AST_MATCHER(clang::TypeLoc, isWithinImplicitTemplateInstantiation) {
+  const auto IsImplicitTemplateInstantiation = [](const auto *Node) {
+    const auto IsImplicitInstantiation = [](const auto *Node) {
+      return (Node != nullptr) && (Node->getTemplateSpecializationKind() ==
+                                   TSK_ImplicitInstantiation);
+    };
+    return (IsImplicitInstantiation(getAs<clang::CXXRecordDecl>(Node)) ||
+            IsImplicitInstantiation(getAs<clang::FunctionDecl>(Node)) ||
+            IsImplicitInstantiation(getAs<clang::VarDecl>(Node)));
+  };
+
+  DynTypedNodeList ParentNodes = Finder->getASTContext().getParents(Node);
+  const clang::NamedDecl *ParentDecl = nullptr;
+  while (!ParentNodes.empty()) {
+    const DynTypedNode &ParentNode = ParentNodes[0];
+    if (IsImplicitTemplateInstantiation(&ParentNode))
+      return true;
+
+    // in case of a `NamedDecl` as parent node, it is more efficient to proceed
+    // with the upward traversal via DeclContexts (see below) instead of via
+    // parent nodes
+    if ((ParentDecl = ParentNode.template get<clang::NamedDecl>()))
+      break;
+
+    ParentNodes = Finder->getASTContext().getParents(ParentNode);
+  }
+
+  if (ParentDecl != nullptr) {
+    const clang::DeclContext *DeclContext = ParentDecl->getDeclContext();
+    while (DeclContext != nullptr) {
+      for (const clang::Decl *Decl : DeclContext->decls()) {
+        if (IsImplicitTemplateInstantiation(Decl))
+          return true;
+      }
----------------
5chmidti wrote:

This would traverse down again. Certain things like `FunctionDecl` inherit from `DeclContext`, so, instead you should use the `DeclContext` variable itself to check for the template instantiation kind (`getAs` might work, otherwise you can use `llvm::dyn_cast` in the above lambda). Otherwise, you would check e.g. `C` when you were really just looking at `B`. The `decls()`  method gives you the contained declarations of the DeclContext.

```
    A
  /   \
B      C
```

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


More information about the cfe-commits mailing list