https://github.com/iamaayushrivastava updated 
https://github.com/llvm/llvm-project/pull/200161

>From 4b927eda9cfaf7c1fb70499ef7e5e4fc372dc34c Mon Sep 17 00:00:00 2001
From: iamaayushrivastava <[email protected]>
Date: Thu, 28 May 2026 16:57:01 +0530
Subject: [PATCH 1/4] [clang] Fix crash in
 VisitVarTemplatePartialSpecializationDecl

---
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  |  9 +++--
 clang/test/SemaTemplate/GH198890.cpp          | 37 +++++++++++++++++++
 2 files changed, 43 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/SemaTemplate/GH198890.cpp

diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp 
b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 324d6bf3857c7..141358325dee7 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2533,12 +2533,15 @@ Decl 
*TemplateDeclInstantiator::VisitVarTemplatePartialSpecializationDecl(
 
   VarTemplateDecl *VarTemplate = D->getSpecializedTemplate();
 
-  // Lookup the already-instantiated declaration and return that.
+  // Lookup the already-instantiated declaration in the instantiation
+  // of the class template and return that.
   DeclContext::lookup_result Found = Owner->lookup(VarTemplate->getDeclName());
-  assert(!Found.empty() && "Instantiation found nothing?");
+  if (Found.empty())
+    return nullptr;
 
   VarTemplateDecl *InstVarTemplate = dyn_cast<VarTemplateDecl>(Found.front());
-  assert(InstVarTemplate && "Instantiation did not find a variable template?");
+  if (!InstVarTemplate)
+    return nullptr;
 
   if (VarTemplatePartialSpecializationDecl *Result =
           InstVarTemplate->findPartialSpecInstantiatedFromMember(D))
diff --git a/clang/test/SemaTemplate/GH198890.cpp 
b/clang/test/SemaTemplate/GH198890.cpp
new file mode 100644
index 0000000000000..ccf1c0a136c8f
--- /dev/null
+++ b/clang/test/SemaTemplate/GH198890.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
+
+// GitHub issue #198890
+// https://github.com/llvm/llvm-project/issues/198890
+//
+// VisitVarTemplatePartialSpecializationDecl used hard assert() calls where the
+// analogous VisitClassTemplatePartialSpecializationDecl used graceful null
+// checks and return nullptr. In a release build (no assertions), the assert 
was
+// compiled out and a null-pointer dereference (SIGSEGV) followed.
+//
+// The crash is triggered when the primary member variable template fails to
+// instantiate (returning nullptr from VisitVarTemplateDecl), so that the
+// subsequent lookup for the instantiated VarTemplateDecl in Owner comes back
+// empty. Without the fix, VisitVarTemplatePartialSpecializationDecl would then
+// dereference a null / invalid pointer via Found.front().
+
+namespace GH198890 {
+
+// T::type does not exist for plain types like int or void.
+// When Outer<int> is instantiated, substituting typename T::type for T=int
+// fails, VisitVarTemplateDecl returns nullptr, and the instantiated
+// VarTemplateDecl is never added to Owner.  The partial specialisation is
+// visited next; Owner->lookup("member") returns empty, which previously
+// triggered the assert / SIGSEGV.
+
+template <typename T>
+struct Outer {
+  template <typename U>
+  static typename T::type member; // expected-error {{type 'int' cannot be 
used prior to '::' because it has no members}}
+
+  template <typename U>
+  static typename T::type member<U *>; // partial specialization
+};
+
+template struct Outer<int>; // expected-note {{in instantiation of template 
class 'GH198890::Outer<int>' requested here}}
+
+} // namespace GH198890

>From a597114a0a58faafc4965b795967b26de5aba93e Mon Sep 17 00:00:00 2001
From: iamaayushrivastava <[email protected]>
Date: Fri, 29 May 2026 04:19:41 +0530
Subject: [PATCH 2/4] [clang] Fix crash in
 VisitVarTemplatePartialSpecializationDecl

---
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  | 14 +++++----
 clang/test/SemaTemplate/GH198890.cpp          | 29 ++++++-------------
 2 files changed, 18 insertions(+), 25 deletions(-)

diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp 
b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 141358325dee7..0485322468489 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1760,13 +1760,14 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,
   TypeSourceInfo *TSI = SemaRef.SubstType(
       D->getTypeSourceInfo(), TemplateArgs, D->getTypeSpecStartLoc(),
       D->getDeclName(), /*AllowDeducedTST*/ true);
-  if (!TSI)
-    return nullptr;
-
-  if (TSI->getType()->isFunctionType()) {
+  bool Invalid = false;
+  if (!TSI) {
+    TSI = D->getTypeSourceInfo();
+    Invalid = true;
+  } else if (TSI->getType()->isFunctionType()) {
     SemaRef.Diag(D->getLocation(), diag::err_variable_instantiates_to_function)
         << D->isStaticDataMember() << TSI->getType();
-    return nullptr;
+    Invalid = true;
   }
 
   DeclContext *DC = Owner;
@@ -1835,6 +1836,9 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,
   if (SemaRef.getLangOpts().OpenACC)
     SemaRef.OpenACC().ActOnVariableDeclarator(Var);
 
+  if (Invalid)
+    Var->setInvalidDecl();
+
   return Var;
 }
 
diff --git a/clang/test/SemaTemplate/GH198890.cpp 
b/clang/test/SemaTemplate/GH198890.cpp
index ccf1c0a136c8f..84a0b4d674fe5 100644
--- a/clang/test/SemaTemplate/GH198890.cpp
+++ b/clang/test/SemaTemplate/GH198890.cpp
@@ -1,35 +1,24 @@
 // RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
 
-// GitHub issue #198890
-// https://github.com/llvm/llvm-project/issues/198890
+// GitHub issue #198890: crash in VisitVarTemplatePartialSpecializationDecl
+// when the primary member variable template fails to instantiate.
 //
-// VisitVarTemplatePartialSpecializationDecl used hard assert() calls where the
-// analogous VisitClassTemplatePartialSpecializationDecl used graceful null
-// checks and return nullptr. In a release build (no assertions), the assert 
was
-// compiled out and a null-pointer dereference (SIGSEGV) followed.
-//
-// The crash is triggered when the primary member variable template fails to
-// instantiate (returning nullptr from VisitVarTemplateDecl), so that the
-// subsequent lookup for the instantiated VarTemplateDecl in Owner comes back
-// empty. Without the fix, VisitVarTemplatePartialSpecializationDecl would then
-// dereference a null / invalid pointer via Found.front().
+// When Outer<int> is instantiated, substituting typename T::type for T=int
+// fails for both the primary template member and the partial specialization.
+// The fix recovers from substitution failure in VisitVarDecl (marking the
+// declaration invalid) so the VarTemplateDecl is still registered in the
+// owner, allowing VisitVarTemplatePartialSpecializationDecl to find it via
+// lookup without crashing.
 
 namespace GH198890 {
 
-// T::type does not exist for plain types like int or void.
-// When Outer<int> is instantiated, substituting typename T::type for T=int
-// fails, VisitVarTemplateDecl returns nullptr, and the instantiated
-// VarTemplateDecl is never added to Owner.  The partial specialisation is
-// visited next; Owner->lookup("member") returns empty, which previously
-// triggered the assert / SIGSEGV.
-
 template <typename T>
 struct Outer {
   template <typename U>
   static typename T::type member; // expected-error {{type 'int' cannot be 
used prior to '::' because it has no members}}
 
   template <typename U>
-  static typename T::type member<U *>; // partial specialization
+  static typename T::type member<U *>; // expected-error {{type 'int' cannot 
be used prior to '::' because it has no members}}
 };
 
 template struct Outer<int>; // expected-note {{in instantiation of template 
class 'GH198890::Outer<int>' requested here}}

>From e42795d83a36ca2ecbc42e3f105c85483069d404 Mon Sep 17 00:00:00 2001
From: iamaayushrivastava <[email protected]>
Date: Fri, 29 May 2026 05:01:11 +0530
Subject: [PATCH 3/4] [clang] Fix regression in VisitVarDecl error recovery

---
 clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp 
b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 0485322468489..b060d889abaa5 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1762,11 +1762,15 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,
       D->getDeclName(), /*AllowDeducedTST*/ true);
   bool Invalid = false;
   if (!TSI) {
+    if (!InstantiatingVarTemplate)
+      return nullptr;
     TSI = D->getTypeSourceInfo();
     Invalid = true;
   } else if (TSI->getType()->isFunctionType()) {
     SemaRef.Diag(D->getLocation(), diag::err_variable_instantiates_to_function)
         << D->isStaticDataMember() << TSI->getType();
+    if (!InstantiatingVarTemplate)
+      return nullptr;
     Invalid = true;
   }
 

>From dff74b053162c07d059fd0f4a09153e945b410aa Mon Sep 17 00:00:00 2001
From: iamaayushrivastava <[email protected]>
Date: Fri, 29 May 2026 06:22:13 +0530
Subject: [PATCH 4/4] [clang] Fix crash when member variable template type
 substitution fails

---
 clang/docs/ReleaseNotes.md                     |  5 +++++
 clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 12 +++++-------
 2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index ba9572e2e7c59..af80d8b9d0495 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -789,6 +789,11 @@ latest release, please see the [Clang Web 
Site](https://clang.llvm.org) or the
 - Clang incorrectly instantiated variable specializations outside of the 
immediate context. (#GH54439)
 - Fixed a crash when pack expansions are used as arguments for non-pack 
parameters of built-in templates. (#GH180307)
 - Fixed crash instantiating class member specializations.
+- Fixed a crash during class template instantiation when a member variable
+  template's type substitution fails (e.g. `typename T::type` with `T=int`),
+  which left the `VarTemplateDecl` unregistered and caused a subsequent
+  assertion failure when instantiating a partial specialization of that member.
+  (#GH198890)
 - Fix a problem where a substitution failure when evaluating a type requirement
   could directly make the program ill-formed.
 - Typo correction now corrects the name qualifier for invalid template names.
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp 
b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index b060d889abaa5..37ef4acd5d3d9 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1764,7 +1764,8 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,
   if (!TSI) {
     if (!InstantiatingVarTemplate)
       return nullptr;
-    TSI = D->getTypeSourceInfo();
+    TSI = SemaRef.Context.getTrivialTypeSourceInfo(SemaRef.Context.IntTy,
+                                                   D->getLocation());
     Invalid = true;
   } else if (TSI->getType()->isFunctionType()) {
     SemaRef.Diag(D->getLocation(), diag::err_variable_instantiates_to_function)
@@ -2541,15 +2542,12 @@ Decl 
*TemplateDeclInstantiator::VisitVarTemplatePartialSpecializationDecl(
 
   VarTemplateDecl *VarTemplate = D->getSpecializedTemplate();
 
-  // Lookup the already-instantiated declaration in the instantiation
-  // of the class template and return that.
+  // Lookup the already-instantiated declaration and return that.
   DeclContext::lookup_result Found = Owner->lookup(VarTemplate->getDeclName());
-  if (Found.empty())
-    return nullptr;
+  assert(!Found.empty() && "Instantiation found nothing?");
 
   VarTemplateDecl *InstVarTemplate = dyn_cast<VarTemplateDecl>(Found.front());
-  if (!InstVarTemplate)
-    return nullptr;
+  assert(InstVarTemplate && "Instantiation did not find a variable template?");
 
   if (VarTemplatePartialSpecializationDecl *Result =
           InstVarTemplate->findPartialSpecInstantiatedFromMember(D))

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to