Skip to content

[clang] preserve exact redeclaration for getTemplateInstantiationPattern#199473

Merged
mizvekov merged 1 commit into
mainfrom
users/mizvekov/get-template-inst-pattern-improvement
May 26, 2026
Merged

[clang] preserve exact redeclaration for getTemplateInstantiationPattern#199473
mizvekov merged 1 commit into
mainfrom
users/mizvekov/get-template-inst-pattern-improvement

Conversation

@mizvekov
Copy link
Copy Markdown
Contributor

This makes these functions not always return the definition if any. The few users which depend on this are updated to fetch the definition themselves.

Also fixes the VarDecl variant returning the queried declaration itself.

@mizvekov mizvekov self-assigned this May 25, 2026
@llvmorg-github-actions llvmorg-github-actions Bot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:static analyzer labels May 25, 2026
@llvmorg-github-actions
Copy link
Copy Markdown

llvmorg-github-actions Bot commented May 25, 2026

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-static-analyzer-1

Author: Matheus Izvekov (mizvekov)

Changes

This makes these functions not always return the definition if any. The few users which depend on this are updated to fetch the definition themselves.

Also fixes the VarDecl variant returning the queried declaration itself.


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

8 Files Affected:

  • (modified) clang/lib/AST/Decl.cpp (+7-28)
  • (modified) clang/lib/AST/DeclCXX.cpp (+3-10)
  • (modified) clang/lib/Sema/SemaLookup.cpp (+6-4)
  • (modified) clang/lib/StaticAnalyzer/Core/BugSuppression.cpp (+1-1)
  • (modified) clang/test/AST/ast-dump-decl.cpp (+6-6)
  • (modified) clang/test/AST/ast-dump-linkage-internal.cpp (+1-1)
  • (modified) clang/test/AST/ast-dump-linkage.cpp (+1-1)
  • (modified) clang/test/AST/ast-dump-templates-pattern.cpp (+9-10)
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 535adcb2ae109..d660fa211db3d 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -2666,14 +2666,6 @@ bool VarDecl::checkForConstantInitialization(
   return Eval->HasConstantInitialization;
 }
 
-template<typename DeclT>
-static DeclT *getDefinitionOrSelf(DeclT *D) {
-  assert(D);
-  if (auto *Def = D->getDefinition())
-    return Def;
-  return D;
-}
-
 bool VarDecl::isEscapingByref() const {
   return hasAttr<BlocksAttr>() && NonParmVarDeclBits.EscapingByref;
 }
@@ -2715,7 +2707,7 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const {
             break;
           VTD = NewVTD;
         }
-        return getDefinitionOrSelf(VTD->getTemplatedDecl());
+        return VTD->getTemplatedDecl();
       }
       if (auto *VTPSD =
               From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
@@ -2725,27 +2717,14 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const {
             break;
           VTPSD = NewVTPSD;
         }
-        return getDefinitionOrSelf<VarDecl>(VTPSD);
+        return VTPSD;
       }
     }
   }
 
-  // If this is the pattern of a variable template, find where it was
-  // instantiated from. FIXME: Is this necessary?
-  if (VarTemplateDecl *VarTemplate = VD->getDescribedVarTemplate()) {
-    while (!VarTemplate->isMemberSpecialization()) {
-      auto *NewVT = VarTemplate->getInstantiatedFromMemberTemplate();
-      if (!NewVT)
-        break;
-      VarTemplate = NewVT;
-    }
-
-    return getDefinitionOrSelf(VarTemplate->getTemplatedDecl());
-  }
-
   if (VD == this)
     return nullptr;
-  return getDefinitionOrSelf(const_cast<VarDecl*>(VD));
+  return const_cast<VarDecl *>(VD);
 }
 
 VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const {
@@ -4269,7 +4248,7 @@ FunctionDecl::getTemplateInstantiationPattern(bool ForDefinition) const {
   if (isGenericLambdaCallOperatorSpecialization(
           dyn_cast<CXXMethodDecl>(this))) {
     assert(getPrimaryTemplate() && "not a generic lambda call operator?");
-    return getDefinitionOrSelf(getPrimaryTemplate()->getTemplatedDecl());
+    return getPrimaryTemplate()->getTemplatedDecl();
   }
 
   // Check for a declaration of this function that was instantiated from a
@@ -4282,7 +4261,7 @@ FunctionDecl::getTemplateInstantiationPattern(bool ForDefinition) const {
     if (ForDefinition &&
         !clang::isTemplateInstantiation(Info->getTemplateSpecializationKind()))
       return nullptr;
-    return getDefinitionOrSelf(cast<FunctionDecl>(Info->getInstantiatedFrom()));
+    return cast<FunctionDecl>(Info->getInstantiatedFrom());
   }
 
   if (ForDefinition &&
@@ -4299,7 +4278,7 @@ FunctionDecl::getTemplateInstantiationPattern(bool ForDefinition) const {
       Primary = NewPrimary;
     }
 
-    return getDefinitionOrSelf(Primary->getTemplatedDecl());
+    return Primary->getTemplatedDecl();
   }
 
   return nullptr;
@@ -5137,7 +5116,7 @@ EnumDecl *EnumDecl::getTemplateInstantiationPattern() const {
       EnumDecl *ED = getInstantiatedFromMemberEnum();
       while (auto *NewED = ED->getInstantiatedFromMemberEnum())
         ED = NewED;
-      return ::getDefinitionOrSelf(ED);
+      return ED;
     }
   }
 
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 1a4753fc29b88..2a58313b699e2 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -2083,13 +2083,6 @@ CXXRecordDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
 }
 
 const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
-  auto GetDefinitionOrSelf =
-      [](const CXXRecordDecl *D) -> const CXXRecordDecl * {
-    if (auto *Def = D->getDefinition())
-      return Def;
-    return D;
-  };
-
   // If it's a class template specialization, find the template or partial
   // specialization from which it was instantiated.
   if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(this)) {
@@ -2100,7 +2093,7 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
           break;
         CTD = NewCTD;
       }
-      return GetDefinitionOrSelf(CTD->getTemplatedDecl());
+      return CTD->getTemplatedDecl();
     }
     if (auto *CTPSD =
             dyn_cast_if_present<ClassTemplatePartialSpecializationDecl *>(
@@ -2110,7 +2103,7 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
           break;
         CTPSD = NewCTPSD;
       }
-      return GetDefinitionOrSelf(CTPSD);
+      return CTPSD;
     }
   }
 
@@ -2119,7 +2112,7 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
       const CXXRecordDecl *RD = this;
       while (auto *NewRD = RD->getInstantiatedFromMemberClass())
         RD = NewRD;
-      return GetDefinitionOrSelf(RD);
+      return RD;
     }
   }
 
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index e4e55bb7d0ac7..65b60964d1192 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -1589,17 +1589,19 @@ static Module *getDefiningModule(Sema &S, Decl *Entity) {
     // If this function was instantiated from a template, the defining module is
     // the module containing the pattern.
     if (FunctionDecl *Pattern = FD->getTemplateInstantiationPattern())
-      Entity = Pattern;
+      Entity = Pattern->getDefinition();
   } else if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Entity)) {
     if (CXXRecordDecl *Pattern = RD->getTemplateInstantiationPattern())
-      Entity = Pattern;
+      Entity = Pattern->getDefinition();
   } else if (EnumDecl *ED = dyn_cast<EnumDecl>(Entity)) {
     if (auto *Pattern = ED->getTemplateInstantiationPattern())
-      Entity = Pattern;
+      Entity = Pattern->getDefinition();
   } else if (VarDecl *VD = dyn_cast<VarDecl>(Entity)) {
     if (VarDecl *Pattern = VD->getTemplateInstantiationPattern())
-      Entity = Pattern;
+      Entity = Pattern->getDefinition();
   }
+  if (!Entity)
+    return nullptr;
 
   // Walk up to the containing context. That might also have been instantiated
   // from a template.
diff --git a/clang/lib/StaticAnalyzer/Core/BugSuppression.cpp b/clang/lib/StaticAnalyzer/Core/BugSuppression.cpp
index b06026984775a..6c1a55f79b908 100644
--- a/clang/lib/StaticAnalyzer/Core/BugSuppression.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugSuppression.cpp
@@ -246,7 +246,7 @@ preferTemplateDefinitionForTemplateSpecializations(const Decl *D) {
   // existing parent-chain walk find the suppression attribute.
   if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
     if (const FunctionDecl *Pattern = FD->getTemplateInstantiationPattern())
-      return Pattern;
+      return Pattern->getDefinition();
   }
 
   const auto *SpecializationDecl = dyn_cast<ClassTemplateSpecializationDecl>(D);
diff --git a/clang/test/AST/ast-dump-decl.cpp b/clang/test/AST/ast-dump-decl.cpp
index 9b745642aedd0..15c2e4e07e95c 100644
--- a/clang/test/AST/ast-dump-decl.cpp
+++ b/clang/test/AST/ast-dump-decl.cpp
@@ -719,7 +719,7 @@ namespace testCanonicalTemplate {
 
   // CHECK:      VarTemplateDecl 0x{{.+}} <{{.+}}:[[@LINE-11]]:7, col:43> col:43 TestVarTemplate external-linkage{{$}}
   // CHECK-NEXT: |-TemplateTypeParmDecl 0x{{.+}} <col:16, col:25> col:25 referenced typename depth 0 index 0 T{{$}}
-  // CHECK-NEXT: |-VarDecl 0x{{.+}} <col:28, col:43> col:43 TestVarTemplate 'const T' static instantiated_from 0x{{.+}}{{$}}
+  // CHECK-NEXT: |-VarDecl 0x{{.+}} <col:28, col:43> col:43 TestVarTemplate 'const T' static{{$}}
   // CHECK-NEXT: |-VarTemplateSpecializationDecl 0x{{.+}} parent 0x{{.+}} prev 0x{{.+}} <line:[[@LINE-12]]:3, line:[[@LINE-11]]:34> col:14 referenced TestVarTemplate 'const int' implicit_instantiation cinit instantiated_from 0x{{.+}}{{$}}
   // CHECK-NEXT: | |-NestedNameSpecifier TypeSpec 'S'{{$}}
   // CHECK-NEXT: | |-TemplateArgument type 'int'{{$}}
@@ -734,7 +734,7 @@ namespace testCanonicalTemplate {
 
   // CHECK:      VarTemplateDecl 0x{{.+}} parent 0x{{.+}} prev 0x{{.+}} <{{.+}}:[[@LINE-24]]:3, line:[[@LINE-23]]:34> col:14 TestVarTemplate external-linkage{{$}}
   // CHECK-NEXT: |-TemplateTypeParmDecl 0x{{.+}} <line:[[@LINE-25]]:12, col:21> col:21 referenced typename depth 0 index 0 T{{$}}
-  // CHECK-NEXT: |-VarDecl 0x{{.+}} parent 0x{{.+}} prev 0x{{.+}} <line:[[@LINE-25]]:3, col:34> col:14 TestVarTemplate 'const T' cinit instantiated_from 0x{{.+}}{{$}}
+  // CHECK-NEXT: |-VarDecl 0x{{.+}} parent 0x{{.+}} prev 0x{{.+}} <line:[[@LINE-25]]:3, col:34> col:14 TestVarTemplate 'const T' cinit{{$}}
   // CHECK-NEXT: | |-NestedNameSpecifier TypeSpec 'S'{{$}}
   // CHECK-NEXT: | `-InitListExpr 0x{{.+}} <col:32, col:34> 'void' explicit{{$}}
   // CHECK-NEXT: |-VarTemplateSpecialization 0x{{.+}} 'TestVarTemplate' 'const int'{{$}}
@@ -945,13 +945,13 @@ namespace TestConstexprVariableTemplateWithInitializer {
   template<typename T> constexpr T foo{};
   // CHECK:      VarTemplateDecl 0x{{.+}} <{{.+}}:[[@LINE-1]]:3, col:40> col:36 foo external-linkage{{$}}
   // CHECK-NEXT: |-TemplateTypeParmDecl 0x{{.+}} <col:12, col:21> col:21 referenced typename depth 0 index 0 T{{$}}
-  // CHECK-NEXT: `-VarDecl 0x{{.+}} <col:24, col:40> col:36 foo 'const T' constexpr listinit instantiated_from 0x{{.+}}{{$}}
+  // CHECK-NEXT: `-VarDecl 0x{{.+}} <col:24, col:40> col:36 foo 'const T' constexpr listinit{{$}}
   // CHECK-NEXT:  `-InitListExpr 0x{{.+}} <col:39, col:40> 'void' explicit{{$}}
 
   template<typename T> constexpr int val{42};
   // CHECK:      VarTemplateDecl 0x{{.+}} <{{.+}}:[[@LINE-1]]:3, col:44> col:38 val external-linkage{{$}}
   // CHECK-NEXT: |-TemplateTypeParmDecl 0x{{.+}} <col:12, col:21> col:21 typename depth 0 index 0 T{{$}}
-  // CHECK-NEXT: `-VarDecl 0x{{.+}} <col:24, col:44> col:38 val 'const int' constexpr listinit instantiated_from 0x{{.+}}{{$}}
+  // CHECK-NEXT: `-VarDecl 0x{{.+}} <col:24, col:44> col:38 val 'const int' constexpr listinit{{$}}
   // CHECK-NEXT:  |-value: Int 42{{$}}
   // CHECK-NEXT:  `-InitListExpr 0x{{.+}} <col:41, col:44> 'int' explicit{{$}}
 
@@ -964,13 +964,13 @@ namespace TestConstexprVariableTemplateWithInitializer {
   inline constexpr in_place_type_t<_Tp> in_place_type{};
   // CHECK:     -VarTemplateDecl 0x{{.+}} <line:[[@LINE-2]]:3, line:[[@LINE-1]]:55> col:41 in_place_type external-linkage{{$}}
   // CHECK-NEXT: |-TemplateTypeParmDecl 0x{{.+}} <line:[[@LINE-3]]:13, col:22> col:22 referenced typename depth 0 index 0 _Tp{{$}}
-  // CHECK-NEXT: `-VarDecl 0x{{.+}} <line:[[@LINE-3]]:3, col:55> col:41 in_place_type 'const in_place_type_t<_Tp>' inline constexpr listinit instantiated_from 0x{{.+}}{{$}}
+  // CHECK-NEXT: `-VarDecl 0x{{.+}} <line:[[@LINE-3]]:3, col:55> col:41 in_place_type 'const in_place_type_t<_Tp>' inline constexpr listinit{{$}}
   // CHECK-NEXT:  `-InitListExpr 0x{{.+}} <col:54, col:55> 'void' explicit{{$}}
 
   template <typename T> constexpr T call_init(0);
   // CHECK:     -VarTemplateDecl 0x{{.+}} <line:[[@LINE-1]]:3, col:48> col:37 call_init external-linkage{{$}}
   // CHECK-NEXT: |-TemplateTypeParmDecl 0x{{.+}} <col:13, col:22> col:22 referenced typename depth 0 index 0 T{{$}}
-  // CHECK-NEXT: `-VarDecl 0x{{.+}} <col:25, col:48> col:37 call_init 'const T' constexpr callinit instantiated_from 0x{{.+}}{{$}}
+  // CHECK-NEXT: `-VarDecl 0x{{.+}} <col:25, col:48> col:37 call_init 'const T' constexpr callinit{{$}}
   // CHECK-NEXT:  `-ParenListExpr 0x{{.+}} <col:46, col:48> 'NULL TYPE'{{$}}
   // CHECK-NEXT:   `-IntegerLiteral 0x{{.+}} <col:47> 'int' 0{{$}}
 }
diff --git a/clang/test/AST/ast-dump-linkage-internal.cpp b/clang/test/AST/ast-dump-linkage-internal.cpp
index 6b961301c4abb..1d88fe3a41d37 100644
--- a/clang/test/AST/ast-dump-linkage-internal.cpp
+++ b/clang/test/AST/ast-dump-linkage-internal.cpp
@@ -80,7 +80,7 @@ const int ConstInt = 0;
 template <typename T>
 T TemplatedVar = T{};
 // CHECK: | |-VarTemplateDecl {{.*}} TemplatedVar internal-linkage
-// CHECK: | | |-VarDecl {{.*}} TemplatedVar 'T' cinit instantiated_from 0x{{[0-9a-f]*}}
+// CHECK: | | |-VarDecl {{.*}} TemplatedVar 'T' cinit
 // CHECK: | | `-VarTemplateSpecializationDecl {{.*}} used TemplatedVar 'int' implicit_instantiation cinit instantiated_from 0x{{[0-9a-f]*}} internal-linkage
 
 // FIXME: VarTemplateSpecializationDecl node is printed twice.
diff --git a/clang/test/AST/ast-dump-linkage.cpp b/clang/test/AST/ast-dump-linkage.cpp
index 18228eb4e8c21..b4ede9a522871 100644
--- a/clang/test/AST/ast-dump-linkage.cpp
+++ b/clang/test/AST/ast-dump-linkage.cpp
@@ -77,7 +77,7 @@ const int ConstInt = 0;
 template <typename T>
 T TemplatedVar = T{};
 // CHECK: |-VarTemplateDecl {{.*}} TemplatedVar external-linkage
-// CHECK: | |-VarDecl {{.*}} TemplatedVar 'T' cinit instantiated_from 0x{{[0-9a-f]*}}
+// CHECK: | |-VarDecl {{.*}} TemplatedVar 'T' cinit
 // CHECK: | `-VarTemplateSpecializationDecl {{.*}} used TemplatedVar 'int' implicit_instantiation cinit instantiated_from 0x{{[0-9a-f]*}} external-linkage
 
 // FIXME: VarTemplateSpecializationDecl node is printed twice.
diff --git a/clang/test/AST/ast-dump-templates-pattern.cpp b/clang/test/AST/ast-dump-templates-pattern.cpp
index 6938f650cc50b..aec86664f9988 100644
--- a/clang/test/AST/ast-dump-templates-pattern.cpp
+++ b/clang/test/AST/ast-dump-templates-pattern.cpp
@@ -18,7 +18,7 @@ namespace TestClassRedecl {
 // CHECK: |-ClassTemplateDecl {{.+}} <line:[[@LINE-6]]:{{.+}} A  external-linkage
 // CHECK: | |-CXXRecordDecl 0x[[TestClassRedecl_D2:[^ ]+]] prev 0x[[TestClassRedecl_D1]] {{.+}} struct A
 // CHECK: | `-ClassTemplateSpecialization 0x[[TestClassRedecl_S]] 'A'
-// CHECK: |-ClassTemplateSpecializationDecl 0x[[TestClassRedecl_S]] <line:[[@LINE-8]]:{{.+}} struct A definition external-linkage instantiated_from 0x[[TestClassRedecl_D1]] explicit_instantiation_definition
+// CHECK: |-ClassTemplateSpecializationDecl 0x[[TestClassRedecl_S]] <line:[[@LINE-8]]:{{.+}} struct A definition external-linkage instantiated_from 0x[[TestClassRedecl_D2]] explicit_instantiation_definition
 // CHECK: `-ExplicitInstantiationDecl {{.+}} <line:[[@LINE-9]]:{{.+}} 'A'
 // CHECK:   |-ClassTemplateSpecialization 0x[[TestClassRedecl_S]] 'A'
 // CHECK:   `-TemplateArgument {{.+}} type 'int'
@@ -32,9 +32,9 @@ namespace TestFunctionRedecl {
 // CHECK-LABEL: Dumping TestFunctionRedecl:
 // CHECK: |-FunctionTemplateDecl 0x[[TestFunctionRedecl_T1:[^ ]+]] <line:[[@LINE-4]]:{{.+}} f external-linkage
 // CHECK: | |-FunctionDecl 0x[[TestFunctionRedecl_D1:[^ ]+]] {{.+}} f 'void ()'
-// CHECK: | `-FunctionDecl 0x[[TestFunctionRedecl_S1:[^ ]+]] {{.+}} f 'void ()' explicit_instantiation_definition instantiated_from 0x[[TestFunctionRedecl_D1]] external-linkage
+// CHECK: | `-FunctionDecl 0x[[TestFunctionRedecl_S1:[^ ]+]] {{.+}} f 'void ()' explicit_instantiation_definition instantiated_from 0x[[TestFunctionRedecl_D2:[^ ]+]] external-linkage
 // CHECK: |-FunctionTemplateDecl 0x[[TestFunctionRedecl_T2:[^ ]+]] prev 0x[[TestFunctionRedecl_T1]] <line:[[@LINE-6]]:{{.+}} f external-linkage
-// CHECK: | |-FunctionDecl 0x[[TestFunctionRedecl_D2:[^ ]+]] prev 0x[[TestFunctionRedecl_D1]] {{.+}} f 'void ()'
+// CHECK: | |-FunctionDecl 0x[[TestFunctionRedecl_D2]] prev 0x[[TestFunctionRedecl_D1]] {{.+}} f 'void ()'
 // CHECK: | `-Function 0x[[TestFunctionRedecl_S1]] 'f' 'void ()'
 // CHECK: `-ExplicitInstantiationDecl {{.+}} <line:[[@LINE-8]]:{{.+}} 'f'
 // CHECK:   |-Function 0x[[TestFunctionRedecl_S1]] 'f' 'void ()'
@@ -44,19 +44,18 @@ namespace TestFunctionRedecl {
 // CHECK:     `-BuiltinType {{.+}} 'int'
 }
 
-// FIXME: Bogus instantiated_from self-reference.
 namespace TestVariableRedecl {
   template <class T> T a = 0;
   template <class T> extern T a;
   template int a<int>;
 // CHECK-LABEL: Dumping TestVariableRedecl:
 // CHECK: |-VarTemplateDecl 0x[[TestVariableRedecl_T1:[^ ]+]] <line:[[@LINE-4]]:{{.+}} a external-linkage
-// CHECK: | |-VarDecl 0x[[TestVariableRedecl_D1:[^ ]+]] {{.+}} a 'T' cinit instantiated_from 0x[[TestVariableRedecl_D1]]
+// CHECK: | |-VarDecl 0x[[TestVariableRedecl_D1:[^ ]+]] {{.+}} a 'T' cinit{{$}}
 // CHECK: | `-VarTemplateSpecialization 0x[[TestVariableRedecl_S1:[^ ]+]] 'a' 'int'
 // CHECK: |-VarTemplateDecl 0x[[TestVariableRedecl_T2:[^ ]+]] prev 0x[[TestVariableRedecl_T1]] <line:[[@LINE-6]]:{{.+}} a external-linkage
-// CHECK: | |-VarDecl 0x[[TestVariableRedecl_D2:[^ ]+]] prev 0x[[TestVariableRedecl_D1]] {{.+}} a 'T' extern instantiated_from 0x[[TestVariableRedecl_D1]]
+// CHECK: | |-VarDecl 0x[[TestVariableRedecl_D2:[^ ]+]] prev 0x[[TestVariableRedecl_D1]] {{.+}} a 'T' extern{{$}}
 // CHECK: | `-VarTemplateSpecialization 0x[[TestVariableRedecl_S1]] 'a' 'int'
-// CHECK: |-VarTemplateSpecializationDecl 0x[[TestVariableRedecl_S1]] {{.+}} a 'int' explicit_instantiation_definition cinit instantiated_from 0x[[TestVariableRedecl_D1]] external-linkage
+// CHECK: |-VarTemplateSpecializationDecl 0x[[TestVariableRedecl_S1]] {{.+}} a 'int' explicit_instantiation_definition cinit instantiated_from 0x[[TestVariableRedecl_D2]] external-linkage
 // CHECK: `-ExplicitInstantiationDecl {{.+}} <line:[[@LINE-9]]:{{.+}} 'a'
 // CHECK:   |-VarTemplateSpecialization 0x[[TestVariableRedecl_S1]] 'a' 'int'
 // CHECK:   |-BuiltinTypeLoc {{.+}} 'int'
@@ -76,16 +75,16 @@ namespace TestNestedClassRedecl {
 // CHECK: | |-CXXRecordDecl 0x[[TestNestedClassRedecl_A_D1:[^ ]+]] <{{.+}}line:[[@LINE-6]]:{{.+}}> line:[[@LINE-8]]:{{.+}} struct A definition
 // CHECK: | | `-ClassTemplateDecl 0x[[TestNestedClassRedecl_B_T1:[^ ]+]] <line:[[@LINE-8]]:{{.+}} B external-linkage
 // CHECK: | |   `-CXXRecordDecl 0x[[TestNestedClassRedecl_B_D1:[^ ]+]] {{.+}} struct B
-// CHECK: | `-ClassTemplateSpecializationDecl 0x[[TestNestedClassRedecl_A_S1:[^ ]+]] <line:[[@LINE-8]]:{{.+}} line:[[@LINE-11]]:{{.+}} struct A definition external-linkage instantiated_from 0x[[TestNestedClassRedecl_A_D1]] implicit_instantiation
+// CHECK: | `-ClassTemplateSpecializationDecl 0x[[TestNestedClassRedecl_A_S1:[^ ]+]] <line:[[@LINE-8]]:{{.+}} line:[[@LINE-11]]:{{.+}} struct A definition external-linkage instantiated_from 0x[[TestNestedClassRedecl_A_D2:[^ ]+]] implicit_instantiation
 // CHECK: |   `-ClassTemplateDecl 0x{{.+}} <line:[[@LINE-11]]:{{.+}} B external-linkage
 // CHECK: |     |-CXXRecordDecl 0x{{.+}} struct B
 // CHECK: |     `-ClassTemplateSpecialization  0x[[TestNestedClassRedecl_B_S1:[^ ]+]] 'B'
 // CHECK: |-ClassTemplateDecl 0x{{.+}} prev 0x[[TestNestedClassRedecl_A_T1]] <line:[[@LINE-12]]:{{.+}} A external-linkage
-// CHECK: | |-CXXRecordDecl 0x[[TestNestedClassRedecl_A_D2:[^ ]+]] prev 0x[[TestNestedClassRedecl_A_D1]] {{.+}} struct A
+// CHECK: | |-CXXRecordDecl 0x[[TestNestedClassRedecl_A_D2]] prev 0x[[TestNestedClassRedecl_A_D1]] {{.+}} struct A
 // CHECK: | `-ClassTemplateSpecialization 0x[[TestNestedClassRedecl_A_S1]] 'A'
 // CHECK: |-ClassTemplateDecl 0x{{.+}} parent 0x[[TestNestedClassRedecl_A_D1]] prev 0x[[TestNestedClassRedecl_B_T1]] <line:[[@LINE-14]]:{{.+}} B external-linkage
 // CHECK: | `-CXXRecordDecl 0x[[TestNestedClassRedecl_B_D2:[^ ]+]] parent 0x[[TestNestedClassRedecl_A_D1]] prev 0x[[TestNestedClassRedecl_B_D1]] {{.+}} struct B definition
-// CHECK: |-ClassTemplateSpecializationDecl 0x[[TestNestedClassRedecl_B_S1]] parent 0x[[TestNestedClassRedecl_A_S1]] <line:[[@LINE-15]]:{{.+}} struct B definition external-linkage instantiated_from 0x[[TestNestedClassRedecl_B_D2]] explicit_instantiation_definition
+// CHECK: |-ClassTemplateSpecializationDecl 0x[[TestNestedClassRedecl_B_S1]] parent 0x[[TestNestedClassRedecl_A_S1]] <line:[[@LINE-15]]:{{.+}} struct B definition external-linkage instantiated_from 0x[[TestNestedClassRedecl_B_D1]] explicit_instantiation_definition
 // CHECK: `-ExplicitInstantiationDecl {{.+}} <line:[[@LINE-16]]:{{.+}} 'B'
 // CHECK:   |-NestedNameSpecifier TypeSpec {{.+}}
 // CHECK:   |-ClassTemplateSpecialization 0x[[TestNestedClassRedecl_B_S1]] 'B'

@mizvekov mizvekov requested review from cor3ntin and zyn0217 May 25, 2026 12:09
This makes these functions not always return the definition if any.
The few users which depend on this are updated to fetch the definition
themselves.

Also fixes the VarDecl variant returning the queried declaration itself.
@mizvekov mizvekov force-pushed the users/mizvekov/get-template-inst-pattern-improvement branch from ad0e4c0 to 720dd96 Compare May 25, 2026 13:31
@mizvekov
Copy link
Copy Markdown
Contributor Author

FYI this is a dependency of #199528

@zyn0217
Copy link
Copy Markdown
Contributor

zyn0217 commented May 26, 2026

Can we add those regression tests from #111852 ? The last attempt seemed to break everything badly and I hope we don't have to suffer from the same thing this time. Thanks

edit: NVM I missed your comment from #199528

Copy link
Copy Markdown
Contributor

@erichkeane erichkeane left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems reasonable to me

@mizvekov mizvekov merged commit 3a25f7b into main May 26, 2026
10 checks passed
@mizvekov mizvekov deleted the users/mizvekov/get-template-inst-pattern-improvement branch May 26, 2026 14:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:static analyzer clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants