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

>From 4e3bbd2452e89acf1f15e8b0d1fdd60488207a3a 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 c9bc613a7c4ea..1f51b37af56a4 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2540,12 +2540,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 e09a7d1c40267a3d745af82b41bf5e15c6c826da 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 1f51b37af56a4..4cd4a9391165c 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1767,13 +1767,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;
@@ -1842,6 +1843,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 80aaf581c682abd672aa46f71048cdb2636289fd 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 4cd4a9391165c..0e4572eeef599 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1769,11 +1769,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 c381f975e3b7182e116673a03ca65130ab336497 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] Use int as recovery type and restore asserts in
 VisitVarTemplatePartialSpecializationDecl

---
 clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp 
b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 0e4572eeef599..46203637922eb 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1771,7 +1771,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)
@@ -2548,15 +2549,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