Author: Aayush Shrivastava
Date: 2026-07-01T22:27:26-03:00
New Revision: 24e7deef7363d5dce2255c5350645b927e5e3313

URL: 
https://github.com/llvm/llvm-project/commit/24e7deef7363d5dce2255c5350645b927e5e3313
DIFF: 
https://github.com/llvm/llvm-project/commit/24e7deef7363d5dce2255c5350645b927e5e3313.diff

LOG: [clang] Fix crash in VisitVarTemplatePartialSpecializationDecl on failed 
instantiation (#200161)

Fixes #198890

When a class template is explicitly instantiated and a member variable
template's type involves a substitution failure (e.g. `typename T::type`
with `T=int`), `VisitVarDecl` returned `nullptr`, causing
`VisitVarTemplateDecl` to bail out before registering the
`VarTemplateDecl` in the owner's lookup table. A subsequent call to
`VisitVarTemplatePartialSpecializationDecl` then hit an assert
(`!Found.empty()`) on the empty lookup result.

Fix: When `SubstType` fails and `InstantiatingVarTemplate=true`, recover
by using `int` as the type (via `getTrivialTypeSourceInfo(IntTy)`) and
mark the resulting `VarDecl` invalid. This ensures
`VisitVarTemplateDecl` always receives a valid `VarDecl` and finishes
registering the `VarTemplateDecl`, preserving the invariant the asserts
rely on.

A regression test is added in `clang/test/SemaTemplate/GH198890.cpp`.

Added: 
    clang/test/SemaTemplate/GH198890.cpp

Modified: 
    clang/docs/ReleaseNotes.md
    clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Removed: 
    


################################################################################
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 324d6bf3857c7..37ef4acd5d3d9 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1760,13 +1760,19 @@ 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) {
+    if (!InstantiatingVarTemplate)
+      return nullptr;
+    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)
         << D->isStaticDataMember() << TSI->getType();
-    return nullptr;
+    if (!InstantiatingVarTemplate)
+      return nullptr;
+    Invalid = true;
   }
 
   DeclContext *DC = Owner;
@@ -1835,6 +1841,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
new file mode 100644
index 0000000000000..84a0b4d674fe5
--- /dev/null
+++ b/clang/test/SemaTemplate/GH198890.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
+
+// GitHub issue #198890: crash in VisitVarTemplatePartialSpecializationDecl
+// when the primary member variable template fails to instantiate.
+//
+// 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 {
+
+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 *>; // 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}}
+
+} // namespace GH198890


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

Reply via email to