Author: Younan Zhang Date: 2024-02-06T09:59:16+08:00 New Revision: 2c2d291b4568381999442e47fc77f949f19be0bc
URL: https://github.com/llvm/llvm-project/commit/2c2d291b4568381999442e47fc77f949f19be0bc DIFF: https://github.com/llvm/llvm-project/commit/2c2d291b4568381999442e47fc77f949f19be0bc.diff LOG: [concepts] Extract function template pack arguments from the current instantiation if possible (#80594) Before the constraint substitution, we employ `getTemplateInstantiationArgs`, which in turn attempts to inspect `TemplateArgument`s from the function template. For parameter packs from their parent contexts, we used to extract the arguments from the specialization type, in which could result in non-canonical argument types e.g. `PackExpansionType`. This may break the contract that, during a tree transformation, in `TreeTransform::TryExpandParameterPacks`, the corresponding `TemplateArgument`s for an `UnexpandedParameterPack` are expected to be of `Pack` kinds if we're expanding template parameters. Fixes https://github.com/llvm/llvm-project/issues/72557. Added: Modified: clang/docs/ReleaseNotes.rst clang/lib/Sema/SemaTemplateInstantiate.cpp clang/test/SemaTemplate/concepts-out-of-line-def.cpp Removed: ################################################################################ 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 <https://github.com/llvm/llvm-project/issues/67976>`_) - Fix crash and diagnostic with const qualified member operator new. Fixes (`#79748 <https://github.com/llvm/llvm-project/issues/79748>`_) +- Fixed a crash where substituting into a requires-expression that involves parameter packs + during the equivalence determination of two constraint expressions. + (`#72557 <https://github.com/llvm/llvm-project/issues/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<TemplateSpecializationType>()) + if (const auto *TSTy = Ty->getAs<TemplateSpecializationType>()) { + ArrayRef<TemplateArgument> Arguments = TSTy->template_arguments(); + // Prefer template arguments from the injected-class-type if possible. + // For example, + // ```cpp + // template <class... Pack> struct S { + // template <class T> void foo(); + // }; + // template <class... Pack> template <class T> + // ^^^^^^^^^^^^^ InjectedTemplateArgs + // They're of kind TemplateArgument::Pack, not of + // TemplateArgument::Type. + // void S<Pack...>::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<ClassTemplateSpecializationDecl>(RD)) + Arguments = + Specialization->getTemplateInstantiationArgs().asArray(); + } Result.addOuterTemplateArguments( - const_cast<FunctionTemplateDecl *>(FTD), TSTy->template_arguments(), + const_cast<FunctionTemplateDecl *>(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<T>::test(T target, U... value) } {} } // namespace GH74447 + +namespace GH72557 { + +template <typename...> +concept IsAnyOf = true; + +template <class... DerTs> struct DerivedCollection { + template <class DerT> + requires IsAnyOf<DerTs...> + unsigned long index(); +}; + +template <class... DerTs> +template <class DerT> + requires IsAnyOf<DerTs...> +unsigned long DerivedCollection<DerTs...>::index() {} + +} // namespace GH72557 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits