diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 3596109bf044f..4d57ea4fd55b8 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -197,6 +197,9 @@ Bug Fixes to C++ Support Fixes (`#67976 `_) - Fix crash and diagnostic with const qualified member operator new. Fixes (`#79748 `_) +- Fixed a crash where substituting into a requires-expression that involves parameter packs + during the equivalence determination of two constraint expressions. + (`#72557 `_) - Fix a crash when specializing an out-of-line member function with a default parameter where we did an incorrect specialization of the initialization of the default parameter. diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index e5999fa50117e..6d59180bc446d 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -241,10 +241,38 @@ Response HandleFunctionTemplateDecl(const FunctionTemplateDecl *FTD, while (const Type *Ty = NNS ? NNS->getAsType() : nullptr) { if (NNS->isInstantiationDependent()) { - if (const auto *TSTy = Ty->getAs()) + if (const auto *TSTy = Ty->getAs()) { + ArrayRef Arguments = TSTy->template_arguments(); + // Prefer template arguments from the injected-class-type if possible. + // For example, + // ```cpp + // template struct S { + // template void foo(); + // }; + // template template + // ^^^^^^^^^^^^^ InjectedTemplateArgs + // They're of kind TemplateArgument::Pack, not of + // TemplateArgument::Type. + // void S::foo() {} + // ^^^^^^^ + // TSTy->template_arguments() (which are of PackExpansionType) + // ``` + // This meets the contract in + // TreeTransform::TryExpandParameterPacks that the template arguments + // for unexpanded parameters should be of a Pack kind. + if (TSTy->isCurrentInstantiation()) { + auto *RD = TSTy->getCanonicalTypeInternal()->getAsCXXRecordDecl(); + if (ClassTemplateDecl *CTD = RD->getDescribedClassTemplate()) + Arguments = CTD->getInjectedTemplateArgs(); + else if (auto *Specialization = + dyn_cast(RD)) + Arguments = + Specialization->getTemplateInstantiationArgs().asArray(); + } Result.addOuterTemplateArguments( - const_cast(FTD), TSTy->template_arguments(), + const_cast(FTD), Arguments, /*Final=*/false); + } } NNS = NNS->getPrefix(); diff --git a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp index b6fea2e0b4b31..0142efcdc3ee8 100644 --- a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp +++ b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp @@ -581,3 +581,21 @@ void S::test(T target, U... value) } {} } // namespace GH74447 + +namespace GH72557 { + +template +concept IsAnyOf = true; + +template struct DerivedCollection { + template + requires IsAnyOf + unsigned long index(); +}; + +template +template + requires IsAnyOf +unsigned long DerivedCollection::index() {} + +} // namespace GH72557