[clang] [clang-tools-extra] [RecursiveASTVisitor] Skip implicit instantiations. (PR #110899)

Harald van Dijk via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 24 05:23:06 PDT 2025


https://github.com/hvdijk updated https://github.com/llvm/llvm-project/pull/110899

>From fb5731c1c7595a9c721cb29c2a94a4c683090436 Mon Sep 17 00:00:00 2001
From: Harald van Dijk <harald.vandijk at codeplay.com>
Date: Wed, 24 Sep 2025 13:22:39 +0100
Subject: [PATCH] [RecursiveASTVisitor] Assert we skip implicit instantiations.

In DEF_TRAVERSE_TMPL_SPEC_DECL, we attempt to skip implicit instantiations
by detecting that D->getTemplateArgsAsWritten() returns nullptr.
Previously, this was not reliable. To ensure we do not regress, add an
assertion and a test.
---
 .../checkers/modernize/type-traits.cpp        | 24 +++++++++++++++++++
 clang/include/clang/AST/RecursiveASTVisitor.h |  1 +
 2 files changed, 25 insertions(+)

diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/type-traits.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/type-traits.cpp
index 97ba1fce2a1ec..e5de9e33bccd9 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/type-traits.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/type-traits.cpp
@@ -14,11 +14,25 @@ namespace std {
     static constexpr bool value = true;
   };
 
+  template <typename T, typename U>
+  static constexpr bool is_same_v = is_same<T, U>::value;  // NOLINT
+
   template<bool, typename T = void>
   struct enable_if {
     using type = T;
   };
 
+  template <bool B, typename T = void>
+  using enable_if_t = typename enable_if<B, T>::type;  // NOLINT
+
+  template <typename T>
+  struct remove_reference {
+    using type = T;
+  };
+
+  template <typename T>
+  using remove_reference_t = typename remove_reference<T>::type;  // NOLINT
+
   template <typename...>
   struct common_type {
     using type = int;
@@ -126,3 +140,13 @@ namespace my_std = std;
 using Alias = my_std::add_const<bool>::type;
 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use c++14 style type templates
 // CHECK-FIXES: using Alias = my_std::add_const_t<bool>;
+
+template <typename T>
+struct ImplicitlyInstantiatedConstructor {
+  template <typename U, typename = std::enable_if_t<std::is_same_v<U, T>>>
+  ImplicitlyInstantiatedConstructor(U) {}
+};
+
+const ImplicitlyInstantiatedConstructor<int> ImplicitInstantiation(std::remove_reference<int>::type(123));
+// CHECK-MESSAGES: :[[@LINE-1]]:68: warning: use c++14 style type templates
+// CHECK-FIXES: const ImplicitlyInstantiatedConstructor<int> ImplicitInstantiation(std::remove_reference_t<int>(123));
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 1d1b7f183f75a..af1a073cc4a5a 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2194,6 +2194,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper(
        is the only callback that's made for this instantiation.                \
        We use getTemplateArgsAsWritten() to distinguish. */                    \
     if (const auto *ArgsWritten = D->getTemplateArgsAsWritten()) {             \
+      assert(D->getTemplateSpecializationKind() != TSK_ImplicitInstantiation); \
       /* The args that remains unspecialized. */                               \
       TRY_TO(TraverseTemplateArgumentLocsHelper(                               \
           ArgsWritten->getTemplateArgs(), ArgsWritten->NumTemplateArgs));      \



More information about the cfe-commits mailing list