[clang] [Clang] [Sema] Fix crash instantiating a member variable template partial specialization when the enclosing class template is deserialized (PR #202958)

Shengxin Pei via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 30 02:43:25 PDT 2026


================
@@ -2535,10 +2535,34 @@ Decl *TemplateDeclInstantiator::VisitVarTemplatePartialSpecializationDecl(
 
   // Lookup the already-instantiated declaration and return that.
   DeclContext::lookup_result Found = Owner->lookup(VarTemplate->getDeclName());
+
+  // Normally the primary member variable template has already been instantiated
+  // into Owner, because it is declared before its partial specializations and
+  // so is visited first while instantiating the enclosing class. However, when
+  // the class template pattern is deserialized from a module or precompiled
+  // preamble, the primary may not have been materialized into Owner yet,
+  // leaving the lookup empty. Previously this asserted (and crashed release
+  // builds with a null dereference). Instantiate the primary on demand and look
+  // it up again.
+  if (Found.empty()) {
+    if (Decl *InstPrimary = Visit(VarTemplate))
+      if (auto *InstVTD = dyn_cast<VarTemplateDecl>(InstPrimary))
+        Found = Owner->lookup(InstVTD->getDeclName());
+  }
+
+  // After the on-demand instantiation above the primary must be present. Keep
+  // the original invariant assertions so a genuinely-missing primary is still
+  // flagged in +Asserts builds, with a null return as a release-safe guard so a
+  // stray case degrades gracefully instead of dereferencing an empty lookup
+  // result.
   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;
----------------
TPPPP72 wrote:

I believe this code lacks human review. I don't understand its meaning. Could you explain why an if statement is added after `assert`? It seems meaningless for `assert`.

https://github.com/llvm/llvm-project/pull/202958


More information about the cfe-commits mailing list