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(this)) { auto From = TD->getInstantiatedFrom(); if (auto *CTD = dyn_cast_if_present(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( 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::f() == 1); static_assert(A::x == 1); static_assert(A::x == 2); -#if 0 - // FIXME: crashes static_assert(A::B::y == 1); static_assert(A::B::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 uk4; // expected-error 1+{{partial specialization of 'cls' must be imported}} expected-error 1+{{definition of}} cls::nested_cls unk1; // expected-error 1+{{explicit specialization of 'nested_cls' must be imported}} expected-error 1+{{definition of}} cls::nested_cls_t unk2; // expected-error 1+{{explicit specialization of 'nested_cls_t' must be imported}} expected-error 1+{{definition of}} - // expected-error@cxx-templates-unimported.h:29 {{explicit specialization of 'nested_cls_t' must be imported}} - // expected-note@-2 {{in evaluation of exception specification}} + // expected-error@+1 1+{{definition of 'nested_cls_t' must be imported}} cls::nested_cls_t unk3; // expected-error 1+{{explicit specialization of 'nested_cls_t' must be imported}} // For enums, uses that would trigger instantiations of definitions are not