[clang] [clang] fix finding class template instantiation pattern for member specializations (PR #199979)
via cfe-commits
cfe-commits at lists.llvm.org
Wed May 27 06:56:56 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Matheus Izvekov (mizvekov)
<details>
<summary>Changes</summary>
Stop treating the member which a member specialization specializes as the pattern of the former.
Split off from https://github.com/llvm/llvm-project/pull/199528
---
Full diff: https://github.com/llvm/llvm-project/pull/199979.diff
4 Files Affected:
- (modified) clang/docs/ReleaseNotes.rst (+1)
- (modified) clang/lib/AST/DeclCXX.cpp (+9-6)
- (modified) clang/test/CXX/temp/temp.spec/temp.expl.spec/p7.cpp (-6)
- (modified) clang/test/Modules/cxx-templates.cpp (+1-2)
``````````diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index fb70b83d6a7c4..73cc466355d36 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -651,6 +651,7 @@ Bug Fixes to C++ Support
- Fixed a crash when diagnosing an invalid static member function with an explicit object parameter (#GH177741)
- 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.
- Fix a problem where a substitution failure when evaluating a type requirement
could directly make the program ill-formed.
- Fix a problem where pack index expressions where incorrectly being regarded as equivalent.
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 2a58313b699e2..2de8ba8f484f4 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -2088,20 +2088,23 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(this)) {
auto From = TD->getInstantiatedFrom();
if (auto *CTD = dyn_cast_if_present<ClassTemplateDecl *>(From)) {
- while (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate()) {
- if (NewCTD->isMemberSpecialization())
+ while (!CTD->isMemberSpecialization()) {
+ ClassTemplateDecl *D = CTD->getInstantiatedFromMemberTemplate();
+ if (!D)
break;
- CTD = NewCTD;
+ CTD = D;
}
return CTD->getTemplatedDecl();
}
if (auto *CTPSD =
dyn_cast_if_present<ClassTemplatePartialSpecializationDecl *>(
From)) {
- while (auto *NewCTPSD = CTPSD->getInstantiatedFromMember()) {
- if (NewCTPSD->isMemberSpecialization())
+ while (!CTPSD->isMemberSpecialization()) {
+ ClassTemplatePartialSpecializationDecl *D =
+ CTPSD->getInstantiatedFromMember();
+ if (!D)
break;
- CTPSD = NewCTPSD;
+ CTPSD = D;
}
return CTPSD;
}
diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p7.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p7.cpp
index b93562a60de57..af07024cb7af5 100644
--- a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p7.cpp
+++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p7.cpp
@@ -83,11 +83,8 @@ namespace Undefined {
static_assert(A<short>::f<int>() == 1);
static_assert(A<short>::x<int> == 1);
static_assert(A<short>::x<int*> == 2);
-#if 0
- // FIXME: crashes
static_assert(A<short>::B<int>::y == 1);
static_assert(A<short>::B<int*>::y == 2);
-#endif
} // namespace Undefined
namespace Defined {
@@ -337,8 +334,5 @@ namespace Dependent {
static_assert(A<0>::f<2>() == 2);
static_assert(A<0>::x<2> == 2);
-#if 0
- // FIXME: crashes
static_assert(A<0>::B<2>::y == 2);
-#endif
} // namespace Dependent
diff --git a/clang/test/Modules/cxx-templates.cpp b/clang/test/Modules/cxx-templates.cpp
index 15f6091774424..e36511d8e315f 100644
--- a/clang/test/Modules/cxx-templates.cpp
+++ b/clang/test/Modules/cxx-templates.cpp
@@ -193,8 +193,7 @@ namespace hidden_specializations {
cls<char*> uk4; // expected-error 1+{{partial specialization of 'cls<T *>' must be imported}} expected-error 1+{{definition of}}
cls<void>::nested_cls unk1; // expected-error 1+{{explicit specialization of 'nested_cls' must be imported}} expected-error 1+{{definition of}}
cls<void>::nested_cls_t<int> unk2; // expected-error 1+{{explicit specialization of 'nested_cls_t' must be imported}} expected-error 1+{{definition of}}
- // expected-error at cxx-templates-unimported.h:29 {{explicit specialization of 'nested_cls_t' must be imported}}
- // expected-note at -2 {{in evaluation of exception specification}}
+ // expected-error at +1 1+{{definition of 'nested_cls_t' must be imported}}
cls<void>::nested_cls_t<char> unk3; // expected-error 1+{{explicit specialization of 'nested_cls_t' must be imported}}
// For enums, uses that would trigger instantiations of definitions are not
``````````
</details>
https://github.com/llvm/llvm-project/pull/199979
More information about the cfe-commits
mailing list