https://github.com/hbatagelo updated https://github.com/llvm/llvm-project/pull/202006
>From 36cdf84c20828a550e0334bb31834fe86f8f08aa Mon Sep 17 00:00:00 2001 From: Harlen Batagelo <[email protected]> Date: Sat, 6 Jun 2026 02:05:54 -0300 Subject: [PATCH 1/4] Bail out when the lookup finds nothing --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 3 ++- clang/test/SemaTemplate/GH195988.cpp | 8 ++++++++ 3 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 clang/test/SemaTemplate/GH195988.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index cf4826f50e5a5..774a650c2c517 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -731,6 +731,7 @@ Bug Fixes to C++ Support - Fixed a use-after-free bug when parsing default arguments containing lambdas in declarations with template-id declarators. (#GH196725) - Fixed a crash in constant evaluation using placement new on an array which was later initialized. (#GH196450) - Fixed an issue where Clang incorrectly accepted invalid unqualified uses of local nested class names outside their declaring scope. (#GH184622) +- Fixed a crash when instantiating a class template whose member variable partial specialization has an invalid primary template. (#GH195988) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 324d6bf3857c7..d6e0b63f71e54 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2535,7 +2535,8 @@ Decl *TemplateDeclInstantiator::VisitVarTemplatePartialSpecializationDecl( // Lookup the already-instantiated declaration 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?"); diff --git a/clang/test/SemaTemplate/GH195988.cpp b/clang/test/SemaTemplate/GH195988.cpp new file mode 100644 index 0000000000000..1924a8c98c262 --- /dev/null +++ b/clang/test/SemaTemplate/GH195988.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template <typename> struct A { + template <typename T> static B x; // expected-error {{unknown type name 'B'}} + template <typename T> static int x<T*>; +}; + +A<int> a; >From 16c5b0ce33aecf4285152b2f139b859eed99c493 Mon Sep 17 00:00:00 2001 From: Harlen Batagelo <[email protected]> Date: Wed, 17 Jun 2026 00:45:25 -0300 Subject: [PATCH 2/4] Keep assertion and bail out before lookup --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index d6e0b63f71e54..c58ed293deca5 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2532,11 +2532,12 @@ Decl *TemplateDeclInstantiator::VisitVarTemplatePartialSpecializationDecl( "Only static data member templates are allowed."); VarTemplateDecl *VarTemplate = D->getSpecializedTemplate(); + if (VarTemplate->isInvalidDecl()) + return nullptr; // 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()); assert(InstVarTemplate && "Instantiation did not find a variable template?"); >From b78cc188253ffbc591c8100247bce05fa868e46f Mon Sep 17 00:00:00 2001 From: Harlen Batagelo <[email protected]> Date: Fri, 26 Jun 2026 19:02:08 -0300 Subject: [PATCH 3/4] Fallback to int to keep a valid AST --- clang/lib/Sema/SemaDecl.cpp | 4 +++- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index cddcf3a010279..495486656ae8e 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -8055,7 +8055,9 @@ NamedDecl *Sema::ActOnVariableDeclarator( if (R->getContainedDeducedType()) ParsingInitForAutoVars.insert(NewVD); - if (D.isInvalidType() || Invalid) { + // Mark the declaration as invalid on error, but exempt variable templates + // with invalid types for error recovery. + if ((D.isInvalidType() && !IsVariableTemplate) || Invalid) { NewVD->setInvalidDecl(); if (NewTemplate) NewTemplate->setInvalidDecl(); diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index c58ed293deca5..324d6bf3857c7 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2532,8 +2532,6 @@ Decl *TemplateDeclInstantiator::VisitVarTemplatePartialSpecializationDecl( "Only static data member templates are allowed."); VarTemplateDecl *VarTemplate = D->getSpecializedTemplate(); - if (VarTemplate->isInvalidDecl()) - return nullptr; // Lookup the already-instantiated declaration and return that. DeclContext::lookup_result Found = Owner->lookup(VarTemplate->getDeclName()); >From 6e21b630e3e0d761fa4443ee8086736ed04e03a3 Mon Sep 17 00:00:00 2001 From: Harlen Batagelo <[email protected]> Date: Wed, 1 Jul 2026 22:14:00 -0300 Subject: [PATCH 4/4] Fix InstantiateClassImpl instead --- clang/lib/Sema/SemaDecl.cpp | 4 +--- clang/lib/Sema/SemaTemplateInstantiate.cpp | 7 ++++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 8effeab6c9281..d45c3eb35094f 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -8055,9 +8055,7 @@ NamedDecl *Sema::ActOnVariableDeclarator( if (R->getContainedDeducedType()) ParsingInitForAutoVars.insert(NewVD); - // Mark the declaration as invalid on error, but exempt variable templates - // with invalid types for error recovery. - if ((D.isInvalidType() && !IsVariableTemplate) || Invalid) { + if (D.isInvalidType() || Invalid) { NewVD->setInvalidDecl(); if (NewTemplate) NewTemplate->setInvalidDecl(); diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index a77ea5fd3dfff..ad37903f03c9b 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -3623,7 +3623,9 @@ bool Sema::InstantiateClassImpl( if (Member->isInvalidDecl()) { Instantiation->setInvalidDecl(); - continue; + // Keep invalid variable templates for partial specialization lookup. + if (!isa<VarTemplateDecl>(Member)) + continue; } Decl *NewMember = Instantiator.Visit(Member); @@ -3655,6 +3657,9 @@ bool Sema::InstantiateClassImpl( MightHaveConstexprVirtualFunctions = true; } + if (Member->isInvalidDecl()) + NewMember->setInvalidDecl(); + if (NewMember->isInvalidDecl()) Instantiation->setInvalidDecl(); } else { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
